Skip to content

Commit

Permalink
Support git submodules
Browse files Browse the repository at this point in the history
Fixes #61.
  • Loading branch information
mgedmin committed Dec 9, 2015
1 parent bf4c37f commit effec6c
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 9 deletions.
43 changes: 34 additions & 9 deletions check_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def __init__(self, command, status, output):
command, status, output))


def run(command, encoding=None, decode=True):
def run(command, encoding=None, decode=True, cwd=None):
"""Run a command [cmd, arg1, arg2, ...].
Returns the output (stdout + stderr).
Expand All @@ -139,7 +139,7 @@ def run(command, encoding=None, decode=True):
encoding = locale.getpreferredencoding()
try:
pipe = subprocess.Popen(command, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
stderr=subprocess.STDOUT, cwd=cwd)
except OSError as e:
raise Failure("could not run %s: %s" % (command, e))
output = pipe.communicate()[0]
Expand Down Expand Up @@ -263,6 +263,16 @@ def strip_toplevel_name(filelist):
return [name[len(prefix):] for name in names]


def add_prefix_to_each(prefix, filelist):
"""Add a prefix to each name in a file list.
>>> add_prefix_to_each('foo/bar', ['a', 'b', 'c/d'])
['foo/bar/a', 'foo/bar/b', 'foo/bar/c/d']
"""
return [os.path.join(prefix, name) for name in filelist]


class VCS(object):

@classmethod
Expand All @@ -273,19 +283,34 @@ def detect(cls, location):
class Git(VCS):
metadata_name = '.git'

# Git for Windows uses UTF-8 instead of the locale encoding.
# Git on POSIX systems uses the locale encoding.
_encoding = 'UTF-8' if sys.platform == 'win32' else None

@classmethod
def detect(cls, location):
# .git can be a file for submodules
return os.path.exists(os.path.join(location, cls.metadata_name))

@staticmethod
def get_versioned_files():
@classmethod
def get_versioned_files(cls):
"""List all files versioned by git in the current directory."""
# Git for Windows uses UTF-8 instead of the locale encoding.
# Regular Git on sane POSIX systems uses the locale encoding
encoding = 'UTF-8' if sys.platform == 'win32' else None
output = run(['git', 'ls-files', '-z'], encoding=encoding)
return add_directories(output.split('\0')[:-1])
files = cls._git_ls_files()
submodules = cls._list_submodules()
for subdir in submodules:
subdir = os.path.relpath(subdir)
files += add_prefix_to_each(subdir, cls._git_ls_files(subdir))
return add_directories(files)

@classmethod
def _git_ls_files(cls, cwd=None):
output = run(['git', 'ls-files', '-z'], encoding=cls._encoding, cwd=cwd)
return output.rstrip('\0').split('\0')

@classmethod
def _list_submodules(cls):
return run(['git', 'submodule', '--quiet', 'foreach', '--recursive',
'printf "%s/%s\\n" $toplevel $path'], encoding=cls._encoding).splitlines()


class Mercurial(VCS):
Expand Down
40 changes: 40 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,20 @@ def _commit(self):
class TestGit(VCSMixin, unittest.TestCase):
vcs = GitHelper()

def _init_repo_with_files(self, dirname, filenames):
os.mkdir(dirname)
os.chdir(dirname)
self._init_vcs()
self._create_and_add_to_vcs(filenames)
self._commit()
os.chdir(self.tmpdir)

def _add_submodule(self, repo, subdir, subrepo):
os.chdir(repo)
self.vcs._run('git', 'submodule', 'add', subrepo, subdir)
self._commit()
os.chdir(self.tmpdir)

def test_detect_git_submodule(self):
from check_manifest import detect_vcs, Failure
with self.assertRaises(Failure) as cm:
Expand All @@ -875,6 +889,32 @@ def test_detect_git_submodule(self):
open(os.path.join(self.tmpdir, '.git'), 'w').close()
self.assertEqual(detect_vcs().metadata_name, '.git')

def test_get_versioned_files_with_git_submodules(self):
from check_manifest import get_vcs_files
self._init_repo_with_files('repo1', ['file1', 'file2'])
self._init_repo_with_files('repo2', ['file3'])
self._init_repo_with_files('repo3', ['file4'])
self._add_submodule('repo2', 'sub3', '../repo3')
self._init_repo_with_files('main', ['file5'])
self._add_submodule('main', 'sub1', '../repo1')
self._add_submodule('main', 'sub2', '../repo2')
os.chdir('main')
self.vcs._run('git', 'submodule', 'update', '--init', '--recursive')
self.assertEqual(
get_vcs_files(),
[
'.gitmodules',
'file5',
'sub1',
'sub1/file1',
'sub1/file2',
'sub2',
'sub2/.gitmodules',
'sub2/file3',
'sub2/sub3',
'sub2/sub3/file4',
])


class BzrHelper(VCSHelper):

Expand Down

0 comments on commit effec6c

Please sign in to comment.