summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-10-27 20:46:26 +0100
committerSebastian Thiel <byronimo@gmail.com>2009-10-27 20:46:26 +0100
commit038f183313f796dc0313c03d652a2bcc1698e78e (patch)
tree11eeaeaec4512e9764d4be568ed24034bd356306
parent5047344a22ed824735d6ed1c91008767ea6638b7 (diff)
downloadgitpython-038f183313f796dc0313c03d652a2bcc1698e78e.tar.gz
implemented test for rejection handling and fixed a bug when parsing remote reference paths
-rw-r--r--TODO7
-rw-r--r--lib/git/remote.py39
-rw-r--r--test/git/test_remote.py33
3 files changed, 58 insertions, 21 deletions
diff --git a/TODO b/TODO
index 4dced9c6..869d9003 100644
--- a/TODO
+++ b/TODO
@@ -107,10 +107,9 @@ Remote
* Fetch should return heads that where updated, pull as well.
* Creation and deletion methods for references should be part of the interface, allowing
repo.create_head(...) instaed of Head.create(repo, ...). Its a convenience thing, clearly
-* When parsing fetch-info, the regex will have problems properly handling white-space in the
- actual head or tag name as it does not know when the optional additional message will begin.
- This can possibly improved by making stronger assumptions about the possible messages or
- by using the data from FETCH_HEAD instead or as additional source of information
+* When parsing fetch-info, the regex will not allow spaces in the target remote ref as
+ I couldn't properly parse the optional space separated note in that case. Probably
+ the regex should be improved to handle this gracefully.
Repo
----
diff --git a/lib/git/remote.py b/lib/git/remote.py
index 90b43467..36c71e7a 100644
--- a/lib/git/remote.py
+++ b/lib/git/remote.py
@@ -8,6 +8,7 @@ Module implementing a remote object allowing easy access to git remotes
"""
from git.utils import LazyMixin, Iterable, IterableList
+from objects import Commit
from refs import Reference, RemoteReference
import re
import os
@@ -58,24 +59,39 @@ class Remote(LazyMixin, Iterable):
info = remote.fetch()[0]
info.remote_ref # Symbolic Reference or RemoteReference to the changed remote head or FETCH_HEAD
info.flags # additional flags to be & with enumeration members, i.e. info.flags & info.REJECTED
- info.note # additional notes given by git-fetch intended for the user
+ info.note # additional notes given by git-fetch intended for the user
+ info.commit_before_forced_update # if info.flags & info.FORCED_UPDATE, field is set to the
+ # previous location of remote_ref, otherwise None
"""
- __slots__ = ('remote_ref', 'flags', 'note')
+ __slots__ = ('remote_ref','commit_before_forced_update', 'flags', 'note')
+
BRANCH_UPTODATE, REJECTED, FORCED_UPDATE, FAST_FORWARD, NEW_TAG, \
TAG_UPDATE, NEW_BRANCH, ERROR = [ 1 << x for x in range(1,9) ]
# %c %-*s %-*s -> %s (%s)
- re_fetch_result = re.compile("^(.) (\[?[\w\s]+\]?)\s+(.+) -> (.+/.+)( \(.*\)?$)?")
+ re_fetch_result = re.compile("^(.) (\[?[\w\s\.]+\]?)\s+(.+) -> (.+/[\w_\.-]+)( \(.*\)?$)?")
_flag_map = { '!' : ERROR, '+' : FORCED_UPDATE, '-' : TAG_UPDATE, '*' : 0,
'=' : BRANCH_UPTODATE, ' ' : FAST_FORWARD }
- def __init__(self, remote_ref, flags, note = ''):
+ def __init__(self, remote_ref, flags, note = '', old_commit = None):
"""
Initialize a new instance
"""
self.remote_ref = remote_ref
self.flags = flags
self.note = note
+ self.commit_before_forced_update = old_commit
+
+ def __str__(self):
+ return self.name
+
+ @property
+ def name(self):
+ """
+ Returns
+ Name of our remote ref
+ """
+ return self.remote_ref.name
@classmethod
def _from_line(cls, repo, line):
@@ -112,14 +128,18 @@ class Remote(LazyMixin, Iterable):
# END control char exception hanlding
# parse operation string for more info
+ old_commit = None
if 'rejected' in operation:
flags |= cls.REJECTED
if 'new tag' in operation:
flags |= cls.NEW_TAG
if 'new branch' in operation:
flags |= cls.NEW_BRANCH
+ if '...' in operation:
+ old_commit = Commit(repo, operation.split('...')[0])
+ # END handle refspec
- return cls(remote_local_ref, flags, note)
+ return cls(remote_local_ref, flags, note, old_commit)
# END FetchInfo definition
@@ -275,7 +295,10 @@ class Remote(LazyMixin, Iterable):
def _get_fetch_info_from_stderr(self, stderr):
# skip first line as it is some remote info we are not interested in
- return [ self.FetchInfo._from_line(self.repo, line) for line in stderr.splitlines()[1:] ]
+ print stderr
+ output = IterableList('name')
+ output.extend(self.FetchInfo._from_line(self.repo, line) for line in stderr.splitlines()[1:])
+ return output
def fetch(self, refspec=None, **kwargs):
"""
@@ -297,7 +320,7 @@ class Remote(LazyMixin, Iterable):
Additional arguments to be passed to git-fetch
Returns
- list(FetchInfo, ...) list of FetchInfo instances providing detailed
+ IterableList(FetchInfo, ...) list of FetchInfo instances providing detailed
information about the fetch results
"""
status, stdout, stderr = self.repo.git.fetch(self, refspec, with_extended_output=True, v=True, **kwargs)
@@ -315,7 +338,7 @@ class Remote(LazyMixin, Iterable):
Additional arguments to be passed to git-pull
Returns
- list(Fetch
+ Please see 'fetch' method
"""
status, stdout, stderr = self.repo.git.pull(self, refspec, v=True, with_extended_output=True, **kwargs)
return self._get_fetch_info_from_stderr(stderr)
diff --git a/test/git/test_remote.py b/test/git/test_remote.py
index ae828cbc..3b145468 100644
--- a/test/git/test_remote.py
+++ b/test/git/test_remote.py
@@ -17,13 +17,18 @@ class TestRemote(TestBase):
fp.close()
- def _check_fetch_results(self, results, remote):
- self._print_fetchhead(remote.repo)
+ def _test_fetch_result(self, results, remote):
+ # self._print_fetchhead(remote.repo)
assert len(results) > 0 and isinstance(results[0], remote.FetchInfo)
- for result in results:
- assert result.flags != 0
- assert isinstance(result.remote_ref, (SymbolicReference, Reference))
- # END for each result
+ for info in results:
+ assert info.flags != 0
+ assert isinstance(info.remote_ref, (SymbolicReference, Reference))
+ if info.flags & info.FORCED_UPDATE:
+ assert isinstance(info.commit_before_forced_update, Commit)
+ else:
+ assert info.commit_before_forced_update is None
+ # END forced update checking
+ # END for each info
def _test_fetch_info(self, repo):
self.failUnlessRaises(ValueError, Remote.FetchInfo._from_line, repo, "nonsense")
@@ -33,10 +38,20 @@ class TestRemote(TestBase):
# specialized fetch testing to de-clutter the main test
self._test_fetch_info(rw_repo)
- fetch_result = remote.fetch()
- self._check_fetch_results(fetch_result, remote)
+ # put remote head to master as it is garantueed to exist
+ remote_repo.head.reference = remote_repo.heads.master
+
+ res = remote.fetch()
+ self._test_fetch_result(res, remote)
+
+ # rewind remote head to trigger rejection
+ # index must be false as remote is a bare repo
+ remote_repo.head.reset("HEAD~2", index=False)
+ res = remote.fetch()
+ self._test_fetch_result(res, remote)
+ master_info = res["%s/master" % remote]
+ assert master_info.flags & Remote.FetchInfo.FORCED_UPDATE and master_info.note is not None
- self.fail("rejected parsing")
self.fail("test parsing of each individual flag")
self.fail("tag handling")