22from io import BytesIO
33import logging
44import os
5+ import re
56import stat
67from unittest import SkipTest
78import uuid
2425 BadName
2526)
2627from git .objects .base import IndexObject , Object
28+ from git .objects .submodule .util import SM_SECTION_NAME_REGEX
2729from git .objects .util import Traversable
2830from git .util import (
2931 Iterable ,
@@ -116,20 +118,28 @@ def __init__(self, repo, binsha, mode=None, path=None, name=None, parent_commit=
116118 self ._name = name
117119
118120 def _set_cache_ (self , attr ):
119- if attr in ('path' , '_url' , '_branch_path' ):
121+ if attr in ('path' , '_url' , '_branch_path' , '_name' ):
120122 reader = self .config_reader ()
121123 # default submodule values
122124 try :
123125 self .path = reader .get ('path' )
124126 except cp .NoSectionError as e :
125- raise ValueError ("This submodule instance does not exist anymore in '%s' file"
126- % osp .join (self .repo .working_tree_dir , '.gitmodules' )) from e
127+ if self .repo .working_tree_dir :
128+ raise ValueError ("This submodule instance does not exist anymore in '%s' file"
129+ % osp .join (self .repo .working_tree_dir , '.gitmodules' )) from e
130+ else :
131+ raise ValueError ("This submodule instance does not exist anymore in bare repo at '%s'"
132+ % self .repo .git_dir ) from e
127133 # end
128134 self ._url = reader .get ('url' )
129135 # git-python extension values - optional
130136 self ._branch_path = reader .get_value (self .k_head_option , git .Head .to_full_path (self .k_head_default ))
131- elif attr == '_name' :
132- raise AttributeError ("Cannot retrieve the name of a submodule if it was not set initially" )
137+ section_name = reader ._section_name
138+ m = re .match (SM_SECTION_NAME_REGEX , section_name )
139+ if not m :
140+ raise RuntimeError ('Unexpected submodule section name in %s: %s' % (reader .file_or_files , section_name ))
141+ name = m ['name' ]
142+ self ._name = name
133143 else :
134144 super (Submodule , self )._set_cache_ (attr )
135145 # END handle attribute name
@@ -362,9 +372,7 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False, depth=N
362372 if sm .exists ():
363373 # reretrieve submodule from tree
364374 try :
365- sm = repo .head .commit .tree [path ]
366- sm ._name = name
367- return sm
375+ return repo .head .commit [path ]
368376 except KeyError :
369377 # could only be in index
370378 index = repo .index
@@ -927,7 +935,7 @@ def remove(self, module=True, force=False, configuration=True, dry_run=False):
927935
928936 return self
929937
930- def set_parent_commit (self , commit , check = True ):
938+ def set_parent_commit (self , commit , check = True , pcommit_name = None ):
931939 """Set this instance to use the given commit whose tree is supposed to
932940 contain the .gitmodules blob.
933941
@@ -953,20 +961,17 @@ def set_parent_commit(self, commit, check=True):
953961
954962 prev_pc = self ._parent_commit
955963 self ._parent_commit = pcommit
964+ if pcommit_name :
965+ self ._name = pcommit_name
956966
957967 if check :
958- parser = self ._config_parser (self .repo , self ._parent_commit , read_only = True )
959- if not parser .has_section (sm_section (self .name )):
960- self ._parent_commit = prev_pc
961- raise ValueError ("Submodule at path %r did not exist in parent commit %s" % (self .path , commit ))
962- # END handle submodule did not exist
963- # END handle checking mode
968+ self ._set_cache_ ('path' )
964969
965970 # update our sha, it could have changed
966971 # If check is False, we might see a parent-commit that doesn't even contain the submodule anymore.
967972 # in that case, mark our sha as being NULL
968973 try :
969- self .binsha = pctree [ self .path ] .binsha
974+ self .binsha = pctree . join ( self .path , parent_commit = pcommit ) .binsha
970975 except KeyError :
971976 self .binsha = self .NULL_BIN_SHA
972977 # end
@@ -1140,6 +1145,14 @@ def parent_commit(self):
11401145 return self .repo .commit ()
11411146 return self ._parent_commit
11421147
1148+ @parent_commit .setter
1149+ def parent_commit (self , parent_commit ):
1150+ assert parent_commit
1151+ if self ._parent_commit != parent_commit :
1152+ self ._clear_cache ()
1153+ self ._parent_commit = parent_commit
1154+
1155+
11431156 @property
11441157 def name (self ):
11451158 """:return: The name of this submodule. It is used to identify it within the
@@ -1195,7 +1208,7 @@ def iter_items(cls, repo, parent_commit='HEAD'):
11951208 # get the binsha
11961209 index = repo .index
11971210 try :
1198- sm = rt [p ]
1211+ sm = pc [p ]
11991212 except KeyError :
12001213 # try the index, maybe it was just added
12011214 try :
0 commit comments