11import base
2+ from util import Traversable
23from StringIO import StringIO # need a dict to set bloody .name field
34from git .util import Iterable
45from git .config import GitConfigParser , SectionConstraint
56from git .util import join_path_native
67from git .exc import InvalidGitRepositoryError , NoSuchPathError
8+ import stat
79
810import os
911
10- __all__ = ("Submodule" , )
12+ __all__ = ("Submodule" , "RootModule" )
1113
1214#{ Utilities
1315
@@ -31,7 +33,7 @@ class SubmoduleConfigParser(GitConfigParser):
3133 _mutating_methods_ = tuple ()
3234
3335
34- class Submodule (base .IndexObject , Iterable ):
36+ class Submodule (base .IndexObject , Iterable , Traversable ):
3537 """Implements access to a git submodule. They are special in that their sha
3638 represents a commit in the submodule's repository which is to be checked out
3739 at the path of this instance.
@@ -40,10 +42,11 @@ class Submodule(base.IndexObject, Iterable):
4042
4143 All methods work in bare and non-bare repositories."""
4244
43- _id_attribute_ = "path "
45+ _id_attribute_ = "name "
4446 k_modules_file = '.gitmodules'
4547 k_ref_option = 'ref'
4648 k_ref_default = 'master'
49+ k_def_mode = stat .S_IFDIR | stat .S_IFLNK # submodules are directories with link-status
4750
4851 # this is a bogus type for base class compatability
4952 type = 'submodule'
@@ -86,6 +89,14 @@ def _set_cache_(self, attr):
8689 super (Submodule , self )._set_cache_ (attr )
8790 # END handle attribute name
8891
92+ def _get_intermediate_items (self , item ):
93+ """:return: all the submodules of our module repository"""
94+ try :
95+ return type (self ).list_items (item .module ())
96+ except InvalidGitRepositoryError :
97+ return list ()
98+ # END handle intermeditate items
99+
89100 def __eq__ (self , other ):
90101 """Compare with another submodule"""
91102 return self .path == other .path and self .url == other .url and super (Submodule , self ).__eq__ (other )
@@ -107,6 +118,7 @@ def _config_parser(cls, repo, parent_commit, read_only):
107118 if not os .path .isfile (fp_module_path ):
108119 raise IOError ("%s file was not accessible" % fp_module_path )
109120 # END handle existance
121+ fp_module = fp_module_path
110122 else :
111123 try :
112124 fp_module = cls ._sio_modules (parent_commit )
@@ -300,4 +312,32 @@ def iter_items(cls, repo, parent_commit='HEAD'):
300312
301313 #} END iterable interface
302314
315+
316+ class RootModule (Submodule ):
317+ """A (virtual) Root of all submodules in the given repository. It can be used
318+ to more easily traverse all submodules of the master repository"""
319+
320+ __slots__ = tuple ()
321+
322+ k_root_name = '__ROOT__'
323+
324+ def __init__ (self , repo ):
325+ # repo, binsha, mode=None, path=None, name = None, parent_commit=None, url=None, ref=None)
326+ super (RootModule , self ).__init__ (
327+ repo ,
328+ binsha = self .NULL_BIN_SHA ,
329+ mode = self .k_def_mode ,
330+ path = '' ,
331+ name = self .k_root_name ,
332+ parent_commit = repo .head .commit ,
333+ url = '' ,
334+ ref = self .k_ref_default
335+ )
336+
337+
338+ #{ Interface
339+ def module (self ):
340+ """:return: the actual repository containing the submodules"""
341+ return self .repo
342+ #} END interface
303343#} END classes
0 commit comments