Skip to content

Commit 06bec1b

Browse files
committed
Fetch now deals with custom refspecs much better.
Even though the test-csae only verifies this spec: +refs/pull/*:refs/heads/pull/* I could locally verify that it indeed handles other ones just as well: +refs/pull/*:refs/pull/* Fixes #243
1 parent b54b939 commit 06bec1b

File tree

5 files changed

+40
-6
lines changed

5 files changed

+40
-6
lines changed

git/remote.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
cp,
1515
)
1616
from .refs import (
17+
Head,
1718
Reference,
1819
RemoteReference,
1920
SymbolicReference,
@@ -177,8 +178,9 @@ class FetchInfo(object):
177178
info.note # additional notes given by git-fetch intended for the user
178179
info.old_commit # if info.flags & info.FORCED_UPDATE|info.FAST_FORWARD,
179180
# field is set to the previous location of ref, otherwise None
181+
info.remote_ref_path # The path from which we fetched on the remote. It's the remote's version of our info.ref
180182
"""
181-
__slots__ = ('ref', 'old_commit', 'flags', 'note')
183+
__slots__ = ('ref', 'old_commit', 'flags', 'note', 'remote_ref_path')
182184

183185
NEW_TAG, NEW_HEAD, HEAD_UPTODATE, TAG_UPDATE, REJECTED, FORCED_UPDATE, \
184186
FAST_FORWARD, ERROR = [1 << x for x in range(8)]
@@ -193,14 +195,15 @@ class FetchInfo(object):
193195
'=': HEAD_UPTODATE,
194196
' ': FAST_FORWARD}
195197

196-
def __init__(self, ref, flags, note='', old_commit=None):
198+
def __init__(self, ref, flags, note='', old_commit=None, remote_ref_path=None):
197199
"""
198200
Initialize a new instance
199201
"""
200202
self.ref = ref
201203
self.flags = flags
202204
self.note = note
203205
self.old_commit = old_commit
206+
self.remote_ref_path = remote_ref_path
204207

205208
def __str__(self):
206209
return self.name
@@ -243,7 +246,7 @@ def _from_line(cls, repo, line, fetch_line):
243246
new_hex_sha, fetch_operation, fetch_note = fetch_line.split("\t")
244247
ref_type_name, fetch_note = fetch_note.split(' ', 1)
245248
except ValueError: # unpack error
246-
raise ValueError("Failed to parse FETCH__HEAD line: %r" % fetch_line)
249+
raise ValueError("Failed to parse FETCH_HEAD line: %r" % fetch_line)
247250

248251
# parse flags from control_character
249252
flags = 0
@@ -288,6 +291,11 @@ def _from_line(cls, repo, line, fetch_line):
288291
# note: remote-tracking is just the first part of the 'remote-tracking branch' token.
289292
# We don't parse it correctly, but its enough to know what to do, and its new in git 1.7something
290293
ref_type = RemoteReference
294+
elif '/' in ref_type_name:
295+
# If the fetch spec look something like this '+refs/pull/*:refs/heads/pull/*', and is thus pretty
296+
# much anything the user wants, we will have trouble to determine what's going on
297+
# For now, we assume the local ref is a Head
298+
ref_type = Head
291299
else:
292300
raise TypeError("Cannot handle reference type: %r" % ref_type_name)
293301
# END handle ref type
@@ -325,7 +333,7 @@ def _from_line(cls, repo, line, fetch_line):
325333

326334
note = (note and note.strip()) or ''
327335

328-
return cls(remote_local_ref, flags, note, old_commit)
336+
return cls(remote_local_ref, flags, note, old_commit, local_remote_ref)
329337

330338

331339
class Remote(LazyMixin, Iterable):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
c2e3c20affa3e2b61a05fdc9ee3061dd416d915e 'refs/pull/1/head' of http://github.com/loic-bot/testrepo
2+
fd8695d980e2c6df62b7785f93fd6292d1e283fb 'refs/pull/1/merge' of http://github.com/loic-bot/testrepo
3+
bb46faf089720d1a3f9e4dc3b11ed5ff77d7e764 'refs/pull/2/head' of http://github.com/loic-bot/testrepo
4+
5faa366d58454eceea811e0e34c502bdd7b37e4b 'refs/pull/2/merge' of http://github.com/loic-bot/testrepo
5+
b3ad3c4f1864b50d4d3e09320947a1a3c34c9ea2 'refs/pull/3/head' of http://github.com/loic-bot/testrepo
6+
71fe57e511776042b009ed4bb281b62b0522b434 'refs/pull/3/merge' of http://github.com/loic-bot/testrepo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
= [up to date] refs/pull/1/head -> pull/1/head
2+
= [up to date] refs/pull/1/merge -> pull/1/merge
3+
= [up to date] refs/pull/2/head -> pull/2/head
4+
= [up to date] refs/pull/2/merge -> pull/2/merge
5+
= [up to date] refs/pull/3/head -> pull/3/head
6+
= [up to date] refs/pull/3/merge -> pull/3/merge

git/test/test_docs.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ def update(self, op_code, cur_count, max_count=None, message=''):
181181
def test_references_and_objects(self, rw_dir):
182182
# [1-test_references_and_objects]
183183
import git
184-
repo = git.Repo.clone_from(self._small_repo_url(), os.path.join(rw_dir, 'repo'))
184+
repo = git.Repo.clone_from(self._small_repo_url(), os.path.join(rw_dir, 'repo'), branch='master')
185185

186186
heads = repo.heads
187187
master = heads.master # lists can be accessed by name for convenience

git/test/test_remote.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
from git.test.lib import (
88
TestBase,
99
with_rw_repo,
10-
with_rw_and_rw_remote_repo
10+
with_rw_and_rw_remote_repo,
11+
fixture
1112
)
1213
from git import (
1314
RemoteProgress,
@@ -520,3 +521,16 @@ def test_fetch_info(self):
520521

521522
assert type(fi.ref) is Reference
522523
assert fi.ref.path == "refs/something/branch"
524+
525+
def test_uncommon_branch_names(self):
526+
stderr_lines = fixture('uncommon_branch_prefix_stderr').decode('ascii').splitlines()
527+
fetch_lines = fixture('uncommon_branch_prefix_FETCH_HEAD').decode('ascii').splitlines()
528+
529+
# The contents of the files above must be fetched with a custom refspec:
530+
# +refs/pull/*:refs/heads/pull/*
531+
res = [FetchInfo._from_line('ShouldntMatterRepo', stderr, fetch_line)
532+
for stderr, fetch_line in zip(stderr_lines, fetch_lines)]
533+
assert len(res)
534+
assert res[0].remote_ref_path == 'refs/pull/1/head'
535+
assert res[0].ref.path == 'refs/heads/pull/1/head'
536+
assert isinstance(res[0].ref, Head)

0 commit comments

Comments
 (0)