def _Init(self): """Sets up a local Git repository to get a copy of a superproject. Returns: True if initialization is successful, or False. """ if not os.path.exists(self._superproject_path): os.mkdir(self._superproject_path) if not self._quiet and not os.path.exists(self._work_git): print( '%s: Performing initial setup for superproject; this might take ' 'several minutes.' % self._work_git) cmd = ['init', '--bare', self._work_git_name] p = GitCommand(None, cmd, cwd=self._superproject_path, capture_stdout=True, capture_stderr=True) retval = p.Wait() if retval: print( 'repo: error: git init call failed with return code: %r, stderr: %r' % (retval, p.stderr), file=sys.stderr) return False return True
def _Fetch(self, url): """Fetches a local copy of a superproject for the manifest based on url. Args: url: superproject's url. Returns: True if fetch is successful, or False. """ if not os.path.exists(self._work_git): print('git fetch missing drectory: %s' % self._work_git, file=sys.stderr) return False cmd = ['fetch', url, '--force', '--no-tags', '--filter', 'blob:none'] if self._branch: cmd += [self._branch + ':' + self._branch] p = GitCommand(None, cmd, cwd=self._work_git, capture_stdout=True, capture_stderr=True) retval = p.Wait() if retval: print( 'repo: error: git fetch call failed with return code: %r, stderr: %r' % (retval, p.stderr), file=sys.stderr) return False return True
def _LsTree(self): """Gets the commit ids for all projects. Works only in git repositories. Returns: data: data returned from 'git ls-tree ...' instead of None. """ if not os.path.exists(self._work_git): print('git ls-tree missing drectory: %s' % self._work_git, file=sys.stderr) return None data = None branch = 'HEAD' if not self._branch else self._branch cmd = ['ls-tree', '-z', '-r', branch] p = GitCommand(None, cmd, cwd=self._work_git, capture_stdout=True, capture_stderr=True) retval = p.Wait() if retval == 0: data = p.stdout else: print( 'repo: error: git ls-tree call failed with return code: %r, stderr: %r' % (retval, p.stderr), file=sys.stderr) return data
def _GetEventTargetPath(self): """Get the 'trace2.eventtarget' path from git configuration. Returns: path: git config's 'trace2.eventtarget' path if it exists, or None """ path = None cmd = ['config', '--get', 'trace2.eventtarget'] # TODO(https://crbug.com/gerrit/13706): Use GitConfig when it supports # system git config variables. p = GitCommand(None, cmd, capture_stdout=True, capture_stderr=True, bare=True) retval = p.Wait() if retval == 0: # Strip trailing carriage-return in path. path = p.stdout.rstrip('\n') elif retval != 1: # `git config --get` is documented to produce an exit status of `1` if # the requested variable is not present in the configuration. Report any # other return value as an error. print( "repo: error: 'git config --get' call failed with return code: %r, stderr: %r" % (retval, p.stderr), file=sys.stderr) return path
def _UserAgent(): global _user_agent if _user_agent is None: py_version = sys.version_info os_name = sys.platform if os_name == 'linux2': os_name = 'Linux' elif os_name == 'win32': os_name = 'Win32' elif os_name == 'cygwin': os_name = 'Cygwin' elif os_name == 'darwin': os_name = 'Darwin' p = GitCommand(None, ['describe', 'HEAD'], cwd=_MyRepoPath(), capture_stdout=True) if p.Wait() == 0: repo_version = p.stdout if len(repo_version) > 0 and repo_version[-1] == '\n': repo_version = repo_version[0:-1] if len(repo_version) > 0 and repo_version[0] == 'v': repo_version = repo_version[1:] else: repo_version = 'unknown' _user_agent = 'git-repo/%s (%s) git/%s Python/%d.%d.%d' % ( repo_version, os_name, '.'.join(map(str, git.version_tuple())), py_version[0], py_version[1], py_version[2]) return _user_agent
def _gitPushTag(self, project, tag_name): p = GitCommand(project, ['push', self.remote_name, tag_name], capture_stdout = True, capture_stderr = True) if p.Wait() != 0: err_msg = p.stderr print("Could not push tag for ", project.name) print(err_msg, file=sys.stderr)
def Execute(self, opt, args): rc = 0 out = ChangelogColoring(self.manifest.manifestProject.config) out.redirect(sys.stdout) emails = {} if not opt.regex: projects = self.GetProjects(args) else: projects = self.FindProjects(args) if opt.subscribers is not None: self._ParseSubscribersList(opt.subscribers) else: self.pager = True for project in projects: log_format = '--pretty=format:<li><a href="https://android.googlesource.com/' + project.name + '/+/%h">%h : </a>%s</li>' cmd_args = [ 'log', '--abbrev-commit', '--no-merges', log_format, opt.revisions ] p = GitCommand(project, cmd_args, bare=False, capture_stdout=True, capture_stderr=True) if p.Wait() != 0: out.write("%s", p.stderr) out.nl() continue if len(p.stdout) != 0: proj_header = "<h2>Project: <a href='https://android.googlesource.com/%s'>%s</a></h2>" % ( project.name, project.relpath) out.project(proj_header) out.nl() out.write("%s", p.stdout) out.nl() out.flush() user_list = [] if project.relpath in self.subscribersList: user_list += self.subscribersList[project.relpath] if 'all' in self.subscribersList: user_list += self.subscribersList['all'] for user in user_list: if user not in emails: emails[user] = "" emails[ user] += proj_header + '</br>\n' + p.stdout + '</br>\n' rc = self._SendEmails(emails) sys.exit(rc)
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 p.stdout else: GitError('git config %s: %s' % (str(args), p.stderr))
def PruneHeads(self): """Prune any topic branches already merged into upstream. """ cb = self.CurrentBranch kill = [] left = self._allrefs for name in left.keys(): if name.startswith(R_HEADS): name = name[len(R_HEADS):] if cb is None or name != cb: kill.append(name) rev = self.GetRevisionId(left) if cb is not None \ and not self._revlist(HEAD + '...' + rev) \ and not self.IsDirty(consider_untracked = False): self.work_git.DetachHead(HEAD) kill.append(cb) if kill: old = self.bare_git.GetHead() if old is None: old = 'refs/heads/please_never_use_this_as_a_branch_name' try: self.bare_git.DetachHead(rev) b = ['branch', '-d'] b.extend(kill) b = GitCommand(self, b, bare=True, capture_stdout=True, capture_stderr=True) b.Wait() finally: self.bare_git.SetHead(old) left = self._allrefs for branch in kill: if (R_HEADS + branch) not in left: self.CleanPublishedCache() break if cb and cb not in kill: kill.append(cb) kill.sort() kept = [] for branch in kill: if (R_HEADS + branch) in left: branch = self.GetBranch(branch) base = branch.LocalMerge if not base: base = rev kept.append(ReviewableBranch(self, branch, base)) return kept
def _do(self, *args): command = ["config", "--file", self.file, "--includes"] command.extend(args) p = GitCommand(None, command, capture_stdout=True, capture_stderr=True) if p.Wait() == 0: return p.stdout else: GitError("git config %s: %s" % (str(args), p.stderr))
def _gitRebaseOnto(self, project, dest_sha1, begin_sha1, end_sha1): p = GitCommand(project,['rebase', '--onto', dest_sha1, begin_sha1, end_sha1], capture_stdout = True, capture_stderr = True) if p.Wait(): err_msg = p.stderr print(project.name, err_msg, file=sys.stderr) return False else: return True;
def _gitCreateTag(self, project, tag_name, sha1): p = GitCommand(project, ['tag', tag_name, sha1], capture_stdout = True, capture_stderr = True) if p.Wait(): err_msg = p.stderr print(project.name, err_msg, file=sys.stderr) return False else: return True;
def _gitCreateBranch(self, project, branch_name, sha1): p = GitCommand(project, ['checkout', '-b', branch_name, sha1], capture_stdout = True, capture_stderr = True) if p.Wait(): err_msg = p.stderr print(project.name, err_msg, file=sys.stderr) return False else: return True;
def _gitRebaseCurrent(self, project, sha1): p = GitCommand(project,['rebase', sha1], capture_stdout = True, capture_stderr = True) if p.Wait(): err_msg = p.stderr print(project.name, err_msg, file=sys.stderr) return False else: return True;
def _gitGetMergeBase(self, project, first_sha1, second_sha1): p = GitCommand(project, ['merge-base', first_sha1, second_sha1 ], capture_stdout = True, capture_stderr = True) if p.Wait() == 0: merge_base_sha1 = p.stdout.rstrip() return merge_base_sha1 else: err_msg = p.stderr print(project.name, err_msg, file=sys.stderr) return ""
def _gitGetExprSHA1(self, project, expr): p = GitCommand(project, ['rev-parse', expr], capture_stdout = True, capture_stderr = True) if p.Wait() == 0: sha1 = p.stdout.rstrip() return sha1 else: err_msg = p.stderr print(project.name, err_msg, file=sys.stderr) return ""
def _gitGetCurrentBranch(self, project): p = GitCommand(project, ['rev-parse', '--abbrev-ref', 'HEAD'], capture_stdout = True, capture_stderr = True) if p.Wait() == 0: current_branch = p.stdout.rstrip() return current_branch else: err_msg = p.stderr print(project.name, err_msg, file=sys.stderr) return ""
def LsOthers(self): p = GitCommand( self._project, ['ls-files', '-z', '--others', '--exclude-standard'], bare=False, capture_stdout=True, capture_stderr=True) if p.Wait() == 0: out = p.stdout if out: return out[:-1].split("\0") return []
def _ExecuteOne(self, cmd_argv, project): """Process one project.""" try: p = GitCommand(project, cmd_argv, bare=False, capture_stdout=True, capture_stderr=True) except GitError as e: return (project, -1, None, str(e)) return (project, p.Wait(), p.stdout, p.stderr)
def _allRevisionIds(self): if self._revisionIds is None: a = dict() p = GitCommand(self.manifestProject, ['ls-files', '-z', '--stage'], capture_stdout=True) for line in p.process.stdout.read().split('\0')[:-1]: l_info, l_path = line.split('\t', 2) l_mode, l_id, l_stage = l_info.split(' ', 2) if l_mode == GITLINK and l_stage == '0': a[l_path] = l_id p.Wait() self._revisionIds = a return self._revisionIds
def DiffZ(self, name, *args): cmd = [name] cmd.append('-z') cmd.extend(args) p = GitCommand(self._project, cmd, bare=False, capture_stdout=True, capture_stderr=True) try: out = p.process.stdout.read() r = {} if out: out = iter(out[:-1].split('\0')) while out: try: info = out.next() path = out.next() except StopIteration: break class _Info(object): def __init__(self, path, omode, nmode, oid, nid, state): self.path = path self.src_path = None self.old_mode = omode self.new_mode = nmode self.old_id = oid self.new_id = nid if len(state) == 1: self.status = state self.level = None else: self.status = state[:1] self.level = state[1:] while self.level.startswith('0'): self.level = self.level[1:] info = info[1:].split(' ') info = _Info(path, *info) if info.status in ('R', 'C'): info.src_path = info.path info.path = out.next() r[info.path] = info return r finally: p.Wait()
def runner(*args): cmdv = [name] cmdv.extend(args) p = GitCommand(self._project, cmdv, bare=self._bare, capture_stdout=True, capture_stderr=True) if p.Wait() != 0: raise GitError('%s %s: %s' % (self._project.name, name, p.stderr)) r = p.stdout if r.endswith('\n') and r.index('\n') == len(r) - 1: return r[:-1] return r
def _do(self, *args): if self.file == self._SYSTEM_CONFIG: command = ['config', '--system', '--includes'] else: command = ['config', '--file', self.file, '--includes'] command.extend(args) p = GitCommand(None, command, capture_stdout=True, capture_stderr=True) if p.Wait() == 0: return p.stdout else: raise GitError('git config %s: %s' % (str(args), p.stderr))
def AbandonBranch(self, name): """Destroy a local topic branch. """ rev = R_HEADS + name all = self.bare_ref.all if rev not in all: # Doesn't exist; assume already abandoned. # return True head = self.work_git.GetHead() if head == rev: # We can't destroy the branch while we are sitting # on it. Switch to a detached HEAD. # head = all[head] revid = self.GetRevisionId(all) if head == revid: _lwrite(os.path.join(self.worktree, '.git', HEAD), '%s\n' % revid) else: self._Checkout(revid, quiet=True) return GitCommand(self, ['branch', '-D', name], capture_stdout=True, capture_stderr=True).Wait() == 0
def CheckoutBranch(self, name): """Checkout a local topic branch. """ rev = R_HEADS + name head = self.work_git.GetHead() if head == rev: # Already on the branch # return True all = self.bare_ref.all try: revid = all[rev] except KeyError: # Branch does not exist in this project # return False if head.startswith(R_HEADS): try: head = all[head] except KeyError: head = None if head == revid: # Same revision; just update HEAD to point to the new # target branch, but otherwise take no other action. # _lwrite(os.path.join(self.worktree, '.git', HEAD), 'ref: %s%s\n' % (R_HEADS, name)) return True return GitCommand(self, ['checkout', name, '--'], capture_stdout=True, capture_stderr=True).Wait() == 0
def _Rebase(self, upstream, onto=None): cmd = ['rebase'] if onto is not None: cmd.extend(['--onto', onto]) cmd.append(upstream) if GitCommand(self, cmd).Wait() != 0: raise GitError('%s rebase %s ' % (self.name, upstream))
def _InitWorkTree(self): dotgit = os.path.join(self.worktree, '.git') if not os.path.exists(dotgit): os.makedirs(dotgit) for name in [ 'config', 'description', 'hooks', 'info', 'logs', 'objects', 'packed-refs', 'refs', 'rr-cache', 'svn' ]: try: src = os.path.join(self.gitdir, name) dst = os.path.join(dotgit, name) os.symlink(relpath(src, dst), dst) except OSError, e: if e.errno == errno.EPERM: raise GitError('filesystem must support symlinks') else: raise _lwrite(os.path.join(dotgit, HEAD), '%s\n' % self.GetRevisionId()) cmd = ['read-tree', '--reset', '-u'] cmd.append('-v') cmd.append(HEAD) if GitCommand(self, cmd).Wait() != 0: raise GitError("cannot initialize work tree") self._CopyFiles()
def _ResetHard(self, rev, quiet=True): cmd = ['reset', '--hard'] if quiet: cmd.append('-q') cmd.append(rev) if GitCommand(self, cmd).Wait() != 0: raise GitError('%s reset --hard %s ' % (self.name, rev))
def _Checkout(self, rev, quiet=False): cmd = ['checkout'] if quiet: cmd.append('-q') cmd.append(rev) cmd.append('--') if GitCommand(self, cmd).Wait() != 0: if self._allrefs: raise GitError('%s checkout %s ' % (self.name, rev))
def clone(self): if self.is_cloned(): return logging.warn("Initializing project: %s" % self.name) clone_remote = self.manifest.remotes[self.from_remote] clone_url = clone_remote.fetch % {"name": self.remote_project_name} p = GitCommand( ["clone", "-o", self.from_remote, "-n", clone_url, self.dir]) p.Wait() repo = self.git_repo if repo.command(["show-ref", "-q", "HEAD"]) != 0: # There is no HEAD (maybe origin/master doesnt exist) so check out the tracking # branch self.tracker.create_tracking_branch(repo) repo.check_command(["checkout", self.tracker.tracking_branch]) else: repo.check_command(["checkout"])