command: Respect smart sync override declaratively by default Introduce a `RESPECT_SMART_SYNC_OVERRIDE` class attribute to the base `Command` class, defaulting to `True`. This allows subcommands to automatically respect the smart sync override manifest if it exists. The override is applied in `CommonValidateOptions` before any subcommand-specific validation or execution occurs. The `sync` and `init` commands explicitly opt out. This ensures all workspace-aware subcommands consistently align with the active smart sync override manifest. It also fixes a bug in multi-manifest setups where running a command from a submanifest would not apply the override to the outer manifest, causing inconsistency when resolving projects across all manifests. Bug: 279204331 Change-Id: I9426e90a13a77ce6bd94b4a82efda4d485cbe116 Reviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/585081 Reviewed-by: Mike Frysinger <vapier@google.com> Tested-by: Gavin Mak <gavinmak@google.com> Commit-Queue: Gavin Mak <gavinmak@google.com>
diff --git a/command.py b/command.py index bfafcd4..8b6a4d1 100644 --- a/command.py +++ b/command.py
@@ -66,6 +66,10 @@ # command to show short-vs-full summaries. COMMON = False + # Whether this command should respect the smart sync override manifest if + # it exists. + RESPECT_SMART_SYNC_OVERRIDE = True + # Whether this command supports running in parallel. If greater than 0, # it is the number of parallel jobs to default to. PARALLEL_JOBS = None @@ -247,6 +251,12 @@ # from the user's perspective. opt.outer_manifest = True + if self.RESPECT_SMART_SYNC_OVERRIDE: + if self.manifest: + self.TryOverrideManifestWithSmartSync(self.manifest) + if self.outer_manifest and self.outer_manifest != self.manifest: + self.TryOverrideManifestWithSmartSync(self.outer_manifest) + def ValidateOptions(self, opt, args): """Validate the user options & arguments before executing.
diff --git a/subcmds/abandon.py b/subcmds/abandon.py index 38f6ca4..f1688e7 100644 --- a/subcmds/abandon.py +++ b/subcmds/abandon.py
@@ -94,7 +94,6 @@ def Execute(self, opt, args): nb = args[0].split() - self.TryOverrideManifestWithSmartSync() err = collections.defaultdict(list) success = collections.defaultdict(list) aggregate_errors = []
diff --git a/subcmds/forall.py b/subcmds/forall.py index 03d1270..982b1ba 100644 --- a/subcmds/forall.py +++ b/subcmds/forall.py
@@ -243,8 +243,6 @@ mirror = self.manifest.IsMirror - self.TryOverrideManifestWithSmartSync() - if opt.regex: projects = self.FindProjects(args, all_manifests=all_trees) elif opt.inverse_regex:
diff --git a/subcmds/info.py b/subcmds/info.py index 348a7c8..594e633 100644 --- a/subcmds/info.py +++ b/subcmds/info.py
@@ -147,8 +147,6 @@ if not opt.this_manifest_only: self.manifest = self.manifest.outer_client - self.TryOverrideManifestWithSmartSync() - output_format = OutputFormat[opt.format.upper()] if output_format == OutputFormat.JSON: self._ExecuteJson(opt, args)
diff --git a/subcmds/init.py b/subcmds/init.py index b60ef28..772002e 100644 --- a/subcmds/init.py +++ b/subcmds/init.py
@@ -33,6 +33,7 @@ class Init(InteractiveCommand, MirrorSafeCommand): COMMON = True + RESPECT_SMART_SYNC_OVERRIDE = False MULTI_MANIFEST_SUPPORT = True helpSummary = "Initialize a repo client checkout in the current directory" helpUsage = """
diff --git a/subcmds/start.py b/subcmds/start.py index 9882cf0..73dddf3 100644 --- a/subcmds/start.py +++ b/subcmds/start.py
@@ -104,7 +104,6 @@ def Execute(self, opt, args): nb = args[0] - self.TryOverrideManifestWithSmartSync() err_projects = [] err = [] projects = []
diff --git a/subcmds/sync.py b/subcmds/sync.py index 573c344..6a88530 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py
@@ -312,6 +312,7 @@ class Sync(Command, MirrorSafeCommand): COMMON = True + RESPECT_SMART_SYNC_OVERRIDE = False MULTI_MANIFEST_SUPPORT = True helpSummary = "Update working tree to the latest revision" helpUsage = """
diff --git a/tests/test_subcmds_gc.py b/tests/test_subcmds_gc.py index 708f4a7..f5c415e 100644 --- a/tests/test_subcmds_gc.py +++ b/tests/test_subcmds_gc.py
@@ -24,7 +24,7 @@ """Tests for gc command.""" def setUp(self): - self.cmd = gc.Gc() + self.cmd = gc.Gc(manifest=mock.MagicMock()) self.opt, self.args = self.cmd.OptionParser.parse_args([]) self.opt.this_manifest_only = False self.opt.repack = False