Skip to content

Commit

Permalink
Use version_file as source of version, ignore tags
Browse files Browse the repository at this point in the history
  • Loading branch information
dolfinus committed Apr 8, 2024
1 parent 163ef53 commit f3db77f
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 65 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ Changelog

Drop ``get_branch_tags`` function which was deprecated since ``1.8.0``.

.. change::
:tags: core, breaking

``version_file`` option now have precedence over any tags in the current branch.

1.13
----

Expand Down
4 changes: 0 additions & 4 deletions docs/options/version_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@

Version file path template for :ref:`version-file` versioning schema.

.. note::

This option is completely ignored if :ref:`tag-release` schema is used.

.. note::

This option conflicts with :ref:`version-callback-option`, only one of them can be set.
Expand Down
30 changes: 11 additions & 19 deletions docs/schemas/file/dev_release_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ For example, current repo state is:
|
...
**And there are no tags in the current branch** (``dev``), **all
of them are placed in the** ``master`` **branch.**

If you want to create development releases (prereleases) for the next planned version ``1.1.0``,
so every commit to ``dev`` branch should produce version number like ``1.1.0.dev123`` (just plain increment)
or even ``1.1.0.dev123+git.sha`` (to describe which commit was used for this exact version).
Expand All @@ -39,16 +36,17 @@ Then update your config file:

.. code:: python
import os
# you can use os.path instead of pathlib
from pathlib import Path
HERE = os.path.dirname(__file__)
VERSION_FILE = os.path.join(HERE, "VERSION.txt")
root_path = Path(__file__).parent
version_file = root_path / "VERSION.txt"
setuptools.setup(
...,
setuptools_git_versioning={
"enabled": True,
"version_file": VERSION_FILE,
"version_file": version_file,
"count_commits_from_version_file": True, # enable commits tracking
"dev_template": "{tag}.dev{ccount}", # suffix for versions will be .dev
"dirty_template": "{tag}.dev{ccount}", # same thing here
Expand All @@ -66,22 +64,16 @@ Then update your config file:
dev_template = "{tag}.dev{ccount}"
dirty_template = "{tag}.dev{ccount}"
In case of next release version ``1.1.0`` the third commit to ``dev`` branch will produce
In case of next release version ``1.1.0``, the third commit to ``dev`` branch will produce
version number ``1.1.0.dev3``, and so on.

Release process
""""""""""""""""
"""""""""""""""

- Merge ``dev`` branch into ``master`` branch.
- Tag commit in the ``master`` branch with next release version (e.g. ``1.1.0``). Tag will be used as a version number for the release.

.. warning::

Do not place any tags in the ``dev`` branch!

- Tag commit in the ``master`` branch, and publis a repease from code on this branch.
- Checkout back to ``dev`` branch
- Save next release version (e.g. ``1.2.0``) in ``VERSION`` or ``VERSION.txt`` file in the ``dev`` branch.

- Next commits to a ``dev`` branch will lead to returning this next release version plus dev suffix, like ``1.2.0.dev1`` or so.
- ``N`` in ``.devN`` suffix is a number of commits since the last change of a certain file.

Expand Down Expand Up @@ -109,7 +101,7 @@ For example, if the branch name is something like ``alpha``, ``beta``,
...,
setuptools_git_versioning={
"enabled": True,
"version_file": VERSION_FILE,
"version_file": version_file,
"count_commits_from_version_file": True,
"dev_template": "{tag}.{branch}{ccount}",
"dirty_template": "{tag}.{branch}{ccount}",
Expand Down Expand Up @@ -149,7 +141,7 @@ It is also possible to use branch names like ``1.0-alpha`` or ``1.1.beta``:
"count_commits_from_version_file": True,
"dev_template": "{branch}{ccount}",
"dirty_template": "{branch}{ccount}",
"version_file": VERSION_FILE,
"version_file": version_file,
},
)
Expand All @@ -172,7 +164,7 @@ If branch name is not :pep:`440` compliant, use :ref:`branch-formatter-option` o

.. note::

Although ``VERSION`` file content is not used in this case, you still need to update it
Although ``VERSION`` file content is not used in this particular example, you still need to update it
while changing your next release version.

Otherwise this tool will not be able to properly calculate version number.
Expand Down
6 changes: 1 addition & 5 deletions docs/schemas/file/version_file.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ For example, current repo state is:
|
...
**And there are no tags in the current branch** (``dev``), **all
of them are placed in the** ``master`` **branch.**

By default, when you try to get current version, you'll receive some
initial value (see :ref:`starting-version-option` option).

Expand Down Expand Up @@ -64,8 +61,7 @@ Then place it in both the branches and update your config file:
When you'll try to get current version in non-master branch, the content
of this file (``1.0.0``) will be returned instead default version number.

**Please take into account that version_file is ignored if any tag
is present in the current branch.**
**Please take into account that any tags in the repo are ignored if this option is being used.**

See also
"""""""""
Expand Down
72 changes: 40 additions & 32 deletions setuptools_git_versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,9 @@ def version_from_git(
)
return _get_version_from_callback(version_callback, package_name, root=root)

head_sha = get_sha(root=root)
log.log(INFO, "HEAD SHA-256: %r", head_sha)

filter_callback = None
if tag_filter:
filter_callback = _callable_factory(
Expand All @@ -516,16 +519,22 @@ def version_from_git(
root=root,
)

from_file = False
log.log(INFO, "Getting latest tag")
log.log(DEBUG, "Sorting tags by %r", sort_by)
tag = get_tag(sort_by=sort_by, root=root, filter_callback=filter_callback)
if not tag:
log.log(INFO, "No tags found")
tag_sha = None
on_tag = False
else:
tag_sha = get_sha(tag, root=root)
log.log(INFO, "Tag SHA-256: %r", tag_sha)

if tag is None:
log.log(INFO, "No tag, checking for 'version_file'")
if version_file is None:
log.log(INFO, "No 'version_file' set, return starting_version %r", starting_version)
return _sanitize_version(starting_version)
on_tag = head_sha is not None and head_sha == tag_sha
log.log(INFO, "HEAD is tagged: %r", on_tag)

if version_file:
log.log(INFO, "Checking for 'version_file'")

if not Path(version_file).exists():
log.log(
Expand All @@ -534,26 +543,30 @@ def version_from_git(
version_file,
starting_version,
)
return _sanitize_version(starting_version)
tag = None
else:
log.log(INFO, "Reading version_file '%s' content", version_file)
tag = _read_version_from_file(version_file, root=root) or None

log.log(INFO, "version_file '%s' does exist, reading its content", version_file)
from_file = True
tag = _read_version_from_file(version_file, root=root)
if not tag:
log.log(INFO, "File %r is empty", version_file)
else:
log.log(DEBUG, "File content: %r", tag)
if not count_commits_from_version_file:
return _sanitize_version(tag)

if not tag:
log.log(INFO, "File is empty, return starting_version %r", version_file, starting_version)
return _sanitize_version(starting_version)
file_sha = get_latest_file_commit(version_file, root=root)
log.log(DEBUG, "File SHA-256: %r", file_sha)

log.log(DEBUG, "File content: %r", tag)
if not count_commits_from_version_file:
return _sanitize_version(tag)
ccount = count_since(file_sha, root=root) if file_sha is not None else None
log.log(INFO, "Commits count between HEAD and last version file change: %r", ccount)

tag_sha = get_latest_file_commit(version_file, root=root)
log.log(DEBUG, "File SHA-256: %r", tag_sha)
else:
log.log(INFO, "Latest tag: %r", tag)
tag_sha = get_sha(tag, root=root)
log.log(INFO, "Tag SHA-256: %r", tag_sha)
elif not head_sha:
log.log(INFO, "Not a git repo, or repo without any branch")

elif tag_sha:
ccount = count_since(tag_sha, root=root)
log.log(INFO, "Commits count between HEAD and last tag: %r", ccount)

if tag_formatter is not None:
tag_format_callback = _callable_factory(
Expand All @@ -567,19 +580,13 @@ def version_from_git(
tag = tag_format_callback(tag)
log.log(DEBUG, "Tag after formatting: %r", tag)

if not tag:
log.log(INFO, "No source for version, return starting_version %r", starting_version)
return _sanitize_version(starting_version)

dirty = is_dirty(root=root)
log.log(INFO, "Is dirty: %r", dirty)

head_sha = get_sha(root=root)
log.log(INFO, "HEAD SHA-256: %r", head_sha)

full_sha = head_sha if head_sha is not None else ""
ccount = count_since(tag_sha, root=root) if tag_sha is not None else None
log.log(INFO, "Commits count between HEAD and latest tag: %r", ccount)

on_tag = head_sha is not None and head_sha == tag_sha and not from_file
log.log(INFO, "HEAD is tagged: %r", on_tag)

branch = get_branch(root=root)
log.log(INFO, "Current branch: %r", branch)

Expand All @@ -605,6 +612,7 @@ def version_from_git(
log.log(INFO, "Using template from 'template' option")
t = template

full_sha = head_sha if head_sha is not None else ""
version = _resolve_substitutions(t, sha=full_sha[:8], tag=tag, ccount=ccount, branch=branch, full_sha=full_sha)
log.log(INFO, "Version number after resolving substitutions: %r", version)
return _sanitize_version(version)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_integration/test_version_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def test_version_callback_not_a_repo(repo_dir, create_config):
assert get_version_module(os.getcwd(), args=[repo_dir]) == version


def test_version_callback_has_more_priority_than_tag(repo, create_config):
def test_version_callback_has_higher_priority_than_tag(repo, create_config):
version = "1.0.0"

create_file(repo, "version.py", VERSION_PY.format(version=version), commit=False)
Expand Down
24 changes: 20 additions & 4 deletions tests/test_integration/test_version_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,10 @@ def test_version_file_count_commits(repo, create_config, template, subst):
"count_commits_from_version_file": True,
}
if template:
# template is not ignored
# template is ignored
config["dev_template"] = template

create_config(repo, config)

create_file(repo, "VERSION.txt", "1.0.0")

full_sha = get_full_sha(repo)
Expand Down Expand Up @@ -177,7 +176,7 @@ def test_version_file_wrong_version_number(repo, version, create_config, count_c


@pytest.mark.flaky(reruns=3) # sha and full_sha can start with 0 which are removed, just try again
def test_version_file_tag_is_preferred(repo, create_config):
def test_version_file_tagged_history(repo, create_config):
create_tag(repo, "1.2.3")

create_file(repo, "VERSION.txt", "1.0.0")
Expand All @@ -190,7 +189,24 @@ def test_version_file_tag_is_preferred(repo, create_config):
)

sha = get_sha(repo)
assert get_version(repo) == f"1.2.3.post2+git.{sha}"
assert get_version(repo) == f"1.0.0.post1+git.{sha}"


@pytest.mark.flaky(reruns=3) # sha and full_sha can start with 0 which are removed, just try again
def test_version_file_tagged_head(repo, create_config):
create_file(repo, "VERSION.txt", "1.0.0")
create_config(
repo,
{
"version_file": "VERSION.txt",
"count_commits_from_version_file": True,
},
)
create_tag(repo, "1.2.3")

# template is for release, because commit is tagged
# but version_file content is up to user
assert get_version(repo) == "1.0.0"


@pytest.mark.parametrize("starting_version, version", [(None, "0.0.1"), ("1.2.3", "1.2.3")])
Expand Down

0 comments on commit f3db77f

Please sign in to comment.