@@ -529,10 +529,9 @@ def test_root_module(self, rwrepo):
529529
530530# 'apply work' to the nested submodule and assure this is not removed/altered during updates
531531# Need to commit first, otherwise submodule.update wouldn't have a reason to change the head
532- nsm_file = os .path .join (nsm .module ().working_tree_dir ,'new-file' )
532+ touch ( os .path .join (nsm .module ().working_tree_dir ,'new-file' ) )
533533# We cannot expect is_dirty to even run as we wouldn't reset a head to the same location
534534assert nsm .module ().head .commit .hexsha == nsm .hexsha
535- touch (nsm_file )
536535nsm .module ().index .add ([nsm ])
537536nsm .module ().index .commit ("added new file" )
538537rm .update (recursive = False ,dry_run = True ,progress = prog )# would not change head, and thus doens't fail
@@ -778,3 +777,67 @@ def test_rename(self, rwdir):
778777if os .path .isfile (os .path .join (sm_mod .working_tree_dir ,'.git' ))== sm ._need_gitfile_submodules (parent .git ):
779778assert sm_mod .git_dir .endswith (".git/modules/" + new_sm_name )
780779# end
780+
781+ @with_rw_directory
782+ def test_branch_renames (self ,rw_dir ):
783+ # Setup initial sandbox:
784+ # parent repo has one submodule, which has all the latest changes
785+ source_url = self ._submodule_url ()
786+ sm_source_repo = git .Repo .clone_from (source_url ,os .path .join (rw_dir ,'sm-source' ))
787+ parent_repo = git .Repo .init (os .path .join (rw_dir ,'parent' ))
788+ sm = parent_repo .create_submodule ('mysubmodule' ,'subdir/submodule' ,
789+ sm_source_repo .working_tree_dir ,branch = 'master' )
790+ parent_repo .index .commit ('added submodule' )
791+ assert sm .exists ()
792+
793+ # Create feature branch with one new commit in submodule source
794+ sm_fb = sm_source_repo .create_head ('feature' )
795+ sm_fb .checkout ()
796+ new_file = touch (os .path .join (sm_source_repo .working_tree_dir ,'new-file' ))
797+ sm_source_repo .index .add ([new_file ])
798+ sm .repo .index .commit ("added new file" )
799+
800+ # change designated submodule checkout branch to the new upstream feature branch
801+ smcw = sm .config_writer ()
802+ smcw .set_value ('branch' ,sm_fb .name )
803+ smcw .release ()
804+ assert sm .repo .is_dirty (index = True ,working_tree = False )
805+ sm .repo .index .commit ("changed submodule branch to '%s'" % sm_fb )
806+
807+ # verify submodule update with feature branch that leaves currently checked out branch in it's past
808+ sm_mod = sm .module ()
809+ prev_commit = sm_mod .commit ()
810+ assert sm_mod .head .ref .name == 'master'
811+ assert parent_repo .submodule_update ()
812+ assert sm_mod .head .ref .name == sm_fb .name
813+ assert sm_mod .commit ()== prev_commit ,"Without to_latest_revision, we don't change the commit"
814+
815+ assert parent_repo .submodule_update (to_latest_revision = True )
816+ assert sm_mod .head .ref .name == sm_fb .name
817+ assert sm_mod .commit ()== sm_fb .commit
818+
819+ # Create new branch which is in our past, and thus seemingly unrelated to the currently checked out one
820+ # To make it even 'harder', we shall fork and create a new commit
821+ sm_pfb = sm_source_repo .create_head ('past-feature' ,commit = 'HEAD~20' )
822+ sm_pfb .checkout ()
823+ sm_source_repo .index .add ([touch (os .path .join (sm_source_repo .working_tree_dir ,'new-file' ))])
824+ sm_source_repo .index .commit ("new file added, to past of '%r'" % sm_fb )
825+
826+ # Change designated submodule checkout branch to a new commit in its own past
827+ smcw = sm .config_writer ()
828+ smcw .set_value ('branch' ,sm_pfb .path )
829+ smcw .release ()
830+ sm .repo .index .commit ("changed submodule branch to '%s'" % sm_pfb )
831+
832+ # Test submodule updates - must fail if submodule is dirty
833+ touch (os .path .join (sm_mod .working_tree_dir ,'unstaged file' ))
834+ # This doesn't fail as our own submodule binsha didn't change, and the reset is only triggered if
835+ # to latest revision is True.
836+ parent_repo .submodule_update (to_latest_revision = False )
837+ sm_mod .head .ref .name == sm_pfb .name ,"should have been switched to past head"
838+ sm_mod .commit ()== sm_fb .commit ,"Head wasn't reset"
839+
840+ self .failUnlessRaises (RepositoryDirtyError ,parent_repo .submodule_update ,to_latest_revision = True )
841+ parent_repo .submodule_update (to_latest_revision = True ,force_reset = True )
842+ assert sm_mod .commit ()== sm_pfb .commit ,"Now head should have been reset"
843+ assert sm_mod .head .ref .name == sm_pfb .name