Skip to content

Commit b561ac0

Browse files
committed
refactor(git[sync]): Move to cmd
Attach cmd as attribute for mockability
1 parent 0d0659b commit b561ac0

1 file changed

Lines changed: 33 additions & 34 deletions

File tree

src/libvcs/sync/git.py

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ def convert_pip_url(pip_url: str) -> VCSLocation:
142142
class GitSync(BaseSync):
143143
bin_name = "git"
144144
schemes = ("git+http", "git+https", "git+file")
145+
cmd: Git
145146
_remotes: GitSyncRemoteDict
146147

147148
def __init__(
@@ -232,6 +233,8 @@ def __init__(
232233
)
233234
super().__init__(url=url, dir=dir, **kwargs)
234235

236+
self.cmd = Git(dir=dir, progress_callback=self.progress_callback)
237+
235238
origin = (
236239
self._remotes.get("origin")
237240
if "origin" in self._remotes
@@ -251,7 +254,7 @@ def from_pip_url(cls, pip_url: str, **kwargs: Any) -> "GitSync":
251254
def get_revision(self) -> str:
252255
"""Return current revision. Initial repositories return 'initial'."""
253256
try:
254-
return self.run(["rev-parse", "--verify", "HEAD"])
257+
return self.cmd.rev_parse(verify=True, args="HEAD", check_returncode=True)
255258
except exc.CommandError:
256259
return "initial"
257260

@@ -339,7 +342,7 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
339342

340343
if not git_tag:
341344
self.log.debug("No git revision set, defaulting to origin/master")
342-
symref = self.run(["symbolic-ref", "--short", "HEAD"])
345+
symref = self.cmd.symbolic_ref(name="HEAD", short=True)
343346
if symref:
344347
git_tag = symref.rstrip()
345348
else:
@@ -350,7 +353,9 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
350353

351354
# Get head sha
352355
try:
353-
head_sha = self.run(["rev-list", "--max-count=1", "HEAD"])
356+
head_sha = self.cmd.rev_list(
357+
commit="HEAD", max_count=1, check_returncode=True
358+
)
354359
except exc.CommandError:
355360
self.log.error("Failed to get the hash for HEAD")
356361
return
@@ -359,7 +364,7 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
359364

360365
# If a remote ref is asked for, which can possibly move around,
361366
# we must always do a fetch and checkout.
362-
show_ref_output = self.run(["show-ref", git_tag], check_returncode=False)
367+
show_ref_output = self.cmd.show_ref(pattern=git_tag, check_returncode=False)
363368
self.log.debug("show_ref_output: %s" % show_ref_output)
364369
is_remote_ref = "remotes" in show_ref_output
365370
self.log.debug("is_remote_ref: %s" % is_remote_ref)
@@ -387,13 +392,11 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
387392
# been fetched yet).
388393
try:
389394
error_code = 0
390-
tag_sha = self.run(
391-
[
392-
"rev-list",
393-
"--max-count=1",
394-
git_remote_name + "/" + git_tag if is_remote_ref else git_tag,
395-
]
395+
tag_sha = self.cmd.rev_list(
396+
commit=git_remote_name + "/" + git_tag if is_remote_ref else git_tag,
397+
max_count=1,
396398
)
399+
397400
except exc.CommandError as e:
398401
error_code = e.returncode if e.returncode is not None else 0
399402
tag_sha = ""
@@ -406,15 +409,15 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
406409
return
407410

408411
try:
409-
process = self.run(["fetch"], log_in_real_time=True)
412+
process = self.cmd.fetch(log_in_real_time=True, check_returncode=True)
410413
except exc.CommandError:
411414
self.log.error("Failed to fetch repository '%s'" % url)
412415
return
413416

414417
if is_remote_ref:
415418
# Check if stash is needed
416419
try:
417-
process = self.run(["status", "--porcelain", "--untracked-files=no"])
420+
process = self.cmd.status(porcelain=True, untracked_files="no")
418421
except exc.CommandError:
419422
self.log.error("Failed to get the status")
420423
return
@@ -426,28 +429,28 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
426429
# If Git < 1.7.6, uses --quiet --all
427430
git_stash_save_options = "--quiet"
428431
try:
429-
process = self.run(["stash", "save", git_stash_save_options])
432+
process = self.cmd.stash.save(message=git_stash_save_options)
430433
except exc.CommandError:
431434
self.log.error("Failed to stash changes")
432435

433436
# Checkout the remote branch
434437
try:
435-
process = self.run(["checkout", git_tag])
438+
process = self.cmd.checkout(branch=git_tag)
436439
except exc.CommandError:
437440
self.log.error("Failed to checkout tag: '%s'" % git_tag)
438441
return
439442

440443
# Rebase changes from the remote branch
441444
try:
442-
process = self.run(["rebase", git_remote_name + "/" + git_tag])
445+
process = self.cmd.rebase(upstream=git_remote_name + "/" + git_tag)
443446
except exc.CommandError as e:
444447
if any(msg in str(e) for msg in ["invalid_upstream", "Aborting"]):
445448
self.log.error(e)
446449
else:
447450
# Rebase failed: Restore previous state.
448-
self.run(["rebase", "--abort"])
451+
self.cmd.rebase(abort=True)
449452
if need_stash:
450-
self.run(["stash", "pop", "--index", "--quiet"])
453+
self.cmd.stash.pop(index=True, quiet=True)
451454

452455
self.log.error(
453456
"\nFailed to rebase in: '%s'.\n"
@@ -457,16 +460,16 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
457460

458461
if need_stash:
459462
try:
460-
process = self.run(["stash", "pop", "--index", "--quiet"])
463+
process = self.cmd.stash.pop(index=True, quiet=True)
461464
except exc.CommandError:
462465
# Stash pop --index failed: Try again dropping the index
463-
self.run(["reset", "--hard", "--quiet"])
466+
self.cmd.reset(hard=True, quiet=True)
464467
try:
465-
process = self.run(["stash", "pop", "--quiet"])
468+
process = self.cmd.stash.pop(quiet=True)
466469
except exc.CommandError:
467470
# Stash pop failed: Restore previous state.
468-
self.run(["reset", "--hard", "--quiet", head_sha])
469-
self.run(["stash", "pop", "--index", "--quiet"])
471+
self.cmd.reset(pathspec=head_sha, hard=True, quiet=True)
472+
self.cmd.stash.pop(index=True, quiet=True)
470473
self.log.error(
471474
"\nFailed to rebase in: '%s'.\n"
472475
"You will have to resolve the "
@@ -476,13 +479,12 @@ def update_repo(self, set_remotes: bool = False, *args: Any, **kwargs: Any) -> N
476479

477480
else:
478481
try:
479-
process = self.run(["checkout", git_tag])
482+
process = self.cmd.checkout(branch=git_tag)
480483
except exc.CommandError:
481484
self.log.error("Failed to checkout tag: '%s'" % git_tag)
482485
return
483486

484-
cmd = ["submodule", "update", "--recursive", "--init"]
485-
self.run(cmd, log_in_real_time=True)
487+
self.cmd.submodule.update(recursive=True, init=True, log_in_real_time=True)
486488

487489
def remotes(self) -> GitSyncRemoteDict:
488490
"""Return remotes like git remote -v.
@@ -498,7 +500,7 @@ def remotes(self) -> GitSyncRemoteDict:
498500
"""
499501
remotes = {}
500502

501-
cmd = self.run(["remote"])
503+
cmd = self.cmd.remote.run()
502504
ret: filter[str] = filter(None, cmd.split("\n"))
503505

504506
for remote_name in ret:
@@ -521,7 +523,9 @@ def remote(self, name: str, **kwargs: Any) -> Optional[GitRemote]:
521523
"""
522524

523525
try:
524-
ret = self.run(["remote", "show", "-n", name])
526+
ret = self.cmd.remote.show(
527+
name=name, no_query_remotes=True, log_in_real_time=True
528+
)
525529
lines = ret.split("\n")
526530
remote_fetch_url = lines[1].replace("Fetch URL: ", "").strip()
527531
remote_push_url = lines[2].replace("Push URL: ", "").strip()
@@ -551,9 +555,9 @@ def set_remote(
551555
url = self.chomp_protocol(url)
552556

553557
if self.remote(name) and overwrite:
554-
self.run(["remote", "set-url", name, url])
558+
self.cmd.remote.set_url(name=name, url=url, check_returncode=True)
555559
else:
556-
self.run(["remote", "add", name, url])
560+
self.cmd.remote.add(name=name, url=url, check_returncode=True)
557561

558562
remote = self.remote(name=name)
559563
if remote is None:
@@ -631,7 +635,6 @@ def status(self) -> GitStatus:
631635
return GitStatus.from_stdout(
632636
self.cmd.status(short=True, branch=True, porcelain="2")
633637
)
634-
# return GitStatus.from_stdout(self.run(["status", "-sb", "--porcelain=2"]))
635638

636639
def get_current_remote_name(self) -> str:
637640
"""Retrieve name of the remote / upstream of currently checked out branch.
@@ -651,7 +654,3 @@ def get_current_remote_name(self) -> str:
651654
return match.branch_upstream
652655

653656
return match.branch_upstream.replace("/" + match.branch_head, "")
654-
655-
@property
656-
def cmd(self, *args: object, **kwargs: object) -> Git:
657-
return Git(dir=self.dir, *args, **kwargs)

0 commit comments

Comments
 (0)