Skip to content

Commit 78d2cd6

Browse files
committed
implemented update to_last_revision option including test. Its now possible to update submodules such as svn-externals
1 parent 21b4db5 commit 78d2cd6

File tree

2 files changed

+60
-6
lines changed

2 files changed

+60
-6
lines changed

lib/git/objects/submodule.py

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,18 +211,26 @@ def add(cls, repo, path, url, skip_init=False):
211211
:param skip_init: if True, the new repository will not be cloned to its location.
212212
:return: The newly created submodule instance"""
213213

214-
def update(self, recursive=False, init=True):
214+
def update(self, recursive=False, init=True, to_latest_revision=False):
215215
"""Update the repository of this submodule to point to the checkout
216216
we point at with the binsha of this instance.
217217
:param recursive: if True, we will operate recursively and update child-
218218
modules as well.
219219
:param init: if True, the module repository will be cloned into place if necessary
220+
:param to_latest_revision: if True, the submodule's sha will be ignored during checkout.
221+
Instead, the remote will be fetched, and the local tracking branch updated.
222+
This only works if we have a local tracking branch, which is the case
223+
if the remote repository had a master branch, or of the 'branch' option
224+
was specified for this submodule and the branch existed remotely
220225
:note: does nothing in bare repositories
221226
:return: self"""
222227
if self.repo.bare:
223228
return self
224229
#END pass in bare mode
225230

231+
232+
# ASSURE REPO IS PRESENT AND UPTODATE
233+
#####################################
226234
try:
227235
mrepo = self.module()
228236
for remote in mrepo.remotes:
@@ -277,22 +285,45 @@ def update(self, recursive=False, init=True):
277285
#END handle tracking branch
278286
#END handle initalization
279287

288+
289+
# DETERMINE SHAS TO CHECKOUT
290+
############################
291+
binsha = self.binsha
292+
hexsha = self.hexsha
293+
is_detached = mrepo.head.is_detached
294+
if to_latest_revision:
295+
msg_base = "Cannot update to latest revision in repository at %r as " % mrepo.working_dir
296+
if not is_detached:
297+
rref = mrepo.head.ref.tracking_branch()
298+
if rref is not None:
299+
rcommit = rref.commit
300+
binsha = rcommit.binsha
301+
hexsha = rcommit.hexsha
302+
else:
303+
print >> sys.stderr, "%s a tracking branch was not set for local branch '%s'" % (msg_base, mrepo.head.ref)
304+
# END handle remote ref
305+
else:
306+
print >> sys.stderr, "%s there was no local tracking branch" % msg_base
307+
# END handle detached head
308+
# END handle to_latest_revision option
309+
280310
# update the working tree
281-
if mrepo.head.commit.binsha != self.binsha:
282-
if mrepo.head.is_detached:
283-
mrepo.git.checkout(self.hexsha)
311+
if mrepo.head.commit.binsha != binsha:
312+
if is_detached:
313+
mrepo.git.checkout(hexsha)
284314
else:
285315
# TODO: allow to specify a rebase, merge, or reset
286316
# TODO: Warn if the hexsha forces the tracking branch off the remote
287317
# branch - this should be prevented when setting the branch option
288-
mrepo.head.reset(self.hexsha, index=True, working_tree=True)
318+
mrepo.head.reset(hexsha, index=True, working_tree=True)
289319
# END handle checkout
290320
# END update to new commit only if needed
291321

292322
# HANDLE RECURSION
323+
##################
293324
if recursive:
294325
for submodule in self.iter_items(self.module()):
295-
submodule.update(recursive, init)
326+
submodule.update(recursive, init, to_latest_revision)
296327
# END handle recursive update
297328
# END for each submodule
298329

test/git/test_submodule.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,29 @@ def _do_base_tests(self, rwrepo):
132132

133133
# this flushed in a sub-submodule
134134
assert len(list(rwrepo.iter_submodules())) == 2
135+
136+
137+
# reset both heads to the previous version, verify that to_latest_revision works
138+
for repo in (csm.module(), sm.module()):
139+
repo.head.reset('HEAD~1', working_tree=1)
140+
# END for each repo to reset
141+
142+
sm.update(recursive=True, to_latest_revision=True)
143+
for repo in (sm.module(), csm.module()):
144+
assert repo.head.commit == repo.head.ref.tracking_branch().commit
145+
# END for each repo to check
146+
147+
# if the head is detached, it still works ( but warns )
148+
smref = sm.module().head.ref
149+
sm.module().head.ref = 'HEAD~1'
150+
# if there is no tracking branch, we get a warning as well
151+
csm_tracking_branch = csm.module().head.ref.tracking_branch()
152+
csm.module().head.ref.set_tracking_branch(None)
153+
sm.update(recursive=True, to_latest_revision=True)
154+
155+
# undo the changes
156+
sm.module().head.ref = smref
157+
csm.module().head.ref.set_tracking_branch(csm_tracking_branch)
135158
# END handle bare mode
136159

137160

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy