Преглед изворни кода

Improve checkout performance for the common unmodified case

Most projects will have their branch heads matching in all branches,
so switching between them should be just a matter of updating the
work tree's HEAD symref.  This can be done in pure Python, saving
quite a bit of time over forking 'git checkout'.

Signed-off-by: Shawn O. Pearce <sop@google.com>
Shawn O. Pearce пре 17 година
родитељ
комит
89e717d948
3 измењених фајлова са 56 додато и 23 уклоњено
  1. 32 11
      project.py
  2. 21 10
      subcmds/checkout.py
  3. 3 2
      subcmds/start.py

+ 32 - 11
project.py

@@ -779,9 +779,8 @@ class Project(object):
 
     all = self.bare_ref.all
     if (R_HEADS + name) in all:
-      cmd = ['checkout', name, '--']
       return GitCommand(self,
-                        cmd,
+                        ['checkout', name, '--'],
                         capture_stdout = True,
                         capture_stderr = True).Wait() == 0
 
@@ -815,9 +814,8 @@ class Project(object):
       branch.Save()
       return True
 
-    cmd = ['checkout', '-b', branch.name, rev]
     if GitCommand(self,
-                  cmd,
+                  ['checkout', '-b', branch.name, rev],
                   capture_stdout = True,
                   capture_stderr = True).Wait() == 0:
       branch.Save()
@@ -827,16 +825,39 @@ class Project(object):
   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
 
-    # Be sure the branch exists
+    all = self.bare_ref.all
     try:
-      tip_rev = self.bare_git.rev_parse(R_HEADS + name)
-    except GitError:
-      return False;
+      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
 
-    # Do the checkout
-    cmd = ['checkout', name, '--']
-    return GitCommand(self, cmd).Wait() == 0
+    return GitCommand(self,
+                      ['checkout', name, '--'],
+                      capture_stdout = True,
+                      capture_stderr = True).Wait() == 0
 
   def AbandonBranch(self, name):
     """Destroy a local topic branch.

+ 21 - 10
subcmds/checkout.py

@@ -15,6 +15,7 @@
 
 import sys
 from command import Command
+from progress import Progress
 
 class Checkout(Command):
   common = True
@@ -35,13 +36,23 @@ The command is equivalent to:
     if not args:
       self.Usage()
 
-    retValue = 0;
-
-    branch = args[0]
-    for project in self.GetProjects(args[1:]):
-      if not project.CheckoutBranch(branch):
-        retValue = 1;
-        print >>sys.stderr, "error: checking out branch '%s' in %s failed" % (branch, project.name)
-
-    if (retValue != 0):
-      sys.exit(retValue);
+    nb = args[0]
+    err = []
+    all = self.GetProjects(args[1:])
+
+    pm = Progress('Checkout %s' % nb, len(all))
+    for project in all:
+      pm.update()
+      if not project.CheckoutBranch(nb):
+        err.append(project)
+    pm.end()
+
+    if err:
+      if len(err) == len(all):
+        print >>sys.stderr, 'error: no project has branch %s' % nb
+      else:
+        for p in err:
+          print >>sys.stderr,\
+            "error: %s/: cannot checkout %s" \
+            % (p.relpath, nb)
+      sys.exit(1)

+ 3 - 2
subcmds/start.py

@@ -49,7 +49,8 @@ revision specified in the manifest.
     pm.end()
 
     if err:
-      err.sort()
       for p in err:
-        print >>sys.stderr, "error: cannot start in %s" % p.relpath
+        print >>sys.stderr,\
+          "error: %s/: cannot start %s" \
+          % (p.relpath, nb)
       sys.exit(1)