def _SingleBranch(self, opt, branch, people, no_review): project = branch.project name = branch.name remote = project.GetBranch(name).remote key = "review.%s.autoupload" % remote.review answer = project.config.GetBoolean(key) if answer is False: _die("upload blocked by %s = false" % key) if answer is None: date = branch.date commit_list = branch.commits print("Upload project %s/ to remote branch %s:" % (project.relpath, project.revisionExpr)) print( " branch %s (%2d commit%s, %s):" % (name, len(commit_list), len(commit_list) != 1 and "s" or "", date) ) for commit in commit_list: print(" %s" % portable.stream2str(commit)) sys.stdout.write("to %s (y/N)? " % remote.review) sys.stdout.flush() answer = sys.stdin.readline().strip().lower() answer = answer in ("y", "yes", "1", "true", "t") if answer: if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD: answer = _ConfirmManyUploads() if answer: self._UploadAndReport(opt, [branch], people, no_review) else: _die("upload aborted by user")
def _do(self, *args): command = ['config', '--file', self.file] command.extend(args) p = GitCommand(None, command, capture_stdout=True, capture_stderr=True) if p.Wait() == 0: return portable.stream2str(p.stdout) else: GitError('git config %s: %s' % (str(args), p.stderr))
def Execute(self, opt, args): if len(args) != 1: self.Usage() reference = args[0] p = GitCommand(None, ['rev-parse', '--verify', reference], capture_stdout=True, capture_stderr=True) if p.Wait() != 0: print(p.stderr, file=sys.stderr) sys.exit(1) sha1 = p.stdout.strip() p = GitCommand(None, ['cat-file', 'commit', sha1], capture_stdout=True) if p.Wait() != 0: print("error: Failed to retrieve old commit message", file=sys.stderr) sys.exit(1) old_msg = self._StripHeader(portable.stream2str(p.stdout)) p = GitCommand(None, ['cherry-pick', sha1], capture_stdout=True, capture_stderr=True) status = p.Wait() print(p.stdout, file=sys.stdout) print(p.stderr, file=sys.stderr) if status == 0: # The cherry-pick was applied correctly. We just need to edit the # commit message. new_msg = self._Reformat(old_msg, sha1) p = GitCommand(None, ['commit', '--amend', '-F', '-'], provide_stdin=True, capture_stdout=True, capture_stderr=True) p.stdin.write(new_msg) if p.Wait() != 0: print("error: Failed to update commit message", file=sys.stderr) sys.exit(1) else: print( 'NOTE: When committing (please see above) and editing the commit' 'message, please remove the old Change-Id-line and add:') print(self._GetReference(sha1), file=stderr) print(file=stderr)
def Execute(self, opt, args): if len(args) != 1: self.Usage() reference = args[0] p = GitCommand(None, ['rev-parse', '--verify', reference], capture_stdout=True, capture_stderr=True) if p.Wait() != 0: print(p.stderr, file=sys.stderr) sys.exit(1) sha1 = p.stdout.strip() p = GitCommand(None, ['cat-file', 'commit', sha1], capture_stdout=True) if p.Wait() != 0: print("error: Failed to retrieve old commit message", file=sys.stderr) sys.exit(1) old_msg = self._StripHeader(portable.stream2str(p.stdout)) p = GitCommand(None, ['cherry-pick', sha1], capture_stdout=True, capture_stderr=True) status = p.Wait() print(p.stdout, file=sys.stdout) print(p.stderr, file=sys.stderr) if status == 0: # The cherry-pick was applied correctly. We just need to edit the # commit message. new_msg = self._Reformat(old_msg, sha1) p = GitCommand(None, ['commit', '--amend', '-F', '-'], provide_stdin=True, capture_stdout=True, capture_stderr=True) p.stdin.write(new_msg) if p.Wait() != 0: print("error: Failed to update commit message", file=sys.stderr) sys.exit(1) else: print('NOTE: When committing (please see above) and editing the commit' 'message, please remove the old Change-Id-line and add:') print(self._GetReference(sha1), file=stderr) print(file=stderr)
def _SingleBranch(self, opt, branch, people, no_review): project = branch.project name = branch.name remote = project.GetBranch(name).remote key = 'review.%s.autoupload' % remote.review answer = project.config.GetBoolean(key) if answer is False: _die("upload blocked by %s = false" % key) if answer is None: date = branch.date commit_list = branch.commits print('Upload project %s/ to remote branch %s:' % (project.relpath, project.revisionExpr)) print(' branch %s (%2d commit%s, %s):' % ( name, len(commit_list), len(commit_list) != 1 and 's' or '', date)) for commit in commit_list: print(' %s' % portable.stream2str(commit)) sys.stdout.write('to %s (y/N)? ' % remote.review) sys.stdout.flush() answer = sys.stdin.readline().strip().lower() answer = answer in ('y', 'yes', '1', 'true', 't') if answer: if len(branch.commits) > UNUSUAL_COMMIT_THRESHOLD: answer = _ConfirmManyUploads() if answer: self._UploadAndReport(opt, [branch], people, no_review) else: _die("upload aborted by user")
def version(self): p = GitCommand(None, ['--version'], capture_stdout=True) if p.Wait() == 0: return portable.stream2str(p.stdout) return None
def Execute(self, opt, args): out = GrepColoring(self.manifest.manifestProject.config) cmd_argv = ['grep'] if out.is_on and git_require((1, 6, 3)): cmd_argv.append('--color') cmd_argv.extend(getattr(opt, 'cmd_argv', [])) if '-e' not in cmd_argv: if not args: self.Usage() cmd_argv.append('-e') cmd_argv.append(args[0]) args = args[1:] projects = self.GetProjects(args) full_name = False if len(projects) > 1: cmd_argv.append('--full-name') full_name = True have_rev = False if opt.revision: if '--cached' in cmd_argv: print('fatal: cannot combine --cached and --revision', file=sys.stderr) sys.exit(1) have_rev = True cmd_argv.extend(opt.revision) cmd_argv.append('--') bad_rev = False have_match = False for project in projects: p = GitCommand(project, cmd_argv, bare=False, capture_stdout=True, capture_stderr=True) if p.Wait() != 0: # no results # if p.stderr: if have_rev and 'fatal: ambiguous argument' in p.stderr: bad_rev = True else: out.project('--- project %s ---' % project.relpath) out.nl() out.write("%s", p.stderr) out.nl() continue have_match = True # We cut the last element, to avoid a blank line. # r = portable.stream2str(p.stdout).split('\n') r = r[0:-1] if have_rev and full_name: for line in r: rev, line = line.split(':', 1) out.write("%s", rev) out.write(':') out.project(project.relpath) out.write('/') out.write("%s", line) out.nl() elif full_name: for line in r: out.project(project.relpath) out.write('/') out.write("%s", line) out.nl() else: for line in r: print(line) if have_match: sys.exit(0) elif have_rev and bad_rev: for r in opt.revision: print("error: can't search revision %s" % r, file=sys.stderr) sys.exit(1) else: sys.exit(1)
def Execute(self, opt, args): if opt.jobs: self.jobs = opt.jobs if self.jobs > 1: soft_limit, _ = _rlimit_nofile() self.jobs = min(self.jobs, (soft_limit - 5) / 3) if opt.network_only and opt.detach_head: print('error: cannot combine -n and -d', file=sys.stderr) sys.exit(1) if opt.network_only and opt.local_only: print('error: cannot combine -n and -l', file=sys.stderr) sys.exit(1) if opt.manifest_name and opt.smart_sync: print('error: cannot combine -m and -s', file=sys.stderr) sys.exit(1) if opt.manifest_name and opt.smart_tag: print('error: cannot combine -m and -t', file=sys.stderr) sys.exit(1) if opt.manifest_server_username or opt.manifest_server_password: if not (opt.smart_sync or opt.smart_tag): print('error: -u and -p may only be combined with -s or -t', file=sys.stderr) sys.exit(1) if None in [ opt.manifest_server_username, opt.manifest_server_password ]: print('error: both -u and -p must be given', file=sys.stderr) sys.exit(1) if opt.manifest_name: self.manifest.Override(opt.manifest_name) if opt.smart_sync or opt.smart_tag: if not self.manifest.manifest_server: print( 'error: cannot smart sync: no manifest server defined in' 'manifest', file=sys.stderr) sys.exit(1) manifest_server = self.manifest.manifest_server if not '@' in manifest_server: username = None password = None if opt.manifest_server_username and opt.manifest_server_password: username = opt.manifest_server_username password = opt.manifest_server_password else: try: info = netrc.netrc() except IOError: print( '.netrc file does not exist or could not be opened', file=sys.stderr) else: try: parse_result = urllib.parse(manifest_server) if parse_result.hostname: username, _account, password = \ info.authenticators(parse_result.hostname) except TypeError: # TypeError is raised when the given hostname is not present # in the .netrc file. print('No credentials found for %s in .netrc' % parse_result.hostname, file=sys.stderr) except netrc.NetrcParseError as e: print('Error parsing .netrc file: %s' % e, file=sys.stderr) if username and password: manifest_server = manifest_server.replace( '://', '://%s:%s@' % (username, password), 1) try: server = xmlrpc.server(manifest_server) if opt.smart_sync: p = self.manifest.manifestProject b = p.GetBranch(p.CurrentBranch) branch = b.merge if branch.startswith(R_HEADS): branch = branch[len(R_HEADS):] env = os.environ.copy() if ('TARGET_PRODUCT' in env and 'TARGET_BUILD_VARIANT' in env): target = '%s-%s' % (env['TARGET_PRODUCT'], env['TARGET_BUILD_VARIANT']) [success, manifest_str ] = server.GetApprovedManifest(branch, target) else: [success, manifest_str] = server.GetApprovedManifest(branch) else: assert (opt.smart_tag) [success, manifest_str] = server.GetManifest(opt.smart_tag) if success: manifest_name = "smart_sync_override.xml" manifest_path = os.path.join( self.manifest.manifestProject.worktree, manifest_name) try: f = open(manifest_path, 'w') try: f.write(manifest_str) finally: f.close() except IOError: print('error: cannot write manifest to %s' % manifest_path, file=sys.stderr) sys.exit(1) self.manifest.Override(manifest_name) else: print('error in getting manifest: %s' % manifest_str, file=sys.stderr) sys.exit(1) except (socket.error, IOError, xmlrpc.client.Fault) as e: print('error: cannot connect to manifest server %s:\n%s' % (self.manifest.manifest_server, e), file=sys.stderr) sys.exit(1) except xmlrpc.client.ProtocolError as e: print('error: cannot connect to manifest server %s:\n%d %s' % (self.manifest.manifest_server, e.errcode, e.errmsg), file=sys.stderr) sys.exit(1) rp = self.manifest.repoProject rp.PreSync() mp = self.manifest.manifestProject mp.PreSync() if opt.repo_upgraded: _PostRepoUpgrade(self.manifest, quiet=opt.quiet) if not opt.local_only: mp.Sync_NetworkHalf(quiet=opt.quiet, current_branch_only=opt.current_branch_only) if mp.HasChanges: syncbuf = SyncBuffer(mp.config) mp.Sync_LocalHalf(syncbuf) if not syncbuf.Finish(): sys.exit(1) self.manifest._Unload() if opt.jobs is None: self.jobs = self.manifest.default.sync_j if not portable.isPosix(): # fix broken manifest.xml link pass all_projects = self.GetProjects(args, missing_ok=True, submodules_ok=opt.fetch_submodules) self._fetch_times = _FetchTimes(self.manifest) if not opt.local_only: to_fetch = [] now = time.time() if _ONE_DAY_S <= (now - rp.LastFetch): to_fetch.append(rp) to_fetch.extend(all_projects) to_fetch.sort(key=self._fetch_times.Get, reverse=True) fetched = self._Fetch(to_fetch, opt) _PostRepoFetch(rp, opt.no_repo_verify) if opt.network_only: # bail out now; the rest touches the working tree return # Iteratively fetch missing and/or nested unregistered submodules previously_missing_set = set() while True: self.manifest._Unload() all_projects = self.GetProjects( args, missing_ok=True, submodules_ok=opt.fetch_submodules) missing = [] for project in all_projects: if project.gitdir not in fetched: missing.append(project) if not missing: break # Stop us from non-stopped fetching actually-missing repos: If set of # missing repos has not been changed from last fetch, we break. missing_set = set(p.name for p in missing) if previously_missing_set == missing_set: break previously_missing_set = missing_set fetched.update(self._Fetch(missing, opt)) if self.manifest.IsMirror: # bail out now, we have no working tree return if self.UpdateProjectList(): sys.exit(1) syncbuf = SyncBuffer(mp.config, detach_head=opt.detach_head) pm = Progress('Syncing work tree', len(all_projects)) for project in all_projects: pm.update() if project.worktree: if opt.report: p = GitCommand( project, ['log', '--pretty=%h %s (%cn, %ar)', 'HEAD..m/master'], capture_stdout=True) if p.Wait() != 0: print("Failed to create report") else: if len(p.stdout): print('\n' + project.name + ':\n') print(portable.stream2str(p.stdout)[:-1]) print('\n') if not opt.dry_run: project.Sync_LocalHalf(syncbuf) pm.end() print(file=sys.stderr) if not syncbuf.Finish(): sys.exit(1) # If there's a notice that's supposed to print at the end of the sync, print # it now... if self.manifest.notice: print(self.manifest.notice)
def Execute(self, opt, args): if opt.jobs: self.jobs = opt.jobs if self.jobs > 1: soft_limit, _ = _rlimit_nofile() self.jobs = min(self.jobs, (soft_limit - 5) / 3) if opt.network_only and opt.detach_head: print('error: cannot combine -n and -d', file=sys.stderr) sys.exit(1) if opt.network_only and opt.local_only: print('error: cannot combine -n and -l', file=sys.stderr) sys.exit(1) if opt.manifest_name and opt.smart_sync: print('error: cannot combine -m and -s', file=sys.stderr) sys.exit(1) if opt.manifest_name and opt.smart_tag: print('error: cannot combine -m and -t', file=sys.stderr) sys.exit(1) if opt.manifest_server_username or opt.manifest_server_password: if not (opt.smart_sync or opt.smart_tag): print('error: -u and -p may only be combined with -s or -t', file=sys.stderr) sys.exit(1) if None in [opt.manifest_server_username, opt.manifest_server_password]: print('error: both -u and -p must be given', file=sys.stderr) sys.exit(1) if opt.manifest_name: self.manifest.Override(opt.manifest_name) if opt.smart_sync or opt.smart_tag: if not self.manifest.manifest_server: print('error: cannot smart sync: no manifest server defined in' 'manifest', file=sys.stderr) sys.exit(1) manifest_server = self.manifest.manifest_server if not '@' in manifest_server: username = None password = None if opt.manifest_server_username and opt.manifest_server_password: username = opt.manifest_server_username password = opt.manifest_server_password else: try: info = netrc.netrc() except IOError: print('.netrc file does not exist or could not be opened', file=sys.stderr) else: try: parse_result = urllib.parse(manifest_server) if parse_result.hostname: username, _account, password = \ info.authenticators(parse_result.hostname) except TypeError: # TypeError is raised when the given hostname is not present # in the .netrc file. print('No credentials found for %s in .netrc' % parse_result.hostname, file=sys.stderr) except netrc.NetrcParseError as e: print('Error parsing .netrc file: %s' % e, file=sys.stderr) if username and password: manifest_server = manifest_server.replace('://', '://%s:%s@' % (username, password), 1) try: server = xmlrpc.server(manifest_server) if opt.smart_sync: p = self.manifest.manifestProject b = p.GetBranch(p.CurrentBranch) branch = b.merge if branch.startswith(R_HEADS): branch = branch[len(R_HEADS):] env = os.environ.copy() if ('TARGET_PRODUCT' in env and 'TARGET_BUILD_VARIANT' in env): target = '%s-%s' % (env['TARGET_PRODUCT'], env['TARGET_BUILD_VARIANT']) [success, manifest_str] = server.GetApprovedManifest(branch, target) else: [success, manifest_str] = server.GetApprovedManifest(branch) else: assert (opt.smart_tag) [success, manifest_str] = server.GetManifest(opt.smart_tag) if success: manifest_name = "smart_sync_override.xml" manifest_path = os.path.join(self.manifest.manifestProject.worktree, manifest_name) try: f = open(manifest_path, 'w') try: f.write(manifest_str) finally: f.close() except IOError: print('error: cannot write manifest to %s' % manifest_path, file=sys.stderr) sys.exit(1) self.manifest.Override(manifest_name) else: print('error in getting manifest: %s' % manifest_str, file=sys.stderr) sys.exit(1) except (socket.error, IOError, xmlrpc.client.Fault) as e: print('error: cannot connect to manifest server %s:\n%s' % (self.manifest.manifest_server, e), file=sys.stderr) sys.exit(1) except xmlrpc.client.ProtocolError as e: print('error: cannot connect to manifest server %s:\n%d %s' % (self.manifest.manifest_server, e.errcode, e.errmsg), file=sys.stderr) sys.exit(1) rp = self.manifest.repoProject rp.PreSync() mp = self.manifest.manifestProject mp.PreSync() if opt.repo_upgraded: _PostRepoUpgrade(self.manifest, quiet=opt.quiet) if not opt.local_only: mp.Sync_NetworkHalf(quiet=opt.quiet, current_branch_only=opt.current_branch_only) if mp.HasChanges: syncbuf = SyncBuffer(mp.config) mp.Sync_LocalHalf(syncbuf) if not syncbuf.Finish(): sys.exit(1) self.manifest._Unload() if opt.jobs is None: self.jobs = self.manifest.default.sync_j if not portable.isPosix(): # fix broken manifest.xml link pass all_projects = self.GetProjects(args, missing_ok=True, submodules_ok=opt.fetch_submodules) self._fetch_times = _FetchTimes(self.manifest) if not opt.local_only: to_fetch = [] now = time.time() if _ONE_DAY_S <= (now - rp.LastFetch): to_fetch.append(rp) to_fetch.extend(all_projects) to_fetch.sort(key=self._fetch_times.Get, reverse=True) fetched = self._Fetch(to_fetch, opt) _PostRepoFetch(rp, opt.no_repo_verify) if opt.network_only: # bail out now; the rest touches the working tree return # Iteratively fetch missing and/or nested unregistered submodules previously_missing_set = set() while True: self.manifest._Unload() all_projects = self.GetProjects(args, missing_ok=True, submodules_ok=opt.fetch_submodules) missing = [] for project in all_projects: if project.gitdir not in fetched: missing.append(project) if not missing: break # Stop us from non-stopped fetching actually-missing repos: If set of # missing repos has not been changed from last fetch, we break. missing_set = set(p.name for p in missing) if previously_missing_set == missing_set: break previously_missing_set = missing_set fetched.update(self._Fetch(missing, opt)) if self.manifest.IsMirror: # bail out now, we have no working tree return if self.UpdateProjectList(): sys.exit(1) syncbuf = SyncBuffer(mp.config, detach_head=opt.detach_head) pm = Progress('Syncing work tree', len(all_projects)) for project in all_projects: pm.update() if project.worktree: if opt.report: p = GitCommand(project, ['log', '--pretty=%h %s (%cn, %ar)', 'HEAD..m/master'], capture_stdout=True) if p.Wait() != 0: print("Failed to create report") else: if len(p.stdout): print('\n' + project.name + ':\n') print(portable.stream2str(p.stdout)[:-1]) print('\n') if not opt.dry_run: project.Sync_LocalHalf(syncbuf) pm.end() print(file=sys.stderr) if not syncbuf.Finish(): sys.exit(1) # If there's a notice that's supposed to print at the end of the sync, print # it now... if self.manifest.notice: print(self.manifest.notice)
def ReviewUrl(self, userEmail): if self._review_url is None: if self.review is None: return None u = self.review if u.endswith('/Gerrit'): u = u[:len(u) - len('/Gerrit')] if u.endswith('/ssh_info'): u = u[:len(u) - len('/ssh_info')] if not u.endswith('/'): u += '/' if u in REVIEW_CACHE: self._review_url = REVIEW_CACHE[u] elif 'REPO_HOST_PORT_INFO' in os.environ: host, port = os.environ['REPO_HOST_PORT_INFO'].split() self._review_url = self._SshReviewUrl(userEmail, host, port) REVIEW_CACHE[u] = self._review_url else: try: # NOTE: contrary to original repo: do not switch automatically to ssh, since this is contra-intuitive # try to fetch ssh infos from http gerrit server if protocol not specified protocolSeperator = "://" protocolSepIndex = u.find(protocolSeperator) if protocolSepIndex == -1: protocols = ["http", "https"] for prefix in protocols: http_url = '%s://%s' % (prefix, u) info_url = http_url + 'ssh_info' info = None try: info = portable.stream2str(urllib.request.urlopen(info_url).read()) if '<' in info: # Assume the server gave us some sort of HTML # response back, like maybe a login page. # raise UploadError('%s: Cannot parse response' % info_url) if info != 'NOT_AVAILABLE': host, port = info.split() self._review_url = self._SshReviewUrl(userEmail, host, port) except Exception as e: Trace("could not get ssh infos of %s from %s (received %s), error %s", u, info_url, info, e) info = 'NOT_AVAILABLE' if not self._review_url: # Assume HTTP if SSH is not enabled. self._review_url = http_url + 'p/' Trace( "warning: proceed upload with http url %s since no protocol given and no infos could be retrieved from %s", self._review_url, info_url) print("detected %s as review url" % self._review_url) else: self._review_url = u except urllib.error.HTTPError as e: raise UploadError('%s: %s' % (self.review, str(e))) except urllib.error.URLError as e: raise UploadError('%s: %s' % (self.review, str(e))) REVIEW_CACHE[u] = self._review_url return self._review_url + self.projectname
def ReviewUrl(self, userEmail): if self._review_url is None: if self.review is None: return None u = self.review if u.endswith('/Gerrit'): u = u[:len(u) - len('/Gerrit')] if u.endswith('/ssh_info'): u = u[:len(u) - len('/ssh_info')] if not u.endswith('/'): u += '/' if u in REVIEW_CACHE: self._review_url = REVIEW_CACHE[u] elif 'REPO_HOST_PORT_INFO' in os.environ: host, port = os.environ['REPO_HOST_PORT_INFO'].split() self._review_url = self._SshReviewUrl(userEmail, host, port) REVIEW_CACHE[u] = self._review_url else: try: # NOTE: contrary to original repo: do not switch automatically to ssh, since this is contra-intuitive # try to fetch ssh infos from http gerrit server if protocol not specified protocolSeperator = "://" protocolSepIndex = u.find(protocolSeperator) if protocolSepIndex == -1: protocols = ["http", "https"] for prefix in protocols: http_url = '%s://%s' % (prefix, u) info_url = http_url + 'ssh_info' info = None try: info = portable.stream2str( urllib.request.urlopen(info_url).read()) if '<' in info: # Assume the server gave us some sort of HTML # response back, like maybe a login page. # raise UploadError( '%s: Cannot parse response' % info_url) if info != 'NOT_AVAILABLE': host, port = info.split() self._review_url = self._SshReviewUrl( userEmail, host, port) except Exception as e: Trace( "could not get ssh infos of %s from %s (received %s), error %s", u, info_url, info, e) info = 'NOT_AVAILABLE' if not self._review_url: # Assume HTTP if SSH is not enabled. self._review_url = http_url + 'p/' Trace( "warning: proceed upload with http url %s since no protocol given and no infos could be retrieved from %s", self._review_url, info_url) print("detected %s as review url" % self._review_url) else: self._review_url = u except urllib.error.HTTPError as e: raise UploadError('%s: %s' % (self.review, str(e))) except urllib.error.URLError as e: raise UploadError('%s: %s' % (self.review, str(e))) REVIEW_CACHE[u] = self._review_url return self._review_url + self.projectname