diff options
author | Stéphane Bidoul (ACSONE) <stephane.bidoul@acsone.eu> | 2018-04-28 18:35:07 +0200 |
---|---|---|
committer | Stéphane Bidoul (ACSONE) <stephane.bidoul@acsone.eu> | 2018-04-28 19:33:00 +0200 |
commit | 7253898ffff71c889d0a8ad2b5c0f4ca44146eee (patch) | |
tree | f527cacadc719ec958f02bfe7b7ec7a61a1daf23 | |
parent | 9b36312cc0f08d052edee1b9567a83219960934f (diff) | |
download | setuptools-scm-7253898ffff71c889d0a8ad2b5c0f4ca44146eee.tar.gz |
Refactor hg and git file finders to use the same algorithm
Also make the test parametric.
-rw-r--r-- | setup.py | 4 | ||||
-rw-r--r-- | setuptools_scm/file_finder.py | 33 | ||||
-rw-r--r-- | setuptools_scm/file_finder_git.py (renamed from setuptools_scm/git_file_finder.py) | 28 | ||||
-rw-r--r-- | setuptools_scm/file_finder_hg.py | 44 | ||||
-rw-r--r-- | setuptools_scm/hg.py | 2 | ||||
-rw-r--r-- | testing/test_file_finder.py (renamed from testing/test_git_file_finder.py) | 25 |
6 files changed, 98 insertions, 38 deletions
@@ -81,8 +81,8 @@ arguments = dict( pip-egg-info = setuptools_scm.hacks:parse_pip_egg_info [setuptools_scm.files_command] - .hg = setuptools_scm.hg:FILES_COMMAND - .git = setuptools_scm.git_file_finder:find_files + .hg = setuptools_scm.file_finder_hg:hg_find_files + .git = setuptools_scm.file_finder_git:git_find_files [setuptools_scm.version_scheme] guess-next-dev = setuptools_scm.version:guess_next_dev_version diff --git a/setuptools_scm/file_finder.py b/setuptools_scm/file_finder.py new file mode 100644 index 0000000..fb7648a --- /dev/null +++ b/setuptools_scm/file_finder.py @@ -0,0 +1,33 @@ +import os + + +def scm_find_files(path, scm_files, scm_dirs): + """ setuptools compatible file finder that follows symlinks + + - path: the root directory from which to search + - scm_files: set of scm controlled files + - scm_files: set of scm controlled directories + + scm_files and scm_dirs must be absolute with symlinks resolved (realpath), + with normalized case (normcase) + + Spec here: http://setuptools.readthedocs.io/en/latest/setuptools.html#\ + adding-support-for-revision-control-systems + """ + realpath = os.path.normcase(os.path.realpath(path)) + seen = set() + res = [] + for dirpath, dirnames, filenames in os.walk(realpath, followlinks=True): + # dirpath with symlinks resolved + realdirpath = os.path.normcase(os.path.realpath(dirpath)) + if realdirpath not in scm_dirs or realdirpath in seen: + dirnames[:] = [] + continue + for filename in filenames: + # dirpath + filename with symlinks preserved + fullfilename = os.path.join(dirpath, filename) + if os.path.normcase(os.path.realpath(fullfilename)) in scm_files: + res.append( + os.path.join(path, os.path.relpath(fullfilename, path))) + seen.add(realdirpath) + return res diff --git a/setuptools_scm/git_file_finder.py b/setuptools_scm/file_finder_git.py index da3d8e7..ecb5cf6 100644 --- a/setuptools_scm/git_file_finder.py +++ b/setuptools_scm/file_finder_git.py @@ -2,6 +2,8 @@ import os import subprocess import tarfile +from .file_finder import scm_find_files + def _git_toplevel(path): try: @@ -35,31 +37,9 @@ def _git_ls_files_and_dirs(toplevel): return git_files, git_dirs -def find_files(path=''): - """ setuptools compatible git file finder that follows symlinks - - Spec here: http://setuptools.readthedocs.io/en/latest/setuptools.html#\ - adding-support-for-revision-control-systems - """ +def git_find_files(path=''): toplevel = _git_toplevel(path) if not toplevel: return [] git_files, git_dirs = _git_ls_files_and_dirs(toplevel) - realpath = os.path.normcase(os.path.realpath(path)) - assert realpath.startswith(toplevel) - seen = set() - res = [] - for dirpath, dirnames, filenames in os.walk(realpath, followlinks=True): - # dirpath with symlinks resolved - realdirpath = os.path.normcase(os.path.realpath(dirpath)) - if realdirpath not in git_dirs or realdirpath in seen: - dirnames[:] = [] - continue - for filename in filenames: - # dirpath + filename with symlinks preserved - fullfilename = os.path.join(dirpath, filename) - if os.path.normcase(os.path.realpath(fullfilename)) in git_files: - res.append( - os.path.join(path, os.path.relpath(fullfilename, path))) - seen.add(realdirpath) - return res + return scm_find_files(path, git_files, git_dirs) diff --git a/setuptools_scm/file_finder_hg.py b/setuptools_scm/file_finder_hg.py new file mode 100644 index 0000000..2f5ccda --- /dev/null +++ b/setuptools_scm/file_finder_hg.py @@ -0,0 +1,44 @@ +import os +import subprocess + +from .file_finder import scm_find_files + + +def _hg_toplevel(path): + try: + with open(os.devnull, 'wb') as devnull: + out = subprocess.check_output([ + 'hg', 'root', + ], cwd=(path or '.'), universal_newlines=True, stderr=devnull) + return os.path.normcase(os.path.realpath(out.strip())) + except subprocess.CalledProcessError: + # hg returned error, we are not in a mercurial repo + return None + except OSError: + # hg command not found, probably + return None + + +def _hg_ls_files_and_dirs(toplevel): + hg_files = set() + hg_dirs = set([toplevel]) + out = subprocess.check_output([ + 'hg', 'files', + ], cwd=toplevel, universal_newlines=True) + for name in out.split(): + name = os.path.normcase(name).replace('/', os.path.sep) + fullname = os.path.join(toplevel, name) + hg_files.add(fullname) + dirname = os.path.dirname(fullname) + while len(dirname) > len(toplevel) and dirname not in hg_dirs: + hg_dirs.add(dirname) + dirname = os.path.dirname(dirname) + return hg_files, hg_dirs + + +def hg_find_files(path=''): + toplevel = _hg_toplevel(path) + if not toplevel: + return [] + hg_files, hg_dirs = _hg_ls_files_and_dirs(toplevel) + return scm_find_files(path, hg_files, hg_dirs) diff --git a/setuptools_scm/hg.py b/setuptools_scm/hg.py index 422e468..ccf6603 100644 --- a/setuptools_scm/hg.py +++ b/setuptools_scm/hg.py @@ -2,8 +2,6 @@ import os from .utils import do, trace, data_from_mime, has_command from .version import meta, tags_to_versions -FILES_COMMAND = 'hg locate -I .' - def _hg_tagdist_normalize_tagcommit(root, tag, dist, node, branch): dirty = node.endswith('+') diff --git a/testing/test_git_file_finder.py b/testing/test_file_finder.py index fb7d6f1..81a599f 100644 --- a/testing/test_git_file_finder.py +++ b/testing/test_file_finder.py @@ -3,16 +3,21 @@ import sys import pytest -from setuptools_scm.git_file_finder import find_files - - -@pytest.fixture -def inwd(wd): - wd('git init') - wd('git config user.email test@example.com') - wd('git config user.name "a test"') - wd.add_command = 'git add .' - wd.commit_command = 'git commit -m test-{reason}' +from setuptools_scm.integration import find_files + + +@pytest.fixture(params=['git', 'hg']) +def inwd(request, wd): + if request.param == 'git': + wd('git init') + wd('git config user.email test@example.com') + wd('git config user.name "a test"') + wd.add_command = 'git add .' + wd.commit_command = 'git commit -m test-{reason}' + elif request.param == 'hg': + wd('hg init') + wd.add_command = 'hg add .' + wd.commit_command = 'hg commit -m test-{reason} -u test -d "0 0"' (wd.cwd / 'file1').ensure(file=True) adir = (wd.cwd / 'adir').ensure(dir=True) (adir / 'filea').ensure(file=True) |