Skip to content

Commit d041864

Browse files
fix issue #86 - detect dirty git workdirs even in the absence of tags
2 parents 9f360e6 + 23b8d74 commit d041864

File tree

4 files changed

+74
-26
lines changed

4 files changed

+74
-26
lines changed

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
v1.13.1
2+
=======
3+
4+
* fix issue #86 - detect dirty git workdir without tags
5+
16
v1.13.0
27
=======
38

setuptools_scm/git.py

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,69 @@
1-
from .utils import do, do_ex, trace
1+
from .utils import do_ex, trace
22
from .version import meta
33
from os.path import abspath, normcase, realpath
44

55

66
FILES_COMMAND = 'git ls-files'
7-
DEFAULT_DESCRIBE = 'git describe --dirty --tags --long --match *.*'
7+
DEFAULT_DESCRIBE = 'git describe --tags --long --match *.*'
8+
9+
10+
def _normalized(path):
11+
return normcase(abspath(realpath(path)))
12+
13+
14+
class GitWorkdir(object):
15+
def __init__(self, path):
16+
self.path = path
17+
18+
def do_ex(self, cmd):
19+
return do_ex(cmd, cwd=self.path)
20+
21+
@classmethod
22+
def from_potential_worktree(cls, wd):
23+
real_wd, _, ret = do_ex('git rev-parse --show-toplevel', wd)
24+
if ret:
25+
return
26+
trace('real root', real_wd)
27+
if _normalized(real_wd) != _normalized(wd):
28+
return
29+
30+
return cls(real_wd)
31+
32+
def is_dirty(self):
33+
out, _, _ = self.do_ex("git status --porcelain")
34+
return bool(out)
35+
36+
def node(self):
37+
rev_node, _, ret = self.do_ex('git rev-parse --verify --quiet HEAD')
38+
if not ret:
39+
return rev_node[:7]
40+
41+
def count_all_nodes(self):
42+
revs, _, _ = self.do_ex('git rev-list HEAD')
43+
return revs.count('\n') + 1
844

945

1046
def parse(root, describe_command=DEFAULT_DESCRIBE):
11-
real_root, _, ret = do_ex('git rev-parse --show-toplevel', root)
12-
if ret:
13-
return
14-
trace('real root', real_root)
15-
if (normcase(abspath(realpath(real_root))) !=
16-
normcase(abspath(realpath(root)))):
17-
return
18-
rev_node, _, ret = do_ex('git rev-parse --verify --quiet HEAD', root)
19-
if ret:
20-
return meta('0.0')
21-
rev_node = rev_node[:7]
47+
wd = GitWorkdir(root)
48+
49+
rev_node = wd.node()
50+
dirty = wd.is_dirty()
51+
52+
if rev_node is None:
53+
return meta('0.0', dirty=dirty)
54+
2255
out, err, ret = do_ex(describe_command, root)
23-
if '-' not in out and '.' not in out:
24-
revs = do('git rev-list HEAD', root)
25-
count = revs.count('\n')
26-
if ret:
27-
out = rev_node
28-
return meta('0.0', distance=count + 1, node=out)
2956
if ret:
30-
return
31-
dirty = out.endswith('-dirty')
32-
if dirty:
33-
out = out.rsplit('-', 1)[0]
57+
return meta(
58+
'0.0',
59+
distance=wd.count_all_nodes(),
60+
node=rev_node,
61+
dirty=dirty,
62+
)
3463

3564
tag, number, node = out.rsplit('-', 2)
3665
number = int(number)
3766
if number:
3867
return meta(tag, distance=number, node=node, dirty=dirty)
3968
else:
40-
return meta(tag, dirty=dirty, node=node)
69+
return meta(tag, node=node, dirty=dirty)

setuptools_scm/utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@ def _always_strings(env_dict):
4343

4444
def do_ex(cmd, cwd='.'):
4545
trace('cmd', repr(cmd))
46+
if not isinstance(cmd, (list, tuple)):
47+
cmd = shlex.split(cmd)
48+
4649
p = subprocess.Popen(
47-
shlex.split(cmd),
50+
cmd,
4851
stdout=subprocess.PIPE,
4952
stderr=subprocess.PIPE,
5053
cwd=str(cwd),
@@ -70,7 +73,6 @@ def do_ex(cmd, cwd='.'):
7073
def do(cmd, cwd='.'):
7174
out, err, ret = do_ex(cmd, cwd)
7275
if ret:
73-
trace('ret', ret)
7476
print(err)
7577
return out
7678

testing/test_git.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from setuptools_scm import integration
22
import pytest
3+
from datetime import date
34

45

56
@pytest.fixture
@@ -32,6 +33,17 @@ def test_version_from_git(wd):
3233
assert wd.version.startswith('0.2')
3334

3435

36+
@pytest.mark.issue(86)
37+
def test_git_dirty_notag(wd):
38+
wd.commit_testfile()
39+
wd.write('test.txt', 'test2')
40+
wd("git add test.txt")
41+
assert wd.version.startswith('0.1.dev1')
42+
today = date.today()
43+
# we are dirty, check for the tag
44+
assert today.strftime('.d%Y%m%d') in wd.version
45+
46+
3547
def test_find_files_stop_at_root_git(wd):
3648
wd.commit_testfile()
3749
wd.cwd.ensure('project/setup.cfg')

0 commit comments

Comments
 (0)