git: use backend-provided trie in GitTree (#5044)

This commit is contained in:
Ruslan Kuprieiev
2020-12-09 23:51:23 +02:00
committed by GitHub
parent 13bb56aa8e
commit 3b23dfebae
7 changed files with 296 additions and 192 deletions
+38 -5
View File
@@ -1,3 +1,5 @@
import io
import locale
import logging
import os
from functools import partial
@@ -7,9 +9,9 @@ from funcy import first
from dvc.progress import Tqdm
from dvc.scm.base import CloneError, RevError, SCMError
from dvc.tree.base import BaseTree
from dvc.utils import fix_env, is_binary
from ..objects import GitObject
from .base import BaseGitBackend
logger = logging.getLogger(__name__)
@@ -47,6 +49,38 @@ class TqdmGit(Tqdm):
return ops.get(op_code & OP.OP_MASK, "")
class GitPythonObject(GitObject):
def __init__(self, obj):
self.obj = obj
def open(self, mode: str = "r", encoding: str = None):
if not encoding:
encoding = locale.getpreferredencoding(False)
# GitPython's obj.data_stream is a fragile thing, it is better to
# read it immediately, also it needs to be to decoded if we follow
# the `open()` behavior (since data_stream.read() returns bytes,
# and `open` with default "r" mode returns str)
data = self.obj.data_stream.read()
if mode == "rb":
return io.BytesIO(data)
return io.StringIO(data.decode(encoding))
@property
def name(self) -> str:
# NOTE: `obj.name` is not always a basename. See [1] for more details.
#
# [1] https://github.com/iterative/dvc/issues/3481
return os.path.basename(self.obj.path)
@property
def mode(self) -> int:
return self.obj.mode
def scandir(self) -> Iterable["GitPythonObject"]:
for obj in self.obj:
yield GitPythonObject(obj)
class GitPythonBackend(BaseGitBackend): # pylint:disable=abstract-method
"""git-python Git backend."""
@@ -227,10 +261,9 @@ class GitPythonBackend(BaseGitBackend): # pylint:disable=abstract-method
)
]
def get_tree(self, rev: str, **kwargs) -> BaseTree:
from dvc.tree.git import GitTree
return GitTree(self.repo, self.resolve_rev(rev), **kwargs)
def get_tree_obj(self, rev: str, **kwargs) -> GitPythonObject:
tree = self.repo.tree(rev)
return GitPythonObject(tree)
def get_rev(self):
return self.repo.rev_parse("HEAD").hexsha