Skip to content

Commit

Permalink
implemented update to_last_revision option including test. Its now po…
Browse files Browse the repository at this point in the history
…ssible to update submodules such as svn-externals
  • Loading branch information
Byron committed Nov 16, 2010
1 parent 21b4db5 commit 78d2cd6
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 6 deletions.
43 changes: 37 additions & 6 deletions lib/git/objects/submodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,18 +211,26 @@ def add(cls, repo, path, url, skip_init=False):
:param skip_init: if True, the new repository will not be cloned to its location.
:return: The newly created submodule instance"""

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


# ASSURE REPO IS PRESENT AND UPTODATE
#####################################
try:
mrepo = self.module()
for remote in mrepo.remotes:
Expand Down Expand Up @@ -277,22 +285,45 @@ def update(self, recursive=False, init=True):
#END handle tracking branch
#END handle initalization


# DETERMINE SHAS TO CHECKOUT
############################
binsha = self.binsha
hexsha = self.hexsha
is_detached = mrepo.head.is_detached
if to_latest_revision:
msg_base = "Cannot update to latest revision in repository at %r as " % mrepo.working_dir
if not is_detached:
rref = mrepo.head.ref.tracking_branch()
if rref is not None:
rcommit = rref.commit
binsha = rcommit.binsha
hexsha = rcommit.hexsha
else:
print >> sys.stderr, "%s a tracking branch was not set for local branch '%s'" % (msg_base, mrepo.head.ref)
# END handle remote ref
else:
print >> sys.stderr, "%s there was no local tracking branch" % msg_base
# END handle detached head
# END handle to_latest_revision option

# update the working tree
if mrepo.head.commit.binsha != self.binsha:
if mrepo.head.is_detached:
mrepo.git.checkout(self.hexsha)
if mrepo.head.commit.binsha != binsha:
if is_detached:
mrepo.git.checkout(hexsha)
else:
# TODO: allow to specify a rebase, merge, or reset
# TODO: Warn if the hexsha forces the tracking branch off the remote
# branch - this should be prevented when setting the branch option
mrepo.head.reset(self.hexsha, index=True, working_tree=True)
mrepo.head.reset(hexsha, index=True, working_tree=True)
# END handle checkout
# END update to new commit only if needed

# HANDLE RECURSION
##################
if recursive:
for submodule in self.iter_items(self.module()):
submodule.update(recursive, init)
submodule.update(recursive, init, to_latest_revision)
# END handle recursive update
# END for each submodule

Expand Down
23 changes: 23 additions & 0 deletions test/git/test_submodule.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,29 @@ def _do_base_tests(self, rwrepo):

# this flushed in a sub-submodule
assert len(list(rwrepo.iter_submodules())) == 2


# reset both heads to the previous version, verify that to_latest_revision works
for repo in (csm.module(), sm.module()):
repo.head.reset('HEAD~1', working_tree=1)
# END for each repo to reset

sm.update(recursive=True, to_latest_revision=True)
for repo in (sm.module(), csm.module()):
assert repo.head.commit == repo.head.ref.tracking_branch().commit
# END for each repo to check

# if the head is detached, it still works ( but warns )
smref = sm.module().head.ref
sm.module().head.ref = 'HEAD~1'
# if there is no tracking branch, we get a warning as well
csm_tracking_branch = csm.module().head.ref.tracking_branch()
csm.module().head.ref.set_tracking_branch(None)
sm.update(recursive=True, to_latest_revision=True)

# undo the changes
sm.module().head.ref = smref
csm.module().head.ref.set_tracking_branch(csm_tracking_branch)
# END handle bare mode


Expand Down

0 comments on commit 78d2cd6

Please sign in to comment.