mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-04 15:28:27 +01:00
* git: add support for dulwich Stash * git: start adding support for custom refs * git: add Stash and helper context managers for preserving workspace state * scm: cleanup refs/stash and add push_refspec * tests: add tests for git refs and stash * fix push_refspec * tests: add tests for git push_refspec * scm: add git fetch-refspecs * add test for fetch refspecs * scm: add test for git refs containing * remove extraneous log msgs * fix typing issues * stash: only try to push if workspace is dirty * update dulwich to 0.20.14 * scm: move dulwich into scm.backend * move stash internals to backends * scm: move git code into dvc/scm/git/... module * git: use ABC for BaseGitBackend * fix rebase issue * git: fix refspec tests on windows - git file:// URLs need posix style paths * git: move get_refs_containing to backend * scm: add callback for handling diverged refs during fetch
102 lines
3.0 KiB
Python
102 lines
3.0 KiB
Python
import logging
|
|
from typing import Callable, Iterable, Optional, Tuple
|
|
|
|
from .base import BaseGitBackend
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class GitPythonBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
"""git-python Git backend."""
|
|
|
|
@property
|
|
def git(self):
|
|
return self.scm.repo.git
|
|
|
|
def is_ignored(self, path):
|
|
raise NotImplementedError
|
|
|
|
def set_ref(
|
|
self,
|
|
name: str,
|
|
new_ref: str,
|
|
old_ref: Optional[str] = None,
|
|
message: Optional[str] = None,
|
|
symbolic: Optional[bool] = False,
|
|
):
|
|
raise NotImplementedError
|
|
|
|
def get_ref(self, name, follow: Optional[bool] = True) -> Optional[str]:
|
|
raise NotImplementedError
|
|
|
|
def remove_ref(self, name: str, old_ref: Optional[str] = None):
|
|
raise NotImplementedError
|
|
|
|
def get_refs_containing(self, rev: str, pattern: Optional[str] = None):
|
|
from git.exc import GitCommandError
|
|
|
|
try:
|
|
if pattern:
|
|
args = [pattern]
|
|
else:
|
|
args = []
|
|
for line in self.git.for_each_ref(
|
|
*args, contains=rev, format=r"%(refname)"
|
|
).splitlines():
|
|
line = line.strip()
|
|
if line:
|
|
yield line
|
|
except GitCommandError:
|
|
pass
|
|
|
|
def push_refspec(self, url: str, src: Optional[str], dest: str):
|
|
raise NotImplementedError
|
|
|
|
def fetch_refspecs(
|
|
self,
|
|
url: str,
|
|
refspecs: Iterable[str],
|
|
force: Optional[bool] = False,
|
|
on_diverged: Optional[Callable[[bytes, bytes], bool]] = None,
|
|
):
|
|
raise NotImplementedError
|
|
|
|
def _stash_iter(self, ref: str):
|
|
raise NotImplementedError
|
|
|
|
def _stash_push(
|
|
self,
|
|
ref: str,
|
|
message: Optional[str] = None,
|
|
include_untracked: Optional[bool] = False,
|
|
) -> Tuple[Optional[str], bool]:
|
|
from dvc.scm.git import Stash
|
|
|
|
args = ["push"]
|
|
if message:
|
|
args.extend(["-m", message])
|
|
if include_untracked:
|
|
args.append("--include-untracked")
|
|
self.git.stash(*args)
|
|
commit = self.scm.resolve_commit("stash@{0}")
|
|
if ref != Stash.DEFAULT_STASH:
|
|
# `git stash` CLI doesn't support using custom refspecs,
|
|
# so we push a commit onto refs/stash, make our refspec
|
|
# point to the new commit, then pop it from refs/stash
|
|
# `git stash create` is intended to be used for this kind of
|
|
# behavior but it doesn't support --include-untracked so we need to
|
|
# use push
|
|
self.scm.set_ref(ref, commit.hexsha, message=commit.message)
|
|
self.git.stash("drop")
|
|
return commit.hexsha, False
|
|
|
|
def _stash_apply(self, rev: str):
|
|
self.git.stash("apply", rev)
|
|
|
|
def reflog_delete(self, ref: str, updateref: bool = False):
|
|
args = ["delete"]
|
|
if updateref:
|
|
args.append("--updateref")
|
|
args.append(ref)
|
|
self.git.reflog(*args)
|