sync: Ignore repo project when checking partial syncs

The repo project is fetched at most once a day and should be ignored
when checking if the tree is partially synced.

Bug: b/286126621, b/271507654
Change-Id: I684ed1669c3b3b9605162f8cc9d57185bb3dfe8e
Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/383494
Commit-Queue: Gavin Mak <gavinmak@google.com>
Tested-by: Gavin Mak <gavinmak@google.com>
Reviewed-by: Josip Sokcevic <sokcevic@google.com>
diff --git a/subcmds/sync.py b/subcmds/sync.py
index df53689..bbe0372 100644
--- a/subcmds/sync.py
+++ b/subcmds/sync.py
@@ -2007,7 +2007,11 @@
         """Return whether a partial sync state is detected."""
         self._Load()
         prev_checkout_t = None
-        for data in self._state.values():
+        for path, data in self._state.items():
+            if path == self._manifest.repoProject.relpath:
+                # The repo project isn't included in most syncs so we should
+                # ignore it here.
+                continue
             checkout_t = data.get(self._LAST_CHECKOUT)
             if not checkout_t:
                 return True
diff --git a/tests/test_subcmds_sync.py b/tests/test_subcmds_sync.py
index 7cc93e3..b43fe18 100644
--- a/tests/test_subcmds_sync.py
+++ b/tests/test_subcmds_sync.py
@@ -119,6 +119,7 @@
         self.repodir = tempfile.mkdtemp(".repo")
         self.manifest = mock.MagicMock(
             repodir=self.repodir,
+            repoProject=mock.MagicMock(relpath=".repo/repo"),
         )
         self.state = self._new_state()
 
@@ -126,8 +127,8 @@
         """Common teardown."""
         shutil.rmtree(self.repodir)
 
-    def _new_state(self):
-        with mock.patch("time.time", return_value=self._TIME):
+    def _new_state(self, time=_TIME):
+        with mock.patch("time.time", return_value=time):
             return sync._LocalSyncState(self.manifest)
 
     def test_set(self):
@@ -202,6 +203,23 @@
         self.state.SetCheckoutTime(projB)
         self.assertEqual(self.state.IsPartiallySynced(), True)
 
+    def test_ignore_repo_project(self):
+        """Sync data for repo project is ignored when checking partial sync."""
+        p = mock.MagicMock(relpath="projA")
+        self.state.SetFetchTime(p)
+        self.state.SetCheckoutTime(p)
+        self.state.SetFetchTime(self.manifest.repoProject)
+        self.state.Save()
+        self.assertEqual(self.state.IsPartiallySynced(), False)
+
+        self.state = self._new_state(self._TIME + 1)
+        self.state.SetFetchTime(self.manifest.repoProject)
+        self.assertEqual(
+            self.state.GetFetchTime(self.manifest.repoProject), self._TIME + 1
+        )
+        self.assertEqual(self.state.GetFetchTime(p), self._TIME)
+        self.assertEqual(self.state.IsPartiallySynced(), False)
+
     def test_nonexistent_project(self):
         """Unsaved projects don't have data."""
         p = mock.MagicMock(relpath="projC")