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

Commit20863cf

Browse files
committed
Implemented Submodule.rename()
A test verifies it's truly working.Related togitpython-developers#238
1 parenta223c7b commit20863cf

File tree

7 files changed

+147
-6
lines changed

7 files changed

+147
-6
lines changed

‎doc/source/changes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ Changelog
66
================
77
* Added `Repo.merge_base()` implementation. See the `respective issue on github<https://github.com/gitpython-developers/GitPython/issues/169>`_
88
* `[include]` sections in git configuration files are now respected
9+
* Added `GitConfigParser.rename_section()`
10+
* Added `Submodule.rename()`
911
* A list of all issues can be found here: https://github.com/gitpython-developers/GitPython/issues?q=milestone%3A%22v0.3.6+-+Features%22+
1012

1113
0.3.5 - Bugfixes

‎git/config.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,8 +478,6 @@ def _assure_writable(self, method_name):
478478
ifself.read_only:
479479
raiseIOError("Cannot execute non-constant method %s.%s"% (self,method_name))
480480

481-
@needs_values
482-
@set_dirty_and_flush_changes
483481
defadd_section(self,section):
484482
"""Assures added options will stay in order"""
485483
returnsuper(GitConfigParser,self).add_section(section)
@@ -546,3 +544,23 @@ def set_value(self, section, option, value):
546544
ifnotself.has_section(section):
547545
self.add_section(section)
548546
self.set(section,option,str(value))
547+
548+
defrename_section(self,section,new_name):
549+
"""rename the given section to new_name
550+
:raise ValueError: if section doesn't exit
551+
:raise ValueError: if a section with new_name does already exist
552+
:return: this instance
553+
"""
554+
ifnotself.has_section(section):
555+
raiseValueError("Source section '%s' doesn't exist"%section)
556+
ifself.has_section(new_name):
557+
raiseValueError("Destination section '%s' already exists"%new_name)
558+
559+
super(GitConfigParser,self).add_section(new_name)
560+
fork,vinself.items(section):
561+
self.set(new_name,k,str(v))
562+
# end for each value to copy
563+
564+
# This call writes back the changes, which is why we don't have the respective decorator
565+
self.remove_section(section)
566+
returnself

‎git/objects/submodule/base.py

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,12 @@ def __init__(self, repo, binsha, mode=None, path=None, name=None, parent_commit=
109109
def_set_cache_(self,attr):
110110
ifattr=='_parent_commit':
111111
# set a default value, which is the root tree of the current head
112-
self._parent_commit=self.repo.commit()
112+
try:
113+
self._parent_commit=self.repo.commit()
114+
exceptValueError:
115+
# This fails in an empty repository.
116+
self._parent_commit=None
117+
# end exception handling
113118
elifattrin ('path','_url','_branch_path'):
114119
reader=self.config_reader()
115120
# default submodule values
@@ -163,7 +168,13 @@ def _config_parser(cls, repo, parent_commit, read_only):
163168
:raise IOError: If the .gitmodules file cannot be found, either locally or in the repository
164169
at the given parent commit. Otherwise the exception would be delayed until the first
165170
access of the config parser"""
166-
parent_matches_head=repo.head.commit==parent_commit
171+
try:
172+
parent_matches_head=repo.head.commit==parent_commit
173+
exceptValueError:
174+
# We are most likely in an empty repository, so the HEAD doesn't point to a valid ref
175+
parent_matches_head=True
176+
# end
177+
167178
ifnotrepo.bareandparent_matches_head:
168179
fp_module=os.path.join(repo.working_tree_dir,cls.k_modules_file)
169180
else:
@@ -370,6 +381,14 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False):
370381
mrepo=cls._clone_repo(repo,url,path,name,**kwargs)
371382
# END verify url
372383

384+
# It's important to add the URL to the parent config, to let `git submodule` know.
385+
# otherwise there is a '-' character in front of the submodule listing
386+
# a38efa84daef914e4de58d1905a500d8d14aaf45 mymodule (v0.9.0-1-ga38efa8)
387+
# -a38efa84daef914e4de58d1905a500d8d14aaf45 submodules/intermediate/one
388+
writer=sm.repo.config_writer()
389+
writer.set_value(sm_section(name),'url',url)
390+
writer.release()
391+
373392
# update configuration and index
374393
index=sm.repo.index
375394
writer=sm.config_writer(index=index,write=False)
@@ -386,11 +405,23 @@ def add(cls, repo, name, path, url=None, branch=None, no_checkout=False):
386405
del(writer)
387406

388407
# we deliberatly assume that our head matches our index !
389-
pcommit=repo.head.commit
390-
sm._parent_commit=pcommit
408+
parent_repo_is_empty=False
409+
try:
410+
sm._parent_commit=repo.head.commit
411+
exceptValueError:
412+
parent_repo_is_empty=True
413+
# Can't set this yet, if the parent repo is empty.
414+
# end
391415
sm.binsha=mrepo.head.commit.binsha
392416
index.add([sm],write=True)
393417

418+
ifparent_repo_is_empty:
419+
# The user is expected to make a commit, and this submodule will initialize itself when
420+
# _parent_commit is required
421+
delsm._parent_commit
422+
log.debug("Will not set _parent_commit now as the parent repository has no commit yet.")
423+
# end
424+
394425
returnsm
395426

396427
defupdate(self,recursive=False,init=True,to_latest_revision=False,progress=None,
@@ -875,6 +906,49 @@ def config_writer(self, index=None, write=True):
875906
writer.config._auto_write=write
876907
returnwriter
877908

909+
@unbare_repo
910+
defrename(self,new_name):
911+
"""Rename this submodule
912+
:note: This method takes care of renaming the submodule in various places, such as
913+
914+
* $parent_git_dir/config
915+
* $working_tree_dir/.gitmodules
916+
* (git >=v1.8.0: move submodule repository to new name)
917+
918+
As .gitmodules will be changed, you would need to make a commit afterwards. The changed .gitmodules file
919+
will already be added to the index
920+
921+
:return: this submodule instance
922+
"""
923+
ifself.name==new_name:
924+
returnself
925+
926+
# .git/config
927+
pw=self.repo.config_writer()
928+
# As we ourselves didn't write anything about submodules into the parent .git/config, we will not require
929+
# it to exist, and just ignore missing entries
930+
ifpw.has_section(sm_section(self.name)):
931+
pw.rename_section(sm_section(self.name),sm_section(new_name))
932+
# end
933+
pw.release()
934+
935+
# .gitmodules
936+
cw=self.config_writer().config
937+
cw.rename_section(sm_section(self.name),sm_section(new_name))
938+
cw.release()
939+
940+
self._name=new_name
941+
942+
# .git/modules
943+
mod=self.module()
944+
ifmod.has_separate_working_tree():
945+
module_abspath=self._module_abspath(self.repo,self.path,new_name)
946+
os.renames(mod.git_dir,module_abspath)
947+
self._write_git_file_and_module_config(mod.working_tree_dir,module_abspath)
948+
# end move separate git repository
949+
950+
returnself
951+
878952
#} END edit interface
879953

880954
#{ Query Interface

‎git/repo/base.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,15 @@ def archive(self, ostream, treeish=None, prefix=None, **kwargs):
868868
self.git.archive(treeish,*path,**kwargs)
869869
returnself
870870

871+
defhas_separate_working_tree(self):
872+
""":return: True if our git_dir is not at the root of our working_tree_dir, but a .git file with a
873+
platform agnositic symbolic link. Our git_dir will be whereever the .git file points to
874+
:note: bare repositories will always return False here
875+
"""
876+
ifself.bare:
877+
returnFalse
878+
returnos.path.isfile(os.path.join(self.working_tree_dir,'.git'))
879+
871880
rev_parse=rev_parse
872881

873882
def__repr__(self):

‎git/test/test_config.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,16 @@ def check_test_value(cr, value):
193193
cr=GitConfigParser(fpa,read_only=True)
194194
check_test_value(cr,tv)
195195
cr.release()
196+
197+
deftest_rename(self):
198+
file_obj=self._to_memcache(fixture_path('git_config'))
199+
cw=GitConfigParser(file_obj,read_only=False,merge_includes=False)
200+
201+
self.failUnlessRaises(ValueError,cw.rename_section,"doesntexist","foo")
202+
self.failUnlessRaises(ValueError,cw.rename_section,"core","include")
203+
204+
nn="bee"
205+
assertcw.rename_section('core',nn)iscw
206+
assertnotcw.has_section('core')
207+
assertlen(cw.items(nn))==4
208+
cw.release()

‎git/test/test_repo.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ def test_init(self):
164164
r=Repo.init(path=path,bare=True)
165165
assertisinstance(r,Repo)
166166
assertr.bareisTrue
167+
assertnotr.has_separate_working_tree()
167168
assertos.path.isdir(r.git_dir)
168169

169170
self._assert_empty_repo(r)
@@ -200,6 +201,7 @@ def test_init(self):
200201
os.chdir(git_dir_rela)
201202
r=Repo.init(bare=False)
202203
assertr.bareisFalse
204+
assertnotr.has_separate_working_tree()
203205

204206
self._assert_empty_repo(r)
205207
finally:

‎git/test/test_submodule.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,8 +670,10 @@ def test_git_submodule_compatibility(self, rwdir):
670670
assertmodule_repo_path.startswith(os.path.join(parent.working_tree_dir,sm_path))
671671
ifnotsm._need_gitfile_submodules(parent.git):
672672
assertos.path.isdir(module_repo_path)
673+
assertnotsm.module().has_separate_working_tree()
673674
else:
674675
assertos.path.isfile(module_repo_path)
676+
assertsm.module().has_separate_working_tree()
675677
assertfind_git_dir(module_repo_path)isnotNone,"module pointed to by .git file must be valid"
676678
# end verify submodule 'style'
677679

@@ -689,6 +691,8 @@ def test_git_submodule_compatibility(self, rwdir):
689691
# Fails because there are new commits, compared to the remote we cloned from
690692
self.failUnlessRaises(InvalidGitRepositoryError,sm.remove,dry_run=True)
691693

694+
# TODO: rename nested submodule
695+
692696
# remove
693697
sm_module_path=sm.module().git_dir
694698

@@ -698,3 +702,22 @@ def test_git_submodule_compatibility(self, rwdir):
698702
assertsm.module_exists()==dry_run
699703
assertos.path.isdir(sm_module_path)==dry_run
700704
# end for each dry-run mode
705+
706+
@with_rw_directory
707+
deftest_rename(self,rwdir):
708+
parent=git.Repo.init(os.path.join(rwdir,'parent'))
709+
sm_name='mymodules/myname'
710+
sm=parent.create_submodule(sm_name,'submodules/intermediate/one',url=self._submodule_url())
711+
parent.index.commit("Added submodule")
712+
assertsm._parent_commitisnotNone
713+
714+
assertsm.rename(sm_name)issmandsm.name==sm_name
715+
716+
new_sm_name="shortname"
717+
assertsm.rename(new_sm_name)issm
718+
assertsm.exists()
719+
720+
sm_mod=sm.module()
721+
ifos.path.isfile(os.path.join(sm_mod.working_tree_dir,'.git'))==sm._need_gitfile_submodules(parent.git):
722+
assertsm_mod.git_dir.endswith(".git/modules/"+new_sm_name)
723+
# end

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp