sync: Fix how sync times for shared projects are recorded

https://gerrit.googlesource.com/git-repo/+/d947858325ae70ff9c0b2f463a9e8c4ffd00002a introduced a moving average of fetch times in 2012.

The code does not handle shared projects, and averages times based on project names which is incorrect.

Change-Id: I9926122cdb1ecf201887a81e96f5f816d3c2f72a
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/373574
Tested-by: Gavin Mak <gavinmak@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: Josip Sokcevic <sokcevic@google.com>
diff --git a/subcmds/sync.py b/subcmds/sync.py
index 324f15b..68a076d 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -1805,44 +1805,40 @@
 
     def __init__(self, manifest):
         self._path = os.path.join(manifest.repodir, ".repo_fetchtimes.json")
-        self._times = None
-        self._seen = set()
+        self._saved = None
+        self._seen = {}
 
     def Get(self, project):
         self._Load()
-        return self._times.get(project.name, _ONE_DAY_S)
+        return self._saved.get(project.name, _ONE_DAY_S)
 
     def Set(self, project, t):
-        self._Load()
         name = project.name
-        old = self._times.get(name, t)
-        self._seen.add(name)
-        a = self._ALPHA
-        self._times[name] = (a * t) + ((1 - a) * old)
+
+        # For shared projects, save the longest time.
+        self._seen[name] = max(self._seen.get(name, 0), t)
 
     def _Load(self):
-        if self._times is None:
+        if self._saved is None:
             try:
                 with open(self._path) as f:
-                    self._times = json.load(f)
+                    self._saved = json.load(f)
             except (IOError, ValueError):
                 platform_utils.remove(self._path, missing_ok=True)
-                self._times = {}
+                self._saved = {}
 
     def Save(self):
-        if self._times is None:
+        if self._saved is None:
             return
 
-        to_delete = []
-        for name in self._times:
-            if name not in self._seen:
-                to_delete.append(name)
-        for name in to_delete:
-            del self._times[name]
+        for name, t in self._seen.items():
+            # Keep a moving average across the previous/current sync runs.
+            old = self._saved.get(name, t)
+            self._seen[name] = (self._ALPHA * t) + ((1 - self._ALPHA) * old)
 
         try:
             with open(self._path, "w") as f:
-                json.dump(self._times, f, indent=2)
+                json.dump(self._seen, f, indent=2)
         except (IOError, TypeError):
             platform_utils.remove(self._path, missing_ok=True)