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

Commitda12df9

Browse files
committed
Merge branch 'remote-fixes'
2 parentsb7ae99c +3379127 commitda12df9

File tree

7 files changed

+146
-29
lines changed

7 files changed

+146
-29
lines changed

‎git/db/cmd/base.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,20 +432,47 @@ def _from_line(cls, repo, line, fetch_line):
432432
ref_type=None
433433
ifremote_local_ref=="FETCH_HEAD":
434434
ref_type=SymbolicReference
435-
elifref_type_name=="branch":
435+
elifref_type_namein ("remote-tracking","branch"):
436+
# note: remote-tracking is just the first part of the 'remote-tracking branch' token.
437+
# We don't parse it correctly, but its enough to know what to do, and its new in git 1.7something
436438
ref_type=RemoteReference
437439
elifref_type_name=="tag":
438440
ref_type=TagReference
439441
else:
440442
raiseTypeError("Cannot handle reference type: %r"%ref_type_name)
443+
#END handle ref type
441444

442445
# create ref instance
443446
ifref_typeisSymbolicReference:
444447
remote_local_ref=ref_type(repo,"FETCH_HEAD")
445448
else:
446-
remote_local_ref=Reference.from_path(repo,join_path(ref_type._common_path_default,remote_local_ref.strip()))
449+
# determine prefix. Tags are usually pulled into refs/tags, they may have subdirectories.
450+
# It is not clear sometimes where exactly the item is, unless we have an absolute path as indicated
451+
# by the 'ref/' prefix. Otherwise even a tag could be in refs/remotes, which is when it will have the
452+
# 'tags/' subdirectory in its path.
453+
# We don't want to test for actual existence, but try to figure everything out analytically.
454+
ref_path=None
455+
remote_local_ref=remote_local_ref.strip()
456+
ifremote_local_ref.startswith(Reference._common_path_default+"/"):
457+
# always use actual type if we get absolute paths
458+
# Will always be the case if something is fetched outside of refs/remotes (if its not a tag)
459+
ref_path=remote_local_ref
460+
ifref_typeisnotTagReferenceandnotremote_local_ref.startswith(RemoteReference._common_path_default+"/"):
461+
ref_type=Reference
462+
#END downgrade remote reference
463+
elifref_typeisTagReferenceand'tags/'inremote_local_ref:
464+
# even though its a tag, it is located in refs/remotes
465+
ref_path=join_path(RemoteReference._common_path_default,remote_local_ref)
466+
else:
467+
ref_path=join_path(ref_type._common_path_default,remote_local_ref)
468+
#END obtain refpath
469+
470+
# even though the path could be within the git conventions, we make
471+
# sure we respect whatever the user wanted, and disabled path checking
472+
remote_local_ref=ref_type(repo,ref_path,check_path=False)
447473
# END create ref instance
448474

475+
449476
note= (noteandnote.strip() )or''
450477

451478
# parse flags from control_character

‎git/refs/reference.py

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@
1111

1212
__all__= ["Reference"]
1313

14+
#{ Utilities
15+
defrequire_remote_ref_path(func):
16+
"""A decorator raising a TypeError if we are not a valid remote, based on the path"""
17+
defwrapper(self,*args):
18+
ifnotself.path.startswith(self._remote_common_path_default+"/"):
19+
raiseValueError("ref path does not point to a remote reference: %s"%path)
20+
returnfunc(self,*args)
21+
#END wrapper
22+
wrapper.__name__=func.__name__
23+
returnwrapper
24+
#}END utilites
25+
1426

1527
classReference(SymbolicReference,LazyMixin,Iterable):
1628
"""Represents a named reference to any object. Subclasses may apply restrictions though,
@@ -20,20 +32,24 @@ class Reference(SymbolicReference, LazyMixin, Iterable):
2032
_resolve_ref_on_create=True
2133
_common_path_default="refs"
2234

23-
def__init__(self,repo,path):
35+
def__init__(self,repo,path,check_path=True):
2436
"""Initialize this instance
2537
:param repo: Our parent repository
2638
2739
:param path:
2840
Path relative to the .git/ directory pointing to the ref in question, i.e.
29-
refs/heads/master"""
30-
ifnotpath.startswith(self._common_path_default+'/'):
31-
raiseValueError("Cannot instantiate %r from path %s, maybe use %s.to_full_path(name) to safely generate a valid full path from a name"% (self.__class__.__name__,path,type(self).__name__))
41+
refs/heads/master
42+
:param check_path: if False, you can provide any path. Otherwise the path must start with the
43+
default path prefix of this type."""
44+
ifcheck_pathandnotpath.startswith(self._common_path_default+'/'):
45+
raiseValueError("Cannot instantiate %r from path %s"% (self.__class__.__name__,path))
3246
super(Reference,self).__init__(repo,path)
3347

3448

3549
def__str__(self):
3650
returnself.name
51+
52+
#{ Interface
3753

3854
defset_object(self,object,logmsg=None):
3955
"""Special version which checks if the head-log needs an update as well"""
@@ -80,3 +96,30 @@ def iter_items(cls, repo, common_path = None):
8096
"""Equivalent to SymbolicReference.iter_items, but will return non-detached
8197
references as well."""
8298
returncls._iter_items(repo,common_path)
99+
100+
#}END interface
101+
102+
103+
#{ Remote Interface
104+
105+
@property
106+
@require_remote_ref_path
107+
defremote_name(self):
108+
"""
109+
:return:
110+
Name of the remote we are a reference of, such as 'origin' for a reference
111+
named 'origin/master'"""
112+
tokens=self.path.split('/')
113+
# /refs/remotes/<remote name>/<branch_name>
114+
returntokens[2]
115+
116+
@property
117+
@require_remote_ref_path
118+
defremote_head(self):
119+
""":return: Name of the remote head itself, i.e. master.
120+
:note: The returned name is usually not qualified enough to uniquely identify
121+
a branch"""
122+
tokens=self.path.split('/')
123+
return'/'.join(tokens[3:])
124+
125+
#} END remote interface

‎git/refs/remote.py

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class RemoteReference(Head):
1212
"""Represents a reference pointing to a remote head."""
1313
__slots__=tuple()
1414

15-
_common_path_default="refs/remotes"
15+
_common_path_default=Head._remote_common_path_default
1616

1717

1818
@classmethod
@@ -24,24 +24,6 @@ def iter_items(cls, repo, common_path = None, remote=None):
2424
# END handle remote constraint
2525
returnsuper(RemoteReference,cls).iter_items(repo,common_path)
2626

27-
@property
28-
defremote_name(self):
29-
"""
30-
:return:
31-
Name of the remote we are a reference of, such as 'origin' for a reference
32-
named 'origin/master'"""
33-
tokens=self.path.split('/')
34-
# /refs/remotes/<remote name>/<branch_name>
35-
returntokens[2]
36-
37-
@property
38-
defremote_head(self):
39-
""":return: Name of the remote head itself, i.e. master.
40-
:note: The returned name is usually not qualified enough to uniquely identify
41-
a branch"""
42-
tokens=self.path.split('/')
43-
return'/'.join(tokens[3:])
44-
4527
@classmethod
4628
defcreate(cls,*args,**kwargs):
4729
"""Used to disable this method"""

‎git/refs/symbolic.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class SymbolicReference(object):
3636
_resolve_ref_on_create=False
3737
_points_to_commits_only=True
3838
_common_path_default=""
39+
_remote_common_path_default="refs/remotes"
3940
_id_attribute_="name"
4041

4142
re_hexsha_only=re.compile('^[0-9A-Fa-f]{40}$')

‎git/test/db/cmd/test_base.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
fromgit.db.compleximportCmdCompatibilityGitDB
1212
fromgit.db.cmd.baseimport*
1313

14+
fromgit.refsimportTagReference,Reference,RemoteReference
15+
1416
classTestBase(RepoBase):
1517
RepoCls=CmdCompatibilityGitDB
1618

@@ -28,5 +30,62 @@ def test_basics(self):
2830
self.failUnlessRaises(BadObject,gdb.partial_to_complete_sha_hex,invalid_rev)
2931

3032
deftest_fetch_info(self):
31-
self.failUnlessRaises(ValueError,CmdFetchInfo._from_line,self.rorepo,"nonsense",'')
32-
self.failUnlessRaises(ValueError,CmdFetchInfo._from_line,self.rorepo,"? [up to date] 0.1.7RC -> origin/0.1.7RC",'')
33+
self.failUnlessRaises(ValueError,CmdCmdFetchInfo._from_line,self.rorepo,"nonsense",'')
34+
self.failUnlessRaises(ValueError,CmdCmdFetchInfo._from_line,self.rorepo,"? [up to date] 0.1.7RC -> origin/0.1.7RC",'')
35+
36+
37+
deftest_fetch_info(self):
38+
# assure we can handle remote-tracking branches
39+
fetch_info_line_fmt="c437ee5deb8d00cf02f03720693e4c802e99f390not-for-merge%s '0.3' of git://github.com/gitpython-developers/GitPython"
40+
remote_info_line_fmt="* [new branch] nomatter -> %s"
41+
fi=CmdFetchInfo._from_line(self.rorepo,
42+
remote_info_line_fmt%"local/master",
43+
fetch_info_line_fmt%'remote-tracking branch')
44+
45+
# we wouldn't be here if it wouldn't have worked
46+
47+
# handles non-default refspecs: One can specify a different path in refs/remotes
48+
# or a special path just in refs/something for instance
49+
50+
fi=CmdFetchInfo._from_line(self.rorepo,
51+
remote_info_line_fmt%"subdir/tagname",
52+
fetch_info_line_fmt%'tag')
53+
54+
assertisinstance(fi.ref,TagReference)
55+
assertfi.ref.path.startswith('refs/tags')
56+
57+
# it could be in a remote direcftory though
58+
fi=CmdFetchInfo._from_line(self.rorepo,
59+
remote_info_line_fmt%"remotename/tags/tagname",
60+
fetch_info_line_fmt%'tag')
61+
62+
assertisinstance(fi.ref,TagReference)
63+
assertfi.ref.path.startswith('refs/remotes/')
64+
65+
# it can also be anywhere !
66+
tag_path="refs/something/remotename/tags/tagname"
67+
fi=CmdFetchInfo._from_line(self.rorepo,
68+
remote_info_line_fmt%tag_path,
69+
fetch_info_line_fmt%'tag')
70+
71+
assertisinstance(fi.ref,TagReference)
72+
assertfi.ref.path==tag_path
73+
74+
# branches default to refs/remotes
75+
fi=CmdFetchInfo._from_line(self.rorepo,
76+
remote_info_line_fmt%"remotename/branch",
77+
fetch_info_line_fmt%'branch')
78+
79+
assertisinstance(fi.ref,RemoteReference)
80+
assertfi.ref.remote_name=='remotename'
81+
82+
# but you can force it anywhere, in which case we only have a references
83+
fi=CmdFetchInfo._from_line(self.rorepo,
84+
remote_info_line_fmt%"refs/something/branch",
85+
fetch_info_line_fmt%'branch')
86+
87+
asserttype(fi.ref)isReference
88+
assertfi.ref.path=="refs/something/branch"
89+
90+
91+

‎git/test/refs/test_refs.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ def test_from_path(self):
2929
assertisinstance(instance,ref_type)
3030
# END for each name
3131
# END for each type
32+
33+
# invalid path
34+
self.failUnlessRaises(ValueError,TagReference,self.rorepo,"refs/invalid/tag")
35+
# works without path check
36+
TagReference(self.rorepo,"refs/invalid/tag",check_path=False)
3237

3338
deftest_tag_base(self):
3439
tag_object_refs=list()

‎git/test/test_remote.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ def get_info(res, remote, name):
256256
shutil.rmtree(other_repo_dir)
257257
# END test and cleanup
258258

259-
def_test_push_and_pull(self,remote,rw_repo,remote_repo):
259+
def_verify_push_and_pull(self,remote,rw_repo,remote_repo):
260260
# push our changes
261261
lhead=rw_repo.head
262262
lindex=rw_repo.index
@@ -407,7 +407,7 @@ def test_base(self, rw_repo, remote_repo):
407407
# END for each rename ( back to prev_name )
408408

409409
# PUSH/PULL TESTING
410-
self._test_push_and_pull(remote,rw_repo,remote_repo)
410+
self._verify_push_and_pull(remote,rw_repo,remote_repo)
411411

412412
# FETCH TESTING
413413
# Only for remotes - local cases are the same or less complicated

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp