Skip to content

Commit 33964af

Browse files
committed
Added tests for all failure modes of submodule add ( except for one ), and fixed a few issues on the way
1 parent 98e6edb commit 33964af

File tree

2 files changed

+53
-11
lines changed

2 files changed

+53
-11
lines changed

Diff for: lib/git/objects/submodule.py

+29-11
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import base
22
from util import Traversable
33
from StringIO import StringIO # need a dict to set bloody .name field
4-
from git.util import Iterable
4+
from git.util import Iterable, join_path_native, to_native_path_linux
55
from git.config import GitConfigParser, SectionConstraint
6-
from git.util import join_path_native
76
from git.exc import InvalidGitRepositoryError, NoSuchPathError
87
import stat
8+
import git
99

1010
import os
1111
import sys
@@ -87,6 +87,7 @@ class Submodule(base.IndexObject, Iterable, Traversable):
8787
type = 'submodule'
8888

8989
__slots__ = ('_parent_commit', '_url', '_branch', '_name', '__weakref__')
90+
_cache_attrs = ('path', '_url', '_branch')
9091

9192
def __init__(self, repo, binsha, mode=None, path=None, name = None, parent_commit=None, url=None, branch=None):
9293
"""Initialize this instance with its attributes. We only document the ones
@@ -178,7 +179,7 @@ def _config_parser(cls, repo, parent_commit, read_only):
178179

179180
def _clear_cache(self):
180181
# clear the possibly changed values
181-
for name in ('path', '_branch', '_url'):
182+
for name in self._cache_attrs:
182183
try:
183184
delattr(self, name)
184185
except AttributeError:
@@ -235,18 +236,19 @@ def add(cls, repo, name, path, url=None, branch=k_head_default, no_checkout=Fals
235236
path = path[:-1]
236237
# END handle trailing slash
237238

239+
# INSTANTIATE INTERMEDIATE SM
238240
sm = cls(repo, cls.NULL_BIN_SHA, cls.k_def_mode, path, name)
239241
if sm.exists():
240242
# reretrieve submodule from tree
241243
return repo.head.commit.tree[path]
242244
# END handle existing
243245

244-
branch = Head(repo, head.to_full_path(branch))
246+
branch = git.Head(repo, git.Head.to_full_path(branch))
245247
has_module = sm.module_exists()
246248
branch_is_default = branch.name == cls.k_head_default
247249
if has_module and url is not None:
248250
if url not in [r.url for r in sm.module().remotes]:
249-
raise ValueError("Specified URL %s does not match any remote url of the repository at %s" % (url, sm.module_path()))
251+
raise ValueError("Specified URL '%s' does not match any remote url of the repository at '%s'" % (url, sm.module_path()))
250252
# END check url
251253
# END verify urls match
252254

@@ -611,14 +613,30 @@ def exists(self):
611613
""":return: True if the submodule exists, False otherwise. Please note that
612614
a submodule may exist (in the .gitmodules file) even though its module
613615
doesn't exist"""
616+
# keep attributes for later, and restore them if we have no valid data
617+
# this way we do not actually alter the state of the object
618+
loc = locals()
619+
for attr in self._cache_attrs:
620+
if hasattr(self, attr):
621+
loc[attr] = getattr(self, attr)
622+
# END if we have the attribute cache
623+
#END for each attr
614624
self._clear_cache()
625+
615626
try:
616-
self.path
617-
return True
618-
except Exception:
619-
# we raise if the path cannot be restored from configuration
620-
return False
621-
# END handle exceptions
627+
try:
628+
self.path
629+
return True
630+
except Exception:
631+
return False
632+
# END handle exceptions
633+
finally:
634+
for attr in self._cache_attrs:
635+
if attr in loc:
636+
setattr(self, attr, loc[attr])
637+
# END if we have a cache
638+
# END reapply each attribute
639+
# END handle object state consistency
622640

623641
@property
624642
def branch(self):

Diff for: test/git/test_submodule.py

+24
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,21 @@ def _do_base_tests(self, rwrepo):
9999
# currently there is only one submodule
100100
assert len(list(rwrepo.iter_submodules())) == 1
101101

102+
# TEST ADD
103+
###########
104+
# preliminary tests
105+
# adding existing returns exactly the existing
106+
sma = Submodule.add(rwrepo, sm.name, sm.path)
107+
assert sma.path == sm.path
108+
109+
# no url and no module at path fails
110+
self.failUnlessRaises(ValueError, Submodule.add, rwrepo, "newsubm", "pathtorepo", url=None)
111+
112+
# TODO: Test no remote url in existing repository
113+
114+
# CONTINUE UPDATE
115+
#################
116+
102117
# lets update it - its a recursive one too
103118
newdir = os.path.join(sm.module_path(), 'dir')
104119
os.makedirs(newdir)
@@ -112,6 +127,15 @@ def _do_base_tests(self, rwrepo):
112127
assert isinstance(sm.module(), git.Repo)
113128
assert sm.module().working_tree_dir == sm.module_path()
114129

130+
# INTERLEAVE ADD TEST
131+
#####################
132+
# url must match the one in the existing repository ( if submodule name suggests a new one )
133+
# or we raise
134+
self.failUnlessRaises(ValueError, Submodule.add, rwrepo, "newsubm", sm.path, "git://someurl/repo.git")
135+
136+
137+
# CONTINUE UPDATE
138+
#################
115139
# we should have setup a tracking branch, which is also active
116140
assert sm.module().head.ref.tracking_branch() is not None
117141

0 commit comments

Comments
 (0)