4949
5050
5151# typing ----------------------------------------------------------------------
52- from typing import Callable , Dict ,Mapping , Sequence , TYPE_CHECKING , cast
52+ from typing import Dict ,TYPE_CHECKING
5353from typing import Any ,Iterator ,Union
5454
55- from git .types import Commit_ish ,PathLike , TBD
55+ from git .types import Commit_ish ,PathLike
5656
5757if TYPE_CHECKING :
5858from git .repo import Repo
59- from git .index import IndexFile
6059
6160
6261# -----------------------------------------------------------------------------
@@ -132,17 +131,17 @@ def __init__(self, repo: 'Repo', binsha: bytes,
132131if url is not None :
133132self ._url = url
134133if branch_path is not None :
135- # assert isinstance(branch_path, str)
134+ assert isinstance (branch_path ,str )
136135self ._branch_path = branch_path
137136if name is not None :
138137self ._name = name
139138
140139def _set_cache_ (self ,attr :str )-> None :
141140if attr in ('path' ,'_url' ,'_branch_path' ):
142- reader : SectionConstraint = self .config_reader ()
141+ reader = self .config_reader ()
143142# default submodule values
144143try :
145- self .path : PathLike = reader .get ('path' )
144+ self .path = reader .get ('path' )
146145except cp .NoSectionError as e :
147146if self .repo .working_tree_dir is not None :
148147raise ValueError ("This submodule instance does not exist anymore in '%s' file"
@@ -227,7 +226,7 @@ def _config_parser(cls, repo: 'Repo',
227226
228227return SubmoduleConfigParser (fp_module ,read_only = read_only )
229228
230- def _clear_cache (self )-> None :
229+ def _clear_cache (self ):
231230# clear the possibly changed values
232231for name in self ._cache_attrs :
233232try :
@@ -247,7 +246,7 @@ def _sio_modules(cls, parent_commit: Commit_ish) -> BytesIO:
247246def _config_parser_constrained (self ,read_only :bool )-> SectionConstraint :
248247""":return: Config Parser constrained to our submodule in read or write mode"""
249248try :
250- pc : Union [ 'Commit_ish' , None ] = self .parent_commit
249+ pc = self .parent_commit
251250except ValueError :
252251pc = None
253252# end handle empty parent repository
@@ -256,12 +255,10 @@ def _config_parser_constrained(self, read_only: bool) -> SectionConstraint:
256255return SectionConstraint (parser ,sm_section (self .name ))
257256
258257@classmethod
259- def _module_abspath (cls ,parent_repo : 'Repo' ,path : PathLike ,name : str ) -> PathLike :
258+ def _module_abspath (cls ,parent_repo ,path ,name ) :
260259if cls ._need_gitfile_submodules (parent_repo .git ):
261260return osp .join (parent_repo .git_dir ,'modules' ,name )
262- if parent_repo .working_tree_dir :
263- return osp .join (parent_repo .working_tree_dir ,path )
264- raise NotADirectoryError ()
261+ return osp .join (parent_repo .working_tree_dir ,path )
265262# end
266263
267264@classmethod
@@ -289,15 +286,15 @@ def _clone_repo(cls, repo, url, path, name, **kwargs):
289286return clone
290287
291288@classmethod
292- def _to_relative_path (cls ,parent_repo : 'Repo' ,path : PathLike ) -> PathLike :
289+ def _to_relative_path (cls ,parent_repo ,path ) :
293290""":return: a path guaranteed to be relative to the given parent - repository
294291 :raise ValueError: if path is not contained in the parent repository's working tree"""
295292path = to_native_path_linux (path )
296293if path .endswith ('/' ):
297294path = path [:- 1 ]
298295# END handle trailing slash
299296
300- if osp .isabs (path )and parent_repo . working_tree_dir :
297+ if osp .isabs (path ):
301298working_tree_linux = to_native_path_linux (parent_repo .working_tree_dir )
302299if not path .startswith (working_tree_linux ):
303300raise ValueError ("Submodule checkout path '%s' needs to be within the parents repository at '%s'"
@@ -311,7 +308,7 @@ def _to_relative_path(cls, parent_repo: 'Repo', path: PathLike) -> PathLike:
311308return path
312309
313310@classmethod
314- def _write_git_file_and_module_config (cls ,working_tree_dir : PathLike ,module_abspath : PathLike ) -> None :
311+ def _write_git_file_and_module_config (cls ,working_tree_dir ,module_abspath ) :
315312"""Writes a .git file containing a(preferably) relative path to the actual git module repository.
316313 It is an error if the module_abspath cannot be made into a relative path, relative to the working_tree_dir
317314 :note: will overwrite existing files !
@@ -338,8 +335,7 @@ def _write_git_file_and_module_config(cls, working_tree_dir: PathLike, module_ab
338335
339336@classmethod
340337def add (cls ,repo :'Repo' ,name :str ,path :PathLike ,url :Union [str ,None ]= None ,
341- branch :Union [str ,None ]= None ,no_checkout :bool = False ,depth :Union [int ,None ]= None ,
342- env :Mapping [str ,str ]= None ,clone_multi_options :Union [Sequence [TBD ],None ]= None
338+ branch = None ,no_checkout :bool = False ,depth = None ,env = None
343339 )-> 'Submodule' :
344340"""Add a new submodule to the given repository. This will alter the index
345341 as well as the .gitmodules file, but will not create a new commit.
@@ -373,8 +369,6 @@ def add(cls, repo: 'Repo', name: str, path: PathLike, url: Union[str, None] = No
373369 and is defined in `os.environ`, value from `os.environ` will be used.
374370 If you want to unset some variable, consider providing empty string
375371 as its value.
376- :param clone_multi_options: A list of Clone options. Please see ``git.repo.base.Repo.clone``
377- for details.
378372 :return: The newly created submodule instance
379373 :note: works atomically, such that no change will be done if the repository
380374 update fails for instance"""
@@ -387,15 +381,15 @@ def add(cls, repo: 'Repo', name: str, path: PathLike, url: Union[str, None] = No
387381# assure we never put backslashes into the url, as some operating systems
388382# like it ...
389383if url is not None :
390- url = to_native_path_linux (url )
384+ url = to_native_path_linux (url )# to_native_path_linux does nothing??
391385# END assure url correctness
392386
393387# INSTANTIATE INTERMEDIATE SM
394388sm = cls (repo ,cls .NULL_BIN_SHA ,cls .k_default_mode ,path ,name ,url = 'invalid-temporary' )
395389if sm .exists ():
396390# reretrieve submodule from tree
397391try :
398- sm = repo .head .commit .tree [str ( path )]
392+ sm = repo .head .commit .tree [path ] # type: ignore
399393sm ._name = name
400394return sm
401395except KeyError :
@@ -418,8 +412,7 @@ def add(cls, repo: 'Repo', name: str, path: PathLike, url: Union[str, None] = No
418412# END check url
419413# END verify urls match
420414
421- mrepo :Union [Repo ,None ]= None
422-
415+ mrepo = None
423416if url is None :
424417if not has_module :
425418raise ValueError ("A URL was not given and a repository did not exist at %s" % path )
@@ -432,7 +425,7 @@ def add(cls, repo: 'Repo', name: str, path: PathLike, url: Union[str, None] = No
432425url = urls [0 ]
433426else :
434427# clone new repo
435- kwargs :Dict [str ,Union [bool ,int , Sequence [ TBD ] ]]= {'n' :no_checkout }
428+ kwargs :Dict [str ,Union [bool ,int ]]= {'n' :no_checkout }
436429if not branch_is_default :
437430kwargs ['b' ]= br .name
438431# END setup checkout-branch
@@ -442,8 +435,6 @@ def add(cls, repo: 'Repo', name: str, path: PathLike, url: Union[str, None] = No
442435kwargs ['depth' ]= depth
443436else :
444437raise ValueError ("depth should be an integer" )
445- if clone_multi_options :
446- kwargs ['multi_options' ]= clone_multi_options
447438
448439# _clone_repo(cls, repo, url, path, name, **kwargs):
449440mrepo = cls ._clone_repo (repo ,url ,path ,name ,env = env ,** kwargs )
@@ -456,8 +447,6 @@ def add(cls, repo: 'Repo', name: str, path: PathLike, url: Union[str, None] = No
456447# otherwise there is a '-' character in front of the submodule listing
457448# a38efa84daef914e4de58d1905a500d8d14aaf45 mymodule (v0.9.0-1-ga38efa8)
458449# -a38efa84daef914e4de58d1905a500d8d14aaf45 submodules/intermediate/one
459- writer :Union [GitConfigParser ,SectionConstraint ]
460-
461450with sm .repo .config_writer ()as writer :
462451writer .set_value (sm_section (name ),'url' ,url )
463452
@@ -474,16 +463,13 @@ def add(cls, repo: 'Repo', name: str, path: PathLike, url: Union[str, None] = No
474463sm ._branch_path = br .path
475464
476465# we deliberately assume that our head matches our index !
477- mrepo = cast ('Repo' ,mrepo )
478466sm .binsha = mrepo .head .commit .binsha
479467index .add ([sm ],write = True )
480468
481469return sm
482470
483- def update (self ,recursive :bool = False ,init :bool = True ,to_latest_revision :bool = False ,
484- progress :Union ['UpdateProgress' ,None ]= None ,dry_run :bool = False ,
485- force :bool = False ,keep_going :bool = False ,env :Mapping [str ,str ]= None ,
486- clone_multi_options :Union [Sequence [TBD ],None ]= None ):
471+ def update (self ,recursive = False ,init = True ,to_latest_revision = False ,progress = None ,dry_run = False ,
472+ force = False ,keep_going = False ,env = None ):
487473"""Update the repository of this submodule to point to the checkout
488474 we point at with the binsha of this instance.
489475
@@ -514,8 +500,6 @@ def update(self, recursive: bool = False, init: bool = True, to_latest_revision:
514500 and is defined in `os.environ`, value from `os.environ` will be used.
515501 If you want to unset some variable, consider providing empty string
516502 as its value.
517- :param clone_multi_options: list of Clone options. Please see ``git.repo.base.Repo.clone``
518- for details. Only take effect with `init` option.
519503 :note: does nothing in bare repositories
520504 :note: method is definitely not atomic if recurisve is True
521505 :return: self"""
@@ -582,16 +566,13 @@ def update(self, recursive: bool = False, init: bool = True, to_latest_revision:
582566progress .update (BEGIN | CLONE ,0 ,1 ,prefix + "Cloning url '%s' to '%s' in submodule %r" %
583567 (self .url ,checkout_module_abspath ,self .name ))
584568if not dry_run :
585- mrepo = self ._clone_repo (self .repo ,self .url ,self .path ,self .name ,n = True ,env = env ,
586- multi_options = clone_multi_options )
569+ mrepo = self ._clone_repo (self .repo ,self .url ,self .path ,self .name ,n = True ,env = env )
587570# END handle dry-run
588571progress .update (END | CLONE ,0 ,1 ,prefix + "Done cloning to %s" % checkout_module_abspath )
589572
590573if not dry_run :
591574# see whether we have a valid branch to checkout
592575try :
593- # assert isinstance(mrepo, Repo) # cant do this cos of circular import
594- mrepo = cast ('Repo' ,mrepo )# Try TypeGuard wirh hasattr, or has_remotes&_head protocol?
595576# find a remote which has our branch - we try to be flexible
596577remote_branch = find_first_remote_branch (mrepo .remotes ,self .branch_name )
597578local_branch = mkhead (mrepo ,self .branch_path )
@@ -652,7 +633,7 @@ def update(self, recursive: bool = False, init: bool = True, to_latest_revision:
652633may_reset = True
653634if mrepo .head .commit .binsha != self .NULL_BIN_SHA :
654635base_commit = mrepo .merge_base (mrepo .head .commit ,hexsha )
655- if len (base_commit )== 0 or base_commit [0 ].hexsha == hexsha :# type: ignore
636+ if len (base_commit )== 0 or base_commit [0 ].hexsha == hexsha :
656637if force :
657638msg = "Will force checkout or reset on local branch that is possibly in the future of"
658639msg += "the commit it will be checked out to, effectively 'forgetting' new commits"
@@ -819,8 +800,7 @@ def move(self, module_path, configuration=True, module=True):
819800return self
820801
821802@unbare_repo
822- def remove (self ,module :bool = True ,force :bool = False ,
823- configuration :bool = True ,dry_run :bool = False )-> 'Submodule' :
803+ def remove (self ,module = True ,force = False ,configuration = True ,dry_run = False ):
824804"""Remove this submodule from the repository. This will remove our entry
825805 from the .gitmodules file and the entry in the .git / config file.
826806
@@ -874,7 +854,7 @@ def remove(self, module: bool = True, force: bool = False,
874854# TODO: If we run into permission problems, we have a highly inconsistent
875855# state. Delete the .git folders last, start with the submodules first
876856mp = self .abspath
877- method : Union [ None , Callable [[ PathLike ], None ]] = None
857+ method = None
878858if osp .islink (mp ):
879859method = os .remove
880860elif osp .isdir (mp ):
@@ -927,7 +907,7 @@ def remove(self, module: bool = True, force: bool = False,
927907import gc
928908gc .collect ()
929909try :
930- rmtree (str ( wtd ) )
910+ rmtree (wtd )
931911except Exception as ex :
932912if HIDE_WINDOWS_KNOWN_ERRORS :
933913raise SkipTest ("FIXME: fails with: PermissionError\n {}" .format (ex ))from ex
@@ -941,7 +921,7 @@ def remove(self, module: bool = True, force: bool = False,
941921rmtree (git_dir )
942922except Exception as ex :
943923if HIDE_WINDOWS_KNOWN_ERRORS :
944- raise SkipTest (f "FIXME: fails with: PermissionError\n { ex } " )from ex
924+ raise SkipTest ("FIXME: fails with: PermissionError\n %s" , ex )from ex
945925else :
946926raise
947927# end handle separate bare repository
@@ -965,8 +945,6 @@ def remove(self, module: bool = True, force: bool = False,
965945
966946# now git config - need the config intact, otherwise we can't query
967947# information anymore
968- writer :Union [GitConfigParser ,SectionConstraint ]
969-
970948with self .repo .config_writer ()as writer :
971949writer .remove_section (sm_section (self .name ))
972950
@@ -976,7 +954,7 @@ def remove(self, module: bool = True, force: bool = False,
976954
977955return self
978956
979- def set_parent_commit (self ,commit :Union [Commit_ish ,None ],check : bool = True )-> 'Submodule' :
957+ def set_parent_commit (self ,commit :Union [Commit_ish ,None ],check = True ):
980958"""Set this instance to use the given commit whose tree is supposed to
981959 contain the .gitmodules blob.
982960
@@ -1015,7 +993,7 @@ def set_parent_commit(self, commit: Union[Commit_ish, None], check: bool = True)
1015993# If check is False, we might see a parent-commit that doesn't even contain the submodule anymore.
1016994# in that case, mark our sha as being NULL
1017995try :
1018- self .binsha = pctree [str ( self .path ) ].binsha
996+ self .binsha = pctree [self .path ].binsha # type: ignore
1019997except KeyError :
1020998self .binsha = self .NULL_BIN_SHA
1021999# end
@@ -1024,7 +1002,7 @@ def set_parent_commit(self, commit: Union[Commit_ish, None], check: bool = True)
10241002return self
10251003
10261004@unbare_repo
1027- def config_writer (self ,index : Union [ 'IndexFile' , None ] = None ,write : bool = True )-> SectionConstraint :
1005+ def config_writer (self ,index = None ,write = True ):
10281006""":return: a config writer instance allowing you to read and write the data
10291007 belonging to this submodule into the .gitmodules file.
10301008
@@ -1045,7 +1023,7 @@ def config_writer(self, index: Union['IndexFile', None] = None, write: bool = Tr
10451023return writer
10461024
10471025@unbare_repo
1048- def rename (self ,new_name : str ) -> 'Submodule' :
1026+ def rename (self ,new_name ) :
10491027"""Rename this submodule
10501028 :note: This method takes care of renaming the submodule in various places, such as
10511029
@@ -1080,14 +1058,13 @@ def rename(self, new_name: str) -> 'Submodule':
10801058destination_module_abspath = self ._module_abspath (self .repo ,self .path ,new_name )
10811059source_dir = mod .git_dir
10821060# Let's be sure the submodule name is not so obviously tied to a directory
1083- if str ( destination_module_abspath ) .startswith (str ( mod .git_dir ) ):
1061+ if destination_module_abspath .startswith (mod .git_dir ):
10841062tmp_dir = self ._module_abspath (self .repo ,self .path ,str (uuid .uuid4 ()))
10851063os .renames (source_dir ,tmp_dir )
10861064source_dir = tmp_dir
10871065# end handle self-containment
10881066os .renames (source_dir ,destination_module_abspath )
1089- if mod .working_tree_dir :
1090- self ._write_git_file_and_module_config (mod .working_tree_dir ,destination_module_abspath )
1067+ self ._write_git_file_and_module_config (mod .working_tree_dir ,destination_module_abspath )
10911068# end move separate git repository
10921069
10931070return self
@@ -1097,7 +1074,7 @@ def rename(self, new_name: str) -> 'Submodule':
10971074#{ Query Interface
10981075
10991076@unbare_repo
1100- def module (self )-> 'Repo' :
1077+ def module (self ):
11011078""":return: Repo instance initialized from the repository at our submodule path
11021079 :raise InvalidGitRepositoryError: if a repository was not available. This could
11031080 also mean that it was not yet initialized"""
@@ -1114,7 +1091,7 @@ def module(self) -> 'Repo':
11141091raise InvalidGitRepositoryError ("Repository at %r was not yet checked out" % module_checkout_abspath )
11151092# END handle exceptions
11161093
1117- def module_exists (self )-> bool :
1094+ def module_exists (self ):
11181095""":return: True if our module exists and is a valid git repository. See module() method"""
11191096try :
11201097self .module ()
@@ -1123,7 +1100,7 @@ def module_exists(self) -> bool:
11231100return False
11241101# END handle exception
11251102
1126- def exists (self )-> bool :
1103+ def exists (self ):
11271104"""
11281105 :return: True if the submodule exists, False otherwise. Please note that
11291106 a submodule may exist ( in the .gitmodules file) even though its module
@@ -1164,34 +1141,34 @@ def branch(self):
11641141return mkhead (self .module (),self ._branch_path )
11651142
11661143@property
1167- def branch_path (self )-> PathLike :
1144+ def branch_path (self ):
11681145"""
11691146 :return: full(relative) path as string to the branch we would checkout
11701147 from the remote and track"""
11711148return self ._branch_path
11721149
11731150@property
1174- def branch_name (self )-> str :
1151+ def branch_name (self ):
11751152""":return: the name of the branch, which is the shortest possible branch name"""
11761153# use an instance method, for this we create a temporary Head instance
11771154# which uses a repository that is available at least ( it makes no difference )
11781155return git .Head (self .repo ,self ._branch_path ).name
11791156
11801157@property
1181- def url (self )-> str :
1158+ def url (self ):
11821159""":return: The url to the repository which our module - repository refers to"""
11831160return self ._url
11841161
11851162@property
1186- def parent_commit (self )-> 'Commit_ish' :
1163+ def parent_commit (self ):
11871164""":return: Commit instance with the tree containing the .gitmodules file
11881165 :note: will always point to the current head's commit if it was not set explicitly"""
11891166if self ._parent_commit is None :
11901167return self .repo .commit ()
11911168return self ._parent_commit
11921169
11931170@property
1194- def name (self )-> str :
1171+ def name (self ):
11951172""":return: The name of this submodule. It is used to identify it within the
11961173 .gitmodules file.
11971174 :note: by default, the name is the path at which to find the submodule, but