diff options
-rw-r--r-- | git/objects/submodule/base.py | 39 | ||||
-rw-r--r-- | git/test/test_submodule.py | 48 |
2 files changed, 79 insertions, 8 deletions
diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py index e055cb8c..13183e29 100644 --- a/git/objects/submodule/base.py +++ b/git/objects/submodule/base.py @@ -127,6 +127,10 @@ class Submodule(util.IndexObject, Iterable, Traversable): return list() # END handle intermeditate items + @classmethod + def _need_gitfile_submodules(cls, git): + return git.version_info[:3] >= (1, 8, 0) + def __eq__(self, other): """Compare with another submodule""" # we may only compare by name as this should be the ID they are hashed with @@ -157,9 +161,7 @@ class Submodule(util.IndexObject, Iterable, Traversable): access of the config parser""" parent_matches_head = repo.head.commit == parent_commit if not repo.bare and parent_matches_head: - fp_module = cls.k_modules_file - fp_module_path = os.path.join(repo.working_tree_dir, fp_module) - fp_module = fp_module_path + fp_module = os.path.join(repo.working_tree_dir, cls.k_modules_file) else: try: fp_module = cls._sio_modules(parent_commit) @@ -198,6 +200,23 @@ class Submodule(util.IndexObject, Iterable, Traversable): parser.set_submodule(self) return SectionConstraint(parser, sm_section(self.name)) + @classmethod + def _module_abspath(cls, parent_repo, path, name): + if cls._need_gitfile_submodules(parent_repo.git): + return os.path.join(parent_repo.git_dir, 'modules', name) + else: + return os.path.join(parent_repo.working_tree_dir, path) + # end + + @classmethod + def _write_git_file(cls, working_tree_dir, module_abspath, overwrite_existing=False): + """Writes a .git file containing a (preferably) relative path to the actual git module repository. + It is an error if the module_abspath cannot be made into a relative path, relative to the working_tree_dir + :param working_tree_dir: directory to write the .git file into + :param module_abspath: absolute path to the bare repository + :param overwrite_existing: if True, we may rewrite existing .git files, otherwise we raise""" + raise NotImplementedError + #{ Edit Interface @classmethod @@ -298,7 +317,17 @@ class Submodule(util.IndexObject, Iterable, Traversable): if not branch_is_default: kwargs['b'] = br.name # END setup checkout-branch - mrepo = git.Repo.clone_from(url, os.path.join(repo.working_tree_dir, path), **kwargs) + module_abspath = cls._module_abspath(repo, path, name) + module_checkout_path = module_abspath + if cls._need_gitfile_submodules(repo.git): + kwargs['separate_git_dir'] = module_abspath + module_abspath_dir = os.path.dirname(module_abspath) + if not os.path.isdir(module_abspath_dir): + os.makedirs(module_abspath_dir) + module_checkout_path = os.path.join(repo.working_tree_dir, path) + # end + + mrepo = git.Repo.clone_from(url, module_checkout_path, **kwargs) # END verify url # update configuration and index @@ -390,7 +419,7 @@ class Submodule(util.IndexObject, Iterable, Traversable): import git # there is no git-repository yet - but delete empty paths - module_path = join_path_native(self.repo.working_tree_dir, self.path) + module_path = self._module_abspath(self.repo, self.path, self.name) if not dry_run and os.path.isdir(module_path): try: os.rmdir(module_path) diff --git a/git/test/test_submodule.py b/git/test/test_submodule.py index 3e3a97d8..484e73ae 100644 --- a/git/test/test_submodule.py +++ b/git/test/test_submodule.py @@ -16,6 +16,7 @@ from git.objects.submodule.base import Submodule from git.objects.submodule.root import RootModule, RootUpdateProgress from git.util import to_native_path_linux, join_path_native from git.compat import string_types +from git.repo.fun import find_git_dir from nose import SkipTest @@ -602,11 +603,9 @@ class TestSubmodule(TestBase): @with_rw_directory def test_add_empty_repo(self, rwdir): - parent_dir = os.path.join(rwdir, 'parent') - os.mkdir(parent_dir) empty_repo_dir = os.path.join(rwdir, 'empty-repo') - parent = git.Repo.init(parent_dir) + parent = git.Repo.init(os.path.join(rwdir, 'parent')) git.Repo.init(empty_repo_dir) for checkout_mode in range(2): @@ -614,3 +613,46 @@ class TestSubmodule(TestBase): self.failUnlessRaises(ValueError, parent.create_submodule, name, name, url=empty_repo_dir, no_checkout=checkout_mode and True or False) # end for each checkout mode + + def _submodule_url(self): + return os.path.join(self.rorepo.working_tree_dir, 'git/ext/gitdb/gitdb/ext/smmap') + + @with_rw_directory + def test_git_submodules(self, rwdir): + parent = git.Repo.init(os.path.join(rwdir, 'parent')) + parent.git.submodule('add', self._submodule_url(), 'module') + parent.index.commit("added submodule") + + assert len(parent.submodules) == 1 + sm = parent.submodules[0] + + assert sm.exists() and sm.module_exists() + + # test move and rename + # TODO + + @with_rw_directory + def test_git_submodule_compatibility(self, rwdir): + parent = git.Repo.init(os.path.join(rwdir, 'parent')) + empty_file = os.path.join(parent.working_tree_dir, "empty") + with open(empty_file, 'wb') as fp: + fp.close() + parent.index.add([empty_file]) + parent.index.commit("initial commit - can't yet add submodules to empty parent dir") + + sm_path = 'submodules/intermediate/one' + sm = parent.create_submodule('mymodules/myname', sm_path, url=self._submodule_url()) + parent.index.commit("added submodule") + + # As git is backwards compatible itself, it would still recognize what we do here ... unless we really + # muss it up. That's the only reason why the test is still here ... . + assert len(parent.git.submodule().splitlines()) == 1 + + module_repo_path = os.path.join(sm.module().working_tree_dir, '.git') + assert module_repo_path.startswith(os.path.join(parent.working_tree_dir, sm_path)) + if not sm._need_gitfile_submodules(parent.git): + assert os.path.isdir(module_repo_path) + else: + assert os.path.isfile(module_repo_path) + assert find_git_dir(module_repo_path) is not None, "module pointed to by .git file must be valid" + # end verify submodule 'style' |