summaryrefslogtreecommitdiff
path: root/lib/git
diff options
context:
space:
mode:
Diffstat (limited to 'lib/git')
-rw-r--r--lib/git/objects/submodule.py46
-rw-r--r--lib/git/objects/util.py8
-rw-r--r--lib/git/repo/base.py22
-rw-r--r--lib/git/util.py3
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