vcs-versioning 2.2.2__tar.gz → 2.2.4__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.
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/CHANGELOG.md +24 -0
- {vcs_versioning-2.2.2/src/vcs_versioning.egg-info → vcs_versioning-2.2.4}/PKG-INFO +2 -2
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/pyproject.toml +2 -2
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_backends/_git.py +15 -10
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_backends/_hg_git.py +1 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_backends/_jj.py +91 -82
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_cli/__init__.py +0 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_file_finders/_git.py +2 -2
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_file_finders/_hg.py +1 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_file_finders/_jj.py +1 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_get_version_impl.py +1 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_legacy_parse.py +2 -2
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_paths.py +1 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_run_cmd.py +1 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_schemes/_standard.py +2 -3
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/overrides.py +10 -4
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4/src/vcs_versioning.egg-info}/PKG-INFO +2 -2
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning.egg-info/requires.txt +1 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_git.py +19 -3
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_jj.py +63 -4
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_mercurial.py +1 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_version.py +1 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/uv.lock +1 -1
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/LICENSE.txt +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/MANIFEST.in +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/README.md +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/setup.cfg +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/setup.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/__init__.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/__main__.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_backends/__init__.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_backends/_discover_vcs.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_backends/_hg.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_backends/_scm_workdir.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_cli/_args.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_cli/git_archival_full.txt +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_cli/git_archival_stable.txt +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_compat.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_config.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_discover.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_dump_version.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_entrypoints.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_environment.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_exceptions.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_fallback_workdir.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_fallbacks.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_file_finders/__init__.py +3 -3
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_integration.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_integrator_helpers.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_log.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_modify_version.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_node_utils.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_overrides.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_project_overrides.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_protocols.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_pyproject_reading.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_requirement_cls.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_scm_metadata.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_scm_version.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_test_utils.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_toml.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_types.py +3 -3
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_cls.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_fields.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_inference.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_schemes/__init__.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_schemes/_common.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_schemes/_towncrier.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_worktree_discovery.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/py.typed +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/test_api.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning.egg-info/SOURCES.txt +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning.egg-info/dependency_links.txt +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning.egg-info/entry_points.txt +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning.egg-info/top_level.txt +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/__init__.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/conftest.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_better_root_errors.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_chain_api.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_compat.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_config.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_expect_parse.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_file_finders.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_hg_git.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_integrator_helpers.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_internal_log_level.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_legacy_parse.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_overrides_api.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_overrides_env_reader.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_project_overrides.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_project_path.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_regressions.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_scm_metadata.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_tag_config.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_version_scheme_towncrier.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_version_schemes.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_workdir_api.py +0 -0
- {vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/testing_vcs/test_workdir_discovery.py +0 -0
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- towncrier release notes start -->
|
|
4
4
|
|
|
5
|
+
## 2.2.4 (2026-08-07)
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Speed up jujutsu version inference in large repositories.
|
|
10
|
+
|
|
11
|
+
The jj backend filtered whole-ancestry revsets with `empty()`, which makes
|
|
12
|
+
jj diff every commit in the history and took minutes on large repos. The
|
|
13
|
+
scan for the newest real commit is now bounded to the most recent
|
|
14
|
+
generations, distances are counted without the filter, and the working copy
|
|
15
|
+
is snapshotted only once per run (later queries pass
|
|
16
|
+
`--ignore-working-copy`).
|
|
17
|
+
|
|
18
|
+
As a side effect distances now match `git describe --long`: merge commits
|
|
19
|
+
count even though jj considers them empty. ([#1477](https://github.com/pypa/setuptools-scm/issues/1477))
|
|
20
|
+
- Improve reproducibility of scm_file_list.json ([#1488](https://github.com/pypa/setuptools-scm/issues/1488))
|
|
21
|
+
- Route the hg-git tag mismatch warning through the module logger instead of the root logger. ([#1489](https://github.com/pypa/setuptools-scm/issues/1489))
|
|
22
|
+
|
|
23
|
+
## 2.2.3 (2026-07-28)
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Fix `ValueError` when parsing `.git_archival.txt` of a tagged commit whose tag contains more than one dash (e.g. `llvmorg-23.1.0-rc2`) - the `git describe` suffix is now matched precisely instead of splitting on the last two dashes. ([#1481](https://github.com/pypa/setuptools-scm/issues/1481))
|
|
28
|
+
|
|
5
29
|
## 2.2.2 (2026-06-29)
|
|
6
30
|
|
|
7
31
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vcs-versioning
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.4
|
|
4
4
|
Summary: the blessed package to manage your versions by vcs metadata
|
|
5
5
|
Author-email: Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
|
|
6
6
|
License: MIT
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
20
20
|
Requires-Python: >=3.8
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE.txt
|
|
23
|
-
Requires-Dist: packaging>=
|
|
23
|
+
Requires-Dist: packaging>=26.2
|
|
24
24
|
Requires-Dist: tomli>=1; python_version < "3.11"
|
|
25
25
|
Requires-Dist: typing-extensions>=4.1; python_version < "3.11"
|
|
26
26
|
Dynamic: license-file
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
build-backend = "setuptools.build_meta"
|
|
8
8
|
requires = [
|
|
9
9
|
"setuptools>=45",
|
|
10
|
-
"packaging>=
|
|
10
|
+
"packaging>=26.2",
|
|
11
11
|
'typing-extensions>=4.1; python_version < "3.11"',
|
|
12
12
|
]
|
|
13
13
|
|
|
@@ -38,7 +38,7 @@ dynamic = [
|
|
|
38
38
|
"version",
|
|
39
39
|
]
|
|
40
40
|
dependencies = [
|
|
41
|
-
"packaging>=
|
|
41
|
+
"packaging>=26.2",
|
|
42
42
|
'tomli>=1; python_version < "3.11"',
|
|
43
43
|
'typing-extensions>=4.1; python_version < "3.11"',
|
|
44
44
|
]
|
|
@@ -33,6 +33,11 @@ log = logging.getLogger(__name__)
|
|
|
33
33
|
REF_TAG_RE = re.compile(r"(?<=\btag: )([^,]+)\b")
|
|
34
34
|
DESCRIBE_UNSUPPORTED = "%(describe"
|
|
35
35
|
|
|
36
|
+
# ``git describe`` appends ``-<distance>-g<abbreviated node>`` to the tag name.
|
|
37
|
+
# Tags may contain dashes themselves, so the suffix has to be matched precisely
|
|
38
|
+
# instead of just splitting on the last two dashes.
|
|
39
|
+
DESCRIBE_SUFFIX_RE = re.compile(r"^(?P<tag>.+)-(?P<distance>\d+)-g(?P<node>[0-9a-f]+)$")
|
|
40
|
+
|
|
36
41
|
|
|
37
42
|
# If testing command in shell make sure to quote the match argument like
|
|
38
43
|
# '*[0-9]*' as it will expand before being sent to git if there are any matching
|
|
@@ -250,7 +255,7 @@ class GitWorkdir(Workdir):
|
|
|
250
255
|
git_files, git_dirs = _git_ls_files_and_dirs(
|
|
251
256
|
str(self.path), timeout=self._subprocess_timeout
|
|
252
257
|
)
|
|
253
|
-
return scm_find_files(base, git_files, git_dirs)
|
|
258
|
+
return sorted(scm_find_files(base, git_files, git_dirs))
|
|
254
259
|
|
|
255
260
|
def is_file_tracked(self, path: Path) -> bool:
|
|
256
261
|
res = self.run_git(
|
|
@@ -473,15 +478,15 @@ def _git_parse_describe(
|
|
|
473
478
|
else:
|
|
474
479
|
dirty = False
|
|
475
480
|
|
|
476
|
-
|
|
477
|
-
if
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
481
|
+
match = DESCRIBE_SUFFIX_RE.match(describe_output)
|
|
482
|
+
if match is None: # probably a tagged commit
|
|
483
|
+
return describe_output, 0, None, dirty
|
|
484
|
+
return (
|
|
485
|
+
match.group("tag"),
|
|
486
|
+
int(match.group("distance")),
|
|
487
|
+
"g" + match.group("node"),
|
|
488
|
+
dirty,
|
|
489
|
+
)
|
|
485
490
|
|
|
486
491
|
|
|
487
492
|
def archival_to_version(
|
|
@@ -191,7 +191,7 @@ class GitWorkdirHgClient(GitWorkdir, HgWorkdir):
|
|
|
191
191
|
tag = hg_tag
|
|
192
192
|
break
|
|
193
193
|
else:
|
|
194
|
-
|
|
194
|
+
log.warning("tag not found hg=%s git=%s", hg_tags, git_tags)
|
|
195
195
|
return _FAKE_GIT_DESCRIBE_ERROR
|
|
196
196
|
|
|
197
197
|
res = self.run_hg(["log", "-r", f"'{tag}'::.", "-T", "."])
|
|
@@ -35,6 +35,16 @@ if TYPE_CHECKING:
|
|
|
35
35
|
|
|
36
36
|
log = logging.getLogger(__name__)
|
|
37
37
|
|
|
38
|
+
ANCESTOR_SCAN_LIMIT = 20
|
|
39
|
+
"""Generations of ancestors examined when looking for the newest real commit.
|
|
40
|
+
|
|
41
|
+
Revsets filtered by ``empty()`` force jj to diff every candidate commit
|
|
42
|
+
against its parents, so applying such a filter to the full ancestry costs
|
|
43
|
+
O(history) and takes minutes in large repositories (issue #1477). Empty
|
|
44
|
+
commits only occur near the head in practice -- ``@`` itself, plus the
|
|
45
|
+
occasional ``jj new`` chain -- so a small window suffices.
|
|
46
|
+
"""
|
|
47
|
+
|
|
38
48
|
|
|
39
49
|
def run_jj(
|
|
40
50
|
args: Sequence[str | os.PathLike[str]],
|
|
@@ -42,27 +52,45 @@ def run_jj(
|
|
|
42
52
|
*,
|
|
43
53
|
check: bool = False,
|
|
44
54
|
timeout: int | None = None,
|
|
55
|
+
ignore_working_copy: bool = False,
|
|
45
56
|
) -> _CompletedProcess:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
57
|
+
cmd: list[str | os.PathLike[str]] = ["jj", "--no-pager", "--repository", str(repo)]
|
|
58
|
+
if ignore_working_copy:
|
|
59
|
+
cmd.append("--ignore-working-copy")
|
|
60
|
+
cmd.extend(args)
|
|
61
|
+
return _run(cmd, cwd=repo, check=check, timeout=timeout)
|
|
52
62
|
|
|
53
63
|
|
|
54
64
|
class JjWorkdir(Workdir):
|
|
55
65
|
"""Work directory backed by Jujutsu (jj)."""
|
|
56
66
|
|
|
67
|
+
_snapshot_taken: bool = False
|
|
68
|
+
"""Whether a command in this process refreshed the working-copy commit."""
|
|
69
|
+
|
|
57
70
|
def run_jj(
|
|
58
71
|
self,
|
|
59
72
|
args: Sequence[str | os.PathLike[str]],
|
|
60
73
|
*,
|
|
61
74
|
check: bool = False,
|
|
62
75
|
timeout: int | None = None,
|
|
76
|
+
needs_snapshot: bool = False,
|
|
63
77
|
) -> _CompletedProcess:
|
|
78
|
+
"""Run a jj command in this work directory.
|
|
79
|
+
|
|
80
|
+
jj snapshots the working copy on every invocation, which scans the
|
|
81
|
+
whole tree and writes an operation-log entry. One snapshot per
|
|
82
|
+
process is enough, so history queries following it pass
|
|
83
|
+
``--ignore-working-copy``. Commands that must observe uncommitted
|
|
84
|
+
edits set ``needs_snapshot``.
|
|
85
|
+
"""
|
|
86
|
+
ignore_working_copy = self._snapshot_taken and not needs_snapshot
|
|
87
|
+
self._snapshot_taken = True
|
|
64
88
|
return run_jj(
|
|
65
|
-
args,
|
|
89
|
+
args,
|
|
90
|
+
self.path,
|
|
91
|
+
check=check,
|
|
92
|
+
timeout=timeout or self._subprocess_timeout,
|
|
93
|
+
ignore_working_copy=ignore_working_copy,
|
|
66
94
|
)
|
|
67
95
|
|
|
68
96
|
@classmethod
|
|
@@ -74,7 +102,7 @@ class JjWorkdir(Workdir):
|
|
|
74
102
|
return None
|
|
75
103
|
|
|
76
104
|
timeout = config.env.subprocess_timeout if config is not None else None
|
|
77
|
-
res = run_jj(["root"], wd, timeout=timeout)
|
|
105
|
+
res = run_jj(["root"], wd, timeout=timeout, ignore_working_copy=True)
|
|
78
106
|
root = res.parse_success(parse=str)
|
|
79
107
|
if root is None:
|
|
80
108
|
return None
|
|
@@ -84,7 +112,7 @@ class JjWorkdir(Workdir):
|
|
|
84
112
|
return result
|
|
85
113
|
|
|
86
114
|
def is_dirty(self) -> bool:
|
|
87
|
-
res = self.run_jj(["diff", "--summary"])
|
|
115
|
+
res = self.run_jj(["diff", "--summary"], needs_snapshot=True)
|
|
88
116
|
return res.parse_success(parse=bool, default=False)
|
|
89
117
|
|
|
90
118
|
def get_branch(self) -> str | None:
|
|
@@ -133,25 +161,41 @@ class JjWorkdir(Workdir):
|
|
|
133
161
|
error_msg="failed to get jj head date",
|
|
134
162
|
)
|
|
135
163
|
|
|
164
|
+
def _count_revset(self, revset: str) -> int:
|
|
165
|
+
"""Count the commits a revset resolves to."""
|
|
166
|
+
res = self.run_jj(["log", "--no-graph", "-r", revset, "-T", '"x\\n"'])
|
|
167
|
+
output = res.parse_success(parse=str)
|
|
168
|
+
if not output:
|
|
169
|
+
return 0
|
|
170
|
+
return output.count("\n") + 1
|
|
171
|
+
|
|
136
172
|
def node(self) -> str | None:
|
|
137
|
-
|
|
138
|
-
[
|
|
139
|
-
"log",
|
|
140
|
-
"--no-graph",
|
|
141
|
-
"-r",
|
|
142
|
-
"latest(::@ ~ (empty() ~ tags()))",
|
|
143
|
-
"-T",
|
|
144
|
-
"commit_id",
|
|
145
|
-
],
|
|
146
|
-
)
|
|
147
|
-
result = res.parse_success(parse=str)
|
|
148
|
-
return result if result else None
|
|
173
|
+
"""Return the newest ancestor of ``@`` that is a real commit.
|
|
149
174
|
|
|
150
|
-
|
|
151
|
-
|
|
175
|
+
This is jj's equivalent of git's ``HEAD``: the working-copy commit
|
|
176
|
+
``@`` is skipped while it holds no changes, as are the empty
|
|
177
|
+
commits a ``jj new`` chain leaves behind. Merges and tagged
|
|
178
|
+
commits are kept even when empty -- git counts them too.
|
|
152
179
|
|
|
153
|
-
|
|
180
|
+
Only ``ANCESTOR_SCAN_LIMIT`` generations are examined; the
|
|
181
|
+
unbounded query remains as a fallback for histories that are
|
|
182
|
+
empty all the way down.
|
|
154
183
|
"""
|
|
184
|
+
skip = "empty() ~ tags() ~ merges()"
|
|
185
|
+
revsets = [
|
|
186
|
+
f"latest(ancestors(@, {ANCESTOR_SCAN_LIMIT}) ~ ({skip}))",
|
|
187
|
+
f"latest(::@ ~ ({skip}))",
|
|
188
|
+
]
|
|
189
|
+
for revset in revsets:
|
|
190
|
+
res = self.run_jj(["log", "--no-graph", "-r", revset, "-T", "commit_id"])
|
|
191
|
+
result = res.parse_success(parse=str)
|
|
192
|
+
if result:
|
|
193
|
+
return result
|
|
194
|
+
log.debug("no non-empty commit found in %s", revset)
|
|
195
|
+
return None
|
|
196
|
+
|
|
197
|
+
def _find_latest_tag(self) -> str | None:
|
|
198
|
+
"""Find the tag of the latest tagged ancestor of the working copy."""
|
|
155
199
|
res = self.run_jj(
|
|
156
200
|
[
|
|
157
201
|
"log",
|
|
@@ -159,93 +203,58 @@ class JjWorkdir(Workdir):
|
|
|
159
203
|
"-r",
|
|
160
204
|
"latest(heads(::@ & tags()))",
|
|
161
205
|
"-T",
|
|
162
|
-
'tags.map(|t| t.name()).join(",")
|
|
206
|
+
'tags.map(|t| t.name()).join(",")',
|
|
163
207
|
],
|
|
164
208
|
)
|
|
165
|
-
|
|
166
|
-
if not output:
|
|
167
|
-
return None, None
|
|
168
|
-
|
|
169
|
-
lines = output.strip().split("\n")
|
|
170
|
-
if len(lines) < 2:
|
|
171
|
-
return None, None
|
|
172
|
-
|
|
173
|
-
tag_names = lines[0].strip()
|
|
174
|
-
commit_id = lines[1].strip()
|
|
209
|
+
tag_names = res.parse_success(parse=str)
|
|
175
210
|
if not tag_names:
|
|
176
|
-
return None
|
|
211
|
+
return None
|
|
177
212
|
|
|
178
213
|
# Take the first tag if multiple point at the same commit
|
|
179
|
-
|
|
180
|
-
return tag, commit_id
|
|
214
|
+
return tag_names.split(",")[0].strip() or None
|
|
181
215
|
|
|
182
|
-
def _compute_distance(self, tag_name: str) -> int:
|
|
183
|
-
"""Count
|
|
216
|
+
def _compute_distance(self, tag_name: str, node: str) -> int:
|
|
217
|
+
"""Count the commits between a tag and ``node``.
|
|
184
218
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
is the semantically correct representation.
|
|
219
|
+
Mirrors ``git describe --long``: every commit in the range is
|
|
220
|
+
counted, the tagged commit itself is not.
|
|
188
221
|
"""
|
|
189
|
-
|
|
190
|
-
[
|
|
191
|
-
"log",
|
|
192
|
-
"--no-graph",
|
|
193
|
-
"-r",
|
|
194
|
-
f'"{tag_name}"::@ ~ empty()',
|
|
195
|
-
"-T",
|
|
196
|
-
'commit_id ++ "\\n"',
|
|
197
|
-
],
|
|
198
|
-
)
|
|
199
|
-
output = res.parse_success(parse=str)
|
|
200
|
-
if not output:
|
|
201
|
-
return 0
|
|
222
|
+
return max(0, self._count_revset(f'"{tag_name}"::{node}') - 1)
|
|
202
223
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
return
|
|
224
|
+
def _count_ancestors(self, node: str) -> int:
|
|
225
|
+
"""Count the ancestors of ``node``, excluding jj's virtual root."""
|
|
226
|
+
return self._count_revset(f"::{node} ~ root()")
|
|
206
227
|
|
|
207
228
|
def count_all_nodes(self) -> int:
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
"log",
|
|
211
|
-
"--no-graph",
|
|
212
|
-
"-r",
|
|
213
|
-
"::@ ~ empty()",
|
|
214
|
-
"-T",
|
|
215
|
-
'commit_id ++ "\\n"',
|
|
216
|
-
],
|
|
217
|
-
)
|
|
218
|
-
output = res.parse_success(parse=str)
|
|
219
|
-
if not output:
|
|
220
|
-
return 0
|
|
221
|
-
return len([line for line in output.strip().split("\n") if line.strip()])
|
|
229
|
+
node = self.node()
|
|
230
|
+
return self._count_ancestors(node) if node is not None else 0
|
|
222
231
|
|
|
223
232
|
def get_scm_version(self) -> ScmVersion | None:
|
|
224
233
|
config = self.config
|
|
225
234
|
|
|
226
|
-
|
|
235
|
+
# first command in the process -- refreshes the working-copy commit
|
|
236
|
+
# so that the emptiness of ``@`` below reflects uncommitted edits
|
|
227
237
|
dirty = self.is_dirty()
|
|
228
238
|
|
|
239
|
+
node = self.node()
|
|
240
|
+
tag_name = self._find_latest_tag()
|
|
241
|
+
|
|
229
242
|
if tag_name is not None:
|
|
230
|
-
distance = self._compute_distance(tag_name)
|
|
231
|
-
node = self.node()
|
|
232
|
-
if node:
|
|
233
|
-
node = "j" + node[:12]
|
|
243
|
+
distance = 0 if node is None else self._compute_distance(tag_name, node)
|
|
234
244
|
version = meta(
|
|
235
245
|
tag=tag_name,
|
|
236
246
|
distance=distance,
|
|
237
247
|
dirty=dirty,
|
|
238
|
-
node=node,
|
|
248
|
+
node=None if node is None else "j" + node[:12],
|
|
239
249
|
config=config,
|
|
240
250
|
)
|
|
241
251
|
else:
|
|
242
252
|
tag = config.version_cls(config.fallback_version or "0.0")
|
|
243
|
-
node = self.node()
|
|
244
253
|
if node is None:
|
|
245
254
|
distance = 0
|
|
246
255
|
dirty = True
|
|
247
256
|
else:
|
|
248
|
-
distance = self.
|
|
257
|
+
distance = self._count_ancestors(node)
|
|
249
258
|
node = "j" + node[:12]
|
|
250
259
|
version = meta(
|
|
251
260
|
tag=tag, distance=distance, dirty=dirty, node=node, config=config
|
|
@@ -270,7 +279,7 @@ class JjWorkdir(Workdir):
|
|
|
270
279
|
return scm_find_files(base, jj_files, jj_dirs)
|
|
271
280
|
|
|
272
281
|
def is_file_tracked(self, path: Path) -> bool:
|
|
273
|
-
res = self.run_jj(["file", "list", str(path)])
|
|
282
|
+
res = self.run_jj(["file", "list", str(path)], needs_snapshot=True)
|
|
274
283
|
output = res.parse_success(parse=str)
|
|
275
284
|
return bool(output)
|
|
276
285
|
|
|
@@ -21,7 +21,7 @@ def _git_toplevel(path: str) -> str | None:
|
|
|
21
21
|
res = _run(["git", "rev-parse", "HEAD"], cwd=cwd)
|
|
22
22
|
if res.returncode:
|
|
23
23
|
# This catches you being in a git directory, but the
|
|
24
|
-
# permissions being incorrect. With modern
|
|
24
|
+
# permissions being incorrect. With modern containerized
|
|
25
25
|
# CI environments you can easily end up in a cloned repo
|
|
26
26
|
# with incorrect permissions and we don't want to silently
|
|
27
27
|
# ignore files.
|
|
@@ -119,4 +119,4 @@ def git_archive_find_files(path: _t.PathT = "") -> list[str]:
|
|
|
119
119
|
return scm_find_files(path, set(), set(), force_all_files=True)
|
|
120
120
|
|
|
121
121
|
|
|
122
|
-
__all__ = ["
|
|
122
|
+
__all__ = ["git_archive_find_files", "git_find_files"]
|
|
@@ -21,7 +21,7 @@ log = logging.getLogger(__name__)
|
|
|
21
21
|
def _jj_toplevel(path: str) -> str | None:
|
|
22
22
|
try:
|
|
23
23
|
cwd = os.path.abspath(path or ".")
|
|
24
|
-
res = _run(["jj", "root", "--no-pager"], cwd=cwd)
|
|
24
|
+
res = _run(["jj", "root", "--no-pager", "--ignore-working-copy"], cwd=cwd)
|
|
25
25
|
if res.returncode:
|
|
26
26
|
return None
|
|
27
27
|
toplevel = res.stdout.strip()
|
|
@@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
|
|
20
20
|
|
|
21
21
|
# Backward-compat re-export used by vcs-versioning/setup.py
|
|
22
22
|
from ._legacy_parse import (
|
|
23
|
-
resolved_fallback_root as resolved_fallback_root,
|
|
23
|
+
resolved_fallback_root as resolved_fallback_root,
|
|
24
24
|
)
|
|
25
25
|
from ._overrides import _apply_metadata_overrides, _read_pretended_version_for
|
|
26
26
|
from ._scm_version import ScmVersion
|
|
@@ -80,8 +80,8 @@ def parse_scm_version(config: Configuration) -> ScmVersion | None:
|
|
|
80
80
|
entrypoint="setuptools_scm.parse_scm",
|
|
81
81
|
root=config.absolute_root,
|
|
82
82
|
)
|
|
83
|
-
except _run_cmd.CommandNotFoundError
|
|
84
|
-
log.exception("command
|
|
83
|
+
except _run_cmd.CommandNotFoundError:
|
|
84
|
+
log.exception("command not found while parsing the scm, using fallbacks")
|
|
85
85
|
return None
|
|
86
86
|
|
|
87
87
|
|
|
@@ -116,7 +116,7 @@ def _check_absolute_root(root: _t.PathT, relative_to: _t.PathT | None) -> str:
|
|
|
116
116
|
if (
|
|
117
117
|
os.path.isabs(root)
|
|
118
118
|
and os.path.isabs(relative_to)
|
|
119
|
-
and
|
|
119
|
+
and os.path.commonpath([root, relative_to]) != root
|
|
120
120
|
):
|
|
121
121
|
warnings.warn(
|
|
122
122
|
f"absolute root path '{root}' overrides relative_to '{relative_to}'",
|
{vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_schemes/_standard.py
RENAMED
|
@@ -174,9 +174,8 @@ def guess_next_date_ver(
|
|
|
174
174
|
# deduct date format if not provided
|
|
175
175
|
if date_fmt is None:
|
|
176
176
|
date_fmt = "%Y.%m.%d" if len(match.group("year")) == 4 else "%y.%m.%d"
|
|
177
|
-
if prefix := match.group("prefix"):
|
|
178
|
-
|
|
179
|
-
date_fmt = prefix + date_fmt
|
|
177
|
+
if (prefix := match.group("prefix")) and not date_fmt.startswith(prefix):
|
|
178
|
+
date_fmt = prefix + date_fmt
|
|
180
179
|
|
|
181
180
|
today = version.time.date()
|
|
182
181
|
head_date = node_date or today
|
|
@@ -20,11 +20,17 @@ from __future__ import annotations
|
|
|
20
20
|
import contextvars
|
|
21
21
|
import logging
|
|
22
22
|
import os
|
|
23
|
+
import sys
|
|
23
24
|
from collections.abc import Mapping, MutableMapping
|
|
24
25
|
from contextlib import ContextDecorator
|
|
25
26
|
from datetime import datetime
|
|
26
27
|
from typing import TYPE_CHECKING, Any, Literal, TypedDict, TypeVar, overload
|
|
27
28
|
|
|
29
|
+
if sys.version_info >= (3, 11):
|
|
30
|
+
from typing import Self
|
|
31
|
+
else:
|
|
32
|
+
from typing_extensions import Self
|
|
33
|
+
|
|
28
34
|
from packaging.utils import canonicalize_name
|
|
29
35
|
|
|
30
36
|
from ._overrides import (
|
|
@@ -262,7 +268,7 @@ class GlobalOverrides:
|
|
|
262
268
|
version = get_version(...)
|
|
263
269
|
"""
|
|
264
270
|
|
|
265
|
-
__slots__ = ("
|
|
271
|
+
__slots__ = ("_token", "dist_name", "tool", "vcs_env")
|
|
266
272
|
|
|
267
273
|
def __init__(
|
|
268
274
|
self,
|
|
@@ -361,13 +367,13 @@ class GlobalOverrides:
|
|
|
361
367
|
# Context manager
|
|
362
368
|
# ------------------------------------------------------------------
|
|
363
369
|
|
|
364
|
-
def __enter__(self) ->
|
|
370
|
+
def __enter__(self) -> Self:
|
|
365
371
|
"""Enter context: set this as the active override and configure logging."""
|
|
366
372
|
self._token = _active_overrides.set(self)
|
|
367
373
|
self.vcs_env.configure_logging()
|
|
368
374
|
return self
|
|
369
375
|
|
|
370
|
-
def __exit__(self, *exc_info:
|
|
376
|
+
def __exit__(self, *exc_info: object) -> None:
|
|
371
377
|
"""Exit context: restore previous override state."""
|
|
372
378
|
if self._token is not None:
|
|
373
379
|
_active_overrides.reset(self._token)
|
|
@@ -523,7 +529,7 @@ class ensure_context(ContextDecorator):
|
|
|
523
529
|
)
|
|
524
530
|
return self._context.__enter__()
|
|
525
531
|
|
|
526
|
-
def __exit__(self, *exc_info:
|
|
532
|
+
def __exit__(self, *exc_info: object) -> None:
|
|
527
533
|
"""Exit context: only exit if we created the context."""
|
|
528
534
|
if self._created_context and self._context is not None:
|
|
529
535
|
self._context.__exit__(*exc_info)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: vcs-versioning
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.4
|
|
4
4
|
Summary: the blessed package to manage your versions by vcs metadata
|
|
5
5
|
Author-email: Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
|
|
6
6
|
License: MIT
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
20
20
|
Requires-Python: >=3.8
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE.txt
|
|
23
|
-
Requires-Dist: packaging>=
|
|
23
|
+
Requires-Dist: packaging>=26.2
|
|
24
24
|
Requires-Dist: tomli>=1; python_version < "3.11"
|
|
25
25
|
Requires-Dist: typing-extensions>=4.1; python_version < "3.11"
|
|
26
26
|
Dynamic: license-file
|
|
@@ -14,7 +14,7 @@ from unittest.mock import Mock, patch
|
|
|
14
14
|
import pytest
|
|
15
15
|
|
|
16
16
|
# File finder imports (now in vcs_versioning)
|
|
17
|
-
import vcs_versioning._file_finders
|
|
17
|
+
import vcs_versioning._file_finders
|
|
18
18
|
import vcs_versioning._file_finders._git
|
|
19
19
|
from vcs_versioning import Configuration
|
|
20
20
|
from vcs_versioning._backends import _git
|
|
@@ -50,10 +50,15 @@ def wd(wd: WorkDir, monkeypatch: pytest.MonkeyPatch, debug_mode: DebugMode) -> W
|
|
|
50
50
|
[
|
|
51
51
|
("3.3.1-rc26-0-g9df187b", "3.3.1-rc26", 0, "g9df187b", False),
|
|
52
52
|
("17.33.0-rc-17-g38c3047c0", "17.33.0-rc", 17, "g38c3047c0", False),
|
|
53
|
+
("v1.15.1rc1-37-g9bd1298-dirty", "v1.15.1rc1", 37, "g9bd1298", True),
|
|
54
|
+
# bare tags containing dashes must not be mistaken for describe output
|
|
55
|
+
("llvmorg-23.1.0-rc2", "llvmorg-23.1.0-rc2", 0, None, False),
|
|
56
|
+
("llvmorg-23.1.0-rc2-dirty", "llvmorg-23.1.0-rc2", 0, None, True),
|
|
57
|
+
("release-1.2.2", "release-1.2.2", 0, None, False),
|
|
53
58
|
],
|
|
54
59
|
)
|
|
55
60
|
def test_parse_describe_output(
|
|
56
|
-
given: str, tag: str, number: int, node: str, dirty: bool
|
|
61
|
+
given: str, tag: str, number: int, node: str | None, dirty: bool
|
|
57
62
|
) -> None:
|
|
58
63
|
parsed = _git._git_parse_describe(given)
|
|
59
64
|
assert parsed == (tag, number, node, dirty)
|
|
@@ -499,7 +504,6 @@ def test_non_dotted_tag_no_version_match(wd: WorkDir) -> None:
|
|
|
499
504
|
|
|
500
505
|
@pytest.mark.issue("https://github.com/pypa/setuptools-scm/issues/381")
|
|
501
506
|
def test_gitdir(monkeypatch: pytest.MonkeyPatch, wd: WorkDir) -> None:
|
|
502
|
-
""" """
|
|
503
507
|
wd.commit_testfile()
|
|
504
508
|
normal = wd.get_version()
|
|
505
509
|
# git hooks set this and break subsequent setuptools-scm unless we clean
|
|
@@ -650,6 +654,18 @@ def test_git_archival_to_version(expected: str, from_data: dict[str, str]) -> No
|
|
|
650
654
|
assert format_version(version) == expected
|
|
651
655
|
|
|
652
656
|
|
|
657
|
+
@pytest.mark.issue("https://github.com/pypa/setuptools-scm/issues/1481")
|
|
658
|
+
def test_git_archival_bare_tag_with_dashes() -> None:
|
|
659
|
+
config = Configuration(tag_regex=r"^llvmorg-(?P<version>.+)$")
|
|
660
|
+
version = archival_to_version(
|
|
661
|
+
{"describe-name": "llvmorg-23.1.0-rc2"}, config=config
|
|
662
|
+
)
|
|
663
|
+
assert version is not None
|
|
664
|
+
assert str(version.tag) == "23.1.0rc2"
|
|
665
|
+
assert version.distance == 0
|
|
666
|
+
assert version.node is None
|
|
667
|
+
|
|
668
|
+
|
|
653
669
|
@pytest.mark.issue("https://github.com/pypa/setuptools-scm/issues/727")
|
|
654
670
|
def test_git_archival_node_missing_no_version() -> None:
|
|
655
671
|
config = Configuration()
|
|
@@ -4,6 +4,7 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
6
|
from pathlib import Path
|
|
7
|
+
from typing import Any
|
|
7
8
|
from unittest.mock import patch
|
|
8
9
|
|
|
9
10
|
import pytest
|
|
@@ -11,7 +12,7 @@ from vcs_versioning import Configuration
|
|
|
11
12
|
from vcs_versioning._backends import _jj as jj
|
|
12
13
|
from vcs_versioning._backends._discover_vcs import discover
|
|
13
14
|
from vcs_versioning._file_finders._jj import jj_find_files
|
|
14
|
-
from vcs_versioning._run_cmd import CommandNotFoundError
|
|
15
|
+
from vcs_versioning._run_cmd import CommandNotFoundError, CompletedProcess, run
|
|
15
16
|
from vcs_versioning.test_api import DebugMode, WorkDir
|
|
16
17
|
|
|
17
18
|
|
|
@@ -104,6 +105,65 @@ def test_jj_distance(wd: WorkDir) -> None:
|
|
|
104
105
|
assert str(version.tag) == "1.0.0"
|
|
105
106
|
|
|
106
107
|
|
|
108
|
+
@pytest.mark.issue(1477)
|
|
109
|
+
def test_jj_distance_counts_merges_like_git(wd: WorkDir) -> None:
|
|
110
|
+
"""Merges are empty in jj terms but git counts them -- so do we."""
|
|
111
|
+
wd.commit_testfile()
|
|
112
|
+
wd("jj tag set v1.0.0 -r @-")
|
|
113
|
+
wd.commit_testfile()
|
|
114
|
+
main = wd("jj log --no-graph -r @- -T commit_id")
|
|
115
|
+
|
|
116
|
+
wd("jj new v1.0.0 -m side")
|
|
117
|
+
wd.write("side.txt", "side")
|
|
118
|
+
wd.add_and_commit("side")
|
|
119
|
+
side = wd("jj log --no-graph -r @- -T commit_id")
|
|
120
|
+
|
|
121
|
+
wd(f"jj new {main} {side} -m merge")
|
|
122
|
+
wd("jj commit -m merged")
|
|
123
|
+
|
|
124
|
+
version = jj.parse(wd.cwd, Configuration())
|
|
125
|
+
assert version is not None
|
|
126
|
+
assert version.distance == int(wd("git rev-list --count v1.0.0..HEAD"))
|
|
127
|
+
assert version.node == "j" + wd("git rev-parse HEAD")[:12]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@pytest.mark.issue(1477)
|
|
131
|
+
def test_jj_avoids_scanning_the_whole_history(
|
|
132
|
+
wd: WorkDir, monkeypatch: pytest.MonkeyPatch
|
|
133
|
+
) -> None:
|
|
134
|
+
"""``empty()`` costs one commit diff per candidate -- keep it bounded.
|
|
135
|
+
|
|
136
|
+
An unbounded ``empty()`` filter turns version inference into a
|
|
137
|
+
minutes-long operation on large repositories.
|
|
138
|
+
"""
|
|
139
|
+
wd.commit_testfile()
|
|
140
|
+
wd("jj tag set v1.0.0 -r @-")
|
|
141
|
+
wd.commit_testfile()
|
|
142
|
+
|
|
143
|
+
commands: list[list[str]] = []
|
|
144
|
+
|
|
145
|
+
def record(cmd: list[str], cwd: Path, **kwargs: Any) -> CompletedProcess:
|
|
146
|
+
commands.append([str(part) for part in cmd])
|
|
147
|
+
return run(cmd, cwd, **kwargs)
|
|
148
|
+
|
|
149
|
+
monkeypatch.setattr("vcs_versioning._backends._jj._run", record)
|
|
150
|
+
assert jj.parse(wd.cwd, Configuration()) is not None
|
|
151
|
+
|
|
152
|
+
revsets = [
|
|
153
|
+
cmd[index + 1]
|
|
154
|
+
for cmd in commands
|
|
155
|
+
for index, arg in enumerate(cmd)
|
|
156
|
+
if arg == "-r"
|
|
157
|
+
]
|
|
158
|
+
assert revsets
|
|
159
|
+
bound = f"ancestors(@, {jj.ANCESTOR_SCAN_LIMIT})"
|
|
160
|
+
assert all("empty()" not in revset or bound in revset for revset in revsets)
|
|
161
|
+
|
|
162
|
+
# the working copy is snapshotted once, the history queries reuse it
|
|
163
|
+
snapshotting = [cmd for cmd in commands if "--ignore-working-copy" not in cmd]
|
|
164
|
+
assert len(snapshotting) == 1
|
|
165
|
+
|
|
166
|
+
|
|
107
167
|
def test_jj_branch_detection(wd: WorkDir) -> None:
|
|
108
168
|
wd.commit_testfile()
|
|
109
169
|
wd("jj bookmark create test-branch -r @-")
|
|
@@ -144,9 +204,8 @@ def test_jj_missing_binary_errors(tmp_path: Path) -> None:
|
|
|
144
204
|
|
|
145
205
|
with patch(
|
|
146
206
|
"vcs_versioning._backends._discover_vcs.has_command", return_value=False
|
|
147
|
-
):
|
|
148
|
-
|
|
149
|
-
discover(tmp_path, config=config)
|
|
207
|
+
), pytest.raises(LookupError, match="jj.*not available"):
|
|
208
|
+
discover(tmp_path, config=config)
|
|
150
209
|
|
|
151
210
|
|
|
152
211
|
def test_jj_colocated_prefers_jj(wd: WorkDir) -> None:
|
|
@@ -4,7 +4,7 @@ import os
|
|
|
4
4
|
import warnings
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
|
-
import vcs_versioning._file_finders
|
|
7
|
+
import vcs_versioning._file_finders
|
|
8
8
|
from vcs_versioning import Configuration
|
|
9
9
|
from vcs_versioning._backends._hg import archival_to_version, parse
|
|
10
10
|
from vcs_versioning._run_cmd import CommandNotFoundError
|
|
@@ -233,7 +233,7 @@ def test_only_version(version: str) -> None:
|
|
|
233
233
|
def test_tag_regex1(tag: str, expected: str) -> None:
|
|
234
234
|
if "+" in tag:
|
|
235
235
|
# pytest bug wrt cardinality
|
|
236
|
-
with pytest.warns(UserWarning):
|
|
236
|
+
with pytest.warns(UserWarning):
|
|
237
237
|
result = meta(tag, config=c)
|
|
238
238
|
else:
|
|
239
239
|
result = meta(tag, config=c)
|
|
@@ -317,7 +317,7 @@ test = [
|
|
|
317
317
|
|
|
318
318
|
[package.metadata]
|
|
319
319
|
requires-dist = [
|
|
320
|
-
{ name = "packaging", specifier = ">=
|
|
320
|
+
{ name = "packaging", specifier = ">=26.2" },
|
|
321
321
|
{ name = "tomli", marker = "python_full_version < '3.11'", specifier = ">=1" },
|
|
322
322
|
{ name = "typing-extensions", marker = "python_full_version < '3.11'", specifier = ">=4.1" },
|
|
323
323
|
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_cli/git_archival_stable.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -16,12 +16,12 @@ if TYPE_CHECKING:
|
|
|
16
16
|
from ._compat import PathT as PathT # noqa: PLC0414
|
|
17
17
|
|
|
18
18
|
__all__ = [
|
|
19
|
-
"PathT",
|
|
20
19
|
"CMD_TYPE",
|
|
20
|
+
"GIT_PRE_PARSE",
|
|
21
|
+
"SCMVERSION",
|
|
21
22
|
"VERSION_SCHEME",
|
|
22
23
|
"VERSION_SCHEMES",
|
|
23
|
-
"
|
|
24
|
-
"GIT_PRE_PARSE",
|
|
24
|
+
"PathT",
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
if TYPE_CHECKING:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_schemes/__init__.py
RENAMED
|
File without changes
|
{vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_schemes/_common.py
RENAMED
|
File without changes
|
{vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning/_version_schemes/_towncrier.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{vcs_versioning-2.2.2 → vcs_versioning-2.2.4}/src/vcs_versioning.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|