Exemplo n.º 1
0
    def hard_reset_to_ref(self, branch, ref, checkout=True):
        """Perform a hard reset of a local branch to any reference.

           :param str branch: Local branch to reset
           :param str ref: Reference (commit, tag, ...) to reset to
           :param bool checkout: Whether to checkout the new branch
        """
        # Ensure the reference maps to a commit
        try:
            commit = git.repo.fun.name_to_object(self.git_repo.repo, ref)
        except git.exc.BadName as ex:
            msg = "Could not find reference {0}.".format(ref)
            raise_from(exceptions.ReferenceNotFoundException(msg), ex)

        try:
            # Preserve the reference name if there is one
            orig = self.git_repo.repo.head.ref.name
        except TypeError:
            # Detached head
            orig = self.git_repo.repo.head.commit.hexsha

        # Switch to the branch
        try:
            self.git_repo.git.checkout(branch)
        except git.GitCommandError as ex:
            msg = (
                "Could not checkout branch {branch}. Error: {error}".format(
                    branch=branch, error=ex)
            )
            raise_from(exceptions.CheckoutException(msg), ex)

        # Reset --hard to that reference
        try:
            self.git_repo.repo.head.reset(commit=commit,
                                          index=True,
                                          working_tree=True)
        except git.GitCommandError as ex:
            msg = (
                "Error resetting branch {branch} to {ref}. "
                "Error: {error}".format(ref=ref, branch=branch, error=ex)
            )
            raise_from(exceptions.ResetException(msg), ex)

        # Return to the original head if required
        if not checkout:
            try:
                self.git_repo.git.checkout(orig)
            except git.GitCommandError as ex:
                msg = (
                    "Could not checkout {orig}. Error: {error}".format(
                        orig=orig, error=ex)
                )
                raise_from(exceptions.CheckoutException(msg), ex)
Exemplo n.º 2
0
    def rebase_to_hash(self, branch_name, hash_):
        """Perform a rebase from a specific reference to another.

           :param str branch_name: The name of the branch to rebase on
           :param str hash_: The commit hash or reference to rebase to
        """
        self.logger.debug(
            "Rebasing branch %s to hash %s. Repo currently at commit %s.",
            branch_name, hash_, self.git_repo.repo.head.commit
        )

        if self.git_repo.repo.is_dirty():
            msg = ("Repository {0} is dirty. Please clean workspace "
                   "before proceeding.".format(self.git_repo.repo.working_dir))
            raise exceptions.DirtyRepositoryException(msg)

        # Checkout
        try:
            self.git_repo.git.checkout(branch_name)
        except git.GitCommandError as ex:
            msg = "Could not checkout branch {name}. Error: {error}".format(name=branch_name, error=ex)
            raise_from(exceptions.CheckoutException(msg), ex)

        # Rebase
        try:
            self.git_repo.git.rebase(hash_)
        except git.GitCommandError as ex:
            msg = "Could not rebase hash {hash_} onto branch {name}. Error: {error}".format(hash_=hash_, name=branch_name, error=ex)
            raise_from(exceptions.RebaseException(msg), ex)

        self.logger.debug("Successfully rebased branch %s to %s", branch_name, hash_)
Exemplo n.º 3
0
    def apply_patch(self, branch_name, path, keep_square_brackets=False):
        """Apply a git patch file on top of the specified branch.

           :param str branch_name: The name of the branch or reference to apply the patch to
           :param str path: Path to a git-formatted patch file (cf. git format-patch)
           :param bool keep_square_brackets: Preserve non-[PATCH] brackets in commit subject
        """
        # Expand file (also needed for git-am) and check it exists
        full_path = self._expand_file_path(path)

        # Checkout
        try:
            self.git_repo.git.checkout(branch_name)
        except git.GitCommandError as ex:
            msg = "Could not checkout branch {name}. Error: {error}".format(name=branch_name, error=ex)
            raise_from(exceptions.CheckoutException(msg), ex)

        # Apply the patch file
        try:
            if keep_square_brackets:
                self.git_repo.git.am("--keep-non-patch", full_path)
            else:
                self.git_repo.git.am(full_path)
        except git.GitCommandError as ex:
            msg = "Could not apply patch {path} on branch {name}. Error: {error}".format(path=full_path, name=branch_name, error=ex)
            raise_from(exceptions.ChangeNotAppliedException(msg), ex)
Exemplo n.º 4
0
    def rebase_to_hash(self, branch_name, hash_):
        """Perform a rebase from a specific reference to another.

           :param str branch_name: The name of the branch to rebase on
           :param str hash_: The commit hash or reference to rebase to
        """
        self.logger.debug(
            f"Rebasing branch {branch_name} to hash {hash_}. "
            f"Repo currently at commit {self.git_repo.repo.head.commit}.")

        if self.git_repo.repo.is_dirty():
            working_dir = self.git_repo.repo.working_dir
            msg = (
                f"Repository {working_dir} is dirty. Please clean workspace "
                "before proceeding.")
            raise exceptions.DirtyRepositoryException(msg)

        # Checkout
        try:
            self.git_repo.git.checkout(branch_name)
        except git.GitCommandError as ex:
            msg = f"Could not checkout branch {branch_name}. Error: {ex}"
            raise exceptions.CheckoutException(msg) from ex

        # Rebase
        try:
            self.git_repo.git.rebase(hash_)
        except git.GitCommandError as ex:
            msg = (f"Could not rebase hash {hash_} onto branch {branch_name}. "
                   f"Error: {ex}")
            raise exceptions.RebaseException(msg) from ex

        msg = f"Successfully rebased branch {branch_name} to {hash_}"
        self.logger.debug(msg)
Exemplo n.º 5
0
    def hard_reset_to_ref(self, branch, ref):
        """Perform a hard reset of a local branch to any reference.

           :param str branch: Local branch to reset
           :param str ref: Reference (commit, tag, ...) to reset to
        """
        # Ensure the reference maps to a commit
        try:
            commit = git.repo.fun.name_to_object(self.git_repo.repo, ref)
        except git.exc.BadName as ex:
            msg = "Could not find reference {0}.".format(ref)
            raise_from(exceptions.ReferenceNotFoundException(msg), ex)

        # Switch to the branch
        try:
            self.git_repo.git.checkout(branch)
        except git.GitCommandError as ex:
            msg = (
                "Could not checkout branch {branch}. Error: {error}".format(
                    branch=branch, error=ex)
            )
            raise_from(exceptions.CheckoutException(msg), ex)

        # Reset --hard to that reference
        try:
            self.git_repo.repo.head.reset(commit=commit,
                                          index=True,
                                          working_tree=True)
        except git.GitCommandError as ex:
            msg = (
                "Error resetting branch {branch} to {ref}. "
                "Error: {error}".format(ref=ref, branch=branch, error=ex)
            )
            raise_from(exceptions.ResetException(msg), ex)
Exemplo n.º 6
0
    def apply_diff(self, branch_name, diff_path, message, signoff=False):
        """Apply a diff on top of the specified branch.

           :param str branch_name: The name of the branch or reference to apply the diff to
           :param str diff_path: Path to the diff file
           :param str message: Commit message
           :param bool signoff: Whether to add signed-off-by to commit message
        """
        # Ensure we don't commit more than we mean to
        if self.git_repo.repo.is_dirty():
            msg = ("Repository {repo} contains uncommitted changes. Please clean workspace "
                   "before proceeding.".format(repo=self.git_repo.repo.working_dir))
            raise exceptions.DirtyRepositoryException(msg)

        # Check diff file exists
        full_path = self._expand_file_path(diff_path)

        # Checkout
        try:
            self.git_repo.git.checkout(branch_name)
        except git.GitCommandError as ex:
            msg = "Could not checkout branch {name}. Error: {error}".format(name=branch_name, error=ex)
            raise_from(exceptions.CheckoutException(msg), ex)

        # Apply the diff
        try:
            self.git_repo.git.apply(full_path)
        except git.GitCommandError as ex:
            msg = "Could not apply diff {path} on branch {name}. Error: {error}".format(path=full_path, name=branch_name, error=ex)
            raise_from(exceptions.ChangeNotAppliedException(msg), ex)

        # Commit
        self.git_repo.commit.commit(message, signoff)
Exemplo n.º 7
0
    def cherrypick(self, sha, branch_name):
        """Apply given sha on given branch

           :param str sha: The SHA1 of the commit to cherry-pick
           :param str branch_name: The branch to apply it to
        """
        if self.git_repo.repo.is_dirty():
            working_dir = self.git_repo.repo.working_dir
            msg = (f"Repository {working_dir} is dirty. Please clean "
                   "workspace before proceeding.")
            raise exceptions.DirtyRepositoryException(msg)

        # Checkout
        try:
            self.git_repo.git.checkout(branch_name)
        except git.GitCommandError as ex:
            msg = f"Could not checkout branch {branch_name}. Error: {ex}"
            raise exceptions.CheckoutException(msg) from ex

        # Cherry-pick
        try:
            self.git_repo.git.cherry_pick(sha)
        except git.GitCommandError as ex:
            msg = (f"Could not cherry-pick commit {sha} on {branch_name}. "
                   f"Error: {ex}")
            raise exceptions.ChangeNotAppliedException(msg) from ex

        msg = f"Successfully cherry-picked commit {sha} on {branch_name}"
        self.logger.debug(msg)
Exemplo n.º 8
0
    def cherrypick(self, sha, branch_name):
        """Apply given sha on given branch

           :param str sha: The SHA1 of the commit to cherry-pick
           :param str branch_name: The branch to apply it to
        """
        if self.git_repo.repo.is_dirty():
            msg = ("Repository {0} is dirty. Please clean workspace "
                   "before proceeding.".format(self.git_repo.repo.working_dir))
            raise exceptions.DirtyRepositoryException(msg)

        # Checkout
        try:
            self.git_repo.git.checkout(branch_name)
        except git.GitCommandError as ex:
            msg = "Could not checkout branch {name}. Error: {error}".format(name=branch_name, error=ex)
            raise_from(exceptions.CheckoutException(msg), ex)

        # Cherry-pick
        try:
            self.git_repo.git.cherry_pick(sha)
        except git.GitCommandError as ex:
            msg = "Could not cherry-pick commit {sha} on {name}. Error: {error}".format(name=branch_name, sha=sha, error=ex)
            raise_from(exceptions.ChangeNotAppliedException(msg), ex)

        self.logger.debug("Successfully cherry-picked commit %s on %s", sha, branch_name)
Exemplo n.º 9
0
    def to_hash(self, branch_name, hash_):
        """Perform a rebase from a specific reference to another.

           :param str branch_name: The name of the branch or reference to start from
           :param str hash_: The commit hash or reference to rebase to
        """
        logger.debug(
            "Rebasing branch %s to hash %s. Repo currently at commit %s.",
            branch_name, hash_, self.repo.head.commit)

        if self.repo.is_dirty():
            msg = "Repository %s is dirty. Please clean workspace before proceeding." % self.repo.working_dir
            raise exceptions.DirtyRepositoryException(msg)

        # Does the branch exist?
        try:
            branch = git.repo.fun.name_to_object(self.repo, branch_name)
        except git.exc.BadName as ex:
            msg = "Could not find branch %s." % branch_name
            raise exceptions.ReferenceNotFoundException(msg) from ex

        # Does the hash exists?
        try:
            commit = git.repo.fun.name_to_object(self.repo, hash_)
        except git.exc.BadName as ex:
            msg = "Could not find hash %s." % hash_
            raise exceptions.ReferenceNotFoundException(msg) from ex

        # Checkout
        try:
            self.repo.git.checkout(branch.hexsha)
        except git.GitCommandError as ex:
            msg = "Could not checkout branch %s. Error: %s" % (branch_name, ex)
            raise exceptions.CheckoutException(msg) from ex

        # Rebase
        try:
            self.repo.git.rebase(commit.hexsha)
        except git.GitCommandError as ex:
            msg = "Could not rebase hash %s onto branch %s. Error: %s" % (
                hash_, branch_name, ex)
            raise exceptions.RebaseException(msg) from ex

        logger.debug("Successfully rebased branch %s (%s) to %s" %
                     (branch_name, branch.hexsha, hash_))
Exemplo n.º 10
0
    def apply_diff(self, branch_name, diff_path, message, signoff=False):
        """Apply a diff on top of the specified branch.

           :param str branch_name: The name of the branch or reference to apply the diff to
           :param str diff_path: Path to the diff file
           :param str message: Commit message
           :param bool signoff: Whether to add signed-off-by to commit message
        """
        # Ensure we don't commit more than we mean to
        if self.git_repo.repo.is_dirty(untracked_files=True):
            repo = self.git_repo.repo.working_dir
            msg = (f"Repository {repo} contains uncommitted changes. Please "
                   "clean workspace before proceeding.")
            raise exceptions.DirtyRepositoryException(msg)

        # Check diff file exists
        full_path = self._expand_file_path(diff_path)

        # Checkout
        try:
            self.git_repo.git.checkout(branch_name)
        except git.GitCommandError as ex:
            msg = f"Could not checkout branch {branch_name}. Error: {ex}"
            raise exceptions.CheckoutException(msg) from ex

        # Apply the diff
        try:
            self.git_repo.git.apply(full_path)
        except git.GitCommandError as ex:
            msg = (f"Could not apply diff {full_path} on branch "
                   f"{branch_name}. Error: {ex}")
            raise exceptions.ChangeNotAppliedException(msg) from ex

        # The diff may have added new files, ensure they are staged
        self.git_repo.git.add(".")

        # Commit
        self.git_repo.commit.commit(message, signoff)