diff options
author | Sebastian Thiel <byronimo@gmail.com> | 2009-11-03 20:59:24 +0100 |
---|---|---|
committer | Sebastian Thiel <byronimo@gmail.com> | 2009-11-03 21:00:35 +0100 |
commit | 43ab2afba68fd0e1b5d138ed99ffc788dc685e36 (patch) | |
tree | 2a7281ec51314abe014aa79bd0f760ed7acfbbe7 | |
parent | e648efdcc1ca904709a646c1dbc797454a307444 (diff) | |
download | gitpython-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-- | TODO | 7 | ||||
-rw-r--r-- | lib/git/refs.py | 94 | ||||
-rw-r--r-- | lib/git/remote.py | 1 | ||||
-rw-r--r-- | test/git/test_refs.py | 14 | ||||
-rw-r--r-- | test/git/test_remote.py | 1 |
5 files changed, 54 insertions, 63 deletions
@@ -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() |