from base import Submodule, UpdateProgress
from util import (
find_first_remote_branch
)
from git.exc import InvalidGitRepositoryError
import git
import sys
__all__ = ["RootModule", "RootUpdateProgress"]
class RootUpdateProgress(UpdateProgress):
"""Utility class which adds more opcodes to the UpdateProgress"""
REMOVE, PATHCHANGE, BRANCHCHANGE, URLCHANGE = [1 > 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
sm.binsha = rref.commit.binsha
#END reset binsha
#NOTE: All checkout is performed by the base implementation of update
#END handle dry_run
progress.update(END|URLCHANGE, i, len_csms, prefix+"Done adjusting url of submodule %r" % (sm.name))
# END skip remote handling if new url already exists in module
# END handle url
# HANDLE PATH CHANGES
#####################
if sm.branch_path != psm.branch_path:
# finally, create a new tracking branch which tracks the
# new remote branch
progress.update(BEGIN|BRANCHCHANGE, i, len_csms, prefix+"Changing branch of submodule %r from %s to %s" % (sm.name, psm.branch_path, sm.branch_path))
if not dry_run:
smm = sm.module()
smmr = smm.remotes
try:
tbr = git.Head.create(smm, sm.branch_name, logmsg='branch: Created from HEAD')
except OSError:
# ... or reuse the existing one
tbr = git.Head(smm, sm.branch_path)
#END assure tracking branch exists
tbr.set_tracking_branch(find_first_remote_branch(smmr, sm.branch_name))
# figure out whether the previous tracking branch contains
# new commits compared to the other one, if not we can
# delete it.
try:
tbr = find_first_remote_branch(smmr, psm.branch_name)
if len(smm.git.cherry(tbr, psm.branch)) == 0:
psm.branch.delete(smm, psm.branch)
#END delete original tracking branch if there are no changes
except InvalidGitRepositoryError:
# ignore it if the previous branch couldn't be found in the
# current remotes, this just means we can't handle it
pass
# END exception handling
#NOTE: All checkout is done in the base implementation of update
#END handle dry_run
progress.update(END|BRANCHCHANGE, i, len_csms, prefix+"Done changing branch of submodule %r" % sm.name)
#END handle branch
#END handle
# END for each common submodule
# FINALLY UPDATE ALL ACTUAL SUBMODULES
######################################
for sm in sms:
# update the submodule using the default method
sm.update(recursive=False, init=init, to_latest_revision=to_latest_revision,
progress=progress, dry_run=dry_run)
# update recursively depth first - question is which inconsitent
# state will be better in case it fails somewhere. Defective branch
# or defective depth. The RootSubmodule type will never process itself,
# which was done in the previous expression
if recursive:
# the module would exist by now if we are not in dry_run mode
if sm.module_exists():
type(self)(sm.module()).update( recursive=True, force_remove=force_remove,
init=init, to_latest_revision=to_latest_revision,
progress=progress, dry_run=dry_run)
#END handle dry_run
#END handle recursive
# END for each submodule to update
def module(self):
""":return: the actual repository containing the submodules"""
return self.repo
#} END interface
#} END classes