Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cf5eadd

Browse files
committed
Updated tests and implementation to verify functionality for handling submodule removals, as well as url changes
1 parent c0990b2 commit cf5eadd

File tree

3 files changed

+111
-20
lines changed

3 files changed

+111
-20
lines changed

lib/git/objects/submodule.py

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,6 @@ def update(self, previous_commit=None, recursive=True, force_remove=False, init=
958958
# END handle previous commit
959959

960960

961-
# HANDLE REMOVALS
962961
psms = self.list_items(repo, parent_commit=previous_commit)
963962
sms = self.list_items(self.module())
964963
spsms = set(psms)
@@ -974,7 +973,9 @@ def update(self, previous_commit=None, recursive=True, force_remove=False, init=
974973
rsm.remove(configuration=False, module=True, force=force_remove)
975974
# END for each removed submodule
976975

977-
# HANDLE PATH RENAMES + url changes + branch changes
976+
# HANDLE PATH RENAMES
977+
#####################
978+
# url changes + branch changes
978979
for csm in (spsms & ssms):
979980
psm = psms[csm.name]
980981
sm = sms[csm.name]
@@ -996,35 +997,79 @@ def update(self, previous_commit=None, recursive=True, force_remove=False, init=
996997

997998
# don't do anything if we already have the url we search in place
998999
if len([r for r in rmts if r.url == sm.url]) == 0:
1000+
1001+
9991002
assert nn not in [r.name for r in rmts]
10001003
smr = smm.create_remote(nn, sm.url)
10011004
smr.fetch()
10021005

1006+
# If we have a tracking branch, it should be available
1007+
# in the new remote as well.
1008+
if len([r for r in smr.refs if r.remote_head == sm.branch.name]) == 0:
1009+
raise ValueError("Submodule branch named %r was not available in new submodule remote at %r" % (sm.branch.name, sm.url))
1010+
# END head is not detached
1011+
10031012
# now delete the changed one
1004-
orig_name = None
1013+
rmt_for_deletion = None
10051014
for remote in rmts:
10061015
if remote.url == psm.url:
1007-
orig_name = remote.name
1008-
smm.delete_remote(remote)
1016+
rmt_for_deletion = remote
10091017
break
10101018
# END if urls match
10111019
# END for each remote
10121020

10131021
# if we didn't find a matching remote, but have exactly one,
10141022
# we can safely use this one
1015-
if len(rmts) == 1:
1016-
orig_name = rmts[0].name
1017-
smm.delete_remote(rmts[0])
1018-
else:
1019-
# if we have not found any remote with the original url
1020-
# we may not have a name. This is a special case,
1021-
# and its okay to fail here
1022-
# Alternatively we could just generate a unique name
1023-
raise InvalidGitRepositoryError("Couldn't find original remote-repo at url %r" % psm.url)
1024-
# END only one remove
1023+
if rmt_for_deletion is None:
1024+
if len(rmts) == 1:
1025+
rmt_for_deletion = rmts[0]
1026+
else:
1027+
# if we have not found any remote with the original url
1028+
# we may not have a name. This is a special case,
1029+
# and its okay to fail here
1030+
# Alternatively we could just generate a unique name and leave all
1031+
# existing ones in place
1032+
raise InvalidGitRepositoryError("Couldn't find original remote-repo at url %r" % psm.url)
1033+
#END handle one single remote
1034+
# END handle check we found a remote
1035+
1036+
orig_name = rmt_for_deletion.name
1037+
smm.delete_remote(rmt_for_deletion)
1038+
# NOTE: Currently we leave tags from the deleted remotes
1039+
# as well as separate tracking branches in the possibly totally
1040+
# changed repository ( someone could have changed the url to
1041+
# another project ). At some point, one might want to clean
1042+
# it up, but the danger is high to remove stuff the user
1043+
# has added explicitly
10251044

10261045
# rename the new remote back to what it was
10271046
smr.rename(orig_name)
1047+
1048+
# early on, we verified that the our current tracking branch
1049+
# exists in the remote. Now we have to assure that the
1050+
# sha we point to is still contained in the new remote
1051+
# tracking branch.
1052+
smsha = sm.binsha
1053+
found = False
1054+
rref = smr.refs[self.branch.name]
1055+
for c in rref.commit.traverse():
1056+
if c.binsha == smsha:
1057+
found = True
1058+
break
1059+
# END traverse all commits in search for sha
1060+
# END for each commit
1061+
1062+
if not found:
1063+
# adjust our internal binsha to use the one of the remote
1064+
# this way, it will be checked out in the next step
1065+
# This will change the submodule relative to us, so
1066+
# the user will be able to commit the change easily
1067+
print >> sys.stderr, "WARNING: Current sha %s was not contained in the tracking branch at the new remote, setting it the the remote's tracking branch" % sm.hexsha
1068+
sm.binsha = rref.commit.binsha
1069+
#END reset binsha
1070+
1071+
#NOTE: All checkout is performed by the base implementation of update
1072+
10281073
# END skip remote handling if new url already exists in module
10291074
# END handle url
10301075

@@ -1049,12 +1094,15 @@ def update(self, previous_commit=None, recursive=True, force_remove=False, init=
10491094
# current remotes, this just means we can't handle it
10501095
pass
10511096
# END exception handling
1097+
1098+
#NOTE: All checkout is done in the base implementation of update
1099+
10521100
#END handle branch
10531101
#END handle
10541102
# END for each common submodule
10551103

10561104
# FINALLY UPDATE ALL ACTUAL SUBMODULES
1057-
##########################################
1105+
######################################
10581106
for sm in sms:
10591107
# update the submodule using the default method
10601108
sm.update(recursive=True, init=init, to_latest_revision=to_latest_revision)

lib/git/remote.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import re
3030
import os
31+
import sys
3132

3233
__all__ = ('RemoteProgress', 'PushInfo', 'FetchInfo', 'Remote')
3334

@@ -591,6 +592,10 @@ def _get_fetch_info_from_stderr(self, proc, progress):
591592
for line in self._digest_process_messages(proc.stderr, progress):
592593
if line.startswith('From') or line.startswith('remote: Total'):
593594
continue
595+
elif line.startswith('warning:'):
596+
print >> sys.stderr, line
597+
continue
598+
# END handle special messages
594599
fetch_info_lines.append(line)
595600
# END for each line
596601

test/git/test_submodule.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ def test_root_module(self, rwrepo):
358358

359359
# modify path without modifying the index entry
360360
# ( which is what the move method would do properly )
361+
#==================================================
361362
sm = rm.children()[0]
362363
pp = "path/prefix"
363364
fp = join_path_native(pp, sm.path)
@@ -388,30 +389,67 @@ def test_root_module(self, rwrepo):
388389
rm.update(recursive=False)
389390
sm.set_parent_commit(cpathchange)
390391
assert sm.module_exists()
391-
assert False
392392

393393
# add submodule
394+
#================
394395
nsmn = "newsubmodule"
395396
nsmp = "submrepo"
396397
nsm = Submodule.add(rwrepo, nsmn, nsmp, url=join_path_native(self.rorepo.working_tree_dir, rsms[0].path, rsms[1].path))
397398
csmadded = rwrepo.index.commit("Added submodule")
399+
nsm.set_parent_commit(csmadded)
400+
assert nsm.module_exists()
401+
# in our case, the module should not exist, which happens if we update a parent
402+
# repo and a new submodule comes into life
403+
nsm.remove(configuration=False, module=True)
404+
assert not nsm.module_exists() and nsm.exists()
405+
406+
rm.update(recursive=False)
407+
assert nsm.module_exists()
408+
409+
398410

399411
# remove submodule - the previous one
412+
#====================================
400413
sm.set_parent_commit(csmadded)
401-
assert not sm.remove().exists()
414+
smp = sm.abspath
415+
assert not sm.remove(module=False).exists()
416+
assert os.path.isdir(smp) # module still exists
402417
csmremoved = rwrepo.index.commit("Removed submodule")
403418

404-
# change url - to the first repository, this way we have a fast checkout, and a completely different
419+
# an update will remove the module
420+
rm.update(recursive=False)
421+
assert not os.path.isdir(smp)
422+
423+
424+
# change url
425+
#=============
426+
# to the first repository, this way we have a fast checkout, and a completely different
405427
# repository at the different url
406428
nsm.set_parent_commit(csmremoved)
407-
nsm.config_writer().set_value('url', join_path_native(self.rorepo.working_tree_dir, rsms[0].path))
429+
nsmurl = join_path_native(self.rorepo.working_tree_dir, rsms[0].path)
430+
nsm.config_writer().set_value('url', nsmurl)
408431
csmpathchange = rwrepo.index.commit("changed url")
432+
nsm.set_parent_commit(csmpathchange)
433+
434+
prev_commit = nsm.module().head.commit
435+
rm.update(recursive=False)
436+
assert nsm.module().remotes.origin.url == nsmurl
437+
# head changed, as the remote url and its commit changed
438+
assert prev_commit != nsm.module().head.commit
439+
440+
assert False
409441

410442
# change branch
443+
#=================
411444
nsm.set_parent_commit(csmpathchange)
412445
# the branch used here is an old failure branch which should ideally stay ... lets see how long that works ;)
413446
nbn = 'pack_offset_cache'
414447
assert nsm.branch.name != nbn
415448
nsm.config_writer().set_value(Submodule.k_head_option, nbn)
416449
csmbranchchange = rwrepo.index.commit("changed branch")
417450

451+
452+
# recursive update
453+
# =================
454+
# finally we recursively update a module, just to run the code at least once
455+

0 commit comments

Comments
 (0)