diff --git a/.project b/.project index dc36649..abb1fea 100644 --- a/.project +++ b/.project @@ -1,6 +1,6 @@ - {{project_name}} + gitversionhelper diff --git a/Jenkinsfile b/Jenkinsfile index ceb6d3a..2b80254 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -181,7 +181,6 @@ pipeline { sh("rm -Rf ~/_gitrepo || true") - //sh(". ~/BUILD_ENV/bin/activate && python -m copier --vcs-ref HEAD --prereleases --defaults ./ ~/_gitrepo") sh(script: """#!/bin/sh - |. ~/BUILD_ENV/bin/activate |exec python - << '__EOWRAPPER__' diff --git a/README.md b/README.md index 77fbcfa..65cb993 100644 --- a/README.md +++ b/README.md @@ -3,46 +3,33 @@ ![](docs-static/Library.jpg) -# Python project template +# pyGitVersionHelper -A nice template to start a blank python projet. - -This template automate a lot of handy things and allow CI/CD automatic releases generation. +_A tiny library to help versioning management of git python projects_ -It is also collectings data to feed Jenkins build. +Because a good developer is a lazy developer and version management in CI/CD can be very time consuming. -Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pychachadummyproject/{{branch}}/latest/). + +Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitversionhelper/{{branch}}/latest/). ## Features - -### Generic pipeline skeleton: - - Prepare - - GetCode - - BuildPackage - - Install - - CheckCode - - PlotMetrics - - RunUnitTests - - GenDOC - - PostRelease + - list tags + - get last tag + - get last version + - get current version (bumped) + - convert / switch from SemVer to PEP440 (both ways) + - automatic version format detection (SemVer by default) -### CI/CD Environment - - Jenkins - - Gitea (with patch for dynamic Readme variables: https://chacha.ddns.net/gitea/chacha/GiteaMarkupVariable) - - Docker - - MkDocsWeb - -### CI/CD Helper libs - - VirtualEnv - - Changelog generation based on commits - - copier - - pylint + pylint_json2html - - mypy - - unittest + xmlrunner + junitparser + junit2htmlreport - - mkdocs +## Options + - restrict to same branch + - both SemVer and PEP440 support + - custom output format + - configurable default bump type major, minor, patch or dev + - configurable default bump type: post, pre-patch, pre-minor, pre-major + - ignore non-version tag + - force version format -### Python project - - Full .toml implementation - - .whl automatic generation - - dynamic versionning using git repository - - embedded unit-test \ No newline at end of file +## Process + - full CI/CD developpment: Gitea / Jenkins + few python libs (pytlint, coverage, unittest, mkdocs) + - documentation generated mkdocs and self-hosted + - CI/CD on Linux, manually tested in Windows environnement \ No newline at end of file diff --git a/docs-static/usage.md b/docs-static/usage.md index 7763bbd..18b1cdb 100644 --- a/docs-static/usage.md +++ b/docs-static/usage.md @@ -1,16 +1,113 @@ # Usage -## Pulvinar dolor -Donec dapibus est fermentum justo volutpat condimentum. Integer quis nunc neque. Donec dictum vehicula justo, in facilisis ex tincidunt in. -Vivamus sollicitudin sem dui, id mollis orci facilisis ut. Proin sed pulvinar dolor. Donec volutpat commodo urna imperdiet pulvinar. Fusce eget aliquam risus. -Vivamus viverra luctus ex, in finibus mi. Nullam elementum dapibus mollis. Ut suscipit volutpat ex, quis feugiat lacus consectetur eu. +## Installation -## Condimentum faucibus -Quisque auctor egestas sem, luctus suscipit ex maximus vitae. Duis facilisis augue et condimentum faucibus. -Donec cursus, enim a sagittis egestas, lectus lorem eleifend libero, at tincidunt leo magna at libero. -Nunc eros velit, suscipit luctus tempor vel, finibus et est. Curabitur efficitur pretium pulvinar. -Donec urna lectus, vulputate quis turpis sed, placerat congue urna. Phasellus aliquet fermentum quam, non auctor elit porta nec. Morbi eu ligula at nisl ultricies condimentum vitae id ante. +From master repository: -## Aliquam lacinia -In volutpat lorem ex, et fringilla nibh faucibus quis. Mauris et arcu elementum, auctor dui vitae, egestas arcu. Duis sit amet aliquam quam. -Phasellus a odio turpis. Etiam tristique mi eu enim varius, eget facilisis est vestibulum. Aliquam lacinia nec purus sed luctus. Cras at laoreet erat. \ No newline at end of file + python -m pip install git+https://chacha.ddns.net/gitea/chacha/pygitversionhelper.git@master + +From local .whl file: + + python -m pip install pygitversionhelper--py3-none-any.whl + +From public repository: + + TBD + +## Import in your project + +Add this line on the top of your python script: + + #from pygitversionhelper import gitversionhelper + +[optionnal] If you need to catch exception from this module: + + #from pygitversionhelper import gitversionhelperException + +## Basic API + +All the API commands are static so it is not needed to create instantiate any object. + +They are all executed in the current active directory. + +One easy way to change directory: + + import os + os.chdir("") + +### sublib: repository + +To check if a repository is dirty: + + if gitversionhelper.repository.isDirty(): + print("repository is dirty") + +### sublib: tag + +List all tags [default to taggerdate order]: + + for tag in gitversionhelper.tag.getTags(): + print(f"found tag: {tag}") + +List all tags [using git refname order]: + + for tag in gitversionhelper.tag.getTags("v:refname"): + print(f"found tag: {tag}") + +Get the last tag: + + print(f"most recent repository tag: {gitversionhelper.tag.getLastTag()}") + +Get the last tag [only on same branch]: + + print(f"most recent repository tag: {gitversionhelper.tag.getLastTag(same_branch=True)}") + + +Get the distance from HEAD to last tag: + + print(f"number of commit since last tag: {gitversionhelper.tag.getDistanceFromTag()}") + +Get the distance from HEAD to last tag [only on same branch]: + + print(f"number of commit since last tag: {gitversionhelper.tag.getDistanceFromTag(same_branch=True)}") + +### sublib: version + +Get the last found version in the repository [return MetaVersion object]: + + print(f"most recent repository version: {gitversionhelper.tag.getLastVersion()}") + +Get the last found version in the repository [return formated string]: + + print(f"most recent repository version: {gitversionhelper.tag.getLastVersion(formated_output=True)}") + +Others kwargs available to this function: + - version_std: string to force a version standard for rendering ["PEP440" or "SemVer"] + - same_branch: boolean to force searching on same branch + - ignore_unknown_tags: boolean to allow unknown tag to be ignored + +Get the current version of the repository, automatically bump it if the last one is not tagged [returns MetaVersion object]: + + print(f"most recent repository version: {gitversionhelper.tag.getCurrentVersion()}") + +kwargs available to this function: + - All same args as getLastVersion() + - bump_type: if version need to be pump, allow to configure next release update type: major, minor, patch, dev + - bump_dev_strategy: if bump_type is dev, allow to choose dev update strategy: post, pre-patch, pre-minor, pre-major + +A version object can also be manually formated: + + _version = gitversionhelper.tag.getCurrentVersion() + _version.doFormatVersion() + #or + gitversionhelper.version.doFormatVersion(_version) + +kwargs available to those function: + - output_format: string to choose a rendering format ["Auto","PEP440" or "SemVer"] + +## Limitations + +There is unfortunately some technical limitation : +- MultiThreading and async behavior is not tested. +- Multiple tag on the same commit is not supported. +- Branch filter when searching for a version is only tested with -no-ff strategy \ No newline at end of file diff --git a/helpers/quality_check.py b/helpers/quality_check.py index 6d9ad9c..7616d5f 100644 --- a/helpers/quality_check.py +++ b/helpers/quality_check.py @@ -61,7 +61,7 @@ class quality_check(helper_withresults_base): '--ignore=_version.py', '--reports=y', '--score=yes', - '--max-line-length=120', + '--max-line-length=140', 'src.' + cls.pyproject['project']['name']], exit=False) with open(cls.get_result_dir()/"report.json","w+", encoding='utf-8') as Outfile: diff --git a/pyproject.toml b/pyproject.toml index 67182a2..5d00a65 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,7 +13,7 @@ build-backend = "setuptools.build_meta" [tool.setuptools-git-versioning] enabled = true dev_template = "{tag}.post{ccount}" -#tag_filter = "^\\d+\\.\\d+\\.\\d+$" +tag_filter = "^\\d+\\.\\d+\\.\\d+$" [project] name = "pygitversionhelper" diff --git a/src/pygitversionhelper/__init__.py b/src/pygitversionhelper/__init__.py index 0ab7e56..ed207f0 100644 --- a/src/pygitversionhelper/__init__.py +++ b/src/pygitversionhelper/__init__.py @@ -19,4 +19,4 @@ except PackageNotFoundError: # pragma: no cover warnings.warn("can not read __version__, assuming local test context, setting it to ?.?.?") __version__ = "?.?.?" -from .test_module import test_function +from .gitversionhelper import gitversionhelper, gitversionhelperException diff --git a/src/pygitversionhelper/gitversionhelper.py b/src/pygitversionhelper/gitversionhelper.py new file mode 100644 index 0000000..9b0dfab --- /dev/null +++ b/src/pygitversionhelper/gitversionhelper.py @@ -0,0 +1,655 @@ +# pygitversionhelper (c) by chacha +# +# pygitversionhelper is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. +# +# You should have received a copy of the license along with this +# work. If not, see . +""" +This project try to help doing handy operations with git when +dealing with project versioning and tags on python project - +at leat for project using PEP440 or SemVer standards. + +One requirement is to keep it compact and to not cover too much fancy features. +This is the reason why it is one single file with nested classes. + +=> Design is on-purpose poorly expandable to keep the scope light. + +This library is maid for repository using tag as version. +Support for non-version tags is optional and not well tested. + +This module is the main project file, containing all the code. + +Read the read me for more information. +Check the unittest s for usage samples. + +Note: _Other Parameters_ are **kwargs +""" + +from __future__ import annotations + +import os +import subprocess +import re +from copy import copy +import logging + +from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN + +def _exec(cmd: str, root: str | os.PathLike | None = None, raw:bool = False) -> list[str]: + """ + helper function to handle system cmd execution + Args: + cmd: command line to be executed + root: root directory where the command need to be executed + Returns: + a list of command's return lines + + """ + p = subprocess.run(cmd, text=True, cwd=root, capture_output=True, check=False, timeout=2,shell=True) + if re.search("not a git repository",p.stderr): + raise gitversionhelper.repository.notAGitRepository() + if re.search("fatal:",p.stderr): #pragma: nocover + raise gitversionhelper.unknownGITFatalError(p.stderr) + if int(p.returncode) < 0: #pragma: nocover + raise gitversionhelper.unknownGITError(p.stderr) + + if raw: + return p.stdout + lines = p.stdout.splitlines() + return [line.rstrip() for line in lines if line.rstrip()] + +class gitversionhelperException(Exception): + """ + general Module Exception + """ + +class gitversionhelper: # pylint: disable=too-few-public-methods + """ + main gitversionhelper class + """ + class wrongArguments(gitversionhelperException): + """ + wrong argument generic exception + """ + + class unknownGITError(gitversionhelperException): + """ + unknown git error generic exception + """ + + class unknownGITFatalError(unknownGITError): + """ + unknown fatal git error generic exception + """ + + class repository: + """ + class containing methods focusing on repository + """ + class repositoryException(gitversionhelperException): + """ + generic repository exeption + """ + + class notAGitRepository(repositoryException): + """ + not a git repository exception + """ + + class repositoryDirty(repositoryException): + """ + dirty repository exception + """ + + @classmethod + def isDirty(cls) -> bool: + """ + check if the repository is in dirty state + Returns: + True if it is dirty + """ + return bool(_exec("git status --short")) + class commit: + """ + class containing methods focusing on commits + """ + __OptDict = {"same_branch": "same_branch", + "merged_output":"merged_output"} + + class commitException(gitversionhelperException): + """ + generic commit exception + """ + + class commitNotFound(commitException): + """ + tag not found exception + """ + + @classmethod + def getMessagesSinceTag(cls,tag:str,**kwargs) -> str: + """ + retrieve a commits message history from repository + from LastCommit to the given tag + Keyword Arguments: + merged_output: output one single merged string + same_branch(bool): force searching only in the same branch + Returns: + the commit message + """ + current_commit_id=cls.getLast(**kwargs) + tag_commit_id=cls.getFromTag(tag) + + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + commits = _exec(f"git rev-list --first-parent --ancestry-path {tag_commit_id}..{current_commit_id}") + else: + commits = _exec(f"git rev-list --ancestry-path {tag_commit_id}..{current_commit_id}") + result=[] + for commit in commits: + result.append(cls.getMessage(commit)) + + if ((cls.__OptDict["merged_output"] in kwargs) and (kwargs[cls.__OptDict["merged_output"]] is True)): + print("JOIN") + return os.linesep.join(result) + return result + + @classmethod + def getMessage(cls, commit_hash:str) -> str: + """ + retrieve a commit message from repository + Args: + commit_hash: id of the commit + Returns: + the commit message + """ + try: + res=_exec(f"git log -z --pretty=\"tformat:%B%-C()\" -n 1 {commit_hash}",None,True).rstrip('\x00') + except gitversionhelper.unknownGITFatalError as _e: + raise cls.commitNotFound("no commit found in commit history") from _e + + return res.replace('\r\n','\n').replace('\n','\r\n') + + @classmethod + def getFromTag(cls,tag:str) -> str: + """ + retrieve a commit from repository associated to a tag + Args: + tag: tag of the commit + Returns: + the commit Id + """ + try: + res=_exec(f"git rev-list -n 1 {tag}") + except gitversionhelper.unknownGITFatalError as _e: + raise cls.commitNotFound("no commit found in commit history") from _e + if len(res)==0: + raise cls.commitNotFound("no commit found in commit history") + return res[0] + + @classmethod + def getLast(cls,**kwargs) -> str: + """ + retrieve last commit from repository + Keyword Arguments: + same_branch(bool): force searching only in the same branch + Returns: + the commit Id + """ + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + try: + res = _exec("git rev-parse HEAD") + except gitversionhelper.unknownGITFatalError as _e: + raise cls.commitNotFound("no commit found in commit history") from _e + else: + res = _exec("git for-each-ref --sort=-committerdate refs/heads/ --count 1 --format=\"%(objectname)\"") + + if len(res)==0: + raise cls.commitNotFound("no commit found in commit history") + return res[0] + + class tag: + """ + class containing methods focusing on tags + """ + __OptDict = {"same_branch": "same_branch"} + __validGitTagSort=["","v:refname","-v:refname","taggerdate","committerdate","-taggerdate","-committerdate"] + + class tagException(gitversionhelperException): + """ + generic tag exception + """ + + class tagNotFound(tagException): + """ + tag not found exception + """ + + class moreThanOneTag(tagException): + """ + more than one tag exception + """ + + @classmethod + def getTags(cls,sort:str = "taggerdate",**kwargs) -> list[str|None]: + """ + retrieve all tags from a repository + Args: + sort: sorting constraints (git format) + Returns: + the tags list + """ + + if sort not in cls.__validGitTagSort: + raise gitversionhelper.wrongArguments("sort option not in allowed list") + + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + currentBranch = _exec("git rev-parse --abbrev-ref HEAD") + return list(reversed(_exec(f"git tag --merged {currentBranch[0]} --sort={sort}"))) + return list(reversed(_exec(f"git tag -l --sort={sort}"))) + + @classmethod + def getLastTag(cls,**kwargs) -> str | None: + """ + retrieve the last tag from a repository + Keyword Arguments: + same_branch(bool): force searching only in the same branch + Returns: + the tag + """ + if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)): + res = _exec("git describe --tags --first-parent --abbrev=0") + else: + res = _exec("git rev-list --tags --date-order --max-count=1") + if len(res)==1: + res = _exec(f"git describe --tags {res[0]}") + + if len(res)==0: + raise cls.tagNotFound("no tag found in commit history") + if len(res)!=1: #pragma: nocover + raise cls.moreThanOneTag("multiple tags on same commit is unsupported") + return res[0] + + @classmethod + def getDistanceFromTag(cls,tag:str=None,**kwargs) -> int: + """ + retrieve the distance between HEAD and tag in the repository + Arguments: + tag: reference tag, if None the most recent one will be used + Keyword Arguments: + same_branch(bool): force searching only in the same branch + Returns: + the tag + """ + if tag is None: + tag = cls.getLastTag(**kwargs) + return int(_exec(f"git rev-list {tag}..HEAD --count")[0]) + + class version: + """ + class containing methods focusing on versions + """ + __OptDict = { "version_std": "version_std", + "formated_output": "formated_output", + "output_format": "output_format", + "ignore_unknown_tags": "ignore_unknown_tags"} + DefaultInputFormat = "Auto" + VersionStds = { "SemVer" : { "regex" : r"^(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)\.(?P0|[1-9]\d*)"\ + r"(?:-(?P(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)"\ + r"(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?"\ + r"(?:\+(?P[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$", + "regex_preversion_num": r"(?:\.)(?P(?:\d+(?!\w))+)", + "regex_build_num" : r"(?:\.)(?P(?:\d+(?!\w))+)" + }, + "PEP440" : { "regex" : packaging_VERSION_PATTERN, + "Auto" : None + } + } + __versionReseted = False + class versionException(gitversionhelperException): + """ + generic version exception + """ + + class noValidVersion(versionException): + """ + no valid version found exception + """ + + class PreAndPostVersionUnsupported(versionException): + """ + pre and post release can not be present at the same time + """ + + class MetaVersion: + """ + generic version object + """ + + __OptDict = { "bump_type": "bump_type", + "bump_dev_strategy": "bump_dev_strategy", + "formated_output": "formated_output"} + DefaultBumpType = "patch" + BumpTypes = ["major","minor","patch","dev"] + DefaultBumpDevStrategy = "post" + BumpDevStrategys = ["post","pre-patch","pre-minor","pre-major"] + + version_std: str = "None" + major: int = 0 + minor: int = 1 + patch: int = 0 + pre_count:int = 0 + post_count:int = 0 + raw:str = "0.1.0" + + def __init__(self,version_std,major=0,minor=1,patch=0,pre_count=0,post_count=0,raw="0.1.0"): #pylint: disable=R0913 + self.version_std = version_std + self.major = major + self.minor = minor + self.patch = patch + self.pre_count = pre_count + self.post_count = post_count + self.raw = raw + + @classmethod + def _getBumpDevStrategy(cls,**kwargs) -> str: + """ + get selected bump_dev_strategy + Keyword Arguments: + bump_dev_strategy(str): the given bump_dev_strategy (can be None) + Returns: + Kwargs given bump_dev_strategy or the default one. + """ + BumpDevStrategy = cls.DefaultBumpDevStrategy + if cls.__OptDict["bump_dev_strategy"] in kwargs: + if kwargs[cls.__OptDict["bump_dev_strategy"]] in cls.BumpDevStrategys: + BumpDevStrategy = kwargs[cls.__OptDict["bump_dev_strategy"]] + else: + raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") + return BumpDevStrategy + + @classmethod + def _getBumpType(cls,**kwargs) -> str: + """ + get selected bump_type + Keyword Arguments: + bump_type(str): the given bump_type (can be None) + Returns: + Kwargs given bump_type or the default one. + """ + BumpType = cls.DefaultBumpType + if cls.__OptDict["bump_type"] in kwargs: + if kwargs[cls.__OptDict["bump_type"]] in cls.BumpTypes: + BumpType = kwargs[cls.__OptDict["bump_type"]] + else: + raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['bump_type']} requested") + return BumpType + + def bump(self,amount:int=1,**kwargs) -> gitversionhelper.version.MetaVersion | str : # pylint: disable=R0912 + """ + bump the version to the next one + Keyword Arguments: + bump_type(str): the given bump_type (can be None) + bump_dev_strategy(str): the given bump_dev_strategy (can be None) + Returns: + the bumped version + """ + BumpType = self._getBumpType(**kwargs) + BumpDevStrategy=self._getBumpDevStrategy(**kwargs) + _v=copy(self) + + if BumpType == "dev": + if BumpDevStrategy == "post": + if _v.pre_count > 0: + _v.pre_count = _v.pre_count + amount + else: + _v.post_count = _v.post_count + amount + #elif BumpDevStrategy in ["pre-patch","pre-minor","pre-major"]: + else: + if _v.post_count > 0: + _v.post_count = _v.post_count + amount + else: + if _v.pre_count == 0: + if BumpDevStrategy == "pre-patch": + _v.patch = _v.patch + 1 + elif BumpDevStrategy == "pre-minor": + _v.minor = _v.minor + 1 + _v.patch = 0 + #elif BumpDevStrategy == "pre-major": + else: + _v.major = _v.major + 1 + _v.minor = 0 + _v.patch = 0 + _v.pre_count = _v.pre_count + amount + else: + if BumpType == "major": + _v.major = _v.major + amount + elif BumpType == "minor": + _v.minor = _v.minor + amount + #elif BumpType == "patch": + else: + _v.patch = _v.patch + amount + _v.pre_count=0 + _v.post_count=0 + _v.raw=_v.doFormatVersion(**kwargs) + + if ((self.__OptDict["formated_output"] in kwargs) and (kwargs[self.__OptDict["formated_output"]] is True)): + return _v.doFormatVersion(**kwargs) + return _v + + def doFormatVersion(self,**kwargs) -> str: + """ + output a formated version string + Keyword Arguments: + output_format: output format to render ("Auto" or "PEP440" or "SemVer") + Returns: + formated version string + """ + return gitversionhelper.version.doFormatVersion(self,**kwargs) + + @classmethod + def _getVersionStd(cls,**kwargs) -> str: + """ + get selected version_std + Keyword Arguments: + version_std(str): the given version_std (can be None) + Returns: + Kwargs given version_std or the default one. + """ + VersionStd = cls.DefaultInputFormat + if cls.__OptDict["version_std"] in kwargs: + if kwargs[cls.__OptDict["version_std"]] in cls.VersionStds: + VersionStd = kwargs[cls.__OptDict["version_std"]] + else: + raise gitversionhelper.wrongArguments(f"invalid {cls.__OptDict['version_std']} requested") + return VersionStd + + @classmethod + def getCurrentVersion(cls,**kwargs) -> MetaVersion | str : + """ + get the current version or bump depending of repository state + Keyword Arguments: + version_std(str): the given version_std (can be None) + same_branch(bool): force searching only in the same branch + formated_output(bool) : output a formated version string + bump_type(str): the given bump_type (can be None) + bump_dev_strategy(str): the given bump_dev_strategy (can be None) + Returns: + the last version + """ + if gitversionhelper.repository.isDirty() is not False: + raise gitversionhelper.repository.repositoryDirty( "The repository is dirty and a current version" \ + " can not be generated.") + saved_kwargs = copy(kwargs) + if "formated_output" in kwargs: + del saved_kwargs["formated_output"] + + _v = cls.getLastVersion(**saved_kwargs) + + if not cls.__versionReseted: + amount = gitversionhelper.tag.getDistanceFromTag(_v.raw,**kwargs) + _v = _v.bump(amount,**saved_kwargs) + + if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): + return _v.doFormatVersion(**kwargs) + return _v + + @classmethod + def _parseTag(cls,tag,**kwargs): # pylint: disable=R0914, R0912, R0915 + """get the last version from tags + Arguments: + tag: the tag to be parsed + Keyword Arguments: + version_std(str): the given version_std (can be None) + ignore_unknown_tags(bool): skip tags with not decoded versions (default to False) + Returns: + the last version + """ + VersionStd = cls._getVersionStd(**kwargs) + bAutoVersionStd = False + if VersionStd == "Auto": + bAutoVersionStd = True + bFound = False + if VersionStd == "SemVer" or (bAutoVersionStd is True) : + _r=re.compile(r"^\s*" + cls.VersionStds["SemVer"]["regex"] + r"\s*$", re.VERBOSE | \ + re.IGNORECASE) + _m = re.match(_r,tag) + if not _m: + pass + else: + major, minor, patch = int(_m.group("major")),\ + int(_m.group("minor")),\ + int(_m.group("patch")) + + pre_count = 0 + if _pre := _m.group("prerelease"): + if (_match := re.search (cls.VersionStds["SemVer"]["regex_preversion_num"],_pre)) is not None: + pre_count = int(_match.group("num")) + else: + pre_count = 1 + + post_count = 0 + if _post := _m.group("buildmetadata"): + if (_match := re.search (cls.VersionStds["SemVer"]["regex_build_num"],_post)) is not None: + post_count = int(_match.group("num")) + else: + post_count = 1 + bFound = True + VersionStd = "SemVer" + + if VersionStd == "PEP440" or ( (bAutoVersionStd is True) and (bFound is not True)): + _r=re.compile(r"^\s*" + cls.VersionStds["PEP440"]["regex"] + r"\s*$", re.VERBOSE | \ + re.IGNORECASE) + _m = re.match(_r,tag) + if not _m: + pass + else: + ver=_m.group("release").split(".") + ver += ["0"] * (3 - len(ver)) + ver[0]=int(ver[0]) + ver[1]=int(ver[1]) + ver[2]=int(ver[2]) + major, minor, patch = tuple(ver) + pre_count = int(_m.group("pre_n")) if _m.group("pre_n") else 0 + post_count = int(_m.group("post_n2")) if _m.group("post_n2") else 0 + bFound = True + VersionStd = "PEP440" + + if not bFound : + raise gitversionhelper.version.noValidVersion("no valid version found in tags") + + if pre_count > 0 and post_count > 0: + raise cls.PreAndPostVersionUnsupported("can not parse a version with both pre" \ + " and post release number.") + return cls.MetaVersion(VersionStd, major, minor, patch, pre_count, post_count, tag) + + @classmethod + def getLastVersion(cls,**kwargs) -> MetaVersion | str : # pylint: disable=R0914, R0912, R0915 + """get the last version from tags + Keyword Arguments: + version_std(str): the given version_std (can be None) + same_branch(bool): force searching only in the same branch + formated_output(bool) : output a formated version string + ignore_unknown_tags(bool): skip tags with not decoded versions (default to False) + Returns: + the last version + """ + lastTag=cls.MetaVersion.raw + cls.__versionReseted = False + try: + lastTag = gitversionhelper.tag.getLastTag(**kwargs) + except gitversionhelper.tag.tagNotFound: + logging.warning('tag not found, reseting versionning') + cls.__versionReseted = True + + _v=None + try: + _v=cls._parseTag(lastTag,**kwargs) + except gitversionhelper.version.noValidVersion as _ex: + if ((cls.__OptDict["ignore_unknown_tags"] in kwargs) and (kwargs[cls.__OptDict["ignore_unknown_tags"]] is True)): + tags = gitversionhelper.tag.getTags(sort= "taggerdate",**kwargs) + _v = None + for _tag in tags: + try: + _v=cls._parseTag(_tag,**kwargs) + break + except gitversionhelper.version.noValidVersion: + continue + if _v is None: + raise gitversionhelper.version.noValidVersion() from _ex + + if ((cls.__OptDict["formated_output"] in kwargs) and (kwargs[cls.__OptDict["formated_output"]] is True)): + return _v.doFormatVersion(**kwargs) + return _v + + @classmethod + def doFormatVersion(cls,inputversion:MetaVersion,**kwargs) -> str: + """ + output a formated version string + Keyword Arguments: + output_format: output format to render ("Auto" or "PEP440" or "SemVer") + Args: + inputversion: version to be rendered + Returns: + formated version string + """ + + VersionStd = cls._getVersionStd(**kwargs) + if VersionStd=="Auto" : + VersionStd = inputversion.version_std + + OutputFormat = None + revpattern="" + revcount="" + post_count = inputversion.post_count + pre_count = inputversion.pre_count + patch = inputversion.patch + + if cls.__OptDict["output_format"] in kwargs: + OutputFormat=kwargs[cls.__OptDict["output_format"]] + + if OutputFormat is None: + OutputFormat = "{major}.{minor}.{patch}{revpattern}{revcount}" + if post_count > 0 and pre_count > 0: + raise gitversionhelper.version.PreAndPostVersionUnsupported("cannot output a version with both pre " \ + "and post release number.") + if VersionStd == "PEP440": + if post_count > 0: + revpattern=".post" + revcount=f"{post_count}" + elif pre_count > 0: + revpattern=".pre" + revcount=f"{pre_count}" + #elif VersionStd == "SemVer": + else: + if post_count > 0: + revpattern="+post" + revcount=f".{post_count}" + elif pre_count > 0: + revpattern="-pre" + revcount=f".{pre_count}" + return OutputFormat.format( major=inputversion.major, \ + minor=inputversion.minor, \ + patch=patch, \ + revpattern=revpattern, \ + revcount=revcount) diff --git a/src/pygitversionhelper/test_module.py b/src/pygitversionhelper/test_module.py deleted file mode 100644 index 7a9bff5..0000000 --- a/src/pygitversionhelper/test_module.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# pygitversionhelper (c) by chacha -# -# pygitversionhelper is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -"""Phasellus tellus lectus, volutpat eu dapibus ut, suscipit vel augue. - -Tips: - Aliquam non leo vel libero sagittis viverra. Quisque lobortis nunc sit amet augue euismod laoreet. -Note: - Maecenas volutpat porttitor pretium. Aliquam suscipit quis nisi non imperdiet. -Note: - Vivamus et efficitur lorem, eget imperdiet tortor. Integer vel interdum sem. -""" - -from __future__ import annotations -from typing import TYPE_CHECKING - -if TYPE_CHECKING: # Only imports the below statements during type checking - pass - -def test_function(testvar: int) -> int: - """ A test function that return testvar+1 and print "Hello world !" - - Proin eget sapien eget ipsum efficitur mollis nec ac nibh. - - Note: - Morbi id lectus maximus, condimentum nunc eget, porta felis. In tristique velit tortor. - - Args: - testvar: any integer - - Returns: - testvar+1 - """ - print("Hello world !") - return testvar+1 diff --git a/test/test_gitversionhelper.py b/test/test_gitversionhelper.py new file mode 100644 index 0000000..ed0af02 --- /dev/null +++ b/test/test_gitversionhelper.py @@ -0,0 +1,1336 @@ +# pygitversionhelper (c) by chacha +# +# pygitversionhelper is licensed under a +# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. +# +# You should have received a copy of the license along with this +# work. If not, see . + +import unittest + +import tempfile +import os +import pathlib +import re +import copy +import time +import subprocess + +print(__name__) +print(__package__) + +from src import pygitversionhelper + +HelperRegex=r"^(?P\d+)\.(?P\d+)\.(?P\d+)([\.\-\+])?(?:.*)?" + +class Test_gitversionhelper(unittest.TestCase): + def setUp(self): + self.TmpWorkingDir=tempfile.TemporaryDirectory() + self.TmpWorkingDirPath=pathlib.Path(self.TmpWorkingDir.name) + os.chdir(self.TmpWorkingDirPath) + os.system("git init") + os.system('git config --local user.name "john doe"') + os.system('git config --local user.email "john@doe.org"') + + def _test_version_readback(self,tag:str,**kwargs): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + + os.system("git add .") + os.system("git commit -m \"first commit\"") + os.system(f"git tag {tag}") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(**kwargs) + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self.assertEqual(_v.raw, tag) + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + + + _m = re.match(HelperRegex, tag) + self.assertEqual(int(_m.group("MAJ")),_v.major) + self.assertEqual(int(_m.group("MIN")),_v.minor) + self.assertEqual(int(_m.group("PATCH")),_v.patch) + + return _v + + def _test_version_format(self,_v:pygitversionhelper.gitversionhelper.version.MetaVersion,tag:str,**kwargs): + _f=_v.doFormatVersion(**kwargs) + self.assertRegex(_f,HelperRegex) + self.assertEqual(_f, tag) + + def _test_version_readback_simple(self,tag:str,**kwargs): + _v=self._test_version_readback(tag,**kwargs) + self._test_version_format(_v,tag,**kwargs) + + def test_nominal__version__formated_output(self): + _v = pygitversionhelper.gitversionhelper.version.MetaVersion("PEP440", + 1, + 0, + 0, + 0, + 0, + "1.0.0") + self.assertEqual("1.0.1", _v.bump(formated_output=True)) + self.assertEqual("2.0.0", _v.bump(formated_output=True,bump_type="major")) + + def test_nominal__version__auto_1(self): + self._test_version_readback_simple("0.0.1") + def test_nominal__version__auto_2(self): + self._test_version_readback_simple("0.0.2") + def test_nominal__version__auto_3(self): + self._test_version_readback_simple("0.1.0") + def test_nominal__version__auto_4(self): + self._test_version_readback_simple("0.1.1") + def test_nominal__version__auto_5(self): + self._test_version_readback_simple("1.0.0") + def test_nominal__version__auto_6(self): + self._test_version_readback_simple("1.1.0") + def test_nominal__version__auto_7(self): + self._test_version_readback_simple("1.2.0") + def test_nominal__version__auto_8(self): + self._test_version_readback_simple("1.1.1") + def test_nominal__version__auto_9(self): + self._test_version_readback_simple("1.2.1") + def test_nominal__version__auto_PEP440_post(self): + self._test_version_readback_simple("1.2.1.post1") + def test_nominal__version__auto_PEP440_pre(self): + self._test_version_readback_simple("1.2.1.pre1") + def test_nominal__version__auto_PEP440_post_2(self): + self._test_version_readback_simple("1.2.1.post10") + def test_nominal__version__auto_PEP440_pre_2(self): + self._test_version_readback_simple("1.2.1.pre10") + + def test_nominal__version__auto_SemVer_post(self): + self._test_version_readback_simple("1.2.1+post.1") + def test_nominal__version__auto_SemVer_pre(self): + self._test_version_readback_simple("1.2.1-pre.1") + def test_nominal__version__auto_SemVer_post_2(self): + self._test_version_readback_simple("1.2.1+post.10") + def test_nominal__version__auto_Semver_pre_2(self): + self._test_version_readback_simple("1.2.1-pre.10") + + def test_nominal__version__PEP440_1(self): + self._test_version_readback_simple("0.0.1",version_std="PEP440") + def test_nominal__version__PEP440_2(self): + self._test_version_readback_simple("0.0.2",version_std="PEP440") + def test_nominal__version__PEP440_3(self): + self._test_version_readback_simple("0.1.0",version_std="PEP440") + def test_nominal__version__PEP440_4(self): + self._test_version_readback_simple("0.1.1",version_std="PEP440") + def test_nominal__version__PEP440_5(self): + self._test_version_readback_simple("1.0.0",version_std="PEP440") + def test_nominal__version__PEP440_6(self): + self._test_version_readback_simple("1.1.0",version_std="PEP440") + def test_nominal__version__PEP440_7(self): + self._test_version_readback_simple("1.2.0",version_std="PEP440") + def test_nominal__version__PEP440_8(self): + self._test_version_readback_simple("1.1.1",version_std="PEP440") + def test_nominal__version__PEP440_9(self): + self._test_version_readback_simple("1.2.1",version_std="PEP440") + def test_nominal__version__PEP440_post(self): + self._test_version_readback_simple("1.2.1.post1",version_std="PEP440") + def test_nominal__version__PEP440_pre(self): + self._test_version_readback_simple("1.2.1.pre1",version_std="PEP440") + def test_nominal__version__PEP440_post_2(self): + self._test_version_readback_simple("1.2.1.post10",version_std="PEP440") + def test_nominal__version__PEP440_pre_2(self): + self._test_version_readback_simple("1.2.1.pre10",version_std="PEP440") + + def test_nominal__version__SemVer_1(self): + self._test_version_readback_simple("0.0.1",version_std="SemVer") + def test_nominal__version__SemVer_2(self): + self._test_version_readback_simple("0.0.2",version_std="SemVer") + def test_nominal__version__SemVer_3(self): + self._test_version_readback_simple("0.1.0",version_std="SemVer") + def test_nominal__version__SemVer_4(self): + self._test_version_readback_simple("0.1.1",version_std="SemVer") + def test_nominal__version__SemVer_5(self): + self._test_version_readback_simple("1.0.0",version_std="SemVer") + def test_nominal__version__SemVer_6(self): + self._test_version_readback_simple("1.1.0",version_std="SemVer") + def test_nominal__version__SemVer_7(self): + self._test_version_readback_simple("1.2.0",version_std="SemVer") + def test_nominal__version__SemVer_8(self): + self._test_version_readback_simple("1.1.1",version_std="SemVer") + def test_nominal__version__SemVer_9(self): + self._test_version_readback_simple("1.2.1",version_std="SemVer") + def test_nominal__version__SemVer_post(self): + self._test_version_readback_simple("1.2.1+post.1",version_std="SemVer") + def test_nominal__version__SemVer_pre(self): + self._test_version_readback_simple("1.2.1-pre.1",version_std="SemVer") + def test_nominal__version__SemVer_post_2(self): + self._test_version_readback_simple("1.2.1+post.10",version_std="SemVer") + def test_nominal__version__SemVer_pre_2(self): + self._test_version_readback_simple("1.2.1-pre.10",version_std="SemVer") + + def test_nominal__version__post_PEP440_to_SemVer(self): + _v=self._test_version_readback("1.2.1.post10",version_std="PEP440") + self._test_version_format(_v,"1.2.1+post.10",version_std="SemVer") + + def test_nominal__version__post_SemVer_to_PEP440(self): + _v=self._test_version_readback("1.2.1+post.10",version_std="SemVer") + self._test_version_format(_v,"1.2.1.post10",version_std="PEP440") + + def test_nominal__version__pre_PEP440_to_SemVer(self): + _v=self._test_version_readback("1.2.1.pre10",version_std="PEP440") + self._test_version_format(_v,"1.2.1-pre.10",version_std="SemVer") + + def test_nominal__version__pre_SemVer_to_PEP440(self): + _v=self._test_version_readback("1.2.1-pre.10",version_std="SemVer") + self._test_version_format(_v,"1.2.1.pre10",version_std="PEP440") + + def test_nominal__version__post_SemVer_nonum(self): + _v=self._test_version_readback("1.2.1+post",version_std="SemVer") + self._test_version_format(_v,"1.2.1+post.1",version_std="SemVer") + + def test_nominal__version__post_SemVer_nonum_random(self): + _v=self._test_version_readback("1.2.1+toto",version_std="SemVer") + self._test_version_format(_v,"1.2.1+post.1",version_std="SemVer") + + def test_nominal__version__pre_SemVer_nonum(self): + _v=self._test_version_readback("1.2.1-pre",version_std="SemVer") + self._test_version_format(_v,"1.2.1-pre.1",version_std="SemVer") + + def test_nominal__version__pre_SemVer_nonum_random(self): + _v=self._test_version_readback("1.2.1-toto",version_std="SemVer") + self._test_version_format(_v,"1.2.1-pre.1",version_std="SemVer") + + def test_nominal__version___pump_SemVer(self): + _v = self._test_version_readback("1.0.0",version_std="SemVer") + + _v = _v.bump() + self.assertIsInstance(_v.raw, str) + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + self.assertEqual(_v.raw, "1.0.1") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 0) + self.assertEqual(_v.patch, 1) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.0.1") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "1.0.2") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 0) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.0.2") + + _v = _v.bump(bump_type="minor") + self.assertEqual(_v.raw, "1.1.2") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.1.2") + + _v = _v.bump(bump_type="major") + self.assertEqual(_v.raw, "2.1.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.2") + + _v = _v.bump(bump_type="dev") + self.assertEqual(_v.raw, "2.1.2+post.1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 1) + self.assertEqual(_v.doFormatVersion(), "2.1.2+post.1") + + _v = _v.bump(bump_type="dev") + self.assertEqual(_v.raw, "2.1.2+post.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 2) + self.assertEqual(_v.doFormatVersion(), "2.1.2+post.2") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "2.1.3") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 3) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.3") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.4-pre.1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 1) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4-pre.1") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.4-pre.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 2) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4-pre.2") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="post") + self.assertEqual(_v.raw, "2.1.4-pre.3") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 3) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4-pre.3") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "2.1.5") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.5") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="post") + self.assertEqual(_v.raw, "2.1.5+post.1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 1) + self.assertEqual(_v.doFormatVersion(), "2.1.5+post.1") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.5+post.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 2) + self.assertEqual(_v.doFormatVersion(), "2.1.5+post.2") + + def test_nominal__version___pump_PEP440(self): + _v = self._test_version_readback("1.0.0",version_std="PEP440") + + _v = _v.bump() + self.assertIsInstance(_v.raw, str) + self.assertIsInstance(_v.major, int) + self.assertIsInstance(_v.minor, int) + self.assertIsInstance(_v.patch, int) + self.assertIsInstance(_v.pre_count, int) + self.assertIsInstance(_v.post_count, int) + self.assertEqual(_v.raw, "1.0.1") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 0) + self.assertEqual(_v.patch, 1) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.0.1") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "1.0.2") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 0) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.0.2") + + _v = _v.bump(bump_type="minor") + self.assertEqual(_v.raw, "1.1.2") + self.assertEqual(_v.major, 1) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "1.1.2") + + _v = _v.bump(bump_type="major") + self.assertEqual(_v.raw, "2.1.2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.2") + + _v = _v.bump(bump_type="dev") + self.assertEqual(_v.raw, "2.1.2.post1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 1) + self.assertEqual(_v.doFormatVersion(), "2.1.2.post1") + + _v = _v.bump(bump_type="dev") + self.assertEqual(_v.raw, "2.1.2.post2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 2) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 2) + self.assertEqual(_v.doFormatVersion(), "2.1.2.post2") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "2.1.3") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 3) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.3") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.4.pre1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 1) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4.pre1") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.4.pre2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 2) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4.pre2") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="post") + self.assertEqual(_v.raw, "2.1.4.pre3") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 4) + self.assertEqual(_v.pre_count, 3) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.4.pre3") + + _v = _v.bump(bump_type="patch") + self.assertEqual(_v.raw, "2.1.5") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 0) + self.assertEqual(_v.doFormatVersion(), "2.1.5") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="post") + self.assertEqual(_v.raw, "2.1.5.post1") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 1) + self.assertEqual(_v.doFormatVersion(), "2.1.5.post1") + + _v = _v.bump(bump_type="dev",bump_dev_strategy="pre-patch") + self.assertEqual(_v.raw, "2.1.5.post2") + self.assertEqual(_v.major, 2) + self.assertEqual(_v.minor, 1) + self.assertEqual(_v.patch, 5) + self.assertEqual(_v.pre_count, 0) + self.assertEqual(_v.post_count, 2) + self.assertEqual(_v.doFormatVersion(), "2.1.5.post2") + + def test_nominal__version___SemVer_zeroRev(self): + _v=self._test_version_readback("0.0.0",version_std="SemVer") + self._test_version_format(_v,"0.0.0",version_std="SemVer") + + def test_nominal__version___PEP440_zeroRev(self): + _v=self._test_version_readback("0.0.0",version_std="PEP440") + self._test_version_format(_v,"0.0.0",version_std="PEP440") + + + def test_nominal__version___PEP440_noRev_noTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + + os.system("git add .") + os.system("git commit -m \"first commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + + def test_nominal__version___SemVer_noRev_noTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + + os.system("git add .") + os.system("git commit -m \"first commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="SemVer") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.0",version_std="SemVer") + self.assertEqual(_v.raw, "0.1.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + + def test_nominal__version___AUTO_noRev_noTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + + os.system("git add .") + os.system("git commit -m \"first commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.0") + self.assertEqual(_v.raw, "0.1.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + + def test_nominal__version___AUTO_bump_commits(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"first commit\"") + os.system(f"git tag 0.2.0") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.2.0") + self.assertEqual(_v.raw, "0.2.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,0) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue22") + os.system("git add .") + os.system("git commit -m \"2nd commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.2.1") + self.assertEqual(_v.raw, "0.2.1") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,1) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,0) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue223") + os.system("git add .") + os.system("git commit -m \"3rd commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue224") + os.system("git add .") + os.system("git commit -m \"4th commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.2.3") + self.assertEqual(_v.raw, "0.2.3") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,3) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,0) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue225") + os.system("git add .") + os.system("git commit -m \"5th commit\"") + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self.assertIsInstance(_v.raw, str) + self._test_version_format(_v,"0.2.0+post.4") + self.assertEqual(_v.raw, "0.2.0+post.4") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,4) + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-patch") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.2.1-pre.4") + self.assertEqual(_v.raw, "0.2.1-pre.4") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,1) + self.assertEqual(_v.pre_count,4) + self.assertEqual(_v.post_count,0) + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-minor") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.3.0-pre.4") + self.assertEqual(_v.raw, "0.3.0-pre.4") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,3) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,4) + self.assertEqual(_v.post_count,0) + + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-major") + + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"1.0.0-pre.4") + self.assertEqual(_v.raw, "1.0.0-pre.4") + self.assertEqual(_v.major,1) + self.assertEqual(_v.minor,0) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,4) + self.assertEqual(_v.post_count,0) + + def test_nominal__version___custom_format(self): + _v=self._test_version_readback("0.1.1",version_std="PEP440") + + self.assertEqual("V_0_1_1____",_v.doFormatVersion(output_format="V_{major}_{minor}_{patch}____{revcount}")) + self.assertEqual("V_0_1",_v.doFormatVersion(output_format="V_{major}_{minor}")) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue225") + os.system("git add .") + os.system("git commit -m \"5th commit\"") + + self.assertEqual("V_1_0",pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-major").doFormatVersion(output_format="V_{major}_{minor}")) + self.assertEqual("V_1_0",pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="dev",bump_dev_strategy="pre-major",output_format="V_{major}_{minor}",formated_output=True)) + + + def test_nominal__git__emptyrepo(self): + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.0") + self.assertEqual(_v.raw, "0.1.0") + + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + self.assertEqual(_v.pre_count,0) + self.assertEqual(_v.post_count,0) + + def test_defect__git__dirty(self): + _v=self._test_version_readback("0.1.1",version_std="PEP440") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue225") + + with self.assertRaises(pygitversionhelper.gitversionhelper.repository.repositoryDirty) : + pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + + def test_defect__version_post_and_pre_output(self): + _v = pygitversionhelper.gitversionhelper.version.MetaVersion("PEP440", + 0, + 0, + 1, + 1, + 1, + "0.0.1.pre1.post1") + with self.assertRaises(pygitversionhelper.gitversionhelper.version.PreAndPostVersionUnsupported) : + _v.doFormatVersion() + + _v = pygitversionhelper.gitversionhelper.version.MetaVersion("SemVer", + 0, + 0, + 1, + 1, + 1, + "0.0.1-pre.1+post.1") + with self.assertRaises(pygitversionhelper.gitversionhelper.version.PreAndPostVersionUnsupported) : + _v.doFormatVersion() + + def test_defect__version_post_and_pre_parse(self): + with self.assertRaises(pygitversionhelper.gitversionhelper.version.PreAndPostVersionUnsupported) : + pygitversionhelper.gitversionhelper.version._parseTag("0.0.1.pre1.post1") + + + def test_defect__git__wrongargument_sortargs(self): + with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) : + pygitversionhelper.gitversionhelper.tag.getTags(sort="toto") + + def test_defect__git__notagfound(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"first commit\"") + with self.assertRaises(pygitversionhelper.gitversionhelper.tag.tagNotFound) : + pygitversionhelper.gitversionhelper.tag.getLastTag() + + """ This test is impossible to do because current implementation can only return one tag + def test_defect__git_multipletagsfound(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"first commit\"") + os.system(f"git tag 0.1.0") + os.system(f"git tag 0.2.0") + with self.assertRaises(pygitversionhelper.gitversionhelper.tag.moreThanOneTag) : + pygitversionhelper.gitversionhelper.tag.getLastTag(same_branch=True) + """ + + def test_defect__wrongargument_bump_type(self): + _v=self._test_version_readback("0.1.1",version_std="PEP440") + with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) : + pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_type="toto") + + def test_defect__wrongargument_bump_dev_strategy(self): + _v=self._test_version_readback("0.1.1",version_std="PEP440") + with self.assertRaises(pygitversionhelper.gitversionhelper.wrongArguments) : + pygitversionhelper.gitversionhelper.version.getCurrentVersion(bump_dev_strategy="toto") + + def test_nominal__tag__getDistanceFromTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.2.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + + self.assertEqual(2,pygitversionhelper.gitversionhelper.tag.getDistanceFromTag()) + self.assertEqual(4,pygitversionhelper.gitversionhelper.tag.getDistanceFromTag("0.2.0")) + + def test_nominal__tag__getTags(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.2.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.1") + + self.assertEqual(set(["0.3.0","0.2.0","0.3.1"]),set(pygitversionhelper.gitversionhelper.tag.getTags())) + + def test_nominal__tag__getTags_two_branch(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.2.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.0") + + os.system("git checkout -b dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.1") + + self.assertEqual(set(["0.3.0","0.2.0","0.3.1"]),set(pygitversionhelper.gitversionhelper.tag.getTags())) + + def test_nominal__tag__getTags_two_branch_samebranch(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.2.0") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.0") + + os.system("git checkout -b dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.1") + + self.assertEqual(set(["0.3.0","0.2.0","0.3.1"]),set(pygitversionhelper.gitversionhelper.tag.getTags(same_branch=True))) + + os.system("git switch master") + + self.assertEqual(set(["0.3.0","0.2.0"]),set(pygitversionhelper.gitversionhelper.tag.getTags(same_branch=True))) + + os.system("git switch dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.3.2") + + self.assertEqual(set(["0.3.0","0.2.0","0.3.1","0.3.2"]),set(pygitversionhelper.gitversionhelper.tag.getTags(same_branch=True))) + self.assertEqual(set(["0.3.0","0.2.0","0.3.1","0.3.2"]),set(pygitversionhelper.gitversionhelper.tag.getTags())) + + os.system("git switch master") + + self.assertEqual(set(["0.3.0","0.2.0"]),set(pygitversionhelper.gitversionhelper.tag.getTags(same_branch=True))) + self.assertEqual(set(["0.3.0","0.2.0","0.3.1","0.3.2"]),set(pygitversionhelper.gitversionhelper.tag.getTags())) + + def test_nominal__tag__getLastTag_two_branches(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"first commit\"") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"2nd commit\"") + os.system(f"git tag 0.1.0") + + os.system("git checkout -b dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"3rd commit\"") + os.system(f"git tag 0.2.0") + + """ + print("===") + os.system(f"git status") + print("===") + os.system(f"git describe --tags --abbrev=0") + print("===") + os.system(f"git rev-list --all") + print("===") + os.system(f"git rev-list --tags") + print("===") + os.system(f"git log --oneline --decorate=short") + print("===") + os.system(f"git describe --tags") + print("===") + """ + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.2.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.2.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,2) + self.assertEqual(_v.patch,0) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"3rd commit\"") + os.system(f"git tag 0.3.0") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.3.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.3.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,3) + self.assertEqual(_v.patch,0) + + os.system("git switch master") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.3.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.3.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,3) + self.assertEqual(_v.patch,0) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440",same_branch=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + + os.system("git merge --no-ff dev -m \"merge dev into master\"") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440",same_branch=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,0) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.3.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.3.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,3) + self.assertEqual(_v.patch,0) + + os.system(f"git tag 0.4.0") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440",same_branch=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.4.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.4.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,4) + self.assertEqual(_v.patch,0) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(version_std="PEP440") + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.4.0",version_std="PEP440") + self.assertEqual(_v.raw, "0.4.0") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,4) + self.assertEqual(_v.patch,0) + + def test_defect__tag__invalidtag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"2nd commit\"") + os.system(f"git tag INVALIDTAG") + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + + def test_defect__tag__invalidtag_inbetween(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue1") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.0.1") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTAG") + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.0.1",version_std="PEP440") + self.assertEqual(_v.raw, "0.0.1") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,0) + self.assertEqual(_v.patch,1) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTAG2") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTA3") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTA4") + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.0.1",version_std="PEP440") + self.assertEqual(_v.raw, "0.0.1") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,0) + self.assertEqual(_v.patch,1) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.1.2") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.2",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.2") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,2) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.2",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.2") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,2) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue6") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag INVALIDTA5") + + with self.assertRaises(pygitversionhelper.gitversionhelper.version.noValidVersion) : + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.2",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.2") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,2) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue7") + os.system("git add .") + os.system("git commit -m \"commit\"") + os.system(f"git tag 0.1.3") + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion() + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.3",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.3") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,3) + + _v = pygitversionhelper.gitversionhelper.version.getLastVersion(ignore_unknown_tags=True) + self.assertIsInstance(_v, pygitversionhelper.gitversionhelper.version.MetaVersion) + self._test_version_format(_v,"0.1.3",version_std="PEP440") + self.assertEqual(_v.raw, "0.1.3") + self.assertEqual(_v.major,0) + self.assertEqual(_v.minor,1) + self.assertEqual(_v.patch,3) + + def test_nominal__commit_getLast(self): + # sleeps are needed because commit date have a 1-sec accuracy :-/ + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + initial_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + second_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + self.assertNotEqual(initial_commit,second_commit) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + third_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + self.assertNotEqual(initial_commit,third_commit) + self.assertNotEqual(second_commit,third_commit) + + + os.system("git checkout -b dev") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + fourth_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + self.assertNotEqual(initial_commit,fourth_commit) + self.assertNotEqual(second_commit,fourth_commit) + self.assertNotEqual(third_commit,fourth_commit) + + os.system("git switch master") + + fourth2_commit = pygitversionhelper.gitversionhelper.commit.getLast() + self.assertEqual(fourth2_commit,fourth_commit) + + fourth3_commit = pygitversionhelper.gitversionhelper.commit.getLast(same_branch=True) + + self.assertNotEqual(fourth3_commit,fourth_commit) + self.assertEqual(fourth3_commit,third_commit) + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue5") + os.system("git add .") + os.system("git commit -m \"commit\"") + time.sleep(1) + + fifth_commit = pygitversionhelper.gitversionhelper.commit.getLast() + self.assertNotEqual(fifth_commit,fourth3_commit) + + os.system("git switch dev") + + fifth2_commit = pygitversionhelper.gitversionhelper.commit.getLast() + self.assertEqual(fifth2_commit,fifth_commit) + + fifth2_commit = pygitversionhelper.gitversionhelper.commit.getLast(same_branch=True) + self.assertEqual(fifth2_commit,fourth_commit) + + def test_defect__commit_notfound(self): + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getLast() + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getLast(same_branch=True) + + def test_nominal__commit_getFromTag(self): + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + + initial_commit = pygitversionhelper.gitversionhelper.commit.getLast() + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + os.system("git commit -m \"commit2\"") + os.system(f"git tag TAG") + + second_commit = pygitversionhelper.gitversionhelper.commit.getLast() + self.assertNotEqual(second_commit,initial_commit) + second_commit2 = pygitversionhelper.gitversionhelper.commit.getFromTag("TAG") + self.assertEqual(second_commit,second_commit2) + self.assertNotEqual(second_commit2,initial_commit) + + def test_defect__commit_notfound2(self): + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getFromTag("TAG") + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system("git commit -m \"commit\"") + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getFromTag("TAG") + + os.system(f"git tag OTHER_TAG") + + with self.assertRaises(pygitversionhelper.gitversionhelper.commit.commitNotFound) : + pygitversionhelper.gitversionhelper.commit.getFromTag("TAG") + + def test_nominal__commit_getMessage(self): + commit_message="AAAABBB CCCCDDDD".replace('\r\n','\n').replace('\n','\r\n') + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + os.system(f"git commit -m \"{commit_message}\"") + commit = pygitversionhelper.gitversionhelper.commit.getLast() + message = pygitversionhelper.gitversionhelper.commit.getMessage(commit) + self.assertEqual(message,commit_message) + + def test_nominal__commit_getMessage2(self): + commit_message="""AAAABBB + CCCCDDDD + -f dfsds dfsdfs $""".replace('\r\n','\n').replace('\n','\r\n') + + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message) + subprocess.run(cmd,text=True,check=True) + + commit = pygitversionhelper.gitversionhelper.commit.getLast() + message = pygitversionhelper.gitversionhelper.commit.getMessage(commit) + + self.assertEqual(message,commit_message) + + def test_nominal__commit_getMessagesSinceLastTag(self): + commit_message1="1.1 update this"+ os.linesep+\ + "1.1 fix that" + os.linesep+\ + "1.1 test" + commit_message1=commit_message1.replace('\r\n','\n').replace('\n','\r\n') + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message1) + subprocess.run(cmd,text=True,check=True) + os.system(f"git tag 0.1.1") + + commit_message2="2.1 update this"+ os.linesep+\ + "2.1 fix that" + os.linesep+\ + "2.1 test" + commit_message2=commit_message2.replace('\r\n','\n').replace('\n','\r\n') + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue2") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message2) + subprocess.run(cmd,text=True,check=True) + + commit_message3="3.1 update this"+ os.linesep+\ + "3.1 fix that" + os.linesep+\ + "3.1 test" + commit_message3=commit_message3.replace('\r\n','\n').replace('\n','\r\n') + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue3") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message3) + subprocess.run(cmd,text=True,check=True) + + commit_message4="4.1 update this" + os.linesep+\ + "4.1 fix that" + os.linesep+\ + "4.1 test" + commit_message4=commit_message4.replace('\r\n','\n').replace('\n','\r\n') + with open("demofile.txt", "w+t") as tmpFile: + tmpFile.write("testvalue4") + os.system("git add .") + + cmd = "git commit -m".split() + cmd.append(commit_message4) + subprocess.run(cmd,text=True,check=True) + + res = pygitversionhelper.gitversionhelper.commit.getMessagesSinceTag("0.1.1") + self.assertEqual( [commit_message4,commit_message3,commit_message2],res) + + res = pygitversionhelper.gitversionhelper.commit.getMessagesSinceTag("0.1.1",merged_output=True) + self.assertEqual( os.linesep.join([commit_message4,commit_message3,commit_message2]),res) + + + def tearDown(self): + os.chdir("/") + +class Test_gitversionhelperNoRepo(unittest.TestCase): + def setUp(self): + self.TmpWorkingDir=tempfile.TemporaryDirectory() + self.TmpWorkingDirPath=pathlib.Path(self.TmpWorkingDir.name) + os.chdir(self.TmpWorkingDirPath) + + def test_defect__norepo(self): + with self.assertRaises(pygitversionhelper.gitversionhelper.repository.notAGitRepository) : + _v = pygitversionhelper.gitversionhelper.version.getCurrentVersion() + + def tearDown(self): + os.chdir("/") \ No newline at end of file diff --git a/test/test_test_module.py b/test/test_test_module.py deleted file mode 100644 index add530e..0000000 --- a/test/test_test_module.py +++ /dev/null @@ -1,32 +0,0 @@ -# pygitversionhelper (c) by chacha -# -# pygitversionhelper is licensed under a -# Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Unported License. -# -# You should have received a copy of the license along with this -# work. If not, see . - -import unittest -from io import StringIO -from contextlib import redirect_stdout,redirect_stderr - -print(__name__) -print(__package__) - -from src import pygitversionhelper - -class Testtest_module(unittest.TestCase): - def test_version(self): - self.assertNotEqual(pygitversionhelper.__version__,"?.?.?") - - def test_test_module(self): - - with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(StringIO()) as capted_stderr: - self.assertEqual(pygitversionhelper.test_function(41),42) - - self.assertEqual(len(capted_stderr.getvalue()),0) - self.assertEqual(capted_stdout.getvalue().strip(),"Hello world !") - self.assertEqual(len(capted_stderr.getvalue()),0) - - - \ No newline at end of file