Browse Source

move logic of _commit_distance_version() to shore.utils.version module, it now returns None if the commit distance is 0, _commit_distance_version() now delegates to get_commit_distance_version() and returns the original version unchanged if the commit distance is 0, also adds ".dirty" if the working state is dirty

master
Niklas Rosenstein 6 months ago
parent
commit
ce9a482fbf
Signed by: NiklasRosenstein <rosensteinniklas@gmail.com> GPG Key ID: 06D269B33D25F6C6
3 changed files with 67 additions and 41 deletions
  1. +8
    -38
      src/shore/__main__.py
  2. +12
    -2
      src/shore/util/git.py
  3. +47
    -1
      src/shore/util/version.py

+ 8
- 38
src/shore/__main__.py View File

@@ -36,7 +36,7 @@ from shore.util import git as _git
from shore.util.classifiers import get_classifiers
from shore.util.license import get_license_metadata, wrap_license_text
from shore.util.resources import walk_package_resources
from shore.util.version import parse_version, bump_version, Version
from shore.util.version import get_commit_distance_version, parse_version, bump_version, Version
from termcolor import colored
from typing import Any, Dict, Iterable, List, Optional, Union
import click
@@ -65,43 +65,13 @@ def _get_author_info_from_git():


def _commit_distance_version(subject: [Monorepo, Package]) -> Version:
""" This function creates a string which describes the version of the
monorepo or package that includes the commit distance and SHA revision
number.

For a mono repository, the full commit distance is used. The same is true
for a single package. For a package inside a mono repository that does not
apply mono versioning, the packages' local commit distance is used.

This is close to what `git describe --tags` does. An example version number
generated by this function is: `0.1.0-24-gd9ade3f`

Notes:

- The produced version string is not compatible with PEP440.
- If the tag for the version of *subject* does not exist on the repository,
it will fall back to 0.0.0 as the version number which is treated as
"the beginning of the repository", even if no tag for this version exists.

- Todo: We could try to find the previous tag for this subject and use
that.
"""

if isinstance(subject, Package) and subject.monorepo \
and subject.monorepo.mono_versioning:
subject = subject.monorepo

tag = subject.get_tag(subject.version)
if _git.rev_parse(tag):
version = subject.version
distance = len(_git.rev_list(tag + '..HEAD', subject.directory))
else:
logger.warning('tag "%s" does not exist', tag)
version = Version('0.0.0')
distance = len(_git.rev_list('HEAD', subject.directory))

rev = _git.rev_parse('HEAD')
return parse_version(str(version) + '+{}.g{}'.format(distance, rev[:7]))
return get_commit_distance_version(
subject.directory,
subject.version,
subject.get_tag(subject.version)) or subject.version


def _load_subject() -> Union[Monorepo, Package, None]:
@@ -611,12 +581,12 @@ def status():

@cli.command()
@click.option('--tag', '-t', is_flag=True)
@click.option('--git', '-g', is_flag=True)
def version(git, tag):
@click.option('--snapshot', '-s', is_flag=True)
def version(tag, snapshot):
""" Print the current package or repository version. """

subject = _load_subject()
version = _commit_distance_version(subject) if git else subject.version
version = _commit_distance_version(subject) if snapshot else subject.version
if tag:
print(subject.get_tag(version))
else:


+ 12
- 2
src/shore/util/git.py View File

@@ -78,10 +78,10 @@ def tag(tag_name: str, force: bool=False):
subprocess.check_call(command)


def rev_parse(rev: str) -> Optional[str]:
def rev_parse(rev: str, path: str = None) -> Optional[str]:
command = ['git', 'rev-parse', rev]
try:
return subprocess.check_output(command, stderr=subprocess.STDOUT).decode().strip()
return subprocess.check_output(command, stderr=subprocess.STDOUT, cwd=path).decode().strip()
except subprocess.CalledProcessError:
return None

@@ -94,3 +94,13 @@ def rev_list(rev: str, path: str = None) -> List[str]:
if revlist == ['']:
revlist = []
return revlist


def has_diff(path: str = None) -> bool:
try:
subprocess.check_call(['git', 'diff', '--exit-code'], stdout=subprocess.PIPE)
return False
except subprocess.CalledProcessError as exc:
if exc.returncode == 1:
return True
raise

+ 47
- 1
src/shore/util/version.py View File

@@ -20,7 +20,8 @@
# IN THE SOFTWARE.

from packaging.version import Version as _Version
from typing import Union
from shore.util import git as _git
from typing import Optional, Union
import re


@@ -104,3 +105,48 @@ def bump_version(version: Version, kind: str) -> Version:
if post:
string += '.post' + str(post)
return Version(string)


def get_commit_distance_version(repo_dir: str, version: Version, latest_tag: str) -> Optional[Version]:
"""
This function creates a string which describes the version of the
monorepo or package that includes the commit distance and SHA revision
number.

For a mono repository, the full commit distance is used. The same is true
for a single package. For a package inside a mono repository that does not
apply mono versioning, the packages' local commit distance is used.

This is close to what `git describe --tags` does. An example version number
generated by this function is: `0.1.0+24.gd9ade3f`. If the working state is
dirty, `.dirty` will be appended to the local version.

Notes:

- If there is no commit distance from the *latest_tag* to the current
state of the repository, this function returns None.
- The version returned by this function is a PEP440 local version that
cannot be used for packages when submitting them to PyPI.
- If the tag for the version of *subject* does not exist on the repository,
it will fall back to 0.0.0 as the version number which is treated as
"the beginning of the repository", even if no tag for this version exists.

Todo: We could try to find the previous tag for this subject and use that.
"""

if _git.rev_parse(latest_tag):
distance = len(_git.rev_list(latest_tag + '..HEAD', repo_dir))
else:
logger.warning('tag "%s" does not exist', latest_tag)
version = Version('0.0.0')
distance = len(_git.rev_list('HEAD', repo_dir))

if distance == 0:
return None

suffix = ''
if _git.has_diff(repo_dir):
suffix = '.dirty'

rev = _git.rev_parse('HEAD', repo_dir)
return parse_version(str(version) + '+{}.g{}{}'.format(distance, rev[:7], suffix))

Loading…
Cancel
Save