Skip to content

Commit 8e0e315

Browse files
committed
submodule: Fixed capital error when handling the submodule's branch, which was returned in the submodules super repository, not in the submodule's module
1 parent 8d0aa1e commit 8e0e315

File tree

4 files changed

+62
-41
lines changed

4 files changed

+62
-41
lines changed

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

+39-26
Original file line numberDiff line numberDiff line change
@@ -51,41 +51,41 @@ class Submodule(util.IndexObject, Iterable, Traversable):
5151
# this is a bogus type for base class compatability
5252
type = 'submodule'
5353

54-
__slots__ = ('_parent_commit', '_url', '_branch', '_name', '__weakref__')
55-
_cache_attrs = ('path', '_url', '_branch')
54+
__slots__ = ('_parent_commit', '_url', '_branch_path', '_name', '__weakref__')
55+
_cache_attrs = ('path', '_url', '_branch_path')
5656

57-
def __init__(self, repo, binsha, mode=None, path=None, name = None, parent_commit=None, url=None, branch=None):
57+
def __init__(self, repo, binsha, mode=None, path=None, name = None, parent_commit=None, url=None, branch_path=None):
5858
"""Initialize this instance with its attributes. We only document the ones
5959
that differ from ``IndexObject``
6060
6161
:param repo: Our parent repository
6262
:param binsha: binary sha referring to a commit in the remote repository, see url parameter
6363
:param parent_commit: see set_parent_commit()
6464
:param url: The url to the remote repository which is the submodule
65-
:param branch: Head instance to checkout when cloning the remote repository"""
65+
:param branch_path: full (relative) path to ref to checkout when cloning the remote repository"""
6666
super(Submodule, self).__init__(repo, binsha, mode, path)
6767
self.size = 0
6868
if parent_commit is not None:
6969
self._parent_commit = parent_commit
7070
if url is not None:
7171
self._url = url
72-
if branch is not None:
73-
assert isinstance(branch, git.Head)
74-
self._branch = branch
72+
if branch_path is not None:
73+
assert isinstance(branch_path, basestring)
74+
self._branch_path = branch_path
7575
if name is not None:
7676
self._name = name
7777

7878
def _set_cache_(self, attr):
7979
if attr == '_parent_commit':
8080
# set a default value, which is the root tree of the current head
8181
self._parent_commit = self.repo.commit()
82-
elif attr in ('path', '_url', '_branch'):
82+
elif attr in ('path', '_url', '_branch_path'):
8383
reader = self.config_reader()
8484
# default submodule values
8585
self.path = reader.get_value('path')
8686
self._url = reader.get_value('url')
8787
# git-python extension values - optional
88-
self._branch = mkhead(self.repo, reader.get_value(self.k_head_option, self.k_head_default))
88+
self._branch_path = reader.get_value(self.k_head_option, git.Head.to_full_path(self.k_head_default))
8989
elif attr == '_name':
9090
raise AttributeError("Cannot retrieve the name of a submodule if it was not set initially")
9191
else:
@@ -119,7 +119,7 @@ def __str__(self):
119119
return self._name
120120

121121
def __repr__(self):
122-
return "git.%s(name=%s, path=%s, url=%s, branch=%s)" % (type(self).__name__, self._name, self.path, self.url, self.branch)
122+
return "git.%s(name=%s, path=%s, url=%s, branch_path=%s)" % (type(self).__name__, self._name, self.path, self.url, self.branch_path)
123123

124124
@classmethod
125125
def _config_parser(cls, repo, parent_commit, read_only):
@@ -226,7 +226,7 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False):
226226
# END handle exceptions
227227
# END handle existing
228228

229-
br = mkhead(repo, branch or cls.k_head_default)
229+
br = git.Head.to_full_path(str(branch) or cls.k_head_default)
230230
has_module = sm.module_exists()
231231
branch_is_default = branch is None
232232
if has_module and url is not None:
@@ -250,7 +250,7 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False):
250250
# clone new repo
251251
kwargs = {'n' : no_checkout}
252252
if not branch_is_default:
253-
kwargs['b'] = str(br)
253+
kwargs['b'] = br
254254
# END setup checkout-branch
255255
mrepo = git.Repo.clone_from(url, path, **kwargs)
256256
# END verify url
@@ -264,8 +264,8 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False):
264264
sm._url = url
265265
if not branch_is_default:
266266
# store full path
267-
writer.set_value(cls.k_head_option, br.path)
268-
sm._branch = br.path
267+
writer.set_value(cls.k_head_option, br)
268+
sm._branch_path = br
269269
# END handle path
270270
del(writer)
271271

@@ -327,13 +327,8 @@ def update(self, recursive=False, init=True, to_latest_revision=False):
327327
# see whether we have a valid branch to checkout
328328
try:
329329
# find a remote which has our branch - we try to be flexible
330-
remote_branch = find_first_remote_branch(mrepo.remotes, self.branch)
331-
local_branch = self.branch
332-
if not local_branch.is_valid():
333-
# Setup a tracking configuration - branch doesn't need to
334-
# exist to do that
335-
local_branch.set_tracking_branch(remote_branch)
336-
#END handle local branch
330+
remote_branch = find_first_remote_branch(mrepo.remotes, self.branch_name)
331+
local_branch = mkhead(mrepo, self.branch_path)
337332

338333
# have a valid branch, but no checkout - make sure we can figure
339334
# that out by marking the commit with a null_sha
@@ -349,8 +344,9 @@ def update(self, recursive=False, init=True, to_latest_revision=False):
349344

350345
# make sure HEAD is not detached
351346
mrepo.head.ref = local_branch
347+
mrepo.head.ref.set_tracking_branch(remote_branch)
352348
except IndexError:
353-
print >> sys.stderr, "Warning: Failed to checkout tracking branch %s" % self.branch
349+
print >> sys.stderr, "Warning: Failed to checkout tracking branch %s" % self.branch_path
354350
#END handle tracking branch
355351

356352
# NOTE: Have to write the repo config file as well, otherwise
@@ -516,8 +512,8 @@ def remove(self, module=True, force=False, configuration=True, dry_run=False):
516512
:param module: If True, the module we point to will be deleted
517513
as well. If the module is currently on a commit which is not part
518514
of any branch in the remote, if the currently checked out branch
519-
is ahead of its tracking branch, if you have modifications in the
520515
working tree, or untracked files,
516+
is ahead of its tracking branch, if you have modifications in the
521517
In case the removal of the repository fails for these reasons, the
522518
submodule status will not have been altered.
523519
If this submodule has child-modules on its own, these will be deleted
@@ -611,6 +607,9 @@ def remove(self, module=True, force=False, configuration=True, dry_run=False):
611607
self.repo.config_writer().remove_section(sm_section(self.name))
612608
self.config_writer().remove_section()
613609
# END delete configuration
610+
611+
# void our data not to delay invalid access
612+
self._clear_cache()
614613

615614
return self
616615

@@ -732,8 +731,22 @@ def exists(self):
732731

733732
@property
734733
def branch(self):
735-
""":return: The branch instance that we are to checkout"""
736-
return self._branch
734+
""":return: The branch instance that we are to checkout
735+
:raise InvalidGitRepositoryError: if our module is not yet checked out"""
736+
return mkhead(self.module(), self._branch_path)
737+
738+
@property
739+
def branch_path(self):
740+
""":return: full (relative) path as string to the branch we would checkout
741+
from the remote and track"""
742+
return self._branch_path
743+
744+
@property
745+
def branch_name(self):
746+
""":return: the name of the branch, which is the shortest possible branch name"""
747+
# use an instance method, for this we create a temporary Head instance
748+
# which uses a repository that is available at least ( it makes no difference )
749+
return git.Head(self.repo, self._branch_path).name
737750

738751
@property
739752
def url(self):
@@ -814,7 +827,7 @@ def iter_items(cls, repo, parent_commit='HEAD'):
814827
# fill in remaining info - saves time as it doesn't have to be parsed again
815828
sm._name = n
816829
sm._parent_commit = pc
817-
sm._branch = mkhead(repo, b)
830+
sm._branch_path = git.Head.to_full_path(b)
818831
sm._url = u
819832

820833
yield sm

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

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from base import Submodule
22
from util import (
3-
mkhead,
43
find_first_remote_branch
54
)
65
from git.exc import InvalidGitRepositoryError
@@ -29,7 +28,7 @@ def __init__(self, repo):
2928
name = self.k_root_name,
3029
parent_commit = repo.head.commit,
3130
url = '',
32-
branch = mkhead(repo, self.k_head_default)
31+
branch_path = git.Head.to_full_path(self.k_head_default)
3332
)
3433

3534

@@ -135,8 +134,8 @@ def update(self, previous_commit=None, recursive=True, force_remove=False, init=
135134

136135
# If we have a tracking branch, it should be available
137136
# in the new remote as well.
138-
if len([r for r in smr.refs if r.remote_head == sm.branch.name]) == 0:
139-
raise ValueError("Submodule branch named %r was not available in new submodule remote at %r" % (sm.branch.name, sm.url))
137+
if len([r for r in smr.refs if r.remote_head == sm.branch_name]) == 0:
138+
raise ValueError("Submodule branch named %r was not available in new submodule remote at %r" % (sm.branch_name, sm.url))
140139
# END head is not detached
141140

142141
# now delete the changed one
@@ -181,7 +180,7 @@ def update(self, previous_commit=None, recursive=True, force_remove=False, init=
181180
# tracking branch.
182181
smsha = sm.binsha
183182
found = False
184-
rref = smr.refs[self.branch.name]
183+
rref = smr.refs[self.branch_name]
185184
for c in rref.commit.traverse():
186185
if c.binsha == smsha:
187186
found = True
@@ -203,28 +202,28 @@ def update(self, previous_commit=None, recursive=True, force_remove=False, init=
203202
# END skip remote handling if new url already exists in module
204203
# END handle url
205204

206-
if sm.branch != psm.branch:
205+
if sm.branch_path != psm.branch_path:
207206
# finally, create a new tracking branch which tracks the
208207
# new remote branch
209208
smm = sm.module()
210209
smmr = smm.remotes
211210
try:
212-
tbr = git.Head.create(smm, sm.branch.name)
211+
tbr = git.Head.create(smm, sm.branch_name)
213212
except git.GitCommandError, e:
214213
if e.status != 128:
215214
raise
216215
#END handle something unexpected
217216

218217
# ... or reuse the existing one
219-
tbr = git.Head(smm, git.Head.to_full_path(sm.branch.name))
218+
tbr = git.Head(smm, sm.branch_path)
220219
#END assure tracking branch exists
221220

222-
tbr.set_tracking_branch(find_first_remote_branch(smmr, sm.branch))
221+
tbr.set_tracking_branch(find_first_remote_branch(smmr, sm.branch_name))
223222
# figure out whether the previous tracking branch contains
224223
# new commits compared to the other one, if not we can
225224
# delete it.
226225
try:
227-
tbr = find_first_remote_branch(smmr, psm.branch)
226+
tbr = find_first_remote_branch(smmr, psm.branch_name)
228227
if len(smm.git.cherry(tbr, psm.branch)) == 0:
229228
psm.branch.delete(smm, psm.branch)
230229
#END delete original tracking branch if there are no changes

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,16 @@ def wrapper(self, *args, **kwargs):
3434
wrapper.__name__ = func.__name__
3535
return wrapper
3636

37-
def find_first_remote_branch(remotes, branch):
37+
def find_first_remote_branch(remotes, branch_name):
3838
"""Find the remote branch matching the name of the given branch or raise InvalidGitRepositoryError"""
3939
for remote in remotes:
4040
try:
41-
return remote.refs[branch.name]
41+
return remote.refs[branch_name]
4242
except IndexError:
4343
continue
4444
# END exception handling
4545
#END for remote
46-
raise InvalidGitRepositoryError("Didn't find remote branch %r in any of the given remotes", branch)
46+
raise InvalidGitRepositoryError("Didn't find remote branch %r in any of the given remotes", branch_name)
4747

4848
#} END utilities
4949

Diff for: test/git/test_submodule.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,19 @@ def _do_base_tests(self, rwrepo):
3535
assert sm.path == 'lib/git/ext/gitdb'
3636
assert sm.path != sm.name # in our case, we have ids there, which don't equal the path
3737
assert sm.url == 'git://gitorious.org/git-python/gitdb.git'
38-
assert sm.branch.name == 'master' # its unset in this case
38+
assert sm.branch_path == 'refs/heads/master' # the default ...
39+
assert sm.branch_name == 'master'
3940
assert sm.parent_commit == rwrepo.head.commit
4041
# size is always 0
4142
assert sm.size == 0
43+
# the module is not checked-out yet
44+
self.failUnlessRaises(InvalidGitRepositoryError, sm.module)
45+
46+
# which is why we can't get the branch either - it points into the module() repository
47+
self.failUnlessRaises(InvalidGitRepositoryError, getattr, sm, 'branch')
48+
49+
# branch_path works, as its just a string
50+
assert isinstance(sm.branch_path, basestring)
4251

4352
# some commits earlier we still have a submodule, but its at a different commit
4453
smold = Submodule.iter_items(rwrepo, self.k_subm_changed).next()
@@ -455,7 +464,7 @@ def test_root_module(self, rwrepo):
455464
nsmm = nsm.module()
456465
prev_commit = nsmm.head.commit
457466
for branch in ("some_virtual_branch", cur_branch.name):
458-
nsm.config_writer().set_value(Submodule.k_head_option, branch)
467+
nsm.config_writer().set_value(Submodule.k_head_option, git.Head.to_full_path(branch))
459468
csmbranchchange = rwrepo.index.commit("changed branch to %s" % branch)
460469
nsm.set_parent_commit(csmbranchchange)
461470
# END for each branch to change

0 commit comments

Comments
 (0)