@@ -739,122 +739,124 @@ def update(
739739 mrepo = None
740740 # END init mrepo
741741
742+ def fetch_remotes (module_repo : "Repo" ) -> None :
743+ rmts = module_repo .remotes
744+ len_rmts = len (rmts )
745+ for i , remote in enumerate (rmts ):
746+ op = FETCH
747+ if i == 0 :
748+ op |= BEGIN
749+ # END handle start
750+
751+ progress .update (
752+ op ,
753+ i ,
754+ len_rmts ,
755+ prefix + "Fetching remote %s of submodule %r" % (remote , self .name ),
756+ )
757+ # ===============================
758+ if not dry_run :
759+ remote .fetch (progress = progress )
760+ # END handle dry-run
761+ # ===============================
762+ if i == len_rmts - 1 :
763+ op |= END
764+ # END handle end
765+ progress .update (
766+ op ,
767+ i ,
768+ len_rmts ,
769+ prefix + "Done fetching remote of submodule %r" % self .name ,
770+ )
771+ # END fetch new data
772+
742773 try :
743774 # ENSURE REPO IS PRESENT AND UP-TO-DATE
744775 #######################################
745776 try :
746777 mrepo = self .module ()
747- rmts = mrepo .remotes
748- len_rmts = len (rmts )
749- for i , remote in enumerate (rmts ):
750- op = FETCH
751- if i == 0 :
752- op |= BEGIN
753- # END handle start
754-
755- progress .update (
756- op ,
757- i ,
758- len_rmts ,
759- prefix + "Fetching remote %s of submodule %r" % (remote , self .name ),
760- )
761- # ===============================
762- if not dry_run :
763- remote .fetch (progress = progress )
764- # END handle dry-run
765- # ===============================
766- if i == len_rmts - 1 :
767- op |= END
768- # END handle end
769- progress .update (
770- op ,
771- i ,
772- len_rmts ,
773- prefix + "Done fetching remote of submodule %r" % self .name ,
774- )
775- # END fetch new data
778+ fetch_remotes (mrepo )
776779 except InvalidGitRepositoryError :
777780 mrepo = None
778781 if not init :
779782 return self
780783 # END early abort if init is not allowed
781784
782- # There is no git-repository yet - but delete empty paths.
783785 checkout_module_abspath = self .abspath
784- if not dry_run and osp .isdir (checkout_module_abspath ):
786+ module_abspath = self ._module_abspath (self .repo , self .path , self .name )
787+
788+ # ``git submodule deinit`` leaves the repository in
789+ # ``.git/modules`` and empties the checkout. Reconnect that retained
790+ # repository instead of trying to clone over it.
791+ if not dry_run and osp .isdir (module_abspath ):
785792 try :
786- os .rmdir (checkout_module_abspath )
787- except OSError as e :
788- raise OSError (
789- "Module directory at %r does already exist and is non-empty" % checkout_module_abspath
790- ) from e
791- # END handle OSError
792- # END handle directory removal
793-
794- # Don't check it out at first - nonetheless it will create a local
795- # branch according to the remote-HEAD if possible.
796- progress .update (
797- BEGIN | CLONE ,
798- 0 ,
799- 1 ,
800- prefix
801- + "Cloning url '%s' to '%s' in submodule %r" % (self .url , checkout_module_abspath , self .name ),
802- )
803- if not dry_run :
804- if self .url .startswith ("." ):
805- url = urllib .parse .urljoin (self .repo .remotes .origin .url + "/" , self .url )
793+ git .Repo (module_abspath )
794+ except InvalidGitRepositoryError :
795+ pass
806796 else :
807- url = self .url
808- mrepo = self ._clone_repo (
809- self .repo ,
810- url ,
811- self .path ,
812- self .name ,
813- n = True ,
814- env = env ,
815- multi_options = clone_multi_options ,
816- allow_unsafe_options = allow_unsafe_options ,
817- allow_unsafe_protocols = allow_unsafe_protocols ,
797+ os .makedirs (checkout_module_abspath , exist_ok = True )
798+ self ._write_git_file_and_module_config (checkout_module_abspath , module_abspath )
799+ mrepo = git .Repo (checkout_module_abspath )
800+ mrepo .head .reset (mrepo .head .commit , index = True , working_tree = True )
801+ fetch_remotes (mrepo )
802+ with self .repo .config_writer () as writer :
803+ writer .set_value (sm_section (self .name ), "url" , self .url )
804+
805+ if mrepo is None :
806+ # There is no git-repository yet - but delete empty paths.
807+ if not dry_run and osp .isdir (checkout_module_abspath ):
808+ try :
809+ os .rmdir (checkout_module_abspath )
810+ except OSError as e :
811+ raise OSError (
812+ "Module directory at %r does already exist and is non-empty" % checkout_module_abspath
813+ ) from e
814+ # END handle directory removal
815+
816+ # Don't check it out at first - nonetheless it will create a local
817+ # branch according to the remote-HEAD if possible.
818+ progress .update (
819+ BEGIN | CLONE ,
820+ 0 ,
821+ 1 ,
822+ prefix
823+ + "Cloning url '%s' to '%s' in submodule %r" % (self .url , checkout_module_abspath , self .name ),
818824 )
819- # END handle dry-run
820- progress .update (
821- END | CLONE ,
822- 0 ,
823- 1 ,
824- prefix + "Done cloning to %s" % checkout_module_abspath ,
825- )
826-
827- if not dry_run :
828- # See whether we have a valid branch to check out.
829- try :
830- mrepo = cast ("Repo" , mrepo )
831- # Find a remote which has our branch - we try to be flexible.
832- remote_branch = find_first_remote_branch (mrepo .remotes , self .branch_name )
833- local_branch = mkhead (mrepo , self .branch_path )
834-
835- # Have a valid branch, but no checkout - make sure we can figure
836- # that out by marking the commit with a null_sha.
837- local_branch .set_object (Object (mrepo , self .NULL_BIN_SHA ))
838- # END initial checkout + branch creation
839-
840- # Make sure HEAD is not detached.
841- mrepo .head .set_reference (
842- local_branch ,
843- logmsg = "submodule: attaching head to %s" % local_branch ,
825+ if not dry_run :
826+ if self .url .startswith ("." ):
827+ url = urllib .parse .urljoin (self .repo .remotes .origin .url + "/" , self .url )
828+ else :
829+ url = self .url
830+ mrepo = self ._clone_repo (
831+ self .repo ,
832+ url ,
833+ self .path ,
834+ self .name ,
835+ n = True ,
836+ env = env ,
837+ multi_options = clone_multi_options ,
838+ allow_unsafe_options = allow_unsafe_options ,
839+ allow_unsafe_protocols = allow_unsafe_protocols ,
844840 )
845- mrepo .head .reference .set_tracking_branch (remote_branch )
846- except (IndexError , InvalidGitRepositoryError ):
847- _logger .warning ("Failed to checkout tracking branch %s" , self .branch_path )
848- # END handle tracking branch
849-
850- # NOTE: Have to write the repo config file as well, otherwise the
851- # default implementation will be offended and not update the
852- # repository. Maybe this is a good way to ensure it doesn't get into
853- # our way, but we want to stay backwards compatible too... It's so
854- # redundant!
855- with self .repo .config_writer () as writer :
856- writer .set_value (sm_section (self .name ), "url" , self .url )
857- # END handle dry_run
841+ progress .update (END | CLONE , 0 , 1 , prefix + "Done cloning to %s" % checkout_module_abspath )
842+
843+ if not dry_run :
844+ # See whether we have a valid branch to check out.
845+ try :
846+ mrepo = cast ("Repo" , mrepo )
847+ remote_branch = find_first_remote_branch (mrepo .remotes , self .branch_name )
848+ local_branch = mkhead (mrepo , self .branch_path )
849+ local_branch .set_object (Object (mrepo , self .NULL_BIN_SHA ))
850+ mrepo .head .set_reference (
851+ local_branch ,
852+ logmsg = "submodule: attaching head to %s" % local_branch ,
853+ )
854+ mrepo .head .reference .set_tracking_branch (remote_branch )
855+ except (IndexError , InvalidGitRepositoryError ):
856+ _logger .warning ("Failed to checkout tracking branch %s" , self .branch_path )
857+
858+ with self .repo .config_writer () as writer :
859+ writer .set_value (sm_section (self .name ), "url" , self .url )
858860 # END handle initialization
859861
860862 # DETERMINE SHAS TO CHECK OUT
0 commit comments