def _Main(argv): result = 0 signal.signal(signal.SIGTERM, portable.terminateHandle) opt = optparse.OptionParser(usage="repo wrapperinfo -- ...") opt.add_option("--repo-dir", dest="repodir", help="path to .repo/") opt.add_option("--wrapper-version", dest="wrapper_version", help="version of the wrapper script") opt.add_option("--wrapper-path", dest="wrapper_path", help="location of the wrapper script") _PruneOptions(argv, opt) opt, argv = opt.parse_args(argv) _CheckWrapperVersion(opt.wrapper_version, opt.wrapper_path) _CheckRepoDir(opt.repodir) Version.wrapper_version = opt.wrapper_version Version.wrapper_path = opt.wrapper_path repo = _Repo(opt.repodir) repo._Config(argv) gopts = repo.config[2] if gopts.debug: print("enter debug mode, host %s" % gopts.debug_host) _Debug(gopts.debug_host, gopts.debug_env) if gopts.debug: if portable.isPosix(): # deactivate pager on posix systems since forked process cant be debugged os.environ['GIT_PAGER'] = '' # intercept here if on Windows and Pager is required if not portable.isPosix(): if _WindowsPager(repo): # everything was already done; so exit return 0 try: try: init_ssh() init_http() result = repo._Run() or 0 finally: close_ssh() except KeyboardInterrupt: print('aborted by user', file=sys.stderr) result = 1 except ManifestParseError as mpe: print('fatal: %s' % mpe, file=sys.stderr) result = 1 except RepoChangedException as rce: # If repo changed, re-exec ourselves. # argv = list(sys.argv) argv.extend(rce.extra_args) argv = [sys.executable] + argv try: argv.insert(0, __file__) argv.insert(0, sys.executable) result = subprocess.call(argv) except OSError as e: print('fatal: cannot restart repo after upgrade', file=sys.stderr) print('fatal: %s' % e, file=sys.stderr) result = 128 return result
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 not opt.command: self.Usage() cmd = [opt.command[0]] shell = True if re.compile(r'^[a-z0-9A-Z_/\.-]+$').match(cmd[0]): shell = False if shell and portable.isPosix(): cmd.append(cmd[0]) cmd.extend(opt.command[1:]) if opt.project_header \ and not shell \ and cmd[0] == 'git': # If this is a direct git command that can enable colorized # output and the user prefers coloring, add --color into the # command line because we are going to wrap the command into # a pipe and git won't know coloring should activate. # for cn in cmd[1:]: if not cn.startswith('-'): break else: cn = None # pylint: disable=W0631 if cn and cn in _CAN_COLOR: class ColorCmd(Coloring): def __init__(self, config, cmd): Coloring.__init__(self, config, cmd) if ColorCmd(self.manifest.manifestProject.config, cn).is_on: cmd.insert(cmd.index(cn) + 1, '--color') # pylint: enable=W0631 mirror = self.manifest.IsMirror out = ForallColoring(self.manifest.manifestProject.config) out.redirect(sys.stdout) rc = 0 first = True for project in self.GetProjects(args): env = os.environ.copy() def setenv(name, val): if val is None: val = '' env[name] = val setenv('REPO_PROJECT', project.name) setenv('REPO_PATH', project.relpath) setenv('REPO_REMOTE', project.remote.name) setenv('REPO_LREV', project.GetRevisionId()) setenv('REPO_RREV', project.revisionExpr) for a in project.annotations: setenv("REPO__%s" % (a.name), a.value) if mirror: setenv('GIT_DIR', project.gitdir) cwd = project.gitdir else: cwd = project.worktree if not os.path.exists(cwd): if (opt.project_header and opt.verbose) \ or not opt.project_header: print('skipping %s/' % project.relpath, file=sys.stderr) continue if opt.project_header: stdin = subprocess.PIPE stdout = subprocess.PIPE stderr = subprocess.PIPE else: stdin = None stdout = None stderr = None if not portable.isUnix(): if type(cmd) is list: cmd = " ".join(cmd) if IsTrace(): Trace("execute command: %s" % str(cmd).replace("%", "%%")) Trace("environment is: %s" % str(env)) p = subprocess.Popen(cmd, cwd=cwd, shell=shell, env=env, stdin=stdin, stdout=stdout, stderr=stderr) if opt.project_header: class sfd(object): def __init__(self, fd, dest): self.fd = fd self.dest = dest def fileno(self): return self.fd.fileno() # empty = True # errbuf = '' # # p.stdin.close() # s_in = [sfd(p.stdout, sys.stdout), # sfd(p.stderr, sys.stderr)] # # for s in s_in: # flags = fcntl.fcntl(s.fd, fcntl.F_GETFL) # fcntl.fcntl(s.fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) # # while s_in: # in_ready, _out_ready, _err_ready = select.select(s_in, [], []) # for s in in_ready: # buf = s.fd.read(4096) # if not buf: # s.fd.close() # s_in.remove(s) # continue # # if not opt.verbose: # if s.fd != p.stdout: # errbuf += buf # continue # # if empty: # if first: # first = False # else: # out.nl() # out.project('project %s/', project.relpath) # out.nl() # out.flush() # if errbuf: # sys.stderr.write(errbuf) # sys.stderr.flush() # errbuf = '' # empty = False # # s.dest.write(buf) # s.dest.flush() r = p.wait() if r != 0: if r != rc: rc = r if opt.abort_on_errors: print("error: %s: Aborting due to previous error" % project.relpath, file=sys.stderr) sys.exit(r) if rc != 0: sys.exit(rc)