Compare commits

...

66 Commits

Author SHA1 Message Date
cclecle
8bdc425b3c updates 2023-03-22 23:13:40 +00:00
cclecle
4701015ba8 update name 2023-03-22 23:06:20 +00:00
cclecle
bf9b4f2207 update from pychangelogfactory 2023-03-22 23:05:20 +00:00
cclecle
31df26eb48 fix: twine cmd line 2023-03-22 09:43:00 +00:00
cclecle
7fa5de67a6 remove mermaid caus pyaml is having issue.. 2023-03-22 08:52:17 +00:00
cclecle
99ee668fe0 add mermaid 2023-03-22 01:34:07 +00:00
cclecle
e13561007b add mermaid2 and markdownextradata doc exts 2023-03-22 01:30:17 +00:00
cclecle
fe0bb13d86 revert yo mkdocs-with-pdf 2023-03-22 01:18:28 +00:00
cclecle
4fc9032cd0 test 2023-03-22 01:15:13 +00:00
cclecle
72e43e7c1c disable mermaid/markdown 2023-03-22 00:42:21 +00:00
cclecle
6d7411693e update installation doc
mkdocs options
fix jenkins
2023-03-22 00:31:07 +00:00
cclecle
1338ef5f8e fix usernamePassword in jenkins 2023-03-21 23:56:48 +00:00
cclecle
da411f51e3 add black formating 2023-03-21 23:46:24 +00:00
cclecle
e9559e97fb fix: pypi upload 2023-03-21 23:38:02 +00:00
cclecle
158b85e29c add pypi publish 2023-03-21 23:27:28 +00:00
cclecle
d4545f999b test: fix doc 2023-03-20 09:04:41 +00:00
cclecle
21fc9e7c52 fix: remove tag_regex from toml -> we want the full version 2023-03-20 01:49:01 +00:00
cclecle
13a584c7d9 fix missing packaging 2023-03-20 01:44:37 +00:00
cclecle
6dfe0682d7 fix jenkins script 2023-03-20 01:09:32 +00:00
cclecle
d15b495f0a test local gitversionhelper import 2023-03-20 01:07:14 +00:00
cclecle
c9df0e7409 fix: doc 2023-03-20 00:28:19 +00:00
cclecle
866e8ff7ff test 2023-03-20 00:25:11 +00:00
cclecle
d786d27cd7 fix: ident 2023-03-20 00:19:57 +00:00
cclecle
fb2f3eb412 escape toml 2023-03-20 00:16:11 +00:00
cclecle
d93fd3286c test: tag_regex to extract verison only 2023-03-20 00:03:58 +00:00
cclecle
f361a5189a test doc 2023-03-19 23:09:25 +00:00
cclecle
3751ef1c93 test 2023-03-19 22:55:23 +00:00
cclecle
d5e003c86c update Jenkinsfile 2023-03-19 22:40:38 +00:00
cclecle
8b2b0ca07f update jenkinsfile 2023-03-19 22:31:15 +00:00
cclecle
ab1a69b8f8 cleaning jenkins file
updating documentation in toml
2023-03-19 22:08:22 +00:00
cclecle
a564e04219 fix: remove setuptools-git-versioning stuff 2023-03-19 22:03:09 +00:00
cclecle
a29c1778fc test: fall back to setuptools_scm 2023-03-19 21:57:15 +00:00
cclecle
2ee687959e fix: typo 2023-03-19 21:01:45 +00:00
cclecle
e226f16292 fix: typo 2023-03-19 20:54:02 +00:00
cclecle
8ea6b43a73 fix: git remote credentials 2023-03-19 20:50:50 +00:00
cclecle
cb213df6b6 fix: workaround for setuptools-git-versioning version guess 2023-03-19 20:44:31 +00:00
cclecle
2c87f5488d test: bump dev version 2023-03-19 20:05:32 +00:00
cclecle
348204abb5 fix: project username 2023-03-19 19:59:01 +00:00
cclecle
48114149fb fix: typo in jenkins pipeline file 2023-03-19 19:54:46 +00:00
cclecle
5eb2f1c5cf fix: pipeline 2023-03-19 19:50:23 +00:00
cclecle
65927077aa fix: git credentials for pushing 2023-03-19 19:49:57 +00:00
cclecle
0c02512814 fix: remove branch on git push (useless) 2023-03-19 19:35:37 +00:00
cclecle
9f900ba597 fix git tag cmd 2023-03-19 19:31:37 +00:00
cclecle
97612703b7 fix git username/address in jenkinsfile 2023-03-19 19:26:04 +00:00
cclecle
5bb8b35c73 update jenkinsfile 2023-03-19 19:21:48 +00:00
cclecle
a6c2513d9f fix fstrings 2023-03-19 18:55:58 +00:00
cclecle
70ef90a529 fix jenkinsfile python 2023-03-19 18:53:52 +00:00
cclecle
f728842a5a random fixes 2023-03-19 18:51:35 +00:00
cclecle
4837a99ac6 fix deps 2023-03-19 18:46:52 +00:00
cclecle
3e130e6bdf revert to full setuptools-git-versioning in toml file 2023-03-19 18:42:24 +00:00
cclecle
d7fbf52647 test 2023-03-19 18:23:42 +00:00
cclecle
f5c97757b6 make setuptools-git-versioning use pygitversionhelper
+ add getCurrentFormatedVersion()
2023-03-19 18:22:26 +00:00
cclecle
3c0e5bebc2 update doc 2023-03-19 18:02:02 +00:00
cclecle
c5962d533b fix tag -> version api 2023-03-19 17:59:27 +00:00
cclecle
e9e25793d8 fix doc bullets 2023-03-19 17:57:28 +00:00
cclecle
17f74d6675 test gitversionhelper calls 2023-03-19 17:57:20 +00:00
cclecle
264c51de2e update CI/CD 2023-03-19 17:51:11 +00:00
cclecle
ac942480cb feature: add log-line in pipeline 2023-03-19 10:34:34 +00:00
cclecle
be9ef684e4 update jenkinsFile => no error when master build are skipped because of
no-tag
2023-03-19 10:26:23 +00:00
cclecle
792666c6ec fix: rename hash -> commit_hash to avoid using builtin symbol 2023-03-19 10:17:58 +00:00
cclecle
2951e70c47 fix: escapes git strings options 2023-03-19 10:15:23 +00:00
cclecle
63b3f25b33 fix quality warning + commit messages unittest 2023-03-19 10:03:50 +00:00
cclecle
cefa964a3a add commit class 2023-03-19 09:52:42 +00:00
cclecle
38cde9d700 reword 2023-03-18 21:13:11 +00:00
cclecle
fff52596b1 update doc 2023-03-18 21:06:39 +00:00
cclecle
3ce09a0194 fix typo 2023-03-18 21:04:03 +00:00
9 changed files with 1634 additions and 862 deletions

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>gitversionhelper</name>
<name>pygitversionhelper</name>
<comment></comment>
<projects>
</projects>

188
Jenkinsfile vendored
View File

@@ -6,6 +6,8 @@
// You should have received a copy of the license along with this
// work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
// configurable settings:
// use to send email if workflow problem
def _MaintainerName = "CHACHA"
@@ -17,12 +19,14 @@ def _bPreRelease = false
// toogle Draft flag on Gitea release system => If False, TAG is not created
def _bDraft = false
// release content / changelog management
def _bAutoChangelog = false //Not supported yet
def _bAutoChangelog = true //Not supported yet
def _ReleaseContent_Title = "_CI/CD Automatic Release_"
def bPushMasterOnPypi = true
// full rebuild toogle
def _bFullRebuilt = true
def _MkDocsWebURL = "dabauto--mkdocs-web.dmz.chacha.home/mkdocs-web/"
def _MkDocsWebCredentials = "2c5b684e-3787-4b37-8aca-b3dd4a383fe2"
def _PypiCredentials = "Pypi"
// commands Helper: /!\ Made for GITEA /!\
String determineRepoUserName() {
@@ -94,12 +98,12 @@ pipeline {
PY_PROJECT_VERSION = "__NOTSET__"
PY_PROJECT_VERSION_STRIPPED = "__NOTSET__"
}
stages {
stage("Prepare") {
steps {
script{
script {
if (_bFullRebuilt) {
// start by cleaning the workspace (not using cleanWs() because we want to keep the directory itself)
// => this is needed to fetch it again with custom options
@@ -108,8 +112,7 @@ pipeline {
else {
sh("find ~/. -name . ! -path './TEST_ENV/*' ! -path './BUILD_ENV/*' -o -prune -exec rm -rf -- {} +")
}
if(_GIT_BRANCH!="master")
{
if(_GIT_BRANCH!="master") {
_bPreRelease = true
}
}
@@ -120,51 +123,114 @@ pipeline {
echo("_GITEA_BASE_URL: . . . . . . . . $_GITEA_BASE_URL")
echo("GIT_COMMIT:. . . . . . . . . . . $GIT_COMMIT ")
echo("_PROJECT_USER_NAME:. . . . . . . $_PROJECT_USER_NAME")
echo("_GITEA_PROJECT_NAME: . . . . . . $_PROJECT_NAME")
echo("_PROJECT_NAME: . . . . . . . . . $_PROJECT_NAME")
echo("_MaintainerEmail:. . . . . . . . $_MaintainerEmail")
echo("_MaintainerName:. . . . . . . . $_MaintainerName")
sh("virtualenv --pip=embed --setuptools=embed --wheel=embed --no-periodic-update --activators bash,python BUILD_ENV")
sh("virtualenv --pip=embed --setuptools=embed --wheel=embed --no-periodic-update --activators bash,python TEST_ENV")
sh("virtualenv --pip=embed --setuptools=embed --wheel=embed --no-periodic-update --activators bash,python TOOLS_ENV")
sh(". ~/BUILD_ENV/bin/activate && pip install --upgrade setuptools build pip copier jinja2-slug toml \"setuptools-git-versioning<2\"")
sh(". ~/BUILD_ENV/bin/activate && pip install --upgrade setuptools build pip copier jinja2-slug toml")
sh(". ~/TOOLS_ENV/bin/activate && pip install simple_rest_client requests twine")
script {
if(_PROJECT_NAME!="pygitversionhelper") {
sh(". ~/TOOLS_ENV/bin/activate && pip install pygitversionhelper")
}
else
{
//TODO: need to install pygitversionhelper deps from a better way...
sh(". ~/TOOLS_ENV/bin/activate && pip install packaging")
}
}
sh("git config --global user.email $_MaintainerEmail")
sh("git config --global user.name $_MaintainerName")
sh("git config --global init.defaultBranch master")
}
}
stage("GetCode") {
steps {
dir("gitrepo") {
// manually checkout the repository, with All branches and tags
// manually checkout the repository, with All branches and tags
// => because we might need them for version and changelog computing
checkout([ $class: "GitSCM",
branches: [[name: GIT_BRANCH]],
extensions: [[$class: "CloneOption", noTags: false, shallow: false, depth: 0, reference: '']],
userRemoteConfigs: [[credentialsId: _SCMCredentials, url: GIT_URL]]])
script{
if(_GIT_BRANCH=="master")
{
if(sh(returnStdout: true, script: "git tag --points-at HEAD").trim().isEmpty())
{
error("master push/merge must have an explicit tag release number")
script {
withCredentials([usernamePassword(credentialsId: _SCMCredentials, passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
sh("git remote set-url origin https://${GIT_USERNAME}:${GIT_PASSWORD}@chacha.ddns.net/gitea/${_PROJECT_USER_NAME}/${_PROJECT_NAME}.git")
}
if(_GIT_BRANCH=="master") {
if(sh(returnStdout: true, script: "git tag --points-at HEAD").trim().isEmpty()) {
BUMPED_VERSION = sh(script: """#!/bin/sh -
|. ~/TOOLS_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|import re
|
|try:
| from pygitversionhelper import gitversionhelper
|except ImportError:
| from src.pygitversionhelper import gitversionhelper
|
|lastcommit=gitversionhelper.commit.getLast(same_branch=True)
|msg=gitversionhelper.commit.getMessage(lastcommit)
|
|_match=re.search(r"\\s*(?:#)?\\s*(?<=new-tag:)(?:\\s*)(?P<TAG>\\S*)",msg)
|print(_match.group("TAG"),end="")
|
|__EOWRAPPER__
""".stripMargin(),
returnStdout: true).trim()
if(BUMPED_VERSION.isEmpty()) {
echo "master push/merge must have an explicit tag release number, stopping pipeline"
currentBuild.getRawBuild().getExecutor().doStop()
}
else {
echo "new-tag requested in commit message: $BUMPED_VERSION"
sh("git tag $BUMPED_VERSION")
sh("git push origin --tags")
}
}
}
// using git to get the latest tag on this branch
def latestTag = sh(returnStdout: true, script: "git tag --sort=-creatordate | head -n 1").trim()
latestTag = sh(script: """#!/bin/sh -
|. ~/TOOLS_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|try:
| from pygitversionhelper import gitversionhelper
|except ImportError:
| from src.pygitversionhelper import gitversionhelper
|
|print(gitversionhelper.tag.getLastTag(same_branch=True),end ="")
|
|__EOWRAPPER__
""".stripMargin(),
returnStdout: true)
echo("latestTag:. . . . . . . . . . . . $latestTag ")
// using setuptools_git_versioning to get the generated version number based on Git tags and logs
// TODO: read dev_template from toml
// get current (or bumped) version number from git history
PY_PROJECT_VERSION = sh(script: """#!/bin/sh -
|. ~/BUILD_ENV/bin/activate
|. ~/TOOLS_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|from setuptools_git_versioning import version_from_git
|try:
| from pygitversionhelper import gitversionhelper
|except ImportError:
| from src.pygitversionhelper import gitversionhelper
|
|print(str(version_from_git(tag_filter="^\\d+\\.\\d+\\.\\d+\$",dev_template = "{tag}.post{ccount}")),end ="")
|print(gitversionhelper.version.getCurrentVersion(formated_output=True,version_std="PEP440",bump_type="dev",bump_dev_strategy="post"),end ="")
|
|__EOWRAPPER__
""".stripMargin(),
@@ -172,16 +238,18 @@ pipeline {
echo("PY_PROJECT_VERSION: . . . . . . . . . $PY_PROJECT_VERSION")
PY_PROJECT_VERSION_STRIPPED=ExtractBaseVersion(PY_PROJECT_VERSION)
// Manually pushing a new tag with version string guessed by gitversionhelper
// because setuptools-git-versioning / setuptools_scm cant fing tag on other branches, so will guess a wrong version without this tag.
if(latestTag!=PY_PROJECT_VERSION) {
sh("git tag $PY_PROJECT_VERSION")
sh("git push origin --tags")
}
// specific handling to test the template itself
// => little hacky... creating a new git repo with a commit/tag corresponding to HEAD of the official one
if(_PROJECT_NAME=="pyChaChaDummyProject") //specific case to test the template itself
{
sh("git config --global user.email $_MaintainerEmail")
sh("git config --global user.name $_MaintainerName")
if(_PROJECT_NAME=="pyChaChaDummyProject") { //specific case to test the template itself
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__'
@@ -240,7 +308,7 @@ pipeline {
steps {
// no need for a build-env: setuptools is already creating one
dir("gitrepo") {
script{
script {
// actually doing the package build
sh(". ~/BUILD_ENV/bin/activate && python -m build .")
}
@@ -269,16 +337,16 @@ pipeline {
}
}
post {
always {
dir("gitrepo") {
publishHTML([
reportDir: "helpers-results/quality_check",
reportFiles: "report.html",
reportName: "quality-report",
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true])
}
always {
dir("gitrepo") {
publishHTML([
reportDir: "helpers-results/quality_check",
reportFiles: "report.html",
reportName: "quality-report",
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true])
}
}
}
}
@@ -388,20 +456,27 @@ pipeline {
def GITEA_LOGIN_TOKEN=credentials("GiteaCHACHAPush")
}
steps {
sh("python3 -m pip install simple_rest_client requests")
dir("gitrepo") {
script {
def CurrentDateTime=java.time.LocalDateTime.now()
withCredentials([string( credentialsId: _MkDocsWebCredentials,variable: 'MKDOCSTOKEN' )])
{
sh(script: """#!/usr/bin/env python3
|from simple_rest_client.api import API
|from simple_rest_client.resource import Resource
withCredentials([string( credentialsId: _MkDocsWebCredentials,variable: 'MKDOCSTOKEN' )]) {
sh(script: """#!/bin/sh -
|. ~/TOOLS_ENV/bin/activate
|exec python - << '__EOWRAPPER__'
|
|import json
|import glob
|import requests
|import shutil
|
|from simple_rest_client.api import API
|from simple_rest_client.resource import Resource
|
|try:
| from pygitversionhelper import gitversionhelper
|except ImportError:
| from src.pygitversionhelper import gitversionhelper
|
|from urllib.parse import urljoin
|
|class GiteaRepoCommits(Resource):
@@ -478,9 +553,18 @@ pipeline {
|response=requests.post("http://${_MkDocsWebURL}/API.php?REQ=pushDoc",data=reqData,files=files)
|if response.status_code != 200:
| raise RuntimeError(f"Wrong server response: {response.status_code}")
|
""".stripMargin())
|
|__EOWRAPPER__
""".stripMargin())
}
if((_GIT_BRANCH=="master") && (bPushMasterOnPypi)) {
withCredentials([usernamePassword( credentialsId: _PypiCredentials, passwordVariable: 'PYPI_PASSWORD', usernameVariable: 'PYPI_USERNAME')]) {
sh(script: """#!/bin/sh -
|. ~/TOOLS_ENV/bin/activate
|exec twine upload -u ${PYPI_USERNAME} -p ${PYPI_PASSWORD} --non-interactive --disable-progress-bar dist/*
""".stripMargin())
}
}
}
}
}

View File

@@ -3,9 +3,12 @@
![](docs-static/Library.jpg)
#pyGitVersionHelper
# pyGitVersionHelper
_A tiny library to help versioning management of git python projects_
Because a good developer is a lazy developer and version management in CI/CD can be very time consuming.
a tiny library to help versioning management of git python project
Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitversionhelper/{{branch}}/latest/).
@@ -13,20 +16,20 @@ Checkout [Latest Documentation](https://chacha.ddns.net/mkdocs-web/chacha/pygitv
- list tags
- get last tag
- get last version
- get current version (bump)
- get current version (bumped)
- convert / switch from SemVer to PEP440 (both ways)
- automatic version format detection (SemVer by default)
# Options:
## 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
- configurable default bump type: major, minor, patch or dev
- configurable default bump strategy: post, pre-patch, pre-minor, pre-major
- ignore non-version tag
- force version format
# Process:
- CI/CD developpment: Gitea / Jenkins + few python libs
- Generated documentation through mkdocs
## 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

View File

@@ -1,29 +1,35 @@
# Usage
## Installation
From master repository:
From pypi repository (prefered):
python -m pip install pygitversionhelper
From downloaded .whl file:
python -m pip install pygitversionhelper-<VERSION>-py3-none-any.whl
From master git repository:
python -m pip install git+https://chacha.ddns.net/gitea/chacha/pygitversionhelper.git@master
From local .whl file:
python -m pip install pygitversionhelper-<VERSION>-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:
[optionnal] If you need to catch exception from this module:
#from pygitversionhelper import gitversionhelperException
## Basic API
All the API commands are static and so it is not needed to create instantiate any object.
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.
@@ -33,18 +39,20 @@ One easy way to change directory:
os.chdir("<YOUR DIRECTORY>")
### 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):
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):
List all tags [using git refname order]:
for tag in gitversionhelper.tag.getTags("v:refname"):
print(f"found tag: {tag}")
@@ -53,7 +61,7 @@ Get the last tag:
print(f"most recent repository tag: {gitversionhelper.tag.getLastTag()}")
Get the last tag (only on same branch):
Get the last tag [only on same branch]:
print(f"most recent repository tag: {gitversionhelper.tag.getLastTag(same_branch=True)}")
@@ -62,32 +70,47 @@ 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):
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 MetaVersion object]:
print(f"most recent repository version: {gitversionhelper.version.getLastVersion()}")
Get the last found version in the repository (return formated string):
Get the last found version in the repository [return formated string]:
print(f"most recent repository version: {gitversionhelper.tag.getLastVersion(formated_output=True)}")
print(f"most recent repository version: {gitversionhelper.version.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, including bumped one if the last one is not tagged (return MetaVersion object):
* 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
print(f"most recent repository version: {gitversionhelper.tag.getCurrentVersion()}")
Get the current version of the repository, automatically bump it if the last one is not tagged [returns MetaVersion object]:
print(f"current repository version: {gitversionhelper.version.getCurrentVersion()}")
Or with formated output:
print(f"current repository version: {gitversionhelper.version.getCurrentVersion(formated_output=True)}")
Typical usage in CI/CD env:
bumped_version = gitversionhelper.version.getCurrentVersion( formated_output=True, \
version_std="PEP440", \
bump_type="dev", \
bump_dev_strategy="post")
print(f"current repository version: {bumped_version}")
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
* 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:
@@ -97,9 +120,12 @@ A version object can also be manually formated:
gitversionhelper.version.doFormatVersion(_version)
kwargs available to those function:
- output_format: string to choose a rendering format ("Auto","PEP440" or "SemVer")
- output_format: string to choose a rendering format ["Auto","PEP440" or "SemVer"]
##Limitations
- 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
## 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

View File

@@ -6,57 +6,87 @@
# You should have received a copy of the license along with this
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
docs_dir: docs
site_name: pygitversionhelper
site_url: https://chacha.ddns.net/mkdocs-web/chacha/pygitversionhelper/latest/
site_url: 'https://chacha.ddns.net/mkdocs-web/chacha/pygitversionhelper/latest/'
site_description: pygitversionhelper
site_author: chacha
repo_url: https://chacha.ddns.net/gitea/chacha/pygitversionhelper
site_author: ChaCha
repo_url: 'https://chacha.ddns.net/gitea/chacha/pygitversionhelper'
use_directory_urls: false
copyright: CC BY-NC-SA 4.0
theme:
name: material
features:
- navigation.instant
- navigation.tracking
- navigation.tabs
- navigation.tabs.sticky
- toc.integrate
- navigation.top
- navigation.instant
- navigation.tracking
- navigation.tabs
- navigation.tabs.sticky
- toc.integrate
- navigation.top
palette:
- media: '(prefers-color-scheme: dark)'
scheme: slate
toggle:
icon: material/brightness-4
name: Switch to system preference
- media: (prefers-color-scheme)
toggle:
icon: material/brightness-auto
name: Switch to light mode
- media: '(prefers-color-scheme: light)'
scheme: default
toggle:
icon: material/brightness-7
name: Switch to dark mode
- media: '(prefers-color-scheme: dark)'
scheme: slate
toggle:
icon: material/brightness-4
name: Switch to system preference
- media: (prefers-color-scheme)
toggle:
icon: material/brightness-auto
name: Switch to light mode
- media: '(prefers-color-scheme: light)'
scheme: default
toggle:
icon: material/brightness-7
name: Switch to dark mode
plugins:
- search
- localsearch
- autorefs
- mkdocstrings:
default_handler: python
handlers:
python:
selection:
filters:
- '!^_(?!_init__)'
inherited_members: true
rendering:
show_root_heading: false
show_root_toc_entry: false
show_root_full_path: false
show_if_no_docstring: true
show_signature_annotations: true
show_source: false
heading_level: 2
group_by_category: true
show_category_heading: true
- search
- markdownextradata
- mermaid2
- localsearch
- autorefs
- mkdocstrings:
default_handler: python
handlers:
python:
selection:
filters:
- '!^_(?!_init__)'
inherited_members: true
rendering:
show_root_heading: false
show_root_toc_entry: false
show_root_full_path: false
show_if_no_docstring: true
show_signature_annotations: true
show_source: false
heading_level: 2
group_by_category: true
show_category_heading: true
markdown_extensions:
- def_list
- tables
- attr_list
- abbr
- pymdownx.betterem:
smart_enable: all
- pymdownx.caret
- pymdownx.critic
- pymdownx.details
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.keys
- pymdownx.mark
- pymdownx.progressbar
- pymdownx.smartsymbols
- pymdownx.tasklist:
custom_checkbox: true
- pymdownx.tilde
- footnotes
extra:
branch: master
repository: pygitversionhelper

View File

@@ -7,13 +7,12 @@
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
[build-system]
requires = ["setuptools>=63", "wheel", "setuptools-git-versioning<2"]
requires = ["setuptools>=63", "wheel", "setuptools_scm"]
build-backend = "setuptools.build_meta"
[tool.setuptools-git-versioning]
enabled = true
dev_template = "{tag}.post{ccount}"
tag_filter = "^\\d+\\.\\d+\\.\\d+$"
[tool.setuptools_scm]
version_scheme= "post-release"
# tag_regex="^(?:v)?(?P<version>\\d+\\.\\d+\\.\\d+)([\\.\\-\\+])?(?:.*)?"
[project]
name = "pygitversionhelper"
@@ -36,6 +35,7 @@ classifiers = [
]
dependencies = [
'importlib-metadata; python_version<"3.9"',
'packaging'
]
dynamic = ["version"]
@@ -49,13 +49,9 @@ where = ["src"]
[tool.setuptools.package-data]
"pygitversionhelper.data" = ["*.*"]
#[tool.setuptools_scm]
#write_to = "src/pygitversionhelper/_version.py"
#version_scheme = "python-simplified-semver"
[project.urls]
Homepage = "https://chacha.ddns.net/gitea/chacha/pygitversionhelper"
Documentation = "https://chacha.ddns.net/gitea/chacha/pygitversionhelper/wiki"
Homepage = "https://chacha.ddns.net/gitea/chacha/pygitversionhelper/"
Documentation = "https://chacha.ddns.net/mkdocs-web/chacha/pygitversionhelper/master/latest/"
Tracker = "https://chacha.ddns.net/gitea/chacha/pygitversionhelper/issues"
[project.optional-dependencies]
@@ -63,7 +59,7 @@ test = ["junitparser>=2.8","junit2html>=30.1","xmlrunner>=1.7","myp
coverage-check = ["coverage>=7.0"]
quality-check = ["pylint>=2.15","pylint-json2html>=0.4","pandas>=1.5"]
type-check = ["mypy[reports]>=0.99" ]
doc-gen = ["mkdocs>=1.4.0", "mkdocs-material>=8.5", "mkdocs-localsearch>=0.9.0", "mkdocstrings[python]>=0.19", "mkdocs-with-pdf>=0.9.3","pyyaml>=6.0"]
doc-gen = ["mkdocs>=1.4.0", "mkdocs-material>=8.5", "mkdocs-localsearch>=0.9.0", "mkdocstrings[python]>=0.19", "mkdocs-with-pdf>=0.9.3","pyyaml>=6.0","pymdown-extensions>=9","mkdocs-markdownextradata-plugin","mkdocs-mermaid2-plugin"]
#[project.scripts]
#my-script = "my_package.module:function"

View File

@@ -5,7 +5,6 @@
#
# You should have received a copy of the license along with this
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
"""
This project try to help doing handy operations with git when
dealing with project versioning and tags on python project -
@@ -13,6 +12,7 @@ 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.
@@ -23,8 +23,7 @@ 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
Note: _Other Parameters_ are **kwargs
"""
from __future__ import annotations
@@ -37,7 +36,10 @@ import logging
from packaging.version import VERSION_PATTERN as packaging_VERSION_PATTERN
def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]:
def _exec(
cmd: str, root: str | os.PathLike | None = None, raw: bool = False
) -> list[str]:
"""
helper function to handle system cmd execution
Args:
@@ -45,27 +47,41 @@ def _exec(cmd: str, root: str | os.PathLike | None = None) -> list[str]:
root: root directory where the command need to be executed
Returns:
a list of command's return lines
"""
p = subprocess.run(cmd.split(), text=True, cwd=root, capture_output=True, check=False, timeout=2)
if re.search("not a git repository",p.stderr):
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
if re.search("fatal:", p.stderr): # pragma: nocover
raise gitversionhelper.unknownGITFatalError(p.stderr)
if int(p.returncode) < 0: #pragma: nocover
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
class gitversionhelper: # pylint: disable=too-few-public-methods
"""
main gitversionhelper class
"""
class wrongArguments(gitversionhelperException):
"""
wrong argument generic exception
@@ -85,6 +101,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
"""
class containing methods focusing on repository
"""
class repositoryException(gitversionhelperException):
"""
generic repository exeption
@@ -109,12 +126,137 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
"""
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"]
__validGitTagSort = [
"",
"v:refname",
"-v:refname",
"taggerdate",
"committerdate",
"-taggerdate",
"-committerdate",
]
class tagException(gitversionhelperException):
"""
@@ -132,7 +274,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
"""
@classmethod
def getTags(cls,sort:str = "taggerdate",**kwargs) -> list[str]:
def getTags(cls, sort: str = "taggerdate", **kwargs) -> list[str | None]:
"""
retrieve all tags from a repository
Args:
@@ -144,13 +286,19 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
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)):
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 --merged {currentBranch[0]} --sort={sort}")
)
)
return list(reversed(_exec(f"git tag -l --sort={sort}")))
@classmethod
def getLastTag(cls,**kwargs) -> str | None:
def getLastTag(cls, **kwargs) -> str | None:
"""
retrieve the last tag from a repository
Keyword Arguments:
@@ -158,21 +306,23 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
Returns:
the tag
"""
if ((cls.__OptDict["same_branch"] in kwargs) and (kwargs[cls.__OptDict["same_branch"]] is True)):
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:
if len(res) == 1:
res = _exec(f"git describe --tags {res[0]}")
if len(res)==0:
if len(res) == 0:
raise cls.tagNotFound("no tag found in commit history")
if len(res)!=1: #pragma: nocover
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:
def getDistanceFromTag(cls, tag: str = None, **kwargs) -> int:
"""
retrieve the distance between HEAD and tag in the repository
Arguments:
@@ -190,23 +340,27 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
"""
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"}
__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"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)"\
r"(?:-(?P<prerelease>(?: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<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$",
"regex_preversion_num": r"(?:\.)(?P<num>(?:\d+(?!\w))+)",
"regex_build_num" : r"(?:\.)(?P<num>(?:\d+(?!\w))+)"
},
"PEP440" : { "regex" : packaging_VERSION_PATTERN,
"Auto" : None
}
VersionStds = {
"SemVer": {
"regex": r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)"
r"(?:-(?P<prerelease>(?: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<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$",
"regex_preversion_num": r"(?:\.)(?P<num>(?:\d+(?!\w))+)",
"regex_build_num": r"(?:\.)(?P<num>(?:\d+(?!\w))+)",
},
"PEP440": {"regex": packaging_VERSION_PATTERN, "Auto": None},
}
__versionReseted = False
class versionException(gitversionhelperException):
"""
generic version exception
@@ -227,33 +381,44 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
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"]
__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"
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
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
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:
def _getBumpDevStrategy(cls, **kwargs) -> str:
"""
get selected bump_dev_strategy
Keyword Arguments:
@@ -263,14 +428,19 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
"""
BumpDevStrategy = cls.DefaultBumpDevStrategy
if cls.__OptDict["bump_dev_strategy"] in kwargs:
if kwargs[cls.__OptDict["bump_dev_strategy"]] in cls.BumpDevStrategys:
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")
raise gitversionhelper.wrongArguments(
f"invalid {cls.__OptDict['bump_type']} requested"
)
return BumpDevStrategy
@classmethod
def _getBumpType(cls,**kwargs) -> str:
def _getBumpType(cls, **kwargs) -> str:
"""
get selected bump_type
Keyword Arguments:
@@ -283,10 +453,14 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
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")
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
def bump(
self, amount: int = 1, **kwargs
) -> gitversionhelper.version.MetaVersion | str: # pylint: disable=R0912
"""
bump the version to the next one
Keyword Arguments:
@@ -296,8 +470,8 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
the bumped version
"""
BumpType = self._getBumpType(**kwargs)
BumpDevStrategy=self._getBumpDevStrategy(**kwargs)
_v=copy(self)
BumpDevStrategy = self._getBumpDevStrategy(**kwargs)
_v = copy(self)
if BumpType == "dev":
if BumpDevStrategy == "post":
@@ -305,7 +479,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
_v.pre_count = _v.pre_count + amount
else:
_v.post_count = _v.post_count + amount
#elif BumpDevStrategy in ["pre-patch","pre-minor","pre-major"]:
# elif BumpDevStrategy in ["pre-patch","pre-minor","pre-major"]:
else:
if _v.post_count > 0:
_v.post_count = _v.post_count + amount
@@ -316,7 +490,7 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
elif BumpDevStrategy == "pre-minor":
_v.minor = _v.minor + 1
_v.patch = 0
#elif BumpDevStrategy == "pre-major":
# elif BumpDevStrategy == "pre-major":
else:
_v.major = _v.major + 1
_v.minor = 0
@@ -327,18 +501,20 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
_v.major = _v.major + amount
elif BumpType == "minor":
_v.minor = _v.minor + amount
#elif BumpType == "patch":
# elif BumpType == "patch":
else:
_v.patch = _v.patch + amount
_v.pre_count=0
_v.post_count=0
_v.raw=_v.doFormatVersion(**kwargs)
_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)):
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:
def doFormatVersion(self, **kwargs) -> str:
"""
output a formated version string
Keyword Arguments:
@@ -346,10 +522,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
Returns:
formated version string
"""
return gitversionhelper.version.doFormatVersion(self,**kwargs)
return gitversionhelper.version.doFormatVersion(self, **kwargs)
@classmethod
def _getVersionStd(cls,**kwargs) -> str:
def _getVersionStd(cls, **kwargs) -> str:
"""
get selected version_std
Keyword Arguments:
@@ -362,11 +538,13 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
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")
raise gitversionhelper.wrongArguments(
f"invalid {cls.__OptDict['version_std']} requested"
)
return VersionStd
@classmethod
def getCurrentVersion(cls,**kwargs) -> MetaVersion | str :
def getCurrentVersion(cls, **kwargs) -> MetaVersion | str:
"""
get the current version or bump depending of repository state
Keyword Arguments:
@@ -379,8 +557,10 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
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.")
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"]
@@ -388,15 +568,25 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
_v = cls.getLastVersion(**saved_kwargs)
if not cls.__versionReseted:
amount = gitversionhelper.tag.getDistanceFromTag(_v.raw,**kwargs)
_v = _v.bump(amount,**saved_kwargs)
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)):
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
def getCurrentFormatedVersion(cls, **kwargs) -> str:
"""
Same as getCurrentVersion() with formated_output kwarg activated
"""
kwargs["formated_output"] = True
return cls.getCurrentVersion(kwargs)
@classmethod
def _parseTag(cls, tag, **kwargs): # pylint: disable=R0914, R0912, R0915
"""get the last version from tags
Arguments:
tag: the tag to be parsed
@@ -411,61 +601,84 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
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 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"))
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:
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:
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 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 = _m.group("release").split(".")
ver += ["0"] * (3 - len(ver))
ver[0]=int(ver[0])
ver[1]=int(ver[1])
ver[2]=int(ver[2])
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
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 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)
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
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)
@@ -475,36 +688,40 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
Returns:
the last version
"""
lastTag=cls.MetaVersion.raw
lastTag = cls.MetaVersion.raw
cls.__versionReseted = False
try:
lastTag = gitversionhelper.tag.getLastTag(**kwargs)
except gitversionhelper.tag.tagNotFound:
logging.warning('tag not found, reseting versionning')
logging.warning("tag not found, reseting versionning")
cls.__versionReseted = True
_v=None
_v = None
try:
_v=cls._parseTag(lastTag,**kwargs)
_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)
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)
_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)):
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:
def doFormatVersion(cls, inputversion: MetaVersion, **kwargs) -> str:
"""
output a formated version string
Keyword Arguments:
@@ -516,41 +733,45 @@ class gitversionhelper: # pylint: disable=too-few-public-methods
"""
VersionStd = cls._getVersionStd(**kwargs)
if VersionStd=="Auto" :
if VersionStd == "Auto":
VersionStd = inputversion.version_std
OutputFormat = None
revpattern=""
revcount=""
revpattern = ""
revcount = ""
post_count = inputversion.post_count
pre_count = inputversion.pre_count
patch = inputversion.patch
pre_count = inputversion.pre_count
patch = inputversion.patch
if cls.__OptDict["output_format"] in kwargs:
OutputFormat=kwargs[cls.__OptDict["output_format"]]
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":
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}"
revpattern = ".post"
revcount = f"{post_count}"
elif pre_count > 0:
revpattern=".pre"
revcount=f"{pre_count}"
#elif VersionStd == "SemVer":
revpattern = ".pre"
revcount = f"{pre_count}"
# elif VersionStd == "SemVer":
else:
if post_count > 0:
revpattern="+post"
revcount=f".{post_count}"
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)
revpattern = "-pre"
revcount = f".{pre_count}"
return OutputFormat.format(
major=inputversion.major,
minor=inputversion.minor,
patch=patch,
revpattern=revpattern,
revcount=revcount,
)

View File

@@ -4,4 +4,4 @@
# 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 <https://creativecommons.org/licenses/by-nc-sa/4.0/>.
# work. If not, see <https://creativecommons.org/licenses/by-nc-sa/4.0/>.

File diff suppressed because it is too large Load Diff