mirror of
https://github.com/TECHNOFAB11/bumpver.git
synced 2025-12-13 06:50:08 +01:00
112 lines
2.8 KiB
Python
112 lines
2.8 KiB
Python
|
|
# This file is part of the pycalver project
|
||
|
|
# https://github.com/mbarkhau/pycalver
|
||
|
|
#
|
||
|
|
# (C) 2018 Manuel Barkhau (@mbarkhau)
|
||
|
|
# SPDX-License-Identifier: MIT
|
||
|
|
#
|
||
|
|
# pycalver/vcs.py (this file) is based on code from the
|
||
|
|
# bumpversion project: https://github.com/peritus/bumpversion
|
||
|
|
# MIT License - (C) 2013-2014 Filip Noetzel
|
||
|
|
|
||
|
|
import os
|
||
|
|
import logging
|
||
|
|
import tempfile
|
||
|
|
import subprocess as sp
|
||
|
|
|
||
|
|
|
||
|
|
log = logging.getLogger("pycalver.vcs")
|
||
|
|
|
||
|
|
|
||
|
|
class WorkingDirectoryIsDirtyException(Exception):
|
||
|
|
|
||
|
|
def __init__(self, message):
|
||
|
|
self.message = message
|
||
|
|
|
||
|
|
|
||
|
|
class BaseVCS:
|
||
|
|
|
||
|
|
@classmethod
|
||
|
|
def commit(cls, message):
|
||
|
|
f = tempfile.NamedTemporaryFile("wb", delete=False)
|
||
|
|
f.write(message.encode("utf-8"))
|
||
|
|
f.close()
|
||
|
|
cmd = cls._COMMIT_COMMAND + [f.name]
|
||
|
|
env_items = list(os.environ.items()) + [(b"HGENCODING", b"utf-8")]
|
||
|
|
sp.check_output(cmd, env=dict(env_items))
|
||
|
|
os.unlink(f.name)
|
||
|
|
|
||
|
|
@classmethod
|
||
|
|
def is_usable(cls):
|
||
|
|
try:
|
||
|
|
return sp.call(
|
||
|
|
cls._TEST_USABLE_COMMAND,
|
||
|
|
stderr=sp.PIPE,
|
||
|
|
stdout=sp.PIPE,
|
||
|
|
) == 0
|
||
|
|
except OSError as e:
|
||
|
|
if e.errno == 2:
|
||
|
|
# mercurial is not installed then, ok.
|
||
|
|
return False
|
||
|
|
raise
|
||
|
|
|
||
|
|
@classmethod
|
||
|
|
def assert_nondirty(cls):
|
||
|
|
status_output = sp.check_output(cls._STATUS_COMMAND)
|
||
|
|
lines = [
|
||
|
|
line.strip()
|
||
|
|
for line in status_output.splitlines()
|
||
|
|
if not line.strip().startswith(b"??")
|
||
|
|
]
|
||
|
|
|
||
|
|
if lines:
|
||
|
|
cleaned_output = b"\n".join(lines)
|
||
|
|
cls_name = cls.__name__
|
||
|
|
raise WorkingDirectoryIsDirtyException(
|
||
|
|
f"{cls_name} working directory is not clean:\n{cleaned_output}"
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
class Git(BaseVCS):
|
||
|
|
|
||
|
|
_TEST_USABLE_COMMAND = ["git", "rev-parse", "--git-dir"]
|
||
|
|
_COMMIT_COMMAND = ["git", "commit", "-F"]
|
||
|
|
_STATUS_COMMAND = ["git", "status", "--porcelain"]
|
||
|
|
|
||
|
|
@classmethod
|
||
|
|
def tag(cls, name):
|
||
|
|
sp.check_output(["git", "tag", name])
|
||
|
|
|
||
|
|
|
||
|
|
class Mercurial(BaseVCS):
|
||
|
|
|
||
|
|
_TEST_USABLE_COMMAND = ["hg", "root"]
|
||
|
|
_COMMIT_COMMAND = ["hg", "commit", "--logfile"]
|
||
|
|
_STATUS_COMMAND = ["hg", "status", "-mard"]
|
||
|
|
|
||
|
|
@classmethod
|
||
|
|
def tag(cls, name):
|
||
|
|
sp.check_output(["hg", "tag", name])
|
||
|
|
|
||
|
|
|
||
|
|
VCS = [Git, Mercurial]
|
||
|
|
|
||
|
|
|
||
|
|
def get_vcs(allow_dirty=False):
|
||
|
|
for vcs in VCS:
|
||
|
|
if not vcs.is_usable():
|
||
|
|
continue
|
||
|
|
|
||
|
|
if not allow_dirty:
|
||
|
|
try:
|
||
|
|
vcs.assert_nondirty()
|
||
|
|
except WorkingDirectoryIsDirtyException as e:
|
||
|
|
log.warn(
|
||
|
|
f"{e.message}\n\n"
|
||
|
|
f"Use --allow-dirty to override this if you know what you're doing."
|
||
|
|
)
|
||
|
|
raise
|
||
|
|
|
||
|
|
return vcs
|
||
|
|
|
||
|
|
return None
|