Modify 'repo abandon' to be more like 'repo checkout' and 'repo start'

Signed-off-by: Shawn O. Pearce <sop@google.com>
diff --git a/project.py b/project.py
index 029a80f..3b9535e 100644
--- a/project.py
+++ b/project.py
@@ -862,18 +862,38 @@
   def AbandonBranch(self, name):
     """Destroy a local topic branch.
     """
-    try:
-      tip_rev = self.bare_git.rev_parse(R_HEADS + name)
-    except GitError:
-      return
+    rev = R_HEADS + name
+    all = self.bare_ref.all
+    if rev not in all:
+      # Doesn't exist; assume already abandoned.
+      #
+      return True
 
-    if self.CurrentBranch == name:
-      self._Checkout(
-        self.GetRemote(self.remote.name).ToLocal(self.revision),
-        quiet=True)
+    head = self.work_git.GetHead()
+    if head == rev:
+      # We can't destroy the branch while we are sitting
+      # on it.  Switch to a detached HEAD.
+      #
+      head = all[head]
+
+      rev = self.GetRemote(self.remote.name).ToLocal(self.revision)
+      if rev in all:
+        revid = all[rev]
+      elif IsId(rev):
+        revid = rev
+      else:
+        revid = None
+
+      if revid and head == revid:
+        _lwrite(os.path.join(self.worktree, '.git', HEAD),
+                '%s\n' % revid)
+      else:
+        self._Checkout(rev, quiet=True)
 
-    cmd = ['branch', '-D', name]
-    GitCommand(self, cmd, capture_stdout=True).Wait()
+    return GitCommand(self,
+                      ['branch', '-D', name],
+                      capture_stdout = True,
+                      capture_stderr = True).Wait() == 0
 
   def PruneHeads(self):
     """Prune any topic branches already merged into upstream.
diff --git a/subcmds/abandon.py b/subcmds/abandon.py
index 4f976d7..8af6132 100644
--- a/subcmds/abandon.py
+++ b/subcmds/abandon.py
@@ -16,6 +16,7 @@
 import sys
 from command import Command
 from git_command import git
+from progress import Progress
 
 class Abandon(Command):
   common = True
@@ -38,5 +39,23 @@
       print >>sys.stderr, "error: '%s' is not a valid name" % nb
       sys.exit(1)
 
-    for project in self.GetProjects(args[1:]):
-      project.AbandonBranch(nb)
+    nb = args[0]
+    err = []
+    all = self.GetProjects(args[1:])
+
+    pm = Progress('Abandon %s' % nb, len(all))
+    for project in all:
+      pm.update()
+      if not project.AbandonBranch(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 abandon %s" \
+            % (p.relpath, nb)
+      sys.exit(1)