diff options
| -rw-r--r-- | agents/skills/core_internals/SKILL.md | 4 | ||||
| -rw-r--r-- | git_config.py | 6 | ||||
| -rw-r--r-- | git_refs.py | 11 | ||||
| -rw-r--r-- | git_status.py | 13 | ||||
| -rw-r--r-- | git_superproject.py | 15 | ||||
| -rw-r--r-- | git_trace2_event_log.py | 9 | ||||
| -rwxr-xr-x | main.py | 6 | ||||
| -rw-r--r-- | project.py | 114 | ||||
| -rw-r--r-- | release/update_manpages.py | 4 | ||||
| -rw-r--r-- | ssh.py | 4 | ||||
| -rw-r--r-- | subcmds/abandon.py | 6 | ||||
| -rw-r--r-- | subcmds/cherry_pick.py | 8 | ||||
| -rw-r--r-- | subcmds/gc.py | 19 | ||||
| -rw-r--r-- | subcmds/grep.py | 4 | ||||
| -rw-r--r-- | subcmds/init.py | 10 | ||||
| -rw-r--r-- | subcmds/rebase.py | 4 | ||||
| -rw-r--r-- | subcmds/stage.py | 4 | ||||
| -rw-r--r-- | subcmds/start.py | 4 | ||||
| -rw-r--r-- | subcmds/sync.py | 9 | ||||
| -rw-r--r-- | subcmds/version.py | 15 | ||||
| -rw-r--r-- | tests/test_git_refs.py | 17 | ||||
| -rw-r--r-- | tests/test_git_status.py | 11 | ||||
| -rw-r--r-- | tests/test_git_superproject.py | 10 | ||||
| -rw-r--r-- | tests/test_project.py | 88 | ||||
| -rw-r--r-- | tests/test_subcmds_cherry_pick.py | 20 | ||||
| -rw-r--r-- | tests/test_subcmds_rebase.py | 7 | ||||
| -rw-r--r-- | tests/test_subcmds_sync.py | 21 | ||||
| -rw-r--r-- | tests/test_subcmds_version.py | 5 |
28 files changed, 232 insertions, 216 deletions
diff --git a/agents/skills/core_internals/SKILL.md b/agents/skills/core_internals/SKILL.md index 25796465c..a764ad34e 100644 --- a/agents/skills/core_internals/SKILL.md +++ b/agents/skills/core_internals/SKILL.md @@ -2004,10 +2004,10 @@ def _Run(self, *cmd): **Do:** ```python -from git_command import GitCommand +import git_command def _Run(self, cmd): - p = GitCommand( + p = git_command.GitCommand( None, cmd, capture_stdout=True, diff --git a/git_config.py b/git_config.py index 6c9b96b90..0ad01f5ff 100644 --- a/git_config.py +++ b/git_config.py @@ -27,7 +27,7 @@ import urllib.error import urllib.request import error -from git_command import GitCommand +import git_command from git_refs import R_CHANGES from git_refs import R_HEADS from git_refs import R_TAGS @@ -474,7 +474,9 @@ class GitConfig: command = ["config", "--file", self.file, "--includes"] command.extend(args) - p = GitCommand(None, command, capture_stdout=True, capture_stderr=True) + p = git_command.GitCommand( + None, command, capture_stdout=True, capture_stderr=True + ) if p.Wait() == 0: return p.stdout else: diff --git a/git_refs.py b/git_refs.py index 08716c09f..4575f9740 100644 --- a/git_refs.py +++ b/git_refs.py @@ -14,8 +14,7 @@ import os -from git_command import git_require -from git_command import GitCommand +import git_command import platform_utils import repo_trace @@ -135,7 +134,7 @@ class GitRefs: Returns: Whether root refs, including HEAD when it exists, were loaded. """ - include_root_refs = git_require((2, 45, 0)) + include_root_refs = git_command.git_require((2, 45, 0)) cmd = [ "for-each-ref", "--format=%(objectname)%00%(refname)%00%(symref)", @@ -145,7 +144,7 @@ class GitRefs: # Avoid caching volatile root refs such as ORIG_HEAD. HEAD and # refs/* are the only namespaces GitRefs exposes to callers. cmd.extend([HEAD, "refs"]) - p = GitCommand( + p = git_command.GitCommand( None, cmd, capture_stdout=True, @@ -166,7 +165,7 @@ class GitRefs: def _ReadSymbolicRef(self, name: str) -> None: """Read a symbolic reference.""" - p = GitCommand( + p = git_command.GitCommand( None, ["symbolic-ref", "-q", name], capture_stdout=True, @@ -180,7 +179,7 @@ class GitRefs: self._symref[name] = ref return - p = GitCommand( + p = git_command.GitCommand( None, ["rev-parse", "--verify", "-q", name], capture_stdout=True, diff --git a/git_status.py b/git_status.py index 473ad3d5d..32c8256a3 100644 --- a/git_status.py +++ b/git_status.py @@ -18,8 +18,7 @@ from collections import OrderedDict import os from typing import Iterator, List, Optional, TYPE_CHECKING -from git_command import git_require -from git_command import GitCommand +import git_command if TYPE_CHECKING: @@ -80,7 +79,7 @@ def GetStatus( show_stash: bool = False, ) -> StatusSnapshot: """Return one machine-readable status snapshot for |project|.""" - if not git_require((2, 11, 0)): + if not git_command.git_require((2, 11, 0)): raise UnsupportedStatusError("porcelain v2 requires Git 2.11") cmd = [ "status", @@ -91,18 +90,18 @@ def GetStatus( ] if branch: cmd.append("--branch") - if git_require((2, 17, 0)): + if git_command.git_require((2, 17, 0)): cmd.append( "--ahead-behind" if ahead_behind else "--no-ahead-behind" ) - if git_require((2, 18, 0)): + if git_command.git_require((2, 18, 0)): # Match the existing staged diff's explicit rename detection even if # status.renames is disabled in the user's config. cmd.append("--renames") - if show_stash and git_require((2, 35, 0)): + if show_stash and git_command.git_require((2, 35, 0)): cmd.append("--show-stash") - p = GitCommand( + p = git_command.GitCommand( project, cmd, bare=False, diff --git a/git_superproject.py b/git_superproject.py index d1166fe7c..6507913cd 100644 --- a/git_superproject.py +++ b/git_superproject.py @@ -32,8 +32,7 @@ import time from typing import NamedTuple import urllib.parse -from git_command import git_require -from git_command import GitCommand +import git_command from git_config import IsId from git_config import RepoConfig import platform_utils @@ -140,7 +139,7 @@ class Superproject: def commit_id(self): """Returns the commit ID of the superproject checkout.""" cmd = ["rev-parse", self.revision] - p = GitCommand( + p = git_command.GitCommand( None, # project cmd, gitdir=self._work_git, @@ -242,7 +241,7 @@ class Superproject: try: cmd = ["init", "--bare", tmp_git_name] - p = GitCommand( + p = git_command.GitCommand( None, cmd, cwd=self._superproject_path, @@ -292,7 +291,7 @@ class Superproject: if not os.path.exists(self._work_git): self._LogWarning("git fetch missing directory: {}", self._work_git) return False - if not git_require((2, 28, 0)): + if not git_command.git_require((2, 28, 0)): self._LogWarning( "superproject requires a git version 2.28 or later" ) @@ -329,7 +328,7 @@ class Superproject: else f"{self.revision}:{self.revision}" ) cmd.append(refspec) - p = GitCommand( + p = git_command.GitCommand( None, cmd, gitdir=self._work_git, @@ -351,7 +350,7 @@ class Superproject: def _GetRef(self, ref: str) -> str: """Resolve one local ref without loading the entire ref namespace.""" - p = GitCommand( + p = git_command.GitCommand( None, ["rev-parse", "--verify", "--quiet", ref], gitdir=self._work_git, @@ -381,7 +380,7 @@ class Superproject: branch = "HEAD" if not self.revision else self.revision cmd = ["ls-tree", "-z", "-r", branch] - p = GitCommand( + p = git_command.GitCommand( None, cmd, gitdir=self._work_git, diff --git a/git_trace2_event_log.py b/git_trace2_event_log.py index d7d5cbc21..4f2fe7400 100644 --- a/git_trace2_event_log.py +++ b/git_trace2_event_log.py @@ -14,8 +14,7 @@ """Event logging in the git trace2 EVENT format.""" -from git_command import GetEventTargetPath -from git_command import RepoSourceVersion +import git_command from git_trace2_event_log_base import BaseEventLog @@ -37,7 +36,9 @@ class EventLog(BaseEventLog): """ def __init__(self, **kwargs): - super().__init__(repo_source_version=RepoSourceVersion(), **kwargs) + super().__init__( + repo_source_version=git_command.RepoSourceVersion(), **kwargs + ) def Write(self, path=None, **kwargs): if path is None: @@ -45,4 +46,4 @@ class EventLog(BaseEventLog): return super().Write(path=path, **kwargs) def _GetEventTargetPath(self): - return GetEventTargetPath() + return git_command.GetEventTargetPath() @@ -47,7 +47,7 @@ from command import MirrorSafeCommand from editor import Editor import error import event_log -from git_command import user_agent +import git_command from git_config import RepoConfig from git_trace2_event_log import EventLog from manifest_xml import RepoClient @@ -700,11 +700,11 @@ def _PruneOptions(argv, opt): class _UserAgentHandler(urllib.request.BaseHandler): def http_request(self, req): - req.add_header("User-Agent", user_agent.repo) + req.add_header("User-Agent", git_command.user_agent.repo) return req def https_request(self, req): - req.add_header("User-Agent", user_agent.repo) + req.add_header("User-Agent", git_command.user_agent.repo) return req diff --git a/project.py b/project.py index d0e44f2f8..6cdfb5bcb 100644 --- a/project.py +++ b/project.py @@ -35,9 +35,7 @@ import urllib.parse from color import Coloring import error import fetch -from git_command import git_require -from git_command import GitCommand -from git_command import GitCommandError +import git_command from git_config import GetSchemeFromUrl from git_config import GetUrlCookieFile from git_config import GitConfig @@ -835,7 +833,7 @@ class Project: def _git(*args): # Ignore return code, in case there was no rebase in progress. - GitCommand(self, args, log_as_error=False).Wait() + git_command.GitCommand(self, args, log_as_error=False).Wait() _git("cherry-pick", "--abort") _git("rebase", "--abort") @@ -860,7 +858,7 @@ class Project: # Exit code 1 means there are modified files, which is okay. try: self.work_git.update_index(*args) - except GitCommandError as e: + except git_command.GitCommandError as e: if e.git_rc != 1: raise @@ -887,7 +885,7 @@ class Project: the worktree directory is missing. A missing worktree isn't logged: status can't run there, and the legacy path raises its own error. """ - if not git_require((2, 11, 0)): + if not git_command.git_require((2, 11, 0)): return None if not self.worktree or not platform_utils.isdir(self.worktree): return None @@ -926,7 +924,7 @@ class Project: def HasStash(self) -> bool: """Returns True if there is a stash in the repository.""" - p = GitCommand( + p = git_command.GitCommand( self, ["rev-parse", "--verify", "refs/stash"], bare=True, @@ -938,7 +936,7 @@ class Project: def _HasDirtyOrStash(self) -> bool: """Check dirty and normal stash state with one status when possible.""" - has_status_stash = git_require((2, 35, 0)) + has_status_stash = git_command.git_require((2, 35, 0)) status = self._GetStatusSnapshot( untracked_files="normal", show_stash=has_status_stash, @@ -1372,7 +1370,9 @@ class Project: cmd.append("--dst-prefix=b/%s/" % self.RelPath(local)) cmd.append("--") try: - p = GitCommand(self, cmd, capture_stdout=True, capture_stderr=True) + p = git_command.GitCommand( + self, cmd, capture_stdout=True, capture_stderr=True + ) p.Wait() except error.GitError as e: out.nl() @@ -1574,7 +1574,7 @@ class Project: ref_spec = ref_spec + "%" + ",".join(opts) cmd.append(ref_spec) - push_cmd = GitCommand( + push_cmd = git_command.GitCommand( self, cmd, bare=True, @@ -1971,7 +1971,7 @@ class Project: ) if os.path.exists(alternates_file): cmd = ["repack", "-a", "-d"] - p = GitCommand( + p = git_command.GitCommand( self, cmd, bare=True, @@ -2191,12 +2191,12 @@ class Project: def _doprune() -> None: """Expire reflogs and run prune-now GC for stateless sync.""" - GitCommand( + git_command.GitCommand( self, ["reflog", "expire", "--expire=all", "--all"], bare=True, ).Wait() - p = GitCommand( + p = git_command.GitCommand( self, ["gc", "--prune=now"], bare=True, @@ -2439,14 +2439,14 @@ class Project: remote = self.GetRemote() cmd = ["fetch"] - if git_require((2, 17, 0)): + if git_command.git_require((2, 17, 0)): cmd.append("--no-filter") cmd.append("--no-tags") cmd.append(remote.name) cmd.append( "refs/changes/%2.2d/%d/%d" % (change_id % 100, change_id, patch_id) ) - GitCommand(self, cmd, bare=True, verify_command=True).Wait() + git_command.GitCommand(self, cmd, bare=True, verify_command=True).Wait() return DownloadedChange( self, self.GetRevisionId(), @@ -2654,7 +2654,7 @@ class Project: all_refs = self.bare_ref.all if R_HEADS + name in all_refs: - GitCommand( + git_command.GitCommand( self, ["checkout", "-q", name, "--"], verify_command=True ).Wait() return True @@ -2682,7 +2682,7 @@ class Project: branch.Save() return True - GitCommand( + git_command.GitCommand( self, ["checkout", "-q", "-b", branch.name, revid], verify_command=True, @@ -2725,7 +2725,7 @@ class Project: self.work_git.SetHead(R_HEADS + name) return True - GitCommand( + git_command.GitCommand( self, ["checkout", name, "--"], capture_stdout=True, @@ -2761,7 +2761,7 @@ class Project: self.work_git.DetachHead(revid) else: self._Checkout(revid, quiet=True) - GitCommand( + git_command.GitCommand( self, ["branch", "-D", name], capture_stdout=True, @@ -2811,7 +2811,7 @@ class Project: b = ["branch", "-d"] b.extend(kill) - b = GitCommand( + b = git_command.GitCommand( self, b, bare=True, capture_stdout=True, capture_stderr=True ) b.Wait() @@ -2891,7 +2891,7 @@ class Project: def parse_gitmodules(gitdir, rev): cmd = ["cat-file", "blob", "%s:.gitmodules" % rev] try: - p = GitCommand( + p = git_command.GitCommand( None, cmd, capture_stdout=True, @@ -2910,7 +2910,7 @@ class Project: os.write(fd, p.stdout.encode("utf-8")) os.close(fd) cmd = ["config", "--file", temp_gitmodules_path, "--list"] - p = GitCommand( + p = git_command.GitCommand( None, cmd, capture_stdout=True, @@ -2959,7 +2959,7 @@ class Project: cmd = ["ls-tree", rev, "--"] cmd.extend(paths) try: - p = GitCommand( + p = git_command.GitCommand( None, cmd, capture_stdout=True, @@ -3208,7 +3208,7 @@ class Project: cmd.append("--prefix=%s/" % self.RelPath(local=False)) cmd.append(self.revisionExpr) - command = GitCommand( + command = git_command.GitCommand( self, cmd, cwd=cwd, @@ -3440,7 +3440,7 @@ class Project: alt_tmp_refs.append(r) if update_ref_cmds: - GitCommand( + git_command.GitCommand( self, ["update-ref", "--stdin"], bare=True, @@ -3452,7 +3452,7 @@ class Project: cmd = ["fetch"] if clone_filter: - git_require((2, 19, 0), fail=True, msg="partial clones") + git_command.git_require((2, 19, 0), fail=True, msg="partial clones") cmd.append("--filter=%s" % clone_filter) self.EnableRepositoryExtension("partialclone", self.remote.name) @@ -3473,7 +3473,7 @@ class Project: effective_depth = ( self.clone_depth or self.manifest.manifestProject.depth ) - if effective_depth == 1 and git_require((2, 23, 0)): + if effective_depth == 1 and git_command.git_require((2, 23, 0)): cmd.append("--no-auto-gc") if not verbose: @@ -3549,7 +3549,7 @@ class Project: try: for try_n in range(retry_fetches): verify_command = try_n == retry_fetches - 1 - gitcmd = GitCommand( + gitcmd = git_command.GitCommand( self, cmd, bare=True, @@ -3599,7 +3599,7 @@ class Project: and not prune_tried ): prune_tried = True - prunecmd = GitCommand( + prunecmd = git_command.GitCommand( self, ["remote", "prune", name], bare=True, @@ -3688,7 +3688,7 @@ class Project: delete_cmds = "".join( f"delete {ref}\n" for ref in alt_tmp_refs ) - GitCommand( + git_command.GitCommand( self, ["update-ref", "--stdin"], bare=True, @@ -3774,7 +3774,7 @@ class Project: cmd.append("+refs/tags/*:refs/tags/*") ok = ( - GitCommand( + git_command.GitCommand( self, cmd, bare=True, @@ -3887,7 +3887,7 @@ class Project: cmd.append("-f") cmd.append(rev) cmd.append("--") - if GitCommand(self, cmd).Wait() != 0: + if git_command.GitCommand(self, cmd).Wait() != 0: if self._allrefs: raise error.GitError( f"{self.name} checkout {rev} ", project=self.name @@ -3901,7 +3901,7 @@ class Project: cmd.append("-x") cmd.append(rev) cmd.append("--") - if GitCommand(self, cmd).Wait() != 0: + if git_command.GitCommand(self, cmd).Wait() != 0: if self._allrefs: raise error.GitError( f"{self.name} cherry-pick {rev} ", project=self.name @@ -3909,7 +3909,7 @@ class Project: def _LsRemote(self, refs: str) -> Optional[str]: cmd = ["ls-remote", self.remote.name, refs] - p = GitCommand(self, cmd, bare=True, capture_stdout=True) + p = git_command.GitCommand(self, cmd, bare=True, capture_stdout=True) if p.Wait() == 0: return p.stdout return None @@ -3919,7 +3919,7 @@ class Project: cmd.append("--no-edit") cmd.append(rev) cmd.append("--") - if GitCommand(self, cmd).Wait() != 0: + if git_command.GitCommand(self, cmd).Wait() != 0: if self._allrefs: raise error.GitError( f"{self.name} revert {rev} ", project=self.name @@ -3930,7 +3930,7 @@ class Project: if quiet: cmd.append("-q") cmd.append(rev) - if GitCommand(self, cmd).Wait() != 0: + if git_command.GitCommand(self, cmd).Wait() != 0: raise error.GitError( f"{self.name} reset --hard {rev} ", project=self.name ) @@ -3939,7 +3939,7 @@ class Project: cmd = ["submodule", "update", "--init", "--recursive"] if quiet: cmd.append("-q") - if GitCommand(self, cmd).Wait() != 0: + if git_command.GitCommand(self, cmd).Wait() != 0: raise error.GitError( "%s submodule update --init --recursive " % self.name, project=self.name, @@ -3955,7 +3955,7 @@ class Project: base_delay_secs = 1 jitter_ratio = 1 / 3 for attempt in range(max_retries): - git_cmd = GitCommand( + git_cmd = git_command.GitCommand( None, cmd, cwd=self.parent.worktree, @@ -3984,7 +3984,7 @@ class Project: if onto is not None: cmd.extend(["--onto", onto]) cmd.append(upstream) - if GitCommand(self, cmd).Wait() != 0: + if git_command.GitCommand(self, cmd).Wait() != 0: raise error.GitError( f"{self.name} rebase {upstream} ", project=self.name ) @@ -3994,7 +3994,7 @@ class Project: if quiet: cmd.append("-q") cmd.append(head) - if GitCommand(self, cmd).Wait() != 0: + if git_command.GitCommand(self, cmd).Wait() != 0: raise error.GitError( f"{self.name} merge --ff-only {head}", project=self.name ) @@ -4061,7 +4061,7 @@ class Project: head_tree = None if head_tree: - p = GitCommand( + p = git_command.GitCommand( self, ["diff-index", "-z", "--cached", "--name-only", head_tree], capture_stdout=True, @@ -4075,7 +4075,7 @@ class Project: ) staged = p.stdout.split("\0")[:-1] else: - p = GitCommand( + p = git_command.GitCommand( self, ["ls-files", "-z", "--cached"], capture_stdout=True, @@ -4157,7 +4157,7 @@ class Project: project=self.name, ) - p = GitCommand( + p = git_command.GitCommand( self, ["diff-index", "--cached", "--name-only", f"{revid}^{{tree}}"], capture_stdout=True, @@ -4197,7 +4197,7 @@ class Project: # Enable per-worktree config file support if possible. This # is more a nice-to-have feature for users rather than a # hard requirement. - if git_require((2, 20, 0)): + if git_command.git_require((2, 20, 0)): self.EnableRepositoryExtension("worktreeConfig") # If we have a separate directory to hold refs, initialize it as @@ -4301,7 +4301,7 @@ class Project: # such information is not available here. Instead of passing it, # set it as shared, and rely to be unset down the execution # path. - if git_require((2, 7, 0)): + if git_command.git_require((2, 7, 0)): self.EnableRepositoryExtension("preciousObjects") else: self.config.SetString("gc.pruneExpire", "never") @@ -4659,7 +4659,7 @@ class Project: # Finish checking out the worktree. cmd = ["read-tree", "--reset", "-u", "-v", HEAD] try: - if GitCommand(self, cmd).Wait() != 0: + if git_command.GitCommand(self, cmd).Wait() != 0: raise error.GitError( "Cannot initialize work tree for " + self.name, project=self.name, @@ -4887,7 +4887,7 @@ class Project: cmd.append("--oneline") try: - log = GitCommand( + log = git_command.GitCommand( self, cmd, capture_stdout=True, capture_stderr=True ) if log.Wait() == 0: @@ -4940,7 +4940,7 @@ class Project: self._project, self._bare, self._gitdir = state def LsOthers(self): - p = GitCommand( + p = git_command.GitCommand( self._project, ["ls-files", "-z", "--others", "--exclude-standard"], bare=False, @@ -4960,7 +4960,7 @@ class Project: cmd.append("-z") cmd.append("--ignore-submodules") cmd.extend(args) - p = GitCommand( + p = git_command.GitCommand( self._project, cmd, gitdir=self._gitdir, @@ -5115,7 +5115,7 @@ class Project: def ResolveCommit(self, revision: str) -> str: """Resolve |revision| to a commit without option ambiguity.""" cmdv = ["--verify", "--quiet"] - if git_require((2, 30, 0)): + if git_command.git_require((2, 30, 0)): cmdv.append("--end-of-options") elif revision.startswith("-"): raise error.GitError( @@ -5165,7 +5165,7 @@ class Project: else: cmdv = ["rev-list"] cmdv.extend(args) - p = GitCommand( + p = git_command.GitCommand( self._project, cmdv, bare=self._bare, @@ -5214,7 +5214,7 @@ class Project: cmdv.append(f"{k}={v}") cmdv.append(name) cmdv.extend(args) - p = GitCommand( + p = git_command.GitCommand( self._project, cmdv, bare=self._bare, @@ -5388,7 +5388,7 @@ def _DefaultBranchFallback() -> str: """Return the ref to use when remote default branch can't be resolved.""" def _git(args: List[str]) -> str: - p = GitCommand( + p = git_command.GitCommand( None, args, capture_stdout=True, @@ -5398,7 +5398,7 @@ def _DefaultBranchFallback() -> str: return p.stdout.strip() if p.Wait() == 0 else "" branch = "" - if git_require((2, 35, 0)): + if git_command.git_require((2, 35, 0)): branch = _git(["var", "GIT_DEFAULT_BRANCH"]) if not branch: branch = _git(["config", "--get", "init.defaultBranch"]) @@ -5528,7 +5528,7 @@ class ManifestProject(MetaProject): syncbuf.Finish() return ( - GitCommand( + git_command.GitCommand( self, ["update-ref", "-d", "refs/heads/default"], capture_stdout=True, @@ -6083,7 +6083,9 @@ class ManifestProject(MetaProject): if git_lfs is not None: if git_lfs: - git_require((2, 17, 0), fail=True, msg="Git LFS support") + git_command.git_require( + (2, 17, 0), fail=True, msg="Git LFS support" + ) self.config.SetBoolean("repo.git-lfs", git_lfs) if not is_new: diff --git a/release/update_manpages.py b/release/update_manpages.py index 1abc94796..3cf2406fa 100644 --- a/release/update_manpages.py +++ b/release/update_manpages.py @@ -39,7 +39,7 @@ MANDIR = TOPDIR.joinpath("man") # Load repo local modules. sys.path.insert(0, str(TOPDIR)) -from git_command import RepoSourceVersion +import git_command import subcmds @@ -82,7 +82,7 @@ def main(argv: List[str]) -> int: del subcmds.all_commands["branch"] (MANDIR / "repo-branch.1").write_text(".so man1/repo-branches.1") - version = RepoSourceVersion() + version = git_command.RepoSourceVersion() cmdlist = [ [ *help2man, @@ -24,7 +24,7 @@ import sys import tempfile import time -from git_command import git +import git_command import platform_utils import repo_trace @@ -359,7 +359,7 @@ def _get_git_protocol_version() -> str: if e.returncode == 1: # Exit code 1 means that the git config key was not found. # Try to imitate the defaults that git would have used. - git_version = git.version_tuple() + git_version = git_command.git.version_tuple() if git_version >= (2, 26, 0): # Since git version 2.26, protocol v2 is the default. return "2" diff --git a/subcmds/abandon.py b/subcmds/abandon.py index d27f5f421..651fc8713 100644 --- a/subcmds/abandon.py +++ b/subcmds/abandon.py @@ -19,7 +19,7 @@ import itertools from command import Command from command import DEFAULT_LOCAL_JOBS import error -from git_command import IsValidBranchName +import git_command from progress import Progress import repo_logging @@ -57,7 +57,9 @@ It is equivalent to "git branch -D <branchname>". if not opt.all: branches = args[0].split() - invalid_branches = [x for x in branches if not IsValidBranchName(x)] + invalid_branches = [ + x for x in branches if not git_command.IsValidBranchName(x) + ] if invalid_branches: self.OptionParser.error( diff --git a/subcmds/cherry_pick.py b/subcmds/cherry_pick.py index 0b504e937..9a1dfb941 100644 --- a/subcmds/cherry_pick.py +++ b/subcmds/cherry_pick.py @@ -18,7 +18,7 @@ from typing import Tuple from command import Command import error -from git_command import GitCommand +import git_command import repo_logging @@ -47,7 +47,7 @@ change id will be added. sha1, commit = self._ResolveReference(reference) old_msg = self._StripHeader(commit) - p = GitCommand( + p = git_command.GitCommand( None, ["cherry-pick", sha1], capture_stdout=True, @@ -76,7 +76,7 @@ change id will be added. # the commit message. new_msg = self._Reformat(old_msg, sha1) - p = GitCommand( + p = git_command.GitCommand( None, ["commit", "--amend", "-F", "-"], input=new_msg, @@ -93,7 +93,7 @@ change id will be added. def _ResolveReference(self, reference: str) -> Tuple[str, str]: """Resolve a commit and read it through one cat-file batch request.""" expression = f"{reference}^{{commit}}" - p = GitCommand( + p = git_command.GitCommand( None, ["cat-file", "--batch"], input=expression + "\n", diff --git a/subcmds/gc.py b/subcmds/gc.py index 8b54f8797..fcdeaf6cc 100644 --- a/subcmds/gc.py +++ b/subcmds/gc.py @@ -16,8 +16,7 @@ import os from typing import List, Set from command import Command -from git_command import git_require -from git_command import GitCommand +import git_command import platform_utils from progress import Progress from project import Project @@ -200,13 +199,13 @@ are still in the manifests. # Prepare workspace for repacking - remove all unreachable refs and # their objects. - GitCommand( + git_command.GitCommand( project, ["reflog", "expire", "--expire-unreachable=all"], verify_command=True, ).Wait() pm.update(msg=f"{project.name} | gc", inc=0) - GitCommand( + git_command.GitCommand( project, ["gc"], verify_command=True, @@ -214,7 +213,7 @@ are still in the manifests. # Get all objects that are reachable from the remote, and pack them. pm.update(msg=f"{project.name} | generating list of objects", inc=0) - remote_objects_cmd = GitCommand( + remote_objects_cmd = git_command.GitCommand( project, [ "rev-list", @@ -229,7 +228,7 @@ are still in the manifests. ) # Get all local objects and pack them. - local_head_objects_cmd = GitCommand( + local_head_objects_cmd = git_command.GitCommand( project, [ "rev-list", @@ -240,7 +239,7 @@ are still in the manifests. capture_stdout=True, verify_command=True, ) - local_objects_cmd = GitCommand( + local_objects_cmd = git_command.GitCommand( project, [ "rev-list", @@ -260,7 +259,7 @@ are still in the manifests. remote_objects_cmd.Wait() pm.update(msg=f"{project.name} | remote repack", inc=0) - GitCommand( + git_command.GitCommand( project, ["pack-objects", os.path.join(pack_dir, "pack")], input=remote_objects_cmd.stdout, @@ -276,7 +275,7 @@ are still in the manifests. local_objects_cmd.Wait() pm.update(msg=f"{project.name} | local repack", inc=0) - GitCommand( + git_command.GitCommand( project, ["pack-objects", os.path.join(pack_dir, "pack")], input=local_head_objects_cmd.stdout + local_objects_cmd.stdout, @@ -325,7 +324,7 @@ are still in the manifests. return ret if opt.repack: - git_require((2, 17, 0), fail=True, msg="--repack") + git_command.git_require((2, 17, 0), fail=True, msg="--repack") ret = self.repack_projects(projects, opt) return ret diff --git a/subcmds/grep.py b/subcmds/grep.py index 1a361daf7..cb2645666 100644 --- a/subcmds/grep.py +++ b/subcmds/grep.py @@ -20,7 +20,7 @@ from color import Coloring from command import DEFAULT_LOCAL_JOBS from command import PagedCommand import error -from git_command import GitCommand +import git_command import repo_logging @@ -263,7 +263,7 @@ contain a line that matches both expressions: """Process one project.""" project = cls.get_parallel_context()["projects"][project_idx] try: - p = GitCommand( + p = git_command.GitCommand( project, cmd_argv, bare=False, diff --git a/subcmds/init.py b/subcmds/init.py index 567040820..daa6f0489 100644 --- a/subcmds/init.py +++ b/subcmds/init.py @@ -19,7 +19,7 @@ from color import Coloring from command import InteractiveCommand from command import MirrorSafeCommand import error -from git_command import git_require +import git_command import repo_logging from wrapper import Wrapper from wrapper import WrapperDir @@ -347,9 +347,9 @@ to update the working directory files. wrapper = Wrapper() reqs = wrapper.Requirements.from_dir(WrapperDir()) - git_require(reqs.get_hard_ver("git"), fail=True) + git_command.git_require(reqs.get_hard_ver("git"), fail=True) min_git_version_soft = reqs.get_soft_ver("git") - if not git_require(min_git_version_soft): + if not git_command.git_require(min_git_version_soft): logger.warning( "repo: warning: git-%s+ will soon be required; " "please upgrade your version of git to maintain " @@ -388,7 +388,9 @@ to update the working directory files. if opt.worktree: # Older versions of git supported worktree, but had dangerous gc # bugs. - git_require((2, 15, 0), fail=True, msg="git gc worktree corruption") + git_command.git_require( + (2, 15, 0), fail=True, msg="git gc worktree corruption" + ) # Provide a short notice that we're reinitializing an existing checkout. # Sometimes developers might not realize that they're in one, or that diff --git a/subcmds/rebase.py b/subcmds/rebase.py index a0cc2b195..6b39f36c3 100644 --- a/subcmds/rebase.py +++ b/subcmds/rebase.py @@ -17,7 +17,7 @@ import sys from color import Coloring from command import Command import error -from git_command import GitCommand +import git_command from project import Project import repo_logging @@ -190,7 +190,7 @@ branch but need to incorporate new upstream changes "underneath" them. out.nl() out.flush() - if GitCommand(project, args).Wait() != 0: + if git_command.GitCommand(project, args).Wait() != 0: ret += 1 continue diff --git a/subcmds/stage.py b/subcmds/stage.py index bcab1fcca..5bda7a54d 100644 --- a/subcmds/stage.py +++ b/subcmds/stage.py @@ -16,7 +16,7 @@ import sys from color import Coloring from command import InteractiveCommand -from git_command import GitCommand +import git_command import repo_logging @@ -129,5 +129,5 @@ The '%prog' command stages files to prepare the next commit. def _AddI(project): - p = GitCommand(project, ["add", "--interactive"], bare=False) + p = git_command.GitCommand(project, ["add", "--interactive"], bare=False) p.Wait() diff --git a/subcmds/start.py b/subcmds/start.py index 829e82eb1..6d3b6e71c 100644 --- a/subcmds/start.py +++ b/subcmds/start.py @@ -18,7 +18,7 @@ from typing import NamedTuple from command import Command from command import DEFAULT_LOCAL_JOBS import error -from git_command import IsValidBranchName +import git_command from git_config import IsImmutable from progress import Progress import repo_logging @@ -75,7 +75,7 @@ revision specified in the manifest. self.Usage() nb = args[0] - if not IsValidBranchName(nb): + if not git_command.IsValidBranchName(nb): self.OptionParser.error("'%s' is not a valid name" % nb) @classmethod diff --git a/subcmds/sync.py b/subcmds/sync.py index 331b79d2a..24cd74d2b 100644 --- a/subcmds/sync.py +++ b/subcmds/sync.py @@ -59,8 +59,7 @@ from command import MirrorSafeCommand from command import WORKER_BATCH_SIZE import error import event_log -from git_command import git_require -from git_command import GitCommand +import git_command from git_config import GetUrlCookieFile from git_config import RepoConfig from git_refs import HEAD @@ -1575,7 +1574,7 @@ later is required to fix a server side protocol bug. % (relpath, project.name) ) - if git_require((2, 7, 0)): + if git_command.git_require((2, 7, 0)): project.EnableRepositoryExtension("preciousObjects") else: # This isn't perfect, but it's the best we can do with old @@ -1765,7 +1764,7 @@ later is required to fix a server side protocol bug. # We only care about bloated projects if we have a git version that # supports --no-auto-gc (2.23.0+) since what we use to disable auto-gc # in Project._RemoteFetch. - if not git_require((2, 23, 0)): + if not git_command.git_require((2, 23, 0)): return # Skip projects with no worktree on disk, e.g. ones only ever synced @@ -2492,7 +2491,7 @@ later is required to fix a server side protocol bug. raise error.SyncError("failed to sync superproject") cmd = ["show", f"{opt.superproject_revision}:.supermanifest"] - p = GitCommand( + p = git_command.GitCommand( None, cmd, gitdir=manifest.superproject._work_git, diff --git a/subcmds/version.py b/subcmds/version.py index 5c05f90a3..557bdddca 100644 --- a/subcmds/version.py +++ b/subcmds/version.py @@ -18,10 +18,7 @@ from typing import Any, Tuple from command import Command from command import MirrorSafeCommand -from git_command import git -from git_command import git_require -from git_command import RepoSourceVersion -from git_command import user_agent +import git_command from git_refs import HEAD from wrapper import Wrapper @@ -39,7 +36,7 @@ class Version(Command, MirrorSafeCommand): @staticmethod def _RepoVersion(project: Any) -> Tuple[str, str]: """Return repo's describe string and commit date.""" - if git_require((2, 32, 0)): + if git_command.git_require((2, 32, 0)): output = project.bare_git.log( "-1", "--format=%(describe)%n%cD", HEAD ) @@ -58,7 +55,7 @@ class Version(Command, MirrorSafeCommand): branch = rp.GetBranch("default") # These might not be the same. Report them both. - src_ver = RepoSourceVersion() + src_ver = git_command.RepoSourceVersion() rp_ver, commit_date = self._RepoVersion(rp) print(f"repo version {rp_ver}") print(f" (from {rem.url})") @@ -72,9 +69,9 @@ class Version(Command, MirrorSafeCommand): if src_ver != rp_ver: print(f" (currently at {src_ver})") - print(f"repo User-Agent {user_agent.repo}") - print(f"git {git.version_tuple().full}") - print(f"git User-Agent {user_agent.git}") + print(f"repo User-Agent {git_command.user_agent.repo}") + print(f"git {git_command.git.version_tuple().full}") + print(f"git User-Agent {git_command.user_agent.git}") print(f"Python {sys.version}") uname = platform.uname() if sys.version_info.major < 3: diff --git a/tests/test_git_refs.py b/tests/test_git_refs.py index ab7bdbe97..108e855eb 100644 --- a/tests/test_git_refs.py +++ b/tests/test_git_refs.py @@ -23,6 +23,7 @@ from unittest import mock import pytest import utils_for_test +import git_command import git_refs @@ -99,8 +100,8 @@ def test_reads_head_with_root_refs_in_one_command( def Wait(self) -> int: return 0 - monkeypatch.setattr(git_refs, "GitCommand", FakeGitCommand) - monkeypatch.setattr(git_refs, "git_require", lambda _version: True) + monkeypatch.setattr(git_command, "GitCommand", FakeGitCommand) + monkeypatch.setattr(git_command, "git_require", lambda _version: True) refs = git_refs.GitRefs("/nonexistent") with mock.patch.object(refs, "_ReadSymbolicRef") as read_head: assert refs.get("HEAD") == head @@ -131,8 +132,8 @@ def test_root_ref_snapshot_falls_back_for_unborn_head( def Wait(self) -> int: return 0 - monkeypatch.setattr(git_refs, "GitCommand", FakeGitCommand) - monkeypatch.setattr(git_refs, "git_require", lambda _version: True) + monkeypatch.setattr(git_command, "GitCommand", FakeGitCommand) + monkeypatch.setattr(git_command, "git_require", lambda _version: True) refs = git_refs.GitRefs("/nonexistent") def read_head(name: str) -> None: @@ -161,8 +162,8 @@ def test_old_git_keeps_separate_head_fallback( def Wait(self) -> int: return 0 - monkeypatch.setattr(git_refs, "GitCommand", FakeGitCommand) - monkeypatch.setattr(git_refs, "git_require", lambda _version: False) + monkeypatch.setattr(git_command, "GitCommand", FakeGitCommand) + monkeypatch.setattr(git_command, "git_require", lambda _version: False) refs = git_refs.GitRefs("/nonexistent") def read_head(name: str) -> None: @@ -194,8 +195,8 @@ def test_for_each_ref_failure_falls_back_to_symbolic_ref( def Wait(self) -> int: return 1 - monkeypatch.setattr(git_refs, "GitCommand", FakeGitCommand) - monkeypatch.setattr(git_refs, "git_require", lambda _version: True) + monkeypatch.setattr(git_command, "GitCommand", FakeGitCommand) + monkeypatch.setattr(git_command, "git_require", lambda _version: True) refs = git_refs.GitRefs("/nonexistent") def read_head(name: str) -> None: diff --git a/tests/test_git_status.py b/tests/test_git_status.py index 72698db26..352735f2e 100644 --- a/tests/test_git_status.py +++ b/tests/test_git_status.py @@ -20,6 +20,7 @@ from unittest import mock import pytest +import git_command import git_status @@ -143,8 +144,8 @@ def test_get_status_uses_versioned_machine_options( def Wait(self) -> int: return 0 - monkeypatch.setattr(git_status, "GitCommand", FakeGitCommand) - monkeypatch.setattr(git_status, "git_require", lambda _version: True) + monkeypatch.setattr(git_command, "GitCommand", FakeGitCommand) + monkeypatch.setattr(git_command, "git_require", lambda _version: True) git_status.GetStatus( mock.sentinel.project, @@ -173,7 +174,7 @@ def test_get_status_uses_versioned_machine_options( def test_get_status_rejects_git_before_2_11( monkeypatch: pytest.MonkeyPatch, ) -> None: - monkeypatch.setattr(git_status, "git_require", lambda _version: False) + monkeypatch.setattr(git_command, "git_require", lambda _version: False) with pytest.raises(git_status.UnsupportedStatusError): git_status.GetStatus(mock.sentinel.project, mock.sentinel.gitdir) @@ -194,9 +195,9 @@ def test_get_status_omits_stash_header_before_2_35( def Wait(self) -> int: return 0 - monkeypatch.setattr(git_status, "GitCommand", FakeGitCommand) + monkeypatch.setattr(git_command, "GitCommand", FakeGitCommand) monkeypatch.setattr( - git_status, + git_command, "git_require", lambda version: version <= (2, 34, 0), ) diff --git a/tests/test_git_superproject.py b/tests/test_git_superproject.py index c28eb8ded..6d7140aa8 100644 --- a/tests/test_git_superproject.py +++ b/tests/test_git_superproject.py @@ -465,7 +465,7 @@ class SuperprojectTestCase(unittest.TestCase): """Test _Init succeeds and creates the work git dir.""" self.assertFalse(os.path.exists(self._superproject._work_git)) with mock.patch( - "git_superproject.GitCommand", autospec=True + "git_command.GitCommand", autospec=True ) as mock_git_command: instance = mock_git_command.return_value instance.Wait.return_value = 0 @@ -492,7 +492,7 @@ class SuperprojectTestCase(unittest.TestCase): os.mkdir(self._superproject._superproject_path) os.mkdir(self._superproject._work_git) with mock.patch( - "git_superproject.GitCommand", autospec=True + "git_command.GitCommand", autospec=True ) as mock_git_command: self.assertTrue(self._superproject._Init()) mock_git_command.assert_not_called() @@ -500,7 +500,7 @@ class SuperprojectTestCase(unittest.TestCase): def test_Init_failure_cleans_up(self): """Test _Init cleans up the temporary directory if 'git init' fails.""" with mock.patch( - "git_superproject.GitCommand", autospec=True + "git_command.GitCommand", autospec=True ) as mock_git_command: instance = mock_git_command.return_value instance.Wait.return_value = 1 @@ -540,7 +540,7 @@ class SuperprojectTestCase(unittest.TestCase): os.mkdir(self._superproject._work_git) with mock.patch.object(self._superproject, "_Init", return_value=True): with mock.patch( - "git_superproject.GitCommand", autospec=True + "git_command.GitCommand", autospec=True ) as mock_git_command: with mock.patch.object( self._superproject, "_GetRef" @@ -600,7 +600,7 @@ class SuperprojectTestCase(unittest.TestCase): command = mock.MagicMock(stdout="1234\n") command.Wait.return_value = 0 with mock.patch( - "git_superproject.GitCommand", return_value=command + "git_command.GitCommand", return_value=command ) as git_command: self.assertEqual("1234", self._superproject._GetRef("HEAD")) diff --git a/tests/test_project.py b/tests/test_project.py index 4277136c7..648ddcdc5 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -216,7 +216,7 @@ class ProjectTests(unittest.TestCase): """Check UploadForReview emits repo.uploadstate trace2 data events.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("project.GitCommand") as mock_git_cmd, mock.patch( + with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( "project.ReviewableBranch" ) as mock_rb_cls: mock_cmd = mock.MagicMock() @@ -256,7 +256,7 @@ class ProjectTests(unittest.TestCase): """Check event emission when stderr contains no review URLs.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("project.GitCommand") as mock_git_cmd, mock.patch( + with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( "project.ReviewableBranch" ) as mock_rb_cls: mock_cmd = mock.MagicMock() @@ -290,7 +290,7 @@ class ProjectTests(unittest.TestCase): """Check UploadForReview succeeds when git_event_log is None.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("project.GitCommand") as mock_git_cmd, mock.patch( + with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( "project.ReviewableBranch" ) as mock_rb_cls: mock_cmd = mock.MagicMock() @@ -313,7 +313,7 @@ class ProjectTests(unittest.TestCase): """Check exceptions during tracing are caught and do not fail upload.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("project.GitCommand") as mock_git_cmd, mock.patch( + with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( "project.ReviewableBranch" ) as mock_rb_cls, mock.patch("project.logger") as mock_logger: mock_cmd = mock.MagicMock() @@ -338,7 +338,7 @@ class ProjectTests(unittest.TestCase): """Check integration with real git_trace2_event_log.EventLog.""" proj, _ = self._create_project_for_upload_test() - with mock.patch("project.GitCommand") as mock_git_cmd, mock.patch( + with mock.patch("git_command.GitCommand") as mock_git_cmd, mock.patch( "project.ReviewableBranch" ) as mock_rb_cls: mock_cmd = mock.MagicMock() @@ -408,9 +408,9 @@ class ProjectTests(unittest.TestCase): command.Wait.return_value = 0 with mock.patch.object( - project, "git_require", return_value=True + git_command, "git_require", return_value=True ), mock.patch.object( - project, "GitCommand", return_value=command + git_command, "GitCommand", return_value=command ) as cmd: self.assertEqual("1" * 40, git.ResolveCommit("topic")) @@ -437,7 +437,7 @@ class ProjectTests(unittest.TestCase): proj.name = "project" git = project.Project._GitGetByExec(proj, bare=True, gitdir="gitdir") - with mock.patch.object(project, "git_require", return_value=False): + with mock.patch.object(git_command, "git_require", return_value=False): with self.assertRaises(error.GitError): git.ResolveCommit("--not-a-revision") @@ -735,7 +735,9 @@ class ProjectTests(unittest.TestCase): proj._GetStatusSnapshot = mock.MagicMock(return_value=status) proj.HasStash = mock.MagicMock() - with mock.patch.object(project, "git_require", return_value=True): + with mock.patch.object( + git_command, "git_require", return_value=True + ): self.assertTrue(proj._HasDirtyOrStash()) proj.HasStash.assert_not_called() @@ -748,7 +750,9 @@ class ProjectTests(unittest.TestCase): proj._GetStatusSnapshot = mock.MagicMock(return_value=status) proj.HasStash = mock.MagicMock() - with mock.patch.object(project, "git_require", return_value=True): + with mock.patch.object( + git_command, "git_require", return_value=True + ): self.assertFalse(proj._HasDirtyOrStash()) proj.HasStash.assert_not_called() @@ -761,7 +765,9 @@ class ProjectTests(unittest.TestCase): proj._GetStatusSnapshot = mock.MagicMock(return_value=status) proj.HasStash = mock.MagicMock(return_value=True) - with mock.patch.object(project, "git_require", return_value=False): + with mock.patch.object( + git_command, "git_require", return_value=False + ): self.assertTrue(proj._HasDirtyOrStash()) proj._GetStatusSnapshot.assert_called_once_with( @@ -778,7 +784,7 @@ class ProjectTests(unittest.TestCase): for use_status in (True, False): with self.subTest(expected=expected, status=use_status): with mock.patch.object( - project, "git_require", return_value=use_status + git_command, "git_require", return_value=use_status ): self.assertEqual(expected, proj.GetDirtyAndHead()) @@ -819,7 +825,9 @@ class ProjectTests(unittest.TestCase): proj._IsDirtyLegacy = mock.MagicMock(return_value=False) proj.HasStash = mock.MagicMock(return_value=False) - with mock.patch.object(project, "git_require", return_value=True): + with mock.patch.object( + git_command, "git_require", return_value=True + ): self.assertFalse(proj._HasDirtyOrStash()) proj._GetStatusSnapshot.assert_called_once_with( @@ -834,7 +842,9 @@ class ProjectTests(unittest.TestCase): proj.work_git = mock.MagicMock() proj.work_git.DiffZ.side_effect = [{}, {"tracked": mock.sentinel}] - with mock.patch.object(project, "git_require", return_value=False): + with mock.patch.object( + git_command, "git_require", return_value=False + ): self.assertTrue(proj.IsDirty()) proj.work_git.update_index.assert_called_once_with( @@ -851,7 +861,7 @@ class ProjectTests(unittest.TestCase): with utils_for_test.TempGitTree() as tempdir: proj = _create_mock_project(tempdir) with mock.patch.object( - project, "GitCommand", autospec=True + git_command, "GitCommand", autospec=True ) as run_git: run_git.return_value.Wait.return_value = 0 proj._FastForward("revision") @@ -1339,7 +1349,7 @@ class ProjectTests(unittest.TestCase): hex41 = "a" * 41 proj.SetRevision(hex41) - with mock.patch("project.GitCommand") as mock_git: + with mock.patch("git_command.GitCommand") as mock_git: mock_cmd = mock.MagicMock() mock_cmd.Wait.return_value = 0 mock_git.return_value = mock_cmd @@ -2042,8 +2052,8 @@ def test_default_branch_fallback( project._DefaultBranchFallback.cache_clear() try: with mock.patch.object( - project, "git_require", return_value=supports_git_var - ), mock.patch.object(project, "GitCommand", FakeGitCommand): + git_command, "git_require", return_value=supports_git_var + ), mock.patch.object(git_command, "GitCommand", FakeGitCommand): assert project._DefaultBranchFallback() == expected_ref assert seen == expected_calls finally: @@ -2134,7 +2144,7 @@ def test_remote_fetch_retry_sleep( proj = _create_meta_project(tempdir, project_cls) proj.config.GetRemote("origin").ResetFetch() proj.revisionExpr = "refs/heads/stable" - with mock.patch.object(project, "GitCommand") as mock_git: + with mock.patch.object(git_command, "GitCommand") as mock_git: # What git does while stable is deleted. mock_git.return_value.Wait.return_value = 128 mock_git.return_value.stdout = ( @@ -2353,7 +2363,7 @@ class StatelessSyncTests(unittest.TestCase): proj.work_git = mock.MagicMock() syncbuf = project.SyncBuffer(proj.config) - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -2702,7 +2712,7 @@ class SyncOptimizationTests(unittest.TestCase): if os.path.exists(shallow_path): os.unlink(shallow_path) - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -2725,7 +2735,7 @@ class SyncOptimizationTests(unittest.TestCase): with open(os.path.join(proj.gitdir, "shallow"), "w") as f: f.write("") - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: res = proj._RemoteFetch( current_branch_only=True, depth=1, @@ -2748,7 +2758,7 @@ class SyncOptimizationTests(unittest.TestCase): with open(os.path.join(other.gitdir, "shallow"), "w") as f: f.write("") - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -2777,7 +2787,7 @@ class SyncOptimizationTests(unittest.TestCase): with open(os.path.join(other.gitdir, "shallow"), "w") as f: f.write("") - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: res = proj._RemoteFetch( current_branch_only=True, depth=1, @@ -2971,7 +2981,7 @@ class SyncOptimizationTests(unittest.TestCase): mock_remote.PreConnectFetch.return_value = True proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -3010,7 +3020,7 @@ class SyncOptimizationTests(unittest.TestCase): mock_remote.PreConnectFetch.return_value = True proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -3052,7 +3062,7 @@ class SyncOptimizationTests(unittest.TestCase): mock_remote.PreConnectFetch.return_value = True proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -3100,7 +3110,7 @@ class SyncOptimizationTests(unittest.TestCase): mock_remote.PreConnectFetch.return_value = True proj.GetRemote = mock.MagicMock(return_value=mock_remote) - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -3202,7 +3212,7 @@ class SyncOptimizationTests(unittest.TestCase): return inst with mock.patch( - "project.GitCommand", side_effect=_fake_git_command + "git_command.GitCommand", side_effect=_fake_git_command ): res = proj._RemoteFetch(current_branch_only=True) @@ -3578,7 +3588,7 @@ class ReprojectCmdTests(unittest.TestCase): ) -> mock.MagicMock: """Run _Reproject against mocked Git; return the subprocess mock.""" with mock.patch( - "project.GitCommand", side_effect=self._git_command(**outputs) + "git_command.GitCommand", side_effect=self._git_command(**outputs) ), mock.patch("subprocess.run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") proj._Reproject(self.REVID) @@ -3589,7 +3599,7 @@ class ReprojectCmdTests(unittest.TestCase): with utils_for_test.TempGitTree() as tempdir: proj = self._get_project(tempdir) with mock.patch( - "project.GitCommand", side_effect=self._git_command() + "git_command.GitCommand", side_effect=self._git_command() ), mock.patch("subprocess.run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") proj._Reproject(self.REVID) @@ -3649,7 +3659,7 @@ class ReprojectCmdTests(unittest.TestCase): with utils_for_test.TempGitTree() as tempdir: proj = self._get_project(tempdir) with mock.patch( - "project.GitCommand", side_effect=self._git_command() + "git_command.GitCommand", side_effect=self._git_command() ), mock.patch("subprocess.run") as mock_run: mock_run.return_value = mock.MagicMock( returncode=3, stdout="disk on fire\n" @@ -3665,7 +3675,7 @@ class ReprojectCmdTests(unittest.TestCase): proj = self._get_project(tempdir) proj.work_git.GetHead.side_effect = [self.HEAD_ID, self.REVID] with mock.patch( - "project.GitCommand", side_effect=self._git_command() + "git_command.GitCommand", side_effect=self._git_command() ), mock.patch("subprocess.run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") with self.assertRaises(project.LocalSyncFail) as e: @@ -3683,7 +3693,7 @@ class ReprojectCmdTests(unittest.TestCase): self.REVID, # HEAD after command ] with mock.patch( - "project.GitCommand", side_effect=self._git_command() + "git_command.GitCommand", side_effect=self._git_command() ), mock.patch("subprocess.run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") with self.assertRaises(project.LocalSyncFail) as e: @@ -3695,7 +3705,7 @@ class ReprojectCmdTests(unittest.TestCase): with utils_for_test.TempGitTree() as tempdir: proj = self._get_project(tempdir) with mock.patch( - "project.GitCommand", + "git_command.GitCommand", side_effect=self._git_command(diff="lib/a.c\n"), ), mock.patch("subprocess.run") as mock_run: mock_run.return_value = mock.MagicMock(returncode=0, stdout="") @@ -4361,9 +4371,9 @@ class DownloadPatchSetTests(unittest.TestCase): def test_download_patch_set_with_no_filter_and_no_tags(self) -> None: """Test DownloadPatchSet includes --no-filter and --no-tags.""" with mock.patch( - "project.git_require", return_value=True + "git_command.git_require", return_value=True ) as mock_git_require: - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance @@ -4389,8 +4399,8 @@ class DownloadPatchSetTests(unittest.TestCase): def test_download_patch_set_legacy_git_omits_no_filter(self) -> None: """Test DownloadPatchSet omits --no-filter on git < 2.17.""" - with mock.patch("project.git_require", return_value=False): - with mock.patch("project.GitCommand") as mock_git_cmd: + with mock.patch("git_command.git_require", return_value=False): + with mock.patch("git_command.GitCommand") as mock_git_cmd: mock_cmd_instance = mock.MagicMock() mock_cmd_instance.Wait.return_value = 0 mock_git_cmd.return_value = mock_cmd_instance diff --git a/tests/test_subcmds_cherry_pick.py b/tests/test_subcmds_cherry_pick.py index e454cb9e0..af5702668 100644 --- a/tests/test_subcmds_cherry_pick.py +++ b/tests/test_subcmds_cherry_pick.py @@ -19,7 +19,7 @@ from unittest import mock import pytest import error -from git_command import GitCommand +import git_command from subcmds import cherry_pick @@ -30,12 +30,12 @@ def test_resolve_reference_uses_one_typed_batch_request( commit = "tree " + "2" * 40 + "\n\nSubject 🚀\n\nBody\n" output = oid + " commit " + str(len(commit.encode("utf-8"))) + "\n" output += commit + "\n" - command = mock.create_autospec(GitCommand, instance=True) + command = mock.create_autospec(git_command.GitCommand, instance=True) command.stdout = output command.stderr = "" command.Wait.return_value = 0 - run_git = mock.create_autospec(GitCommand, return_value=command) - monkeypatch.setattr(cherry_pick, "GitCommand", run_git) + run_git = mock.create_autospec(git_command.GitCommand, return_value=command) + monkeypatch.setattr(git_command, "GitCommand", run_git) resolved, contents = cherry_pick.CherryPick()._ResolveReference("topic") @@ -54,14 +54,14 @@ def test_resolve_reference_uses_one_typed_batch_request( def test_resolve_reference_rejects_missing_object( monkeypatch: pytest.MonkeyPatch, ) -> None: - command = mock.create_autospec(GitCommand, instance=True) + command = mock.create_autospec(git_command.GitCommand, instance=True) command.stdout = "topic^{commit} missing\n" command.stderr = "" command.Wait.return_value = 0 monkeypatch.setattr( - cherry_pick, + git_command, "GitCommand", - mock.create_autospec(GitCommand, return_value=command), + mock.create_autospec(git_command.GitCommand, return_value=command), ) with pytest.raises(error.GitError, match="commit topic not found"): @@ -71,14 +71,14 @@ def test_resolve_reference_rejects_missing_object( def test_resolve_reference_rejects_ambiguous_object( monkeypatch: pytest.MonkeyPatch, ) -> None: - command = mock.create_autospec(GitCommand, instance=True) + command = mock.create_autospec(git_command.GitCommand, instance=True) command.stdout = "topic^{commit} ambiguous\n" command.stderr = "" command.Wait.return_value = 0 monkeypatch.setattr( - cherry_pick, + git_command, "GitCommand", - mock.create_autospec(GitCommand, return_value=command), + mock.create_autospec(git_command.GitCommand, return_value=command), ) with pytest.raises(error.GitError, match="commit topic not found"): diff --git a/tests/test_subcmds_rebase.py b/tests/test_subcmds_rebase.py index 201ecc516..46e3317d3 100644 --- a/tests/test_subcmds_rebase.py +++ b/tests/test_subcmds_rebase.py @@ -20,6 +20,7 @@ from types import SimpleNamespace from unittest import mock import error +import git_command from subcmds import rebase @@ -77,11 +78,11 @@ def test_execute_delegates_autostash_to_rebase() -> None: onto_manifest=False, this_manifest_only=False, ) - git_command = mock.MagicMock() - git_command.Wait.return_value = 0 + command = mock.MagicMock() + command.Wait.return_value = 0 with mock.patch.object( - rebase, "GitCommand", return_value=git_command + git_command, "GitCommand", return_value=command ) as run_git, contextlib.redirect_stdout(io.StringIO()): assert cmd.Execute(opt, []) == 0 diff --git a/tests/test_subcmds_sync.py b/tests/test_subcmds_sync.py index 4c54a9fc8..e695e8e4e 100644 --- a/tests/test_subcmds_sync.py +++ b/tests/test_subcmds_sync.py @@ -32,6 +32,7 @@ import pytest import command import error +import git_command import manifest_xml from project import SyncNetworkHalfResult from subcmds import sync @@ -1475,14 +1476,14 @@ class CheckForBloatedProjects(unittest.TestCase): self.project.GetRevisionId.assert_not_called() self.project.bare_git.count_objects.assert_not_called() - @mock.patch("subcmds.sync.git_require") + @mock.patch.object(git_command, "git_require") def test_git_version_unsupported(self, mock_git_require): """Test that it returns early if git version is unsupported.""" mock_git_require.return_value = False self.cmd._CheckForBloatedProjects([self.project], self.opt) self.assertFalse(self.cmd.git_event_log.ErrorEvent.called) - @mock.patch("subcmds.sync.git_require") + @mock.patch.object(git_command, "git_require") def test_no_projects(self, mock_git_require): """Test that it returns early if no projects have clone_depth.""" mock_git_require.return_value = True @@ -1490,7 +1491,7 @@ class CheckForBloatedProjects(unittest.TestCase): self.cmd._CheckForBloatedProjects([self.project], self.opt) self.assertFalse(self.cmd.git_event_log.ErrorEvent.called) - @mock.patch("subcmds.sync.git_require", return_value=True) + @mock.patch.object(git_command, "git_require", return_value=True) @mock.patch("subcmds.sync.Progress") def test_network_only_skips_check( self, mock_progress: mock.Mock, mock_git_require: mock.Mock @@ -1504,7 +1505,7 @@ class CheckForBloatedProjects(unittest.TestCase): mock_progress.assert_not_called() self.cmd.ExecuteInParallel.assert_not_called() - @mock.patch("subcmds.sync.git_require", return_value=True) + @mock.patch.object(git_command, "git_require", return_value=True) @mock.patch("subcmds.sync.Progress") def test_projects_without_worktree_excluded( self, mock_progress: mock.Mock, mock_git_require: mock.Mock @@ -1526,7 +1527,7 @@ class CheckForBloatedProjects(unittest.TestCase): mock_progress.assert_not_called() self.cmd.ExecuteInParallel.assert_not_called() - @mock.patch("subcmds.sync.git_require") + @mock.patch.object(git_command, "git_require") @mock.patch("subcmds.sync.Progress") def test_bloated_project_found(self, mock_progress, mock_git_require): """Test that it adds project to _bloated_projects.""" @@ -1549,7 +1550,7 @@ class CheckForBloatedProjects(unittest.TestCase): self.assertEqual(self.cmd._bloated_projects, ["project"]) - @mock.patch("subcmds.sync.git_require") + @mock.patch.object(git_command, "git_require") @mock.patch("subcmds.sync.Progress") def test_stateless_prune_excluded(self, mock_progress, mock_git_require): """Test that projects pruned for stateless sync are excluded.""" @@ -2847,7 +2848,7 @@ class SyncToSuperprojectRevTests(unittest.TestCase): def tearDown(self): shutil.rmtree(self.repodir) - @mock.patch("subcmds.sync.GitCommand") + @mock.patch.object(git_command, "GitCommand") def test_successful_sync(self, mock_git_command): """Test successful sync to superproject rev.""" mock_superproject = self.manifest.superproject @@ -2872,7 +2873,7 @@ class SyncToSuperprojectRevTests(unittest.TestCase): mock_update.assert_called_once() self.assertEqual(self.errors, []) - @mock.patch("subcmds.sync.GitCommand") + @mock.patch.object(git_command, "GitCommand") def test_parse_error(self, mock_git_command): """Test error when .supermanifest cannot be parsed.""" mock_superproject = self.manifest.superproject @@ -2890,7 +2891,7 @@ class SyncToSuperprojectRevTests(unittest.TestCase): ) self.assertIn("could not parse .supermanifest", str(e.exception)) - @mock.patch("subcmds.sync.GitCommand") + @mock.patch.object(git_command, "GitCommand") def test_read_error(self, mock_git_command): """Test error when reading .supermanifest fails.""" mock_superproject = self.manifest.superproject @@ -2917,7 +2918,7 @@ class SyncToSuperprojectRevTests(unittest.TestCase): ) self.assertIn("superproject not defined", str(e.exception)) - @mock.patch("subcmds.sync.GitCommand") + @mock.patch.object(git_command, "GitCommand") def test_sync_failure(self, mock_git_command): """Test error when superproject sync fails.""" mock_superproject = self.manifest.superproject diff --git a/tests/test_subcmds_version.py b/tests/test_subcmds_version.py index 72935e22b..37c94bd65 100644 --- a/tests/test_subcmds_version.py +++ b/tests/test_subcmds_version.py @@ -18,6 +18,7 @@ from unittest import mock import pytest +import git_command from subcmds import version @@ -26,7 +27,7 @@ def test_repo_version_uses_one_pretty_format_call( ) -> None: project = mock.MagicMock() project.bare_git.log.return_value = "v2.0-1-g12345678\nTue, 25 Aug\n" - monkeypatch.setattr(version, "git_require", lambda _version: True) + monkeypatch.setattr(git_command, "git_require", lambda _version: True) result = version.Version._RepoVersion(project) @@ -43,7 +44,7 @@ def test_repo_version_keeps_old_git_fallback( project = mock.MagicMock() project.bare_git.describe.return_value = "v2.0" project.bare_git.log.return_value = "Tue, 25 Aug" - monkeypatch.setattr(version, "git_require", lambda _version: False) + monkeypatch.setattr(git_command, "git_require", lambda _version: False) result = version.Version._RepoVersion(project) |
