diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2015-01-03 14:34:39 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2015-01-03 14:34:39 +0100 |
commit | de9a6bb0c8931e7f74ea35edb372e5ca7d0a5047 (patch) | |
tree | c3a2d653fce535f6433c4f21d9c30f9f12df76d9 /git/remote.py | |
parent | 6becbaf35fa2f807837284d33649ba5376b3fe21 (diff) | |
download | gitpython-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.py | 82 |
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()) |