scmrepo 2.0.4__tar.gz → 2.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of scmrepo might be problematic. Click here for more details.
- {scmrepo-2.0.4 → scmrepo-2.1.1}/.github/workflows/tests.yaml +1 -1
- {scmrepo-2.0.4 → scmrepo-2.1.1}/CONTRIBUTING.rst +1 -1
- {scmrepo-2.0.4/src/scmrepo.egg-info → scmrepo-2.1.1}/PKG-INFO +5 -5
- {scmrepo-2.0.4 → scmrepo-2.1.1}/noxfile.py +1 -1
- {scmrepo-2.0.4 → scmrepo-2.1.1}/pyproject.toml +4 -4
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/asyn.py +3 -3
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/fs.py +4 -4
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/__init__.py +7 -11
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/backend/base.py +4 -3
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/backend/dulwich/__init__.py +17 -22
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/backend/dulwich/asyncssh_vendor.py +6 -10
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/backend/dulwich/client.py +5 -4
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/backend/gitpython.py +7 -11
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/backend/pygit2/__init__.py +22 -28
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/backend/pygit2/callbacks.py +11 -6
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/backend/pygit2/filter.py +2 -2
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/config.py +4 -4
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/credentials.py +9 -12
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/lfs/client.py +30 -38
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/lfs/fetch.py +9 -8
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/lfs/object.py +2 -2
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/lfs/pointer.py +2 -2
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/lfs/progress.py +2 -2
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/lfs/storage.py +2 -1
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/objects.py +3 -2
- {scmrepo-2.0.4 → scmrepo-2.1.1/src/scmrepo.egg-info}/PKG-INFO +5 -5
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo.egg-info/requires.txt +2 -2
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/conftest.py +5 -4
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/test_dulwich.py +5 -5
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/test_git.py +5 -5
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/test_scmrepo.py +1 -2
- {scmrepo-2.0.4 → scmrepo-2.1.1}/.coveragerc +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/.cruft.json +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/.gitattributes +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/.github/dependabot.yml +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/.github/workflows/release.yaml +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/.github/workflows/update-template.yaml +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/.gitignore +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/.pre-commit-config.yaml +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/CODE_OF_CONDUCT.rst +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/LICENSE +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/README.rst +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/setup.cfg +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/__init__.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/base.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/exceptions.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/backend/__init__.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/lfs/__init__.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/lfs/exceptions.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/lfs/smudge.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/git/stash.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/noscm.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/progress.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/py.typed +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo/utils.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo.egg-info/SOURCES.txt +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo.egg-info/dependency_links.txt +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/src/scmrepo.egg-info/top_level.txt +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/__init__.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/docker-compose.yml +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/git-init/git.sh +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/test_credentials.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/test_fs.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/test_lfs.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/test_noscm.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/test_pygit2.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/test_stash.py +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/user.key +0 -0
- {scmrepo-2.0.4 → scmrepo-2.1.1}/tests/user.key.pub +0 -0
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: scmrepo
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: scmrepo
|
|
5
5
|
Author-email: Iterative <support@dvc.org>
|
|
6
6
|
License: Apache-2.0
|
|
7
7
|
Project-URL: Issues, https://github.com/iterative/scmrepo/issues
|
|
8
8
|
Project-URL: Source, https://github.com/iterative/scmrepo
|
|
9
9
|
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
11
10
|
Classifier: Programming Language :: Python :: 3.9
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
14
|
Classifier: Development Status :: 4 - Beta
|
|
15
|
-
Requires-Python: >=3.
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
16
|
Description-Content-Type: text/x-rst
|
|
17
17
|
License-File: LICENSE
|
|
18
18
|
Requires-Dist: gitpython>3
|
|
19
19
|
Requires-Dist: dulwich>=0.21.6
|
|
20
|
-
Requires-Dist: pygit2>=1.
|
|
20
|
+
Requires-Dist: pygit2>=1.14.0
|
|
21
21
|
Requires-Dist: pygtrie>=2.3.2
|
|
22
22
|
Requires-Dist: fsspec>=2021.7.0
|
|
23
23
|
Requires-Dist: pathspec>=0.9.0
|
|
@@ -34,7 +34,7 @@ Requires-Dist: pytest-mock==3.8.2; extra == "tests"
|
|
|
34
34
|
Requires-Dist: mypy==0.971; extra == "tests"
|
|
35
35
|
Requires-Dist: pytest-test-utils==0.0.8; extra == "tests"
|
|
36
36
|
Requires-Dist: pytest-asyncio==0.18.3; extra == "tests"
|
|
37
|
-
Requires-Dist: pytest-docker==
|
|
37
|
+
Requires-Dist: pytest-docker==2.2.0; (python_version < "3.10" and implementation_name != "pypy") and extra == "tests"
|
|
38
38
|
Requires-Dist: mock==5.1.0; extra == "tests"
|
|
39
39
|
Requires-Dist: paramiko==3.3.1; extra == "tests"
|
|
40
40
|
Requires-Dist: types-certifi==2021.10.8.3; extra == "tests"
|
|
@@ -9,7 +9,7 @@ nox.options.sessions = "lint", "tests"
|
|
|
9
9
|
locations = "src", "tests"
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
@nox.session(python=["3.
|
|
12
|
+
@nox.session(python=["3.9", "3.10", "3.11", "3.12"])
|
|
13
13
|
def tests(session: nox.Session) -> None:
|
|
14
14
|
session.install(".[tests]")
|
|
15
15
|
session.run(
|
|
@@ -12,18 +12,18 @@ license = {text = "Apache-2.0"}
|
|
|
12
12
|
authors = [{ name = "Iterative", email = "support@dvc.org" }]
|
|
13
13
|
classifiers = [
|
|
14
14
|
"Programming Language :: Python :: 3",
|
|
15
|
-
"Programming Language :: Python :: 3.8",
|
|
16
15
|
"Programming Language :: Python :: 3.9",
|
|
17
16
|
"Programming Language :: Python :: 3.10",
|
|
18
17
|
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
19
|
"Development Status :: 4 - Beta",
|
|
20
20
|
]
|
|
21
|
-
requires-python = ">=3.
|
|
21
|
+
requires-python = ">=3.9"
|
|
22
22
|
dynamic = ["version"]
|
|
23
23
|
dependencies = [
|
|
24
24
|
"gitpython>3",
|
|
25
25
|
"dulwich>=0.21.6",
|
|
26
|
-
"pygit2>=1.
|
|
26
|
+
"pygit2>=1.14.0",
|
|
27
27
|
"pygtrie>=2.3.2",
|
|
28
28
|
"fsspec>=2021.7.0",
|
|
29
29
|
"pathspec>=0.9.0",
|
|
@@ -48,7 +48,7 @@ tests = [
|
|
|
48
48
|
"pytest-test-utils==0.0.8",
|
|
49
49
|
"pytest-asyncio==0.18.3",
|
|
50
50
|
# https://github.com/docker/docker-py/issues/2902
|
|
51
|
-
"pytest-docker==
|
|
51
|
+
"pytest-docker==2.2.0; python_version < '3.10' and implementation_name != 'pypy'",
|
|
52
52
|
"mock==5.1.0",
|
|
53
53
|
"paramiko==3.3.1",
|
|
54
54
|
"types-certifi==2021.10.8.3",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import asyncio
|
|
3
3
|
import os
|
|
4
4
|
import threading
|
|
5
|
-
from typing import Any,
|
|
5
|
+
from typing import Any, Optional
|
|
6
6
|
|
|
7
7
|
from fsspec.asyn import ( # noqa: F401, pylint:disable=unused-import
|
|
8
8
|
_selector_policy,
|
|
@@ -11,9 +11,9 @@ from fsspec.asyn import ( # noqa: F401, pylint:disable=unused-import
|
|
|
11
11
|
)
|
|
12
12
|
|
|
13
13
|
# dedicated async IO thread
|
|
14
|
-
iothread:
|
|
14
|
+
iothread: list[Optional[threading.Thread]] = [None]
|
|
15
15
|
# global DVC event loop
|
|
16
|
-
default_loop:
|
|
16
|
+
default_loop: list[Optional[asyncio.AbstractEventLoop]] = [None]
|
|
17
17
|
lock = threading.Lock()
|
|
18
18
|
|
|
19
19
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import errno
|
|
2
2
|
import os
|
|
3
3
|
import posixpath
|
|
4
|
-
from typing import TYPE_CHECKING, Any, BinaryIO, Callable,
|
|
4
|
+
from typing import TYPE_CHECKING, Any, BinaryIO, Callable, Optional
|
|
5
5
|
|
|
6
6
|
from fsspec.callbacks import _DEFAULT_CALLBACK
|
|
7
7
|
from fsspec.spec import AbstractFileSystem
|
|
@@ -169,7 +169,7 @@ class GitFileSystem(AbstractFileSystem):
|
|
|
169
169
|
def as_posix(cls, path):
|
|
170
170
|
return path
|
|
171
171
|
|
|
172
|
-
def _get_key(self, path: str) ->
|
|
172
|
+
def _get_key(self, path: str) -> tuple[str, ...]:
|
|
173
173
|
path = self.abspath(path)
|
|
174
174
|
if path == self.root_marker:
|
|
175
175
|
return ()
|
|
@@ -184,7 +184,7 @@ class GitFileSystem(AbstractFileSystem):
|
|
|
184
184
|
mode: str = "rb",
|
|
185
185
|
block_size: Optional[int] = None,
|
|
186
186
|
autocommit: bool = True,
|
|
187
|
-
cache_options: Optional[
|
|
187
|
+
cache_options: Optional[dict] = None,
|
|
188
188
|
raw: bool = False,
|
|
189
189
|
**kwargs: Any,
|
|
190
190
|
) -> BinaryIO:
|
|
@@ -204,7 +204,7 @@ class GitFileSystem(AbstractFileSystem):
|
|
|
204
204
|
errno.EISDIR, os.strerror(errno.EISDIR), path
|
|
205
205
|
) from exc
|
|
206
206
|
|
|
207
|
-
def info(self, path: str, **kwargs: Any) ->
|
|
207
|
+
def info(self, path: str, **kwargs: Any) -> dict[str, Any]:
|
|
208
208
|
key = self._get_key(path)
|
|
209
209
|
try:
|
|
210
210
|
# NOTE: to avoid wasting time computing object size, trie.info
|
|
@@ -5,18 +5,14 @@ import os
|
|
|
5
5
|
import re
|
|
6
6
|
import typing
|
|
7
7
|
from collections import OrderedDict
|
|
8
|
-
from collections.abc import Mapping
|
|
8
|
+
from collections.abc import Iterable, Mapping
|
|
9
9
|
from contextlib import contextmanager
|
|
10
10
|
from functools import partialmethod
|
|
11
11
|
from typing import (
|
|
12
12
|
TYPE_CHECKING,
|
|
13
13
|
Callable,
|
|
14
14
|
ClassVar,
|
|
15
|
-
Dict,
|
|
16
|
-
Iterable,
|
|
17
15
|
Optional,
|
|
18
|
-
Tuple,
|
|
19
|
-
Type,
|
|
20
16
|
Union,
|
|
21
17
|
)
|
|
22
18
|
|
|
@@ -44,14 +40,14 @@ if TYPE_CHECKING:
|
|
|
44
40
|
|
|
45
41
|
logger = logging.getLogger(__name__)
|
|
46
42
|
|
|
47
|
-
BackendCls =
|
|
43
|
+
BackendCls = type[BaseGitBackend]
|
|
48
44
|
|
|
49
45
|
|
|
50
46
|
_LOW_PRIO_BACKENDS = ("gitpython",)
|
|
51
47
|
|
|
52
48
|
|
|
53
49
|
class GitBackends(Mapping):
|
|
54
|
-
DEFAULT: ClassVar[
|
|
50
|
+
DEFAULT: ClassVar[dict[str, BackendCls]] = {
|
|
55
51
|
"dulwich": DulwichBackend,
|
|
56
52
|
"pygit2": Pygit2Backend,
|
|
57
53
|
"gitpython": GitPythonBackend,
|
|
@@ -72,7 +68,7 @@ class GitBackends(Mapping):
|
|
|
72
68
|
selected = selected or list(self.DEFAULT)
|
|
73
69
|
self.backends = OrderedDict((key, self.DEFAULT[key]) for key in selected)
|
|
74
70
|
|
|
75
|
-
self.initialized:
|
|
71
|
+
self.initialized: dict[str, BaseGitBackend] = {}
|
|
76
72
|
|
|
77
73
|
self.args = args
|
|
78
74
|
self.kwargs = kwargs
|
|
@@ -169,7 +165,7 @@ class Git(Base):
|
|
|
169
165
|
return rev and cls.RE_HEXSHA.search(rev)
|
|
170
166
|
|
|
171
167
|
@classmethod
|
|
172
|
-
def split_ref_pattern(cls, ref: str) ->
|
|
168
|
+
def split_ref_pattern(cls, ref: str) -> tuple[str, str]:
|
|
173
169
|
name = cls.BAD_REF_CHARS_RE.split(ref, maxsplit=1)[0]
|
|
174
170
|
return name, ref[len(name) :]
|
|
175
171
|
|
|
@@ -492,8 +488,8 @@ class Git(Base):
|
|
|
492
488
|
base: Optional[str] = None,
|
|
493
489
|
match: Optional[str] = None,
|
|
494
490
|
exclude: Optional[str] = None,
|
|
495
|
-
) ->
|
|
496
|
-
results:
|
|
491
|
+
) -> dict[str, Optional[str]]:
|
|
492
|
+
results: dict[str, Optional[str]] = {}
|
|
497
493
|
remained_revs = set()
|
|
498
494
|
if base == "refs/heads":
|
|
499
495
|
current_rev = self.get_rev()
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from abc import ABC, abstractmethod
|
|
3
|
+
from collections.abc import Iterable, Mapping
|
|
3
4
|
from enum import Enum
|
|
4
|
-
from typing import TYPE_CHECKING, Callable,
|
|
5
|
+
from typing import TYPE_CHECKING, Callable, Optional, Union
|
|
5
6
|
|
|
6
7
|
from scmrepo.exceptions import SCMError
|
|
7
8
|
from scmrepo.git.objects import GitObject
|
|
@@ -281,7 +282,7 @@ class BaseGitBackend(ABC):
|
|
|
281
282
|
ref: str,
|
|
282
283
|
message: Optional[str] = None,
|
|
283
284
|
include_untracked: bool = False,
|
|
284
|
-
) ->
|
|
285
|
+
) -> tuple[Optional[str], bool]:
|
|
285
286
|
"""Push a commit onto the specified stash.
|
|
286
287
|
|
|
287
288
|
Returns a tuple of the form (rev, need_reset) where need_reset
|
|
@@ -347,7 +348,7 @@ class BaseGitBackend(ABC):
|
|
|
347
348
|
@abstractmethod
|
|
348
349
|
def status(
|
|
349
350
|
self, ignored: bool = False, untracked_files: str = "all"
|
|
350
|
-
) ->
|
|
351
|
+
) -> tuple[Mapping[str, Iterable[str]], Iterable[str], Iterable[str]]:
|
|
351
352
|
"""Return tuple of (staged_files, unstaged_files, untracked_files).
|
|
352
353
|
|
|
353
354
|
staged_files will be a dict mapping status (add, delete, modify) to a
|
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
import re
|
|
6
6
|
import stat
|
|
7
|
+
from collections.abc import Iterable, Iterator, Mapping
|
|
7
8
|
from contextlib import closing
|
|
8
9
|
from functools import partial
|
|
9
10
|
from io import BytesIO, StringIO
|
|
@@ -11,13 +12,7 @@ from typing import (
|
|
|
11
12
|
TYPE_CHECKING,
|
|
12
13
|
Any,
|
|
13
14
|
Callable,
|
|
14
|
-
Dict,
|
|
15
|
-
Iterable,
|
|
16
|
-
Iterator,
|
|
17
|
-
List,
|
|
18
|
-
Mapping,
|
|
19
15
|
Optional,
|
|
20
|
-
Tuple,
|
|
21
16
|
Union,
|
|
22
17
|
)
|
|
23
18
|
|
|
@@ -151,18 +146,18 @@ class DulwichConfig(Config):
|
|
|
151
146
|
return self._config.encoding
|
|
152
147
|
return self._config.backends[0].encoding
|
|
153
148
|
|
|
154
|
-
def get(self, section:
|
|
149
|
+
def get(self, section: tuple[str, ...], name: str) -> str:
|
|
155
150
|
"""Return the specified setting as a string."""
|
|
156
151
|
return self._config.get(section, name).decode(self.encoding)
|
|
157
152
|
|
|
158
|
-
def get_bool(self, section:
|
|
153
|
+
def get_bool(self, section: tuple[str, ...], name: str) -> bool:
|
|
159
154
|
"""Return the specified setting as a boolean."""
|
|
160
155
|
value = self._config.get_boolean(section, name)
|
|
161
156
|
if value is None:
|
|
162
157
|
raise ValueError("setting is not a valid boolean")
|
|
163
158
|
return value
|
|
164
159
|
|
|
165
|
-
def get_multivar(self, section:
|
|
160
|
+
def get_multivar(self, section: tuple[str, ...], name: str) -> Iterator[str]:
|
|
166
161
|
"""Iterate over string values in the specified multivar setting."""
|
|
167
162
|
for value in self._config.get_multivar(section, name):
|
|
168
163
|
yield value.decode(self.encoding)
|
|
@@ -199,17 +194,17 @@ class DulwichBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
199
194
|
except NotGitRepository as exc:
|
|
200
195
|
raise SCMError(f"{root_dir} is not a git repository") from exc
|
|
201
196
|
|
|
202
|
-
self._submodules:
|
|
197
|
+
self._submodules: dict[str, str] = self._find_submodules()
|
|
203
198
|
self._stashes: dict = {}
|
|
204
199
|
|
|
205
|
-
def _find_submodules(self) ->
|
|
200
|
+
def _find_submodules(self) -> dict[str, str]:
|
|
206
201
|
"""Return dict mapping submodule names to submodule paths.
|
|
207
202
|
|
|
208
203
|
Submodule paths will be relative to Git repo root.
|
|
209
204
|
"""
|
|
210
205
|
from dulwich.config import ConfigFile, parse_submodules
|
|
211
206
|
|
|
212
|
-
submodules:
|
|
207
|
+
submodules: dict[str, str] = {}
|
|
213
208
|
config_path = os.path.join(self.root_dir, ".gitmodules")
|
|
214
209
|
if os.path.isfile(config_path):
|
|
215
210
|
config = ConfigFile.from_path(config_path)
|
|
@@ -332,7 +327,7 @@ class DulwichBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
332
327
|
self.repo.stage(list(self.repo.open_index()))
|
|
333
328
|
return
|
|
334
329
|
|
|
335
|
-
files:
|
|
330
|
+
files: list[bytes] = [
|
|
336
331
|
os.fsencode(fpath) for fpath in self._expand_paths(paths, force=force)
|
|
337
332
|
]
|
|
338
333
|
if update:
|
|
@@ -348,7 +343,7 @@ class DulwichBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
348
343
|
else:
|
|
349
344
|
self.repo.stage(files)
|
|
350
345
|
|
|
351
|
-
def _expand_paths(self, paths:
|
|
346
|
+
def _expand_paths(self, paths: list[str], force: bool = False) -> Iterator[str]:
|
|
352
347
|
for path in paths:
|
|
353
348
|
if not os.path.isabs(path) and self._submodules:
|
|
354
349
|
# NOTE: If path is inside a submodule, Dulwich expects the
|
|
@@ -459,7 +454,7 @@ class DulwichBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
459
454
|
return any(p == rel or p.startswith(rel_dir) for p in self.repo.open_index())
|
|
460
455
|
|
|
461
456
|
def is_dirty(self, untracked_files: bool = False) -> bool:
|
|
462
|
-
kwargs:
|
|
457
|
+
kwargs: dict[str, Any] = {} if untracked_files else {"untracked_files": "no"}
|
|
463
458
|
return any(self.status(**kwargs))
|
|
464
459
|
|
|
465
460
|
def active_branch(self) -> str:
|
|
@@ -707,9 +702,9 @@ class DulwichBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
707
702
|
fetch_refs = []
|
|
708
703
|
|
|
709
704
|
def determine_wants(
|
|
710
|
-
remote_refs:
|
|
705
|
+
remote_refs: dict[bytes, bytes],
|
|
711
706
|
depth: Optional[int] = None, # pylint: disable=unused-argument
|
|
712
|
-
) ->
|
|
707
|
+
) -> list[bytes]:
|
|
713
708
|
fetch_refs.extend(
|
|
714
709
|
parse_reftuples(
|
|
715
710
|
DictRefsContainer(remote_refs),
|
|
@@ -782,7 +777,7 @@ class DulwichBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
782
777
|
ref: str,
|
|
783
778
|
message: Optional[str] = None,
|
|
784
779
|
include_untracked: bool = False,
|
|
785
|
-
) ->
|
|
780
|
+
) -> tuple[Optional[str], bool]:
|
|
786
781
|
from dulwich.repo import InvalidUserIdentity
|
|
787
782
|
|
|
788
783
|
from scmrepo.git import Stash
|
|
@@ -836,8 +831,8 @@ class DulwichBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
836
831
|
) -> Mapping[str, Optional[str]]:
|
|
837
832
|
if not base:
|
|
838
833
|
base = "refs/tags"
|
|
839
|
-
rev_mapping:
|
|
840
|
-
results:
|
|
834
|
+
rev_mapping: dict[str, Optional[str]] = {}
|
|
835
|
+
results: dict[str, Optional[str]] = {}
|
|
841
836
|
for ref in self.iter_refs(base=base):
|
|
842
837
|
if (match and not fnmatch.fnmatch(ref, match)) or (
|
|
843
838
|
exclude and fnmatch.fnmatch(ref, exclude)
|
|
@@ -877,7 +872,7 @@ class DulwichBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
877
872
|
|
|
878
873
|
def status(
|
|
879
874
|
self, ignored: bool = False, untracked_files: str = "all"
|
|
880
|
-
) ->
|
|
875
|
+
) -> tuple[Mapping[str, Iterable[str]], Iterable[str], Iterable[str]]:
|
|
881
876
|
from dulwich.porcelain import Error
|
|
882
877
|
from dulwich.porcelain import status as git_status
|
|
883
878
|
|
|
@@ -978,7 +973,7 @@ class DulwichBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
978
973
|
_IDENTITY_RE = re.compile(r"(?P<name>.+)\s+<(?P<email>.+)>")
|
|
979
974
|
|
|
980
975
|
|
|
981
|
-
def _parse_identity(identity: str) ->
|
|
976
|
+
def _parse_identity(identity: str) -> tuple[str, str]:
|
|
982
977
|
m = _IDENTITY_RE.match(identity)
|
|
983
978
|
if not m:
|
|
984
979
|
raise SCMError("Could not parse tagger identity '{identity}'")
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
"""asyncssh SSH vendor for Dulwich."""
|
|
2
2
|
import asyncio
|
|
3
3
|
import os
|
|
4
|
+
from collections.abc import Coroutine, Iterator, Sequence
|
|
4
5
|
from typing import (
|
|
5
6
|
TYPE_CHECKING,
|
|
6
7
|
Callable,
|
|
7
|
-
Coroutine,
|
|
8
|
-
Dict,
|
|
9
|
-
Iterator,
|
|
10
|
-
List,
|
|
11
8
|
Optional,
|
|
12
|
-
Sequence,
|
|
13
9
|
cast,
|
|
14
10
|
)
|
|
15
11
|
|
|
@@ -47,7 +43,7 @@ class _StderrWrapper:
|
|
|
47
43
|
self.stderr = stderr
|
|
48
44
|
self.loop = loop
|
|
49
45
|
|
|
50
|
-
async def _readlines(self) ->
|
|
46
|
+
async def _readlines(self) -> list[bytes]:
|
|
51
47
|
lines = []
|
|
52
48
|
while True:
|
|
53
49
|
line = await self.stderr.readline()
|
|
@@ -140,12 +136,12 @@ def _process_public_key_ok_gh(self, _pkttype, _pktid, packet):
|
|
|
140
136
|
|
|
141
137
|
class InteractiveSSHClient(SSHClient):
|
|
142
138
|
_conn: Optional["SSHClientConnection"] = None
|
|
143
|
-
_keys_to_try: Optional[
|
|
144
|
-
_passphrases:
|
|
139
|
+
_keys_to_try: Optional[list["FilePath"]] = None
|
|
140
|
+
_passphrases: dict[str, str]
|
|
145
141
|
|
|
146
142
|
def __init__(self, *args, **kwargs):
|
|
147
143
|
super(*args, **kwargs)
|
|
148
|
-
_passphrases:
|
|
144
|
+
_passphrases: dict[str, str] = {}
|
|
149
145
|
|
|
150
146
|
def connection_made(self, conn: "SSHClientConnection") -> None:
|
|
151
147
|
self._conn = conn
|
|
@@ -267,7 +263,7 @@ class AsyncSSHVendor(BaseAsyncObject, SSHVendor):
|
|
|
267
263
|
async def _run_command(
|
|
268
264
|
self,
|
|
269
265
|
host: str,
|
|
270
|
-
command:
|
|
266
|
+
command: list[str],
|
|
271
267
|
username: Optional[str] = None,
|
|
272
268
|
port: Optional[int] = None,
|
|
273
269
|
password: Optional[str] = None,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Iterator
|
|
2
|
+
from typing import Optional, Union
|
|
2
3
|
|
|
3
4
|
from dulwich.client import HTTPUnauthorized, Urllib3HttpGitClient
|
|
4
5
|
|
|
@@ -26,10 +27,10 @@ class GitCredentialsHTTPClient(Urllib3HttpGitClient): # pylint: disable=abstrac
|
|
|
26
27
|
def _http_request(
|
|
27
28
|
self,
|
|
28
29
|
url: str,
|
|
29
|
-
headers: Optional[
|
|
30
|
+
headers: Optional[dict[str, str]] = None,
|
|
30
31
|
data: Optional[Union[bytes, Iterator[bytes]]] = None,
|
|
31
32
|
):
|
|
32
|
-
cached_chunks:
|
|
33
|
+
cached_chunks: list[bytes] = []
|
|
33
34
|
|
|
34
35
|
def _cached_data() -> Iterator[bytes]:
|
|
35
36
|
assert data is not None
|
|
@@ -64,7 +65,7 @@ class GitCredentialsHTTPClient(Urllib3HttpGitClient): # pylint: disable=abstrac
|
|
|
64
65
|
self._store_credentials.approve()
|
|
65
66
|
return result
|
|
66
67
|
|
|
67
|
-
def _get_auth(self) ->
|
|
68
|
+
def _get_auth(self) -> dict[str, str]:
|
|
68
69
|
from urllib3.util import make_headers
|
|
69
70
|
|
|
70
71
|
try:
|
|
@@ -4,17 +4,13 @@ import logging
|
|
|
4
4
|
import os
|
|
5
5
|
import re
|
|
6
6
|
import sys
|
|
7
|
+
from collections.abc import Iterable, Mapping
|
|
7
8
|
from functools import partial, wraps
|
|
8
9
|
from typing import (
|
|
9
10
|
TYPE_CHECKING,
|
|
10
11
|
Any,
|
|
11
12
|
Callable,
|
|
12
|
-
Dict,
|
|
13
|
-
Iterable,
|
|
14
|
-
List,
|
|
15
|
-
Mapping,
|
|
16
13
|
Optional,
|
|
17
|
-
Tuple,
|
|
18
14
|
Union,
|
|
19
15
|
)
|
|
20
16
|
|
|
@@ -63,7 +59,7 @@ def is_binary() -> bool:
|
|
|
63
59
|
return getattr(sys, "frozen", False)
|
|
64
60
|
|
|
65
61
|
|
|
66
|
-
def fix_env(env: Optional[
|
|
62
|
+
def fix_env(env: Optional[dict[str, str]] = None) -> dict[str, str]:
|
|
67
63
|
if env is None:
|
|
68
64
|
environ = os.environ.copy()
|
|
69
65
|
else:
|
|
@@ -257,7 +253,7 @@ class GitPythonBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
257
253
|
if update or not force:
|
|
258
254
|
# NOTE: git-python index.add() defines force parameter but
|
|
259
255
|
# ignores it (index.add() behavior is always force=True)
|
|
260
|
-
kwargs:
|
|
256
|
+
kwargs: dict[str, Any] = {}
|
|
261
257
|
if update:
|
|
262
258
|
kwargs["update"] = True
|
|
263
259
|
if isinstance(paths, str):
|
|
@@ -573,7 +569,7 @@ class GitPythonBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
573
569
|
ref: str,
|
|
574
570
|
message: Optional[str] = None,
|
|
575
571
|
include_untracked: bool = False,
|
|
576
|
-
) ->
|
|
572
|
+
) -> tuple[Optional[str], bool]:
|
|
577
573
|
from scmrepo.git import Stash
|
|
578
574
|
|
|
579
575
|
if not self.is_dirty(untracked_files=include_untracked):
|
|
@@ -651,7 +647,7 @@ class GitPythonBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
651
647
|
|
|
652
648
|
def reset(self, hard: bool = False, paths: Optional[Iterable[str]] = None):
|
|
653
649
|
if paths:
|
|
654
|
-
paths_list: Optional[
|
|
650
|
+
paths_list: Optional[list[str]] = [
|
|
655
651
|
relpath(path, self.root_dir) for path in paths
|
|
656
652
|
]
|
|
657
653
|
if os.name == "nt":
|
|
@@ -684,7 +680,7 @@ class GitPythonBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
684
680
|
self.repo.git.checkout(*args)
|
|
685
681
|
else:
|
|
686
682
|
if paths:
|
|
687
|
-
paths_list: Optional[
|
|
683
|
+
paths_list: Optional[list[str]] = [
|
|
688
684
|
relpath(path, self.root_dir) for path in paths
|
|
689
685
|
]
|
|
690
686
|
if os.name == "nt":
|
|
@@ -698,7 +694,7 @@ class GitPythonBackend(BaseGitBackend): # pylint:disable=abstract-method
|
|
|
698
694
|
|
|
699
695
|
def status(
|
|
700
696
|
self, ignored: bool = False, untracked_files: str = "all"
|
|
701
|
-
) ->
|
|
697
|
+
) -> tuple[Mapping[str, Iterable[str]], Iterable[str], Iterable[str]]:
|
|
702
698
|
raise NotImplementedError
|
|
703
699
|
|
|
704
700
|
def merge(
|