summaryrefslogtreecommitdiff
path: root/git/remote.py
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2015-01-03 14:34:39 +0100
committerSebastian Thiel <byronimo@gmail.com>2015-01-03 14:34:39 +0100
commitde9a6bb0c8931e7f74ea35edb372e5ca7d0a5047 (patch)
treec3a2d653fce535f6433c4f21d9c30f9f12df76d9 /git/remote.py
parent6becbaf35fa2f807837284d33649ba5376b3fe21 (diff)
downloadgitpython-de9a6bb0c8931e7f74ea35edb372e5ca7d0a5047.tar.gz
Various fixes and improvements
* GIT_PYTHON_TRACE now behaves correctly for fetch, and pull (i.e. if as_process is used) * Improved parsing of fetch head information However, there is still a messy bit that tries to bring together fetch progress information with fetch head information. Even though it works now, an alternative implementation should be attempted.
Diffstat (limited to 'git/remote.py')
-rw-r--r--git/remote.py82
1 files changed, 52 insertions, 30 deletions
diff --git a/git/remote.py b/git/remote.py
index a9a74ab6..0cd1e2af 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -204,8 +204,12 @@ class FetchInfo(object):
# %c %-*s %-*s -> %s (%s)
re_fetch_result = re.compile("^\s*(.) (\[?[\w\s\.]+\]?)\s+(.+) -> ([/\w_\+\.\-#]+)( \(.*\)?$)?")
- _flag_map = {'!': ERROR, '+': FORCED_UPDATE, '-': TAG_UPDATE, '*': 0,
- '=': HEAD_UPTODATE, ' ': FAST_FORWARD}
+ _flag_map = {'!': ERROR,
+ '+': FORCED_UPDATE,
+ '-': TAG_UPDATE,
+ '*': 0,
+ '=': HEAD_UPTODATE,
+ ' ': FAST_FORWARD}
def __init__(self, ref, flags, note='', old_commit=None):
"""
@@ -259,6 +263,34 @@ class FetchInfo(object):
except ValueError: # unpack error
raise ValueError("Failed to parse FETCH__HEAD line: %r" % fetch_line)
+ # parse flags from control_character
+ flags = 0
+ try:
+ flags |= cls._flag_map[control_character]
+ except KeyError:
+ raise ValueError("Control character %r unknown as parsed from line %r" % (control_character, line))
+ # END control char exception hanlding
+
+ # parse operation string for more info - makes no sense for symbolic refs, but we parse it anyway
+ old_commit = None
+ is_tag_operation = False
+ if 'rejected' in operation:
+ flags |= cls.REJECTED
+ if 'new tag' in operation:
+ flags |= cls.NEW_TAG
+ is_tag_operation = True
+ if 'tag update' in operation:
+ flags |= cls.TAG_UPDATE
+ is_tag_operation = True
+ if 'new branch' in operation:
+ flags |= cls.NEW_HEAD
+ if '...' in operation or '..' in operation:
+ split_token = '...'
+ if control_character == ' ':
+ split_token = split_token[:-1]
+ old_commit = repo.rev_parse(operation.split(split_token)[0])
+ # END handle refspec
+
# handle FETCH_HEAD and figure out ref type
# If we do not specify a target branch like master:refs/remotes/origin/master,
# the fetch result is stored in FETCH_HEAD which destroys the rule we usually
@@ -266,12 +298,12 @@ class FetchInfo(object):
ref_type = None
if remote_local_ref == "FETCH_HEAD":
ref_type = SymbolicReference
+ elif ref_type_name == "tag" or is_tag_operation:
+ ref_type = TagReference
elif ref_type_name in ("remote-tracking", "branch"):
# note: remote-tracking is just the first part of the 'remote-tracking branch' token.
# We don't parse it correctly, but its enough to know what to do, and its new in git 1.7something
ref_type = RemoteReference
- elif ref_type_name == "tag":
- ref_type = TagReference
else:
raise TypeError("Cannot handle reference type: %r" % ref_type_name)
# END handle ref type
@@ -308,31 +340,6 @@ class FetchInfo(object):
note = (note and note.strip()) or ''
- # parse flags from control_character
- flags = 0
- try:
- flags |= cls._flag_map[control_character]
- except KeyError:
- raise ValueError("Control character %r unknown as parsed from line %r" % (control_character, line))
- # END control char exception hanlding
-
- # parse operation string for more info - makes no sense for symbolic refs
- old_commit = None
- if isinstance(remote_local_ref, Reference):
- if 'rejected' in operation:
- flags |= cls.REJECTED
- if 'new tag' in operation:
- flags |= cls.NEW_TAG
- if 'new branch' in operation:
- flags |= cls.NEW_HEAD
- if '...' in operation or '..' in operation:
- split_token = '...'
- if control_character == ' ':
- split_token = split_token[:-1]
- old_commit = repo.rev_parse(operation.split(split_token)[0])
- # END handle refspec
- # END reference flag handling
-
return cls(remote_local_ref, flags, note, old_commit)
@@ -513,9 +520,17 @@ class Remote(LazyMixin, Iterable):
# this also waits for the command to finish
# Skip some progress lines that don't provide relevant information
fetch_info_lines = list()
+ # fetches all for later in case we don't get any ... this handling is a bit fishy as
+ # the underlying logic of git is not properly understood. This fix merely helps a test-case, and probably
+ # won't be too wrong otherwise.
+ fetch_info_lines_reserve = list()
for line in digest_process_messages(proc.stderr, progress):
+ # cc, _, _ = line.split('\t', 3)
if line.startswith('From') or line.startswith('remote: Total') or line.startswith('POST') \
or line.startswith(' ='):
+ # Why do we even skip lines that begin with a = ?
+ if line.startswith(' ='):
+ fetch_info_lines_reserve.append(line)
continue
elif line.startswith('warning:'):
print >> sys.stderr, line
@@ -536,9 +551,15 @@ class Remote(LazyMixin, Iterable):
# This project needs a lot of work !
# assert len(fetch_info_lines) == len(fetch_head_info), "len(%s) != len(%s)" % (fetch_head_info, fetch_info_lines)
+ # EVIL HACK: This basically fixes our test-case, and possibly helps better results to be returned in future
+ # The actual question is why we are unable to properly parse progress messages and sync them to the
+ # respective fetch-head information ... .
+ if len(fetch_info_lines) != len(fetch_head_info) and len(fetch_info_lines_reserve) == len(fetch_head_info):
+ fetch_info_lines = fetch_info_lines_reserve
+ # end
+
output.extend(FetchInfo._from_line(self.repo, err_line, fetch_line)
for err_line, fetch_line in zip(fetch_info_lines, fetch_head_info))
-
finalize_process(proc)
return output
@@ -594,6 +615,7 @@ class Remote(LazyMixin, Iterable):
args = refspec
else:
args = [refspec]
+
proc = self.repo.git.fetch(self, *args, with_extended_output=True, as_process=True, v=True, **kwargs)
return self._get_fetch_info_from_stderr(proc, progress or RemoteProgress())