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

Commit67680a0

Browse files
committed
Assured Submodule.(update|move) are dealing with .git files appropriately.
However, a simple test-case still fails for reasons not yet understood.There is more to be fixed here - .remove() still fails.
1 parent503b62b commit67680a0

File tree

2 files changed

+106
-60
lines changed

2 files changed

+106
-60
lines changed

‎git/objects/submodule/base.py

Lines changed: 92 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@
2525
InvalidGitRepositoryError,
2626
NoSuchPathError
2727
)
28-
fromgit.compatimportstring_types
28+
fromgit.compatimport (
29+
string_types,
30+
defenc
31+
)
2932

3033
importstat
3134
importgit
@@ -209,13 +212,64 @@ def _module_abspath(cls, parent_repo, path, name):
209212
# end
210213

211214
@classmethod
212-
def_write_git_file(cls,working_tree_dir,module_abspath,overwrite_existing=False):
215+
def_clone_repo(cls,repo,url,path,name,**kwargs):
216+
""":return: Repo instance of newly cloned repository
217+
:param repo: our parent repository
218+
:param url: url to clone from
219+
:param path: repository-relative path to the submodule checkout location
220+
:param name: canonical of the submodule
221+
:param kwrags: additinoal arguments given to git.clone"""
222+
module_abspath=cls._module_abspath(repo,path,name)
223+
module_checkout_path=module_abspath
224+
ifcls._need_gitfile_submodules(repo.git):
225+
kwargs['separate_git_dir']=module_abspath
226+
module_abspath_dir=os.path.dirname(module_abspath)
227+
ifnotos.path.isdir(module_abspath_dir):
228+
os.makedirs(module_abspath_dir)
229+
module_checkout_path=os.path.join(repo.working_tree_dir,path)
230+
# end
231+
232+
clone=git.Repo.clone_from(url,module_checkout_path,**kwargs)
233+
ifcls._need_gitfile_submodules(repo.git):
234+
cls._write_git_file(module_checkout_path,module_abspath)
235+
# end
236+
returnclone
237+
238+
@classmethod
239+
def_to_relative_path(cls,parent_repo,path):
240+
""":return: a path guaranteed to be relative to the given parent-repository
241+
:raise ValueError: if path is not contained in the parent repository's working tree"""
242+
path=to_native_path_linux(path)
243+
ifpath.endswith('/'):
244+
path=path[:-1]
245+
# END handle trailing slash
246+
247+
ifos.path.isabs(path):
248+
working_tree_linux=to_native_path_linux(parent_repo.working_tree_dir)
249+
ifnotpath.startswith(working_tree_linux):
250+
raiseValueError("Submodule checkout path '%s' needs to be within the parents repository at '%s'"
251+
% (working_tree_linux,path))
252+
path=path[len(working_tree_linux)+1:]
253+
ifnotpath:
254+
raiseValueError("Absolute submodule path '%s' didn't yield a valid relative path"%path)
255+
# end verify converted relative path makes sense
256+
# end convert to a relative path
257+
258+
returnpath
259+
260+
@classmethod
261+
def_write_git_file(cls,working_tree_dir,module_abspath):
213262
"""Writes a .git file containing a (preferably) relative path to the actual git module repository.
214263
It is an error if the module_abspath cannot be made into a relative path, relative to the working_tree_dir
264+
:note: will overwrite existing files !
215265
:param working_tree_dir: directory to write the .git file into
216266
:param module_abspath: absolute path to the bare repository
217-
:param overwrite_existing: if True, we may rewrite existing .git files, otherwise we raise"""
218-
raiseNotImplementedError
267+
"""
268+
git_file=os.path.join(working_tree_dir,'.git')
269+
rela_path=os.path.relpath(module_abspath,start=working_tree_dir)
270+
fp=open(git_file,'wb')
271+
fp.write(("gitdir: %s"%rela_path).encode(defenc))
272+
fp.close()
219273

220274
#{ Edit Interface
221275

@@ -252,21 +306,7 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False):
252306
raiseInvalidGitRepositoryError("Cannot add submodules to bare repositories")
253307
# END handle bare repos
254308

255-
path=to_native_path_linux(path)
256-
ifpath.endswith('/'):
257-
path=path[:-1]
258-
# END handle trailing slash
259-
260-
ifos.path.isabs(path):
261-
working_tree_linux=to_native_path_linux(repo.working_tree_dir)
262-
ifnotpath.startswith(working_tree_linux):
263-
raiseValueError("Submodule checkout path '%s' needs to be within the parents repository at '%s'"
264-
% (working_tree_linux,path))
265-
path=path[len(working_tree_linux)+1:]
266-
ifnotpath:
267-
raiseValueError("Absolute submodule path '%s' didn't yield a valid relative path"%path)
268-
# end verify converted relative path makes sense
269-
# end convert to a relative path
309+
path=cls._to_relative_path(repo,path)
270310

271311
# assure we never put backslashes into the url, as some operating systems
272312
# like it ...
@@ -317,17 +357,9 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False):
317357
ifnotbranch_is_default:
318358
kwargs['b']=br.name
319359
# END setup checkout-branch
320-
module_abspath=cls._module_abspath(repo,path,name)
321-
module_checkout_path=module_abspath
322-
ifcls._need_gitfile_submodules(repo.git):
323-
kwargs['separate_git_dir']=module_abspath
324-
module_abspath_dir=os.path.dirname(module_abspath)
325-
ifnotos.path.isdir(module_abspath_dir):
326-
os.makedirs(module_abspath_dir)
327-
module_checkout_path=os.path.join(repo.working_tree_dir,path)
328-
# end
329-
330-
mrepo=git.Repo.clone_from(url,module_checkout_path,**kwargs)
360+
361+
# _clone_repo(cls, repo, url, path, name, **kwargs):
362+
mrepo=cls._clone_repo(repo,url,path,name,**kwargs)
331363
# END verify url
332364

333365
# update configuration and index
@@ -416,7 +448,6 @@ def update(self, recursive=False, init=True, to_latest_revision=False, progress=
416448
ifnotinit:
417449
returnself
418450
# END early abort if init is not allowed
419-
importgit
420451

421452
# there is no git-repository yet - but delete empty paths
422453
module_path=self._module_abspath(self.repo,self.path,self.name)
@@ -433,7 +464,7 @@ def update(self, recursive=False, init=True, to_latest_revision=False, progress=
433464
progress.update(BEGIN|CLONE,0,1,prefix+"Cloning %s to %s in submodule %r"%
434465
(self.url,module_path,self.name))
435466
ifnotdry_run:
436-
mrepo=git.Repo.clone_from(self.url,module_path,n=True)
467+
mrepo=self._clone_repo(self.repo,self.url,self.path,self.name,n=True)
437468
# END handle dry-run
438469
progress.update(END|CLONE,0,1,prefix+"Done cloning to %s"%module_path)
439470

@@ -533,16 +564,15 @@ def move(self, module_path, configuration=True, module=True):
533564
the repository at our current path, changing the configuration, as well as
534565
adjusting our index entry accordingly.
535566
536-
:param module_path: the path to which to move our module, given as
537-
repository-relative path. Intermediate directories will be created
567+
:param module_path: the path to which to move our module in the parent repostory's working tree,
568+
given asrepository-relative or absolute path. Intermediate directories will be created
538569
accordingly. If the path already exists, it must be empty.
539-
Trailling (back)slashes are removed automatically
570+
Trailing (back)slashes are removed automatically
540571
:param configuration: if True, the configuration will be adjusted to let
541572
the submodule point to the given path.
542573
:param module: if True, the repository managed by this submodule
543-
will be moved, not the configuration. This will effectively
544-
leave your repository in an inconsistent state unless the configuration
545-
and index already point to the target location.
574+
will be moved as well. If False, we don't move the submodule's checkout, which may leave
575+
the parent repository in an inconsistent state.
546576
:return: self
547577
:raise ValueError: if the module path existed and was not empty, or was a file
548578
:note: Currently the method is not atomic, and it could leave the repository
@@ -552,53 +582,55 @@ def move(self, module_path, configuration=True, module=True):
552582
raiseValueError("You must specify to move at least the module or the configuration of the submodule")
553583
# END handle input
554584

555-
module_path=to_native_path_linux(module_path)
556-
ifmodule_path.endswith('/'):
557-
module_path=module_path[:-1]
558-
# END handle trailing slash
585+
module_checkout_path=self._to_relative_path(self.repo,module_path)
559586

560587
# VERIFY DESTINATION
561-
ifmodule_path==self.path:
588+
ifmodule_checkout_path==self.path:
562589
returnself
563590
# END handle no change
564591

565-
dest_path=join_path_native(self.repo.working_tree_dir,module_path)
566-
ifos.path.isfile(dest_path):
567-
raiseValueError("Cannot move repository onto a file: %s"%dest_path)
592+
module_checkout_abspath=join_path_native(self.repo.working_tree_dir,module_checkout_path)
593+
ifos.path.isfile(module_checkout_abspath):
594+
raiseValueError("Cannot move repository onto a file: %s"%module_checkout_abspath)
568595
# END handle target files
569596

570597
index=self.repo.index
571-
tekey=index.entry_key(module_path,0)
598+
tekey=index.entry_key(module_checkout_path,0)
572599
# if the target item already exists, fail
573600
ifconfigurationandtekeyinindex.entries:
574-
raiseValueError("Index entry for target path didalredy exist")
601+
raiseValueError("Index entry for target path didalready exist")
575602
# END handle index key already there
576603

577604
# remove existing destination
578605
ifmodule:
579-
ifos.path.exists(dest_path):
580-
iflen(os.listdir(dest_path)):
606+
ifos.path.exists(module_checkout_abspath):
607+
iflen(os.listdir(module_checkout_abspath)):
581608
raiseValueError("Destination module directory was not empty")
582-
# END handle non-emptyness
609+
# END handle non-emptiness
583610

584-
ifos.path.islink(dest_path):
585-
os.remove(dest_path)
611+
ifos.path.islink(module_checkout_abspath):
612+
os.remove(module_checkout_abspath)
586613
else:
587-
os.rmdir(dest_path)
614+
os.rmdir(module_checkout_abspath)
588615
# END handle link
589616
else:
590617
# recreate parent directories
591618
# NOTE: renames() does that now
592619
pass
593-
# END handleexistance
620+
# END handleexistence
594621
# END handle module
595622

596623
# move the module into place if possible
597624
cur_path=self.abspath
598625
renamed_module=False
599626
ifmoduleandos.path.exists(cur_path):
600-
os.renames(cur_path,dest_path)
627+
os.renames(cur_path,module_checkout_abspath)
601628
renamed_module=True
629+
630+
ifself._need_gitfile_submodules(self.repo.git):
631+
module_abspath=self._module_abspath(self.repo,self.path,self.name)
632+
self._write_git_file(module_checkout_abspath,module_abspath)
633+
# end handle git file rewrite
602634
# END move physical module
603635

604636
# rename the index entry - have to manipulate the index directly as
@@ -609,22 +641,22 @@ def move(self, module_path, configuration=True, module=True):
609641
ekey=index.entry_key(self.path,0)
610642
entry=index.entries[ekey]
611643
del(index.entries[ekey])
612-
nentry=git.IndexEntry(entry[:3]+ (module_path,)+entry[4:])
644+
nentry=git.IndexEntry(entry[:3]+ (module_checkout_path,)+entry[4:])
613645
index.entries[tekey]=nentry
614646
exceptKeyError:
615647
raiseInvalidGitRepositoryError("Submodule's entry at %r did not exist"% (self.path))
616648
# END handle submodule doesn't exist
617649

618650
# update configuration
619651
writer=self.config_writer(index=index)# auto-write
620-
writer.set_value('path',module_path)
621-
self.path=module_path
652+
writer.set_value('path',module_checkout_path)
653+
self.path=module_checkout_path
622654
writer.release()
623655
del(writer)
624656
# END handle configuration flag
625657
exceptException:
626658
ifrenamed_module:
627-
os.renames(dest_path,cur_path)
659+
os.renames(module_checkout_abspath,cur_path)
628660
# END undo module renaming
629661
raise
630662
# END handle undo rename

‎git/test/test_submodule.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,3 +656,17 @@ def test_git_submodule_compatibility(self, rwdir):
656656
assertos.path.isfile(module_repo_path)
657657
assertfind_git_dir(module_repo_path)isnotNone,"module pointed to by .git file must be valid"
658658
# end verify submodule 'style'
659+
660+
# test move
661+
new_sm_path='submodules/one'
662+
sm.set_parent_commit(parent.commit())
663+
sm.move(new_sm_path)
664+
assertsm.exists()
665+
assertsm.module_exists()
666+
667+
# remove
668+
sm.remove()
669+
assertsm.exist()
670+
sm_module_path=sm.module().git_dir
671+
assertsm.module_exists()
672+
assertos.path.isdir(sm_module_path)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp