diff options
Diffstat (limited to 'lib/git')
-rw-r--r-- | lib/git/objects/submodule.py | 46 | ||||
-rw-r--r-- | lib/git/objects/util.py | 8 | ||||
-rw-r--r-- | lib/git/repo/base.py | 22 | ||||
-rw-r--r-- | lib/git/util.py | 3 |
4 files changed, 75 insertions, 4 deletions
diff --git a/lib/git/objects/submodule.py b/lib/git/objects/submodule.py index 1aa0cfb5..eda95115 100644 --- a/lib/git/objects/submodule.py +++ b/lib/git/objects/submodule.py @@ -1,13 +1,15 @@ import base +from util import Traversable from StringIO import StringIO # need a dict to set bloody .name field from git.util import Iterable from git.config import GitConfigParser, SectionConstraint from git.util import join_path_native from git.exc import InvalidGitRepositoryError, NoSuchPathError +import stat import os -__all__ = ("Submodule", ) +__all__ = ("Submodule", "RootModule") #{ Utilities @@ -31,7 +33,7 @@ class SubmoduleConfigParser(GitConfigParser): _mutating_methods_ = tuple() -class Submodule(base.IndexObject, Iterable): +class Submodule(base.IndexObject, Iterable, Traversable): """Implements access to a git submodule. They are special in that their sha represents a commit in the submodule's repository which is to be checked out at the path of this instance. @@ -40,10 +42,11 @@ class Submodule(base.IndexObject, Iterable): All methods work in bare and non-bare repositories.""" - _id_attribute_ = "path" + _id_attribute_ = "name" k_modules_file = '.gitmodules' k_ref_option = 'ref' k_ref_default = 'master' + k_def_mode = stat.S_IFDIR | stat.S_IFLNK # submodules are directories with link-status # this is a bogus type for base class compatability type = 'submodule' @@ -86,6 +89,14 @@ class Submodule(base.IndexObject, Iterable): super(Submodule, self)._set_cache_(attr) # END handle attribute name + def _get_intermediate_items(self, item): + """:return: all the submodules of our module repository""" + try: + return type(self).list_items(item.module()) + except InvalidGitRepositoryError: + return list() + # END handle intermeditate items + def __eq__(self, other): """Compare with another submodule""" return self.path == other.path and self.url == other.url and super(Submodule, self).__eq__(other) @@ -107,6 +118,7 @@ class Submodule(base.IndexObject, Iterable): if not os.path.isfile(fp_module_path): raise IOError("%s file was not accessible" % fp_module_path) # END handle existance + fp_module = fp_module_path else: try: fp_module = cls._sio_modules(parent_commit) @@ -300,4 +312,32 @@ class Submodule(base.IndexObject, Iterable): #} END iterable interface + +class RootModule(Submodule): + """A (virtual) Root of all submodules in the given repository. It can be used + to more easily traverse all submodules of the master repository""" + + __slots__ = tuple() + + k_root_name = '__ROOT__' + + def __init__(self, repo): + # repo, binsha, mode=None, path=None, name = None, parent_commit=None, url=None, ref=None) + super(RootModule, self).__init__( + repo, + binsha = self.NULL_BIN_SHA, + mode = self.k_def_mode, + path = '', + name = self.k_root_name, + parent_commit = repo.head.commit, + url = '', + ref = self.k_ref_default + ) + + + #{ Interface + def module(self): + """:return: the actual repository containing the submodules""" + return self.repo + #} END interface #} END classes diff --git a/lib/git/objects/util.py b/lib/git/objects/util.py index 21833080..9a54e031 100644 --- a/lib/git/objects/util.py +++ b/lib/git/objects/util.py @@ -4,6 +4,8 @@ # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php """Module for general utility functions""" +from git.util import IterableList + import re from collections import deque as Deque import platform @@ -273,6 +275,12 @@ class Traversable(object): """ raise NotImplementedError("To be implemented in subclass") + def list_traverse(self, *args, **kwargs): + """:return: IterableList with the results of the traversal as produced by + traverse()""" + out = IterableList(self._id_attribute_) + out.extend(self.traverse(*args, **kwargs)) + return out def traverse( self, predicate = lambda i,d: True, prune = lambda i,d: False, depth = -1, branch_first=True, diff --git a/lib/git/repo/base.py b/lib/git/repo/base.py index 790b1283..3a395af0 100644 --- a/lib/git/repo/base.py +++ b/lib/git/repo/base.py @@ -6,7 +6,6 @@ from git.exc import InvalidGitRepositoryError, NoSuchPathError from git.cmd import Git -from git.objects import Actor from git.refs import * from git.index import IndexFile from git.objects import * @@ -222,6 +221,27 @@ class Repo(object): """:return: Remote with the specified name :raise ValueError: if no remote with such a name exists""" return Remote(self, name) + + @property + def submodules(self): + """:return: git.IterableList(Submodule, ...) of direct submodules""" + return self.list_submodules(recursive=False) + + def submodule(self, name): + """:return: Submodule with the given name + :raise ValueError: If no such submodule exists""" + try: + return self.submodules[name] + except IndexError: + raise ValueError("Didn't find submodule named %r" % name) + # END exception handling + + def list_submodules(self, recursive=False): + """A list if Submodule objects available in this repository + :param recursive: If True, submodules of submodules (and so forth) will be + returned as well as part of a depth-first traversal + :return: ``git.IterableList(Submodule, ...)""" + return RootModule(self).list_traverse(ignore_self=1, depth = recursive and -1 or 1) @property def tags(self): diff --git a/lib/git/util.py b/lib/git/util.py index fcb50585..b77e7904 100644 --- a/lib/git/util.py +++ b/lib/git/util.py @@ -296,6 +296,9 @@ class IterableList(list): def __init__(self, id_attr, prefix=''): self._id_attr = id_attr self._prefix = prefix + if not isinstance(id_attr, basestring): + raise ValueError("First parameter must be a string identifying the name-property. Extend the list after initialization") + # END help debugging ! def __getattr__(self, attr): attr = self._prefix + attr |