def name_or_current(self, identifier, name, must_exist=True): """ :param identifier: The identifier for the type of branch to work on. A :class:`BranchManager <git.branches.BranchManager>` for the given identifier must exist in the :attr:`self.managers`. :param name: If the `name` is empty, see if the current branch is of type `identifier`. If so, returns the current branches short name, otherwise raises :exc:`NoSuchBranchError`. :param must_exist: If `True` (the default), raises :exc:`NoSuchBranchError` in case no branch exists with the given `name`. Otherwise return the `name` unchanged. """ repo = self.repo manager = self.managers[identifier] if not name: if repo.active_branch.name.startswith(manager.prefix): return manager.shorten(repo.active_branch.name) else: raise NoSuchBranchError('The current branch is no %s branch. ' 'Please specify one explicitly.' % identifier) elif must_exist and not manager.full_name(name) in ( b.name for b in manager.list()): raise NoSuchBranchError('There is no %s branch named %s.' % (identifier, name)) return name
def by_name_prefix(self, nameprefix, remote=False): """ If exactly one branch of the type that this manager manages starts with the given name prefix, returns that branch. Raises :exc:`NoSuchBranchError` in case no branches exist with the given prefix, or :exc:`PrefixNotUniqueError` in case multiple matches are found. :param nameprefix: The name prefix (or full name) of the short branch name to match. :returns: The :class:`git.refs.Head` instance of the branch that can be uniquely identified by the given name prefix. """ if remote: nameprefix = self.gitflow.origin_name(self.full_name(nameprefix)) else: nameprefix = self.full_name(nameprefix) matches = [ b for b in self.iter(remote) if b.name.startswith(nameprefix) ] num_matches = len(matches) if num_matches == 1: return matches[0] elif num_matches < 1: raise NoSuchBranchError('There is no %s branch matching the ' 'prefix "%s"' % (self.identifier, nameprefix)) else: raise PrefixNotUniqueError('There are multiple %s branches ' 'matching the prefix "%s": %s' % (self.identifier, nameprefix, matches))
def _compare_branches(self, branch1, branch2): """ Tests whether branches and their 'origin' counterparts have diverged and need merging first. It returns error codes to provide more detail, like so: 0 Branch heads point to the same commit 1 First given branch needs fast-forwarding 2 Second given branch needs fast-forwarding 3 Branch needs a real merge 4 There is no merge base, i.e. the branches have no common ancestors """ try: commit1 = self.repo.rev_parse(branch1) commit2 = self.repo.rev_parse(branch2) except (git.BadObject, git.BadName) as e: raise NoSuchBranchError(e.args[0]) if commit1 == commit2: return 0 try: # merge_base() returns a list of Commit objects # this list will have at max one Commit # or it will be empty if no common merge base exists base = self.repo.merge_base(commit1, commit2)[0] except (GitCommandError, IndexError): return 4 if base == commit1: return 1 elif base == commit2: return 2 else: return 3
def nameprefix_or_current(self, identifier, prefix): """ :param identifier: The identifier for the type of branch to work on. A :class:`BranchManager <git.branches.BranchManager>` for the given identifier must exist in the :attr:`self.managers`. :param prefix: If the empty, see if the current branch is of type `identifier`. If so, returns the current branches short name, otherwise raises :exc:`NoSuchBranchError`. :returns: If exactly one branch of type `identifier` starts with the given name `prefix`, returns that branches short name. Raises :exc:`NoSuchBranchError` in case no branch exists with the given prefix, or :exc:`PrefixNotUniqueError` in case multiple matches are found. """ repo = self.repo manager = self.managers[identifier] if not prefix: if repo.active_branch.name.startswith(manager.prefix): return manager.shorten(repo.active_branch.name) else: raise NoSuchBranchError('The current branch is no %s branch. ' 'Please specify one explicitly.' % identifier) return manager.shorten(manager.by_name_prefix(prefix).name)
def publish(self, identifier, name): """ Publish a branch of the given type, with the given short name, to `origin` (or whatever is configured as `remote` for gitflow.) :param identifier: The identifier for the type of branch to create. A :class:`BranchManager <git.branches.BranchManager>` for the given identifier must exist in the :attr:`self.managers`. :param name: The friendly (short) name to create. """ repo = self.repo mgr = self.managers[identifier] # sanity checks # :todo: require_clean_working_tree full_name = mgr.full_name(name) remote_name = self.origin_name(full_name) if not full_name in repo.branches: raise NoSuchBranchError(full_name) if remote_name in repo.refs: raise BranchExistsError(remote_name) # :todo: check if full_name already has a tracking branch # :todo: check if full_name already has the same tracking branch # create remote branch origin = self.origin() info = origin.push('%s:refs/heads/%s' % (full_name, full_name))[0] origin.fetch() # configure remote tracking repo.branches[full_name].set_tracking_branch(info.remote_ref) return full_name
def require_origin_branch(self, branch_name): origin_name = self.origin_name(branch_name) refs = [r for r in self.repo.refs if isinstance(r, RemoteReference) and r.name == origin_name] if len(refs) != 0: assert len(refs) == 1 return refs[0] raise NoSuchBranchError( "Remote branch '{0}' was not found".format(origin_name))
def _compare_branches(self, branch1, branch2): """ Tests whether branches and their 'origin' counterparts have diverged and need merging first. It returns error codes to provide more detail, like so: 0 Branch heads point to the same commit 1 First given branch needs fast-forwarding 2 Second given branch needs fast-forwarding 3 Branch needs a real merge 4 There is no merge base, i.e. the branches have no common ancestors """ try: commit1 = self.repo.rev_parse(branch1) commit2 = self.repo.rev_parse(branch2) except git.BadObject, e: raise NoSuchBranchError('Branch {0} not found'.format(e.args[0]))
def from_prefix(cls, prefix): client = _get_client() options = { 'repository': _get_repo_id(), 'status': 'pending', 'max-results': 200 } requests = client.get_review_requests(options=options) if len(requests) == 200: raise ReviewRequestLimitError(200) reviews = [r for r in requests if r['branch'].startswith(prefix) and \ r['status'] != 'discarded'] if len(reviews) == 0: raise NoSuchBranchError( 'No review request found for branch prefixed with ' + prefix) elif len(reviews) == 1: r = reviews[0] t = type('BranchReview', (cls, ), dict(_rid=r['id'], _status=r['status'])) return t(r['branch']) else: raise MultipleReviewRequestsForBranch(reviews[0]['branch'])