[Asterisk-code-review] digium git: Add additional capabilities for manipulating bra... (repotools[master])

Joshua Colp asteriskteam at digium.com
Wed May 20 05:45:52 CDT 2015


Joshua Colp has submitted this change and it was merged.

Change subject: digium_git: Add additional capabilities for manipulating branches/tags
......................................................................


digium_git: Add additional capabilities for manipulating branches/tags

This patch adds the following:

* The ability to specify which branch should be tracked when checking out and
  creating a remote branch. This is needed anytime we don't want to track
  master in the newly created remote branch.

* The ability to checkout a local branch or tag. When a remote branch already
  exists, we don't want to create it again.

* The ability to check if a remote branch exists. This prevents errors,
  and lets scripts pick whether they want to create a remote branch or a
  local branch.

* The ability to commit local changes, and push them to the 'origin'
  remote. This includes both tags and branches.

REP-15

Change-Id: I2d13af5a8201d349b37f64f9855e45b70309aa95
---
M digium_git.py
1 file changed, 106 insertions(+), 13 deletions(-)

Approvals:
  Samuel Galarneau: Looks good to me, but someone else must approve
  Joshua Colp: Looks good to me, approved; Verified



diff --git a/digium_git.py b/digium_git.py
index 07a6272..2332ec4 100644
--- a/digium_git.py
+++ b/digium_git.py
@@ -128,6 +128,7 @@
                         operations being performed.
         """
 
+        self.show_progress = show_progress
         progress = None
 
         if os.path.isdir(local_path):
@@ -139,44 +140,117 @@
                                  "repo is None".format(local_path))
             os.makedirs(local_path)
             self.repo = Repo()
-            if show_progress:
+            if self.show_progress:
                 progress = GitProgressBar()
             self.repo = self.repo.clone_from(url=repo_url,
                                              to_path=local_path,
                                              progress=progress)
             origin = self.repo.remotes.origin
-        if show_progress:
+        if self.show_progress:
             progress = GitProgressBar()
         origin.fetch(progress=progress)
-        if show_progress:
+        if self.show_progress:
             progress = GitProgressBar()
         origin.pull(progress=progress)
 
-    def checkout_remote_branch(self, branch_name):
+    def checkout_remote_branch(self, branch_name, local_name=None):
         """Set up a local tracking branch of a remote branch
 
         Keyword Arguments:
         branch_name - The remote branch to track
+        local_name  - The name of the local branch. If not specified, will
+                      default to the name of the remote branch
+        """
+        if not local_name:
+            local_name = branch_name
+
+        if local_name in self.repo.heads:
+            # Local version already exists, just use it
+            local_branch = self.repo.heads[local_name]
+        else:
+            origin = self.repo.remotes.origin
+            remote_ref = [ref for ref in origin.refs
+                          if branch_name in ref.name][0]
+
+            local_branch = self.repo.create_head(local_name, remote_ref)
+            local_branch.set_tracking_branch(remote_ref)
+
+        local_branch.checkout()
+
+
+    def switch_local_branch(self, name):
+        """Switch to a local branch or tag
+
+        Keyword Arguments:
+        name - The local tag or branch name to switch to
+        """
+        tag = self.get_tag(name)
+        if tag:
+            self.repo.head.reference = tag
+        else:
+            local_branch = self.repo.heads[name]
+            self.repo.head.reference = local_branch
+
+        assert not self.repo.head.is_detached
+        self.repo.head.reset(index=True, working_tree=True)
+
+
+    def remote_branch_exists(self, branch_name):
+        """Determine if a remote branch exists
+
+        Keyword Arguments:
+        branch_name - The remote branch to look for
+
+        Returns:
+        True if the branch exists
+        False if the branch does not
         """
         origin = self.repo.remotes.origin
-        remote_ref = [ref for ref in origin.refs if branch_name in ref.name][0]
-        local_branch = self.repo.create_head(branch_name, remote_ref)
-        local_branch.set_tracking_branch(remote_ref)
-        local_branch.checkout()
+        remote_ref = [ref for ref in origin.refs if branch_name in ref.name]
+        return (len(remote_ref) != 0)
+
+
+    def create_remote_branch(self, branch_name, tracking='master'):
+        """Create a new remote branch
+
+        Keyword Arguments:
+        branch_name - The remote branch to create
+        tracking    - The branch to track. Defaults to 'master'.
+        """
+        self.checkout_remote_branch(tracking, local_name=branch_name)
+        self.push_changes()
+
 
     def get_tag(self, tag_name):
         """Retrieve a particular tag ref from the repo
-
-        Raises an exception if tag_name is not found.
 
         Keyword Arguments:
         tag_name - The name of the tag to retrieve
 
         Returns:
-        The tag object
+        The tag object, or None
         """
-        tag = [t for t in self.repo.tags if t.name == tag_name][0]
-        return tag
+        tag = [t for t in self.repo.tags if t.name == tag_name]
+        if len(tag) == 0:
+            return None
+        return tag[0]
+
+    def create_tag(self, tag_name):
+        """Create a new local tag
+
+        Keyword Arguments:
+        tag_name - The name of the tag to retrieve
+        """
+        progress = None
+
+        if self.get_tag(tag_name):
+            raise ValueError("Tag '{0}' already exists!".format(tag_name))
+        self.repo.create_tag(tag_name, message="Create '{0}'".format(tag_name))
+
+        origin = self.repo.remotes.origin
+        if self.show_progress:
+            progress = GitProgressBar()
+        origin.push(progress=progress, tags=True)
 
     def _convert_git_to_digium_commit(self, git_commit):
         """Convert a Git commit into a Digium/Asterisk commit
@@ -241,4 +315,23 @@
                 list(self.repo.iter_commits(rev=branch,
                     after=str(start_date), before=str(end_date))))
 
+    def add_and_commit(self, files, commit_msg):
+        """Add and commit modified files
+
+        Keyword Arguments:
+        files - The files to add and commit
+        commit_msg - Our commit message for the changes
+        """
+        self.repo.index.add(files)
+        self.repo.index.commit(commit_msg)
+
+    def push_changes(self):
+        """Push branch changes upstream
+        """
+        progress = None
+        origin = self.repo.remotes.origin
+        if self.show_progress:
+            progress = GitProgressBar()
+        origin.push(progress=progress)
+
 

-- 
To view, visit https://gerrit.asterisk.org/381
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I2d13af5a8201d349b37f64f9855e45b70309aa95
Gerrit-PatchSet: 4
Gerrit-Project: repotools
Gerrit-Branch: master
Gerrit-Owner: Matt Jordan <mjordan at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>
Gerrit-Reviewer: Matt Jordan <mjordan at digium.com>
Gerrit-Reviewer: Samuel Galarneau <sgalarneau at digium.com>



More information about the asterisk-code-review mailing list