Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd4fd7fc

Browse files
committed
Submodule now only supports branches to be given as hint that will svn-external like behaviour. Implemented first version of update, which works for now, but probably needs to see more features
1 parentceee7d7 commitd4fd7fc

File tree

4 files changed

+174
-69
lines changed

4 files changed

+174
-69
lines changed

‎lib/git/config.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,23 @@ def __new__(metacls, name, bases, clsdict):
2323
"""
2424
Equip all base-class methods with a needs_values decorator, and all non-const methods
2525
with a set_dirty_and_flush_changes decorator in addition to that."""
26-
mutating_methods=clsdict['_mutating_methods_']
27-
forbaseinbases:
28-
methods= (tfortininspect.getmembers(base,inspect.ismethod)ifnott[0].startswith("_") )
29-
forname,methodinmethods:
30-
ifnameinclsdict:
31-
continue
32-
method_with_values=needs_values(method)
33-
ifnameinmutating_methods:
34-
method_with_values=set_dirty_and_flush_changes(method_with_values)
35-
# END mutating methods handling
36-
37-
clsdict[name]=method_with_values
38-
# END for each base
26+
kmm='_mutating_methods_'
27+
ifkmminclsdict:
28+
mutating_methods=clsdict[kmm]
29+
forbaseinbases:
30+
methods= (tfortininspect.getmembers(base,inspect.ismethod)ifnott[0].startswith("_") )
31+
forname,methodinmethods:
32+
ifnameinclsdict:
33+
continue
34+
method_with_values=needs_values(method)
35+
ifnameinmutating_methods:
36+
method_with_values=set_dirty_and_flush_changes(method_with_values)
37+
# END mutating methods handling
38+
39+
clsdict[name]=method_with_values
40+
# END for each name/method pair
41+
# END for each base
42+
# END if mutating methods configuration is set
3943

4044
new_type=super(MetaParserBuilder,metacls).__new__(metacls,name,bases,clsdict)
4145
returnnew_type

‎lib/git/objects/submodule.py

Lines changed: 116 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
importstat
99

1010
importos
11+
importsys
12+
importweakref
1113

1214
__all__= ("Submodule","RootModule")
1315

@@ -27,11 +29,43 @@ def sm_name(section):
2729
#{ Classes
2830

2931
classSubmoduleConfigParser(GitConfigParser):
30-
"""Catches calls to _write, and updates the .gitmodules blob in the index
32+
"""
33+
Catches calls to _write, and updates the .gitmodules blob in the index
3134
with the new data, if we have written into a stream. Otherwise it will
32-
add the local file to the index to make it correspond with the working tree."""
33-
_mutating_methods_=tuple()
35+
add the local file to the index to make it correspond with the working tree.
36+
Additionally, the cache must be cleared
37+
"""
3438

39+
def__init__(self,*args,**kwargs):
40+
self._smref=None
41+
super(SubmoduleConfigParser,self).__init__(*args,**kwargs)
42+
43+
#{ Interface
44+
defset_submodule(self,submodule):
45+
"""Set this instance's submodule. It must be called before
46+
the first write operation begins"""
47+
self._smref=weakref.ref(submodule)
48+
49+
defflush_to_index(self):
50+
"""Flush changes in our configuration file to the index"""
51+
assertself._smrefisnotNone
52+
# should always have a file here
53+
assertnotisinstance(self._file_or_files,StringIO)
54+
55+
sm=self._smref()
56+
ifsmisnotNone:
57+
sm.repo.index.add([sm.k_modules_file])
58+
sm._clear_cache()
59+
# END handle weakref
60+
61+
#} END interface
62+
63+
#{ Overridden Methods
64+
defwrite(self):
65+
rval=super(SubmoduleConfigParser,self).write()
66+
self.flush_to_index()
67+
returnrval
68+
# END overridden methods
3569

3670
classSubmodule(base.IndexObject,Iterable,Traversable):
3771
"""Implements access to a git submodule. They are special in that their sha
@@ -44,16 +78,16 @@ class Submodule(base.IndexObject, Iterable, Traversable):
4478

4579
_id_attribute_="name"
4680
k_modules_file='.gitmodules'
47-
k_ref_option='ref'
48-
k_ref_default='master'
81+
k_head_option='branch'
82+
k_head_default='master'
4983
k_def_mode=stat.S_IFDIR|stat.S_IFLNK# submodules are directories with link-status
5084

5185
# this is a bogus type for base class compatability
5286
type='submodule'
5387

54-
__slots__= ('_parent_commit','_url','_ref','_name')
88+
__slots__= ('_parent_commit','_url','_branch','_name','__weakref__')
5589

56-
def__init__(self,repo,binsha,mode=None,path=None,name=None,parent_commit=None,url=None,ref=None):
90+
def__init__(self,repo,binsha,mode=None,path=None,name=None,parent_commit=None,url=None,branch=None):
5791
"""Initialize this instance with its attributes. We only document the ones
5892
that differ from ``IndexObject``
5993
:param repo: Our parent repository
@@ -66,8 +100,8 @@ def __init__(self, repo, binsha, mode=None, path=None, name = None, parent_commi
66100
self._parent_commit=parent_commit
67101
ifurlisnotNone:
68102
self._url=url
69-
ifrefisnotNone:
70-
self._ref=ref
103+
ifbranchisnotNone:
104+
self._branch=branch
71105
ifnameisnotNone:
72106
self._name=name
73107

@@ -77,13 +111,13 @@ def _set_cache_(self, attr):
77111
elifattr=='_parent_commit':
78112
# set a default value, which is the root tree of the current head
79113
self._parent_commit=self.repo.commit()
80-
elifattrin ('path','_url','_ref'):
114+
elifattrin ('path','_url','_branch'):
81115
reader=self.config_reader()
82116
# default submodule values
83117
self.path=reader.get_value('path')
84118
self._url=reader.get_value('url')
85119
# git-python extension values - optional
86-
self._ref=reader.get_value(self.k_ref_option,self.k_ref_default)
120+
self._branch=reader.get_value(self.k_head_option,self.k_head_default)
87121
elifattr=='_name':
88122
raiseAttributeError("Cannot retrieve the name of a submodule if it was not set initially")
89123
else:
@@ -132,12 +166,21 @@ def _config_parser(cls, repo, parent_commit, read_only):
132166
# END handle exceptions
133167
# END handle non-bare working tree
134168

135-
ifnotread_onlyandnotparent_matches_head:
169+
ifnotread_onlyand(repo.bareornotparent_matches_head):
136170
raiseValueError("Cannot write blobs of 'historical' submodule configurations")
137171
# END handle writes of historical submodules
138172

139-
returnGitConfigParser(fp_module,read_only=read_only)
173+
returnSubmoduleConfigParser(fp_module,read_only=read_only)
140174

175+
def_clear_cache(self):
176+
# clear the possibly changed values
177+
fornamein ('path','_branch','_url'):
178+
try:
179+
delattr(self,name)
180+
exceptAttributeError:
181+
pass
182+
# END try attr deletion
183+
# END for each name to delete
141184

142185
@classmethod
143186
def_sio_modules(cls,parent_commit):
@@ -149,6 +192,7 @@ def _sio_modules(cls, parent_commit):
149192
def_config_parser_constrained(self,read_only):
150193
""":return: Config Parser constrained to our submodule in read or write mode"""
151194
parser=self._config_parser(self.repo,self._parent_commit,read_only)
195+
parser.set_submodule(self)
152196
returnSectionConstraint(parser,sm_section(self.name))
153197

154198
#{ Edit Interface
@@ -178,6 +222,9 @@ def update(self, recursive=False, init=True):
178222

179223
try:
180224
mrepo=self.module()
225+
forremoteinmrepo.remotes:
226+
remote.fetch()
227+
#END fetch new data
181228
exceptInvalidGitRepositoryError:
182229
ifnotinit:
183230
returnself
@@ -194,25 +241,42 @@ def update(self, recursive=False, init=True):
194241
# END handle OSError
195242
# END handle directory removal
196243

197-
# don't check it out at first
198-
mrepo=git.Repo.clone_from(self.url,self.path,n=True)
199-
# ref can be a tag or a branch - we can checkout branches, but not tags
200-
# tag_ref = git.TagReference(mrepo, TagReference.to_full_path(self.ref))
201-
iftag_ref.is_valid():
202-
#if tag_ref.commit
203-
mrepo.git.checkout(tag_ref)
204-
else:
205-
# assume it is a branch and try it
206-
mrepo.git.checkout(self.hexsha,b=self.ref)
207-
#if mrepo.head.ref.name != self.ref:
208-
#mrepo.head.ref = git.Head(mrepo, git.Head.to_full_path(self.ref
244+
# don't check it out at first - nonetheless it will create a local
245+
# branch according to the remote-HEAD if possible
246+
mrepo=git.Repo.clone_from(self.url,module_path,n=True)
247+
248+
# see whether we have a valid branch to checkout
249+
try:
250+
remote_branch=mrepo.remotes.origin.refs[self.branch]
251+
local_branch=git.Head(mrepo,git.Head.to_full_path(self.branch))
252+
ifnotlocal_branch.is_valid():
253+
mrepo.git.checkout(remote_branch,b=self.branch)
254+
# END initial checkout + branch creation
255+
# make sure we are not detached
256+
mrepo.head.ref=local_branch
257+
exceptIndexError:
258+
print>>sys.stderr,"Warning: Failed to checkout tracking branch %s"%self.branch
259+
#END handle tracking branch
209260
#END handle initalization
210261

211-
# TODO: handle ref-path
212-
ifmrepo.head.commit.binsha!=self.binsha:
213-
mrepo.git.checkout(self.binsha)
262+
# if the commit to checkout is on the current branch, merge the branch
263+
ifmrepo.head.is_detached:
264+
ifmrepo.head.commit.binsha!=self.binsha:
265+
mrepo.git.checkout(self.hexsha)
266+
# END checkout commit
267+
else:
268+
# TODO: allow to specify a rebase, merge, or reset
269+
# TODO: Warn if the hexsha forces the tracking branch off the remote
270+
# branch - this should be prevented when setting the branch option
271+
mrepo.head.reset(self.hexsha,index=True,working_tree=True)
214272
# END handle checkout
215273

274+
ifrecursive:
275+
forsubmoduleinself.iter_items(self.module()):
276+
submodule.update(recursive,init)
277+
# END handle recursive update
278+
# END for each submodule
279+
216280
returnself
217281

218282
defset_parent_commit(self,commit,check=True):
@@ -245,14 +309,8 @@ def set_parent_commit(self, commit, check=True):
245309
# update our sha, it could have changed
246310
self.binsha=pctree[self.path].binsha
247311

248-
# clear the possibly changed values
249-
fornamein ('path','_ref','_url'):
250-
try:
251-
delattr(self,name)
252-
exceptAttributeError:
253-
pass
254-
# END try attr deletion
255-
# END for each name to delete
312+
self._clear_cache()
313+
256314
returnself
257315

258316
defconfig_writer(self):
@@ -262,6 +320,8 @@ def config_writer(self):
262320
:raise ValueError: if trying to get a writer on a parent_commit which does not
263321
match the current head commit
264322
:raise IOError: If the .gitmodules file/blob could not be read"""
323+
ifself.repo.bare:
324+
raiseInvalidGitRepositoryError("Cannot change submodule configuration in a bare repository")
265325
returnself._config_parser_constrained(read_only=False)
266326

267327
#} END edit interface
@@ -279,24 +339,28 @@ def module(self):
279339
raiseInvalidGitRepositoryError("Cannot retrieve module repository in bare parent repositories")
280340
# END handle bare mode
281341

282-
repo_path=join_path_native(self.repo.working_tree_dir,self.path)
342+
module_path=self.module_path()
283343
try:
284-
repo=Repo(repo_path)
344+
repo=Repo(module_path)
285345
ifrepo!=self.repo:
286346
returnrepo
287347
# END handle repo uninitialized
288348
except (InvalidGitRepositoryError,NoSuchPathError):
289349
raiseInvalidGitRepositoryError("No valid repository at %s"%self.path)
290350
else:
291-
raiseInvalidGitRepositoryError("Repository at %r was not yet checked out"%repo_path)
351+
raiseInvalidGitRepositoryError("Repository at %r was not yet checked out"%module_path)
292352
# END handle exceptions
353+
354+
defmodule_path(self):
355+
""":return: full path to the root of our module. It is relative to the filesystem root"""
356+
returnjoin_path_native(self.repo.working_tree_dir,self.path)
293357

294358
@property
295-
defref(self):
296-
""":return: Thereference's name that we are to checkout"""
297-
returnself._ref
359+
defbranch(self):
360+
""":return: Thebranch name that we are to checkout"""
361+
returnself._branch
298362

299-
@property
363+
@property
300364
defurl(self):
301365
""":return: The url to the repository which our module-repository refers to"""
302366
returnself._url
@@ -347,9 +411,9 @@ def iter_items(cls, repo, parent_commit='HEAD'):
347411
n=sm_name(sms)
348412
p=parser.get_value(sms,'path')
349413
u=parser.get_value(sms,'url')
350-
r=cls.k_ref_default
351-
ifparser.has_option(sms,cls.k_ref_option):
352-
r=parser.get_value(sms,cls.k_ref_option)
414+
b=cls.k_head_default
415+
ifparser.has_option(sms,cls.k_head_option):
416+
b=parser.get_value(sms,cls.k_head_option)
353417
# END handle optional information
354418

355419
# get the binsha
@@ -362,7 +426,7 @@ def iter_items(cls, repo, parent_commit='HEAD'):
362426
# fill in remaining info - saves time as it doesn't have to be parsed again
363427
sm._name=n
364428
sm._parent_commit=pc
365-
sm._ref=r
429+
sm._branch=b
366430
sm._url=u
367431

368432
yieldsm
@@ -389,10 +453,14 @@ def __init__(self, repo):
389453
name=self.k_root_name,
390454
parent_commit=repo.head.commit,
391455
url='',
392-
ref=self.k_ref_default
456+
branch=self.k_head_default
393457
)
394458

395459

460+
def_clear_cache(self):
461+
"""May not do anything"""
462+
pass
463+
396464
#{ Interface
397465
defmodule(self):
398466
""":return: the actual repository containing the submodules"""

‎lib/git/objects/util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ def addToStack( stack, item, branch_first, depth ):
343343
ifprune(rval,d ):
344344
continue
345345

346-
skipStartItem=ignore_selfand (item==self )
346+
skipStartItem=ignore_selfand (itemisself )
347347
ifnotskipStartItemandpredicate(rval,d ):
348348
yieldrval
349349

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp