sync: merge project updates with status bar

The current sync output displays "Fetching project" and "Checking out
project" messages and progress bar updates independently leading to a
lot of spam.  Lets merge these periodic outputs with the status bar to
get a little bit tighter output in the normal case.  This doesn't solve
all our problems, but gets us closer.

Bug: https://crbug.com/gerrit/11293
Change-Id: Icd627830af4dd934a9355b7ace754b56dc96cfef
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/244934
Reviewed-by: David Pursehouse <dpursehouse@collab.net>
Tested-by: Mike Frysinger <vapier@google.com>
diff --git a/progress.py b/progress.py
index 1eff04a..d2ed4ba 100644
--- a/progress.py
+++ b/progress.py
@@ -39,7 +39,7 @@
     self._print_newline = print_newline
     self._always_print_percentage = always_print_percentage
 
-  def update(self, inc=1):
+  def update(self, inc=1, msg=''):
     self._done += inc
 
     if _NOT_TTY or IsTrace():
@@ -62,12 +62,13 @@
 
       if self._lastp != p or self._always_print_percentage:
         self._lastp = p
-        sys.stderr.write('%s\r%s: %3d%% (%d%s/%d%s)%s' % (
+        sys.stderr.write('%s\r%s: %3d%% (%d%s/%d%s)%s%s%s' % (
           CSI_ERASE_LINE,
           self._title,
           p,
           self._done, self._units,
           self._total, self._units,
+          ' ' if msg else '', msg,
           "\n" if self._print_newline else ""))
         sys.stderr.flush()
 
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 97da620..2973a16 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -315,9 +315,6 @@
     # We'll set to true once we've locked the lock.
     did_lock = False
 
-    if not opt.quiet:
-      print('Fetching project %s' % project.name)
-
     # Encapsulate everything in a try/except/finally so that:
     # - We always set err_event in the case of an exception.
     # - We always make sure we unlock the lock if we locked it.
@@ -350,7 +347,7 @@
             raise _FetchError()
 
         fetched.add(project.gitdir)
-        pm.update()
+        pm.update(msg=project.name)
       except _FetchError:
         pass
       except Exception as e:
@@ -371,7 +368,6 @@
     fetched = set()
     lock = _threading.Lock()
     pm = Progress('Fetching projects', len(projects),
-                  print_newline=not(opt.quiet),
                   always_print_percentage=opt.quiet)
 
     objdir_project_map = dict()
@@ -461,9 +457,6 @@
     # We'll set to true once we've locked the lock.
     did_lock = False
 
-    if not opt.quiet:
-      print('Checking out project %s' % project.name)
-
     # Encapsulate everything in a try/except/finally so that:
     # - We always set err_event in the case of an exception.
     # - We always make sure we unlock the lock if we locked it.
@@ -474,11 +467,11 @@
     try:
       try:
         project.Sync_LocalHalf(syncbuf, force_sync=opt.force_sync)
-        success = syncbuf.Finish()
 
         # Lock around all the rest of the code, since printing, updating a set
         # and Progress.update() are not thread safe.
         lock.acquire()
+        success = syncbuf.Finish()
         did_lock = True
 
         if not success:
@@ -487,7 +480,7 @@
                 file=sys.stderr)
           raise _CheckoutError()
 
-        pm.update()
+        pm.update(msg=project.name)
       except _CheckoutError:
         pass
       except Exception as e:
@@ -527,7 +520,7 @@
       syncjobs = 1
 
     lock = _threading.Lock()
-    pm = Progress('Syncing work tree', len(all_projects))
+    pm = Progress('Checking out projects', len(all_projects))
 
     threads = set()
     sem = _threading.Semaphore(syncjobs)