Esempio n. 1
0
    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
Esempio n. 2
0
    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))
Esempio n. 3
0
    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
Esempio n. 4
0
    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)
Esempio n. 5
0
    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
Esempio n. 6
0
 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))
Esempio n. 7
0
    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]))
Esempio n. 8
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'])