summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2009-11-03 20:59:24 +0100
committerSebastian Thiel <byronimo@gmail.com>2009-11-03 21:00:35 +0100
commit43ab2afba68fd0e1b5d138ed99ffc788dc685e36 (patch)
tree2a7281ec51314abe014aa79bd0f760ed7acfbbe7
parente648efdcc1ca904709a646c1dbc797454a307444 (diff)
downloadgitpython-43ab2afba68fd0e1b5d138ed99ffc788dc685e36.tar.gz
refs: iter_items now imlemented natively for additional performance. We did not implement the crazy sorting feature found in git-for-each-ref though
-rw-r--r--TODO7
-rw-r--r--lib/git/refs.py94
-rw-r--r--lib/git/remote.py1
-rw-r--r--test/git/test_refs.py14
-rw-r--r--test/git/test_remote.py1
5 files changed, 54 insertions, 63 deletions
diff --git a/TODO b/TODO
index dc87c8b6..729bb07b 100644
--- a/TODO
+++ b/TODO
@@ -89,9 +89,9 @@ Refs
* Making the reflog available as command might be useful actually. This way historical
references/commits can be returned. Git internally manages this if refs are specified
with HEAD@{0} for instance
-* References should be parsed 'manually' to get around command invocation, but
- be sure to be able to read packed refs.
-
+* Possibly follow symbolic links when manually parsing references by walking the
+ directory tree. Currently the packed-refs file wouldn't be followed either.
+
Remote
------
* When parsing fetch-info, the regex will not allow spaces in the target remote ref as
@@ -113,6 +113,7 @@ Repo
Submodules
----------
* add submodule support
+* see tree
TestSystem
----------
diff --git a/lib/git/refs.py b/lib/git/refs.py
index 9c88c5a1..352c14f4 100644
--- a/lib/git/refs.py
+++ b/lib/git/refs.py
@@ -124,28 +124,57 @@ class Reference(LazyMixin, Iterable):
Defaults to class specific portion if None assuring that only
refs suitable for the actual class are returned.
- ``kwargs``
- Additional options given as keyword arguments, will be passed
- to git-for-each-ref
-
Returns
- git.Ref[]
+ git.Reference[]
- List is sorted by committerdate
- The returned objects are compatible to the Ref base, but represent the
- actual type, such as Head or Tag
+ List is lexigraphically sorted
+ The returned objects represent actual subclasses, such as Head or TagReference
"""
-
- options = {'sort': "committerdate",
- 'format': "%(refname)%00%(objectname)%00%(objecttype)%00%(objectsize)"}
-
if common_path is None:
common_path = cls._common_path_default
- options.update(kwargs)
-
- output = repo.git.for_each_ref(common_path, **options)
- return cls._iter_from_stream(repo, iter(output.splitlines()))
+ rela_paths = set()
+
+ # walk loose refs
+ # Currently we do not follow links
+ for root, dirs, files in os.walk(os.path.join(repo.path, common_path)):
+ for f in files:
+ abs_path = os.path.join(root, f)
+ rela_paths.add(abs_path.replace(repo.path + '/', ""))
+ # END for each file in root directory
+ # END for each directory to walk
+
+ # read packed refs
+ packed_refs_path = os.path.join(repo.path, 'packed-refs')
+ if os.path.isfile(packed_refs_path):
+ fp = open(packed_refs_path, 'r')
+ try:
+ for line in fp.readlines():
+ if line.startswith('#'):
+ continue
+ # 439689865b9c6e2a0dad61db22a0c9855bacf597 refs/heads/hello
+ line = line.rstrip()
+ first_space = line.find(' ')
+ if first_space == -1:
+ continue
+
+ rela_path = line[first_space+1:]
+ if rela_path.startswith(common_path):
+ rela_paths.add(rela_path)
+ # END relative path matches common path
+ # END for each line in packed-refs
+ finally:
+ fp.close()
+ # END packed refs reading
+
+ # return paths in sorted order
+ for path in sorted(rela_paths):
+ if path.endswith('/HEAD'):
+ continue
+ # END skip remote heads
+ yield cls.from_path(repo, path)
+ # END for each sorted relative refpath
+
@classmethod
def from_path(cls, repo, path):
@@ -167,39 +196,6 @@ class Reference(LazyMixin, Iterable):
raise ValueError("Could not find reference type suitable to handle path %r" % path)
- @classmethod
- def _iter_from_stream(cls, repo, stream):
- """ Parse out ref information into a list of Ref compatible objects
- Returns git.Ref[] list of Ref objects """
- heads = []
-
- for line in stream:
- heads.append(cls._from_string(repo, line))
-
- return heads
-
- @classmethod
- def _from_string(cls, repo, line):
- """ Create a new Ref instance from the given string.
- Format
- name: [a-zA-Z_/]+
- <null byte>
- id: [0-9A-Fa-f]{40}
- Returns git.Head """
- full_path, hexsha, type_name, object_size = line.split("\x00")
-
- # No, we keep the object dynamic by allowing it to be retrieved by
- # our path on demand - due to perstent commands it is fast.
- # This reduces the risk that the object does not match
- # the changed ref anymore in case it changes in the meanwhile
- return cls.from_path(repo, full_path)
-
- # obj = get_object_type_by_name(type_name)(repo, hexsha)
- # obj.size = object_size
- # return cls(repo, full_path, obj)
-
-
-
class SymbolicReference(object):
"""
Represents a special case of a reference such that this reference is symbolic.
diff --git a/lib/git/remote.py b/lib/git/remote.py
index 1b054253..b4413cce 100644
--- a/lib/git/remote.py
+++ b/lib/git/remote.py
@@ -445,7 +445,6 @@ class Remote(LazyMixin, Iterable):
Iterator yielding Remote objects of the given repository
"""
for section in repo.config_reader("repository").sections():
- print section
if not section.startswith('remote'):
continue
lbound = section.find('"')
diff --git a/test/git/test_refs.py b/test/git/test_refs.py
index f7f4f71a..6b3c2840 100644
--- a/test/git/test_refs.py
+++ b/test/git/test_refs.py
@@ -32,15 +32,6 @@ class TestRefs(TestBase):
assert tag_object_refs
assert isinstance(self.rorepo.tags['0.1.5'], TagReference)
- @patch_object(Git, '_call_process')
- def test_ref_with_path_component(self, git):
- git.return_value = fixture('for_each_ref_with_path_component')
- head = self.rorepo.heads[0]
-
- assert_equal('refactoring/feature1', head.name)
- assert_true(git.called)
-
-
def test_tags(self):
# tag refs can point to tag objects or to commits
s = set()
@@ -220,3 +211,8 @@ class TestRefs(TestBase):
assert not cur_head.is_detached
assert head.commit == parent_commit
+ # test ref listing - assure we have packed refs
+ rw_repo.git.pack_refs(all=True)
+ assert rw_repo.heads
+ assert rw_repo.tags
+
diff --git a/test/git/test_remote.py b/test/git/test_remote.py
index 156e7764..f049f6f7 100644
--- a/test/git/test_remote.py
+++ b/test/git/test_remote.py
@@ -63,7 +63,6 @@ class TestRemote(TestBase):
def _print_fetchhead(self, repo):
fp = open(os.path.join(repo.path, "FETCH_HEAD"))
- print fp.read()
fp.close()