summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--git/objects/submodule/base.py39
-rw-r--r--git/test/test_submodule.py48
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'