Skip to content

Commit 503b62b

Browse files
committed
Implemented more tests and made use of .git files when adding submodules
There is some more work to do, as renames and updates still have to be adjusted accordinlgy. Relates #233
1 parent a9a5414 commit 503b62b

File tree

2 files changed

+79
-8
lines changed

2 files changed

+79
-8
lines changed

git/objects/submodule/base.py

+34-5
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,10 @@ def _get_intermediate_items(self, item):
127127
return list()
128128
# END handle intermeditate items
129129

130+
@classmethod
131+
def _need_gitfile_submodules(cls, git):
132+
return git.version_info[:3] >= (1, 8, 0)
133+
130134
def __eq__(self, other):
131135
"""Compare with another submodule"""
132136
# we may only compare by name as this should be the ID they are hashed with
@@ -157,9 +161,7 @@ def _config_parser(cls, repo, parent_commit, read_only):
157161
access of the config parser"""
158162
parent_matches_head = repo.head.commit == parent_commit
159163
if not repo.bare and parent_matches_head:
160-
fp_module = cls.k_modules_file
161-
fp_module_path = os.path.join(repo.working_tree_dir, fp_module)
162-
fp_module = fp_module_path
164+
fp_module = os.path.join(repo.working_tree_dir, cls.k_modules_file)
163165
else:
164166
try:
165167
fp_module = cls._sio_modules(parent_commit)
@@ -198,6 +200,23 @@ def _config_parser_constrained(self, read_only):
198200
parser.set_submodule(self)
199201
return SectionConstraint(parser, sm_section(self.name))
200202

203+
@classmethod
204+
def _module_abspath(cls, parent_repo, path, name):
205+
if cls._need_gitfile_submodules(parent_repo.git):
206+
return os.path.join(parent_repo.git_dir, 'modules', name)
207+
else:
208+
return os.path.join(parent_repo.working_tree_dir, path)
209+
# end
210+
211+
@classmethod
212+
def _write_git_file(cls, working_tree_dir, module_abspath, overwrite_existing=False):
213+
"""Writes a .git file containing a (preferably) relative path to the actual git module repository.
214+
It is an error if the module_abspath cannot be made into a relative path, relative to the working_tree_dir
215+
:param working_tree_dir: directory to write the .git file into
216+
:param module_abspath: absolute path to the bare repository
217+
:param overwrite_existing: if True, we may rewrite existing .git files, otherwise we raise"""
218+
raise NotImplementedError
219+
201220
#{ Edit Interface
202221

203222
@classmethod
@@ -298,7 +317,17 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False):
298317
if not branch_is_default:
299318
kwargs['b'] = br.name
300319
# END setup checkout-branch
301-
mrepo = git.Repo.clone_from(url, os.path.join(repo.working_tree_dir, path), **kwargs)
320+
module_abspath = cls._module_abspath(repo, path, name)
321+
module_checkout_path = module_abspath
322+
if cls._need_gitfile_submodules(repo.git):
323+
kwargs['separate_git_dir'] = module_abspath
324+
module_abspath_dir = os.path.dirname(module_abspath)
325+
if not os.path.isdir(module_abspath_dir):
326+
os.makedirs(module_abspath_dir)
327+
module_checkout_path = os.path.join(repo.working_tree_dir, path)
328+
# end
329+
330+
mrepo = git.Repo.clone_from(url, module_checkout_path, **kwargs)
302331
# END verify url
303332

304333
# update configuration and index
@@ -390,7 +419,7 @@ def update(self, recursive=False, init=True, to_latest_revision=False, progress=
390419
import git
391420

392421
# there is no git-repository yet - but delete empty paths
393-
module_path = join_path_native(self.repo.working_tree_dir, self.path)
422+
module_path = self._module_abspath(self.repo, self.path, self.name)
394423
if not dry_run and os.path.isdir(module_path):
395424
try:
396425
os.rmdir(module_path)

git/test/test_submodule.py

+45-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from git.objects.submodule.root import RootModule, RootUpdateProgress
1717
from git.util import to_native_path_linux, join_path_native
1818
from git.compat import string_types
19+
from git.repo.fun import find_git_dir
1920

2021
from nose import SkipTest
2122

@@ -602,15 +603,56 @@ def test_first_submodule(self, rwrepo):
602603

603604
@with_rw_directory
604605
def test_add_empty_repo(self, rwdir):
605-
parent_dir = os.path.join(rwdir, 'parent')
606-
os.mkdir(parent_dir)
607606
empty_repo_dir = os.path.join(rwdir, 'empty-repo')
608607

609-
parent = git.Repo.init(parent_dir)
608+
parent = git.Repo.init(os.path.join(rwdir, 'parent'))
610609
git.Repo.init(empty_repo_dir)
611610

612611
for checkout_mode in range(2):
613612
name = 'empty' + str(checkout_mode)
614613
self.failUnlessRaises(ValueError, parent.create_submodule, name, name,
615614
url=empty_repo_dir, no_checkout=checkout_mode and True or False)
616615
# end for each checkout mode
616+
617+
def _submodule_url(self):
618+
return os.path.join(self.rorepo.working_tree_dir, 'git/ext/gitdb/gitdb/ext/smmap')
619+
620+
@with_rw_directory
621+
def test_git_submodules(self, rwdir):
622+
parent = git.Repo.init(os.path.join(rwdir, 'parent'))
623+
parent.git.submodule('add', self._submodule_url(), 'module')
624+
parent.index.commit("added submodule")
625+
626+
assert len(parent.submodules) == 1
627+
sm = parent.submodules[0]
628+
629+
assert sm.exists() and sm.module_exists()
630+
631+
# test move and rename
632+
# TODO
633+
634+
@with_rw_directory
635+
def test_git_submodule_compatibility(self, rwdir):
636+
parent = git.Repo.init(os.path.join(rwdir, 'parent'))
637+
empty_file = os.path.join(parent.working_tree_dir, "empty")
638+
with open(empty_file, 'wb') as fp:
639+
fp.close()
640+
parent.index.add([empty_file])
641+
parent.index.commit("initial commit - can't yet add submodules to empty parent dir")
642+
643+
sm_path = 'submodules/intermediate/one'
644+
sm = parent.create_submodule('mymodules/myname', sm_path, url=self._submodule_url())
645+
parent.index.commit("added submodule")
646+
647+
# As git is backwards compatible itself, it would still recognize what we do here ... unless we really
648+
# muss it up. That's the only reason why the test is still here ... .
649+
assert len(parent.git.submodule().splitlines()) == 1
650+
651+
module_repo_path = os.path.join(sm.module().working_tree_dir, '.git')
652+
assert module_repo_path.startswith(os.path.join(parent.working_tree_dir, sm_path))
653+
if not sm._need_gitfile_submodules(parent.git):
654+
assert os.path.isdir(module_repo_path)
655+
else:
656+
assert os.path.isfile(module_repo_path)
657+
assert find_git_dir(module_repo_path) is not None, "module pointed to by .git file must be valid"
658+
# end verify submodule 'style'

0 commit comments

Comments
 (0)