Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ v1.15.0
* update trove classifiers
* fix issue #84: document using the installed package metadata for sphinx
* fix issue #81: fail more gracious when git/hg are missing
* address issue #93: provide an experimental api to customize behaviour on shallow git repos
a custom parse function may pick pre parse actions to do when using git


v1.14.1
=======
Expand Down
40 changes: 36 additions & 4 deletions setuptools_scm/git.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .utils import do_ex, trace, has_command
from .version import meta
from os.path import abspath, normcase, realpath

from os.path import abspath, normcase, realpath, isfile, join
import warnings

FILES_COMMAND = 'git ls-files'
DEFAULT_DESCRIBE = 'git describe --tags --long --match *.*'
Expand All @@ -12,6 +12,7 @@ def _normalized(path):


class GitWorkdir(object):
"""experimental, may change at any time"""
def __init__(self, path):
self.path = path

Expand All @@ -33,6 +34,12 @@ def is_dirty(self):
out, _, _ = self.do_ex("git status --porcelain --untracked-files=no")
return bool(out)

def is_shallow(self):
return isfile(join(self.path, '.git/shallow'))

def fetch_shallow(self):
self.do_ex("git fetch --unshallow")

def node(self):
rev_node, _, ret = self.do_ex('git rev-parse --verify --quiet HEAD')
if not ret:
Expand All @@ -43,11 +50,36 @@ def count_all_nodes(self):
return revs.count('\n') + 1


def parse(root, describe_command=DEFAULT_DESCRIBE):
def warn_on_shallow(wd):
"""experimental, may change at any time"""
if wd.is_shallow():
warnings.warn('"%s" is shallow and may cause errors' % (wd.path,))


def fetch_on_shallow(wd):
"""experimental, may change at any time"""
if wd.is_shallow():
warnings.warn('"%s" was shallow, git fetch was used to rectify')
wd.fetch_shallow()


def fail_on_shallow(wd):
"""experimental, may change at any time"""
if wd.is_shallow():
raise ValueError(
'%r is shallow, please correct with '
'"git fetch --unshallow"' % wd.path)


def parse(root, describe_command=DEFAULT_DESCRIBE, pre_parse=warn_on_shallow):
"""
:param pre_parse: experimental pre_parse action, may change at any time
"""
if not has_command('git'):
return
wd = GitWorkdir(root)

if pre_parse:
pre_parse(wd)
rev_node = wd.node()
dirty = wd.is_dirty()

Expand Down
2 changes: 1 addition & 1 deletion testing/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ def version(self):

@pytest.fixture
def wd(tmpdir):
return Wd(tmpdir)
return Wd(tmpdir.ensure('wd', dir=True))
32 changes: 32 additions & 0 deletions testing/test_git.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from setuptools_scm import integration
from setuptools_scm.utils import do
from setuptools_scm import git
import pytest
from datetime import date

Expand Down Expand Up @@ -54,6 +56,36 @@ def test_git_dirty_notag(wd):
assert today.strftime('.d%Y%m%d') in wd.version


@pytest.fixture
def shallow_wd(wd, tmpdir):
wd.commit_testfile()
wd.commit_testfile()
wd.commit_testfile()
target = tmpdir.join('wd_shallow')
do(['git', 'clone', "file://%s" % wd.cwd, str(target,), '--depth=1'])
return target


def test_git_parse_shallow_warns(shallow_wd, recwarn):
git.parse(str(shallow_wd))
msg = recwarn.pop()
assert 'is shallow and may cause errors' in str(msg.message)


def test_git_parse_shallow_fail(shallow_wd):
with pytest.raises(ValueError) as einfo:
git.parse(str(shallow_wd), pre_parse=git.fail_on_shallow)

assert 'git fetch' in str(einfo.value)


def test_git_shallow_autocorrect(shallow_wd, recwarn):
git.parse(str(shallow_wd), pre_parse=git.fetch_on_shallow)
msg = recwarn.pop()
assert 'git fetch was used to rectify' in str(msg.message)
git.parse(str(shallow_wd), pre_parse=git.fail_on_shallow)


def test_find_files_stop_at_root_git(wd):
wd.commit_testfile()
wd.cwd.ensure('project/setup.cfg')
Expand Down