diff --git a/rhodecode/lib/vcs/backends/git/changeset.py b/rhodecode/lib/vcs/backends/git/changeset.py --- a/rhodecode/lib/vcs/backends/git/changeset.py +++ b/rhodecode/lib/vcs/backends/git/changeset.py @@ -10,7 +10,8 @@ from rhodecode.lib.vcs.exceptions import from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError from rhodecode.lib.vcs.exceptions import ImproperArchiveTypeError from rhodecode.lib.vcs.backends.base import BaseChangeset -from rhodecode.lib.vcs.nodes import FileNode, DirNode, NodeKind, RootNode, RemovedFileNode +from rhodecode.lib.vcs.nodes import FileNode, DirNode, NodeKind, RootNode, \ + RemovedFileNode, SubModuleNode from rhodecode.lib.vcs.utils import safe_unicode from rhodecode.lib.vcs.utils import date_fromtimestamp from rhodecode.lib.vcs.utils.lazy import LazyProperty @@ -329,7 +330,13 @@ class GitChangeset(BaseChangeset): tree = self.repository._repo[id] dirnodes = [] filenodes = [] + als = self.repository.alias for name, stat, id in tree.iteritems(): + if objects.S_ISGITLINK(stat): + dirnodes.append(SubModuleNode(name, url=None, changeset=id, + alias=als)) + continue + obj = self.repository._repo.get_object(id) if path != '': obj_path = '/'.join((path, name)) diff --git a/rhodecode/lib/vcs/backends/hg/changeset.py b/rhodecode/lib/vcs/backends/hg/changeset.py --- a/rhodecode/lib/vcs/backends/hg/changeset.py +++ b/rhodecode/lib/vcs/backends/hg/changeset.py @@ -5,8 +5,9 @@ from rhodecode.lib.vcs.backends.base imp from rhodecode.lib.vcs.conf import settings from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError, \ ChangesetError, ImproperArchiveTypeError, NodeDoesNotExistError, VCSError -from rhodecode.lib.vcs.nodes import AddedFileNodesGenerator, ChangedFileNodesGenerator, \ - DirNode, FileNode, NodeKind, RemovedFileNodesGenerator, RootNode +from rhodecode.lib.vcs.nodes import AddedFileNodesGenerator, \ + ChangedFileNodesGenerator, DirNode, FileNode, NodeKind, \ + RemovedFileNodesGenerator, RootNode, SubModuleNode from rhodecode.lib.vcs.utils import safe_str, safe_unicode, date_fromtimestamp from rhodecode.lib.vcs.utils.lazy import LazyProperty @@ -159,6 +160,13 @@ class MercurialChangeset(BaseChangeset): " %r" % (self.revision, path)) return self._ctx.filectx(path) + def _extract_submodules(self): + """ + returns a dictionary with submodule information from substate file + of hg repository + """ + return self._ctx.substate + def get_file_mode(self, path): """ Returns stat mode of the file at the given ``path``. @@ -271,17 +279,27 @@ class MercurialChangeset(BaseChangeset): raise ChangesetError("Directory does not exist for revision %r at " " %r" % (self.revision, path)) path = self._fix_path(path) + filenodes = [FileNode(f, changeset=self) for f in self._file_paths if os.path.dirname(f) == path] dirs = path == '' and '' or [d for d in self._dir_paths if d and posixpath.dirname(d) == path] dirnodes = [DirNode(d, changeset=self) for d in dirs if os.path.dirname(d) == path] + + als = self.repository.alias + for k, vals in self._extract_submodules().iteritems(): + #vals = url,rev,type + loc = vals[0] + cs = vals[1] + dirnodes.append(SubModuleNode(k, url=loc, changeset=cs, + alias=als)) nodes = dirnodes + filenodes # cache nodes for node in nodes: self.nodes[node.path] = node nodes.sort() + return nodes def get_node(self, path): diff --git a/rhodecode/lib/vcs/nodes.py b/rhodecode/lib/vcs/nodes.py --- a/rhodecode/lib/vcs/nodes.py +++ b/rhodecode/lib/vcs/nodes.py @@ -8,19 +8,21 @@ :created_on: Apr 8, 2010 :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak. """ +import os import stat import posixpath import mimetypes +from pygments import lexers + from rhodecode.lib.vcs.utils.lazy import LazyProperty -from rhodecode.lib.vcs.utils import safe_unicode +from rhodecode.lib.vcs.utils import safe_unicode, safe_str from rhodecode.lib.vcs.exceptions import NodeError from rhodecode.lib.vcs.exceptions import RemovedFileNodeError -from pygments import lexers - class NodeKind: + SUBMODULE = -1 DIR = 1 FILE = 2 @@ -209,6 +211,13 @@ class Node(object): """ return self.kind == NodeKind.DIR and self.path == '' + def is_submodule(self): + """ + Returns ``True`` if node's kind is ``NodeKind.SUBMODULE``, ``False`` + otherwise. + """ + return self.kind == NodeKind.SUBMODULE + @LazyProperty def added(self): return self.state is NodeState.ADDED @@ -561,3 +570,31 @@ class RootNode(DirNode): def __repr__(self): return '<%s>' % self.__class__.__name__ + + +class SubModuleNode(Node): + """ + represents a SubModule of Git or SubRepo of Mercurial + """ + def __init__(self, name, url=None, changeset=None, alias=None): + self.path = name + self.kind = NodeKind.SUBMODULE + self.alias = alias + # changeset MUST be STR !! since it can point to non-valid SCM + self.changeset = str(changeset) + self.url = url or self._extract_submodule_url() + + def _extract_submodule_url(self): + if self.alias == 'git': + return self.path + if self.alias == 'hg': + return self.path + + @LazyProperty + def name(self): + """ + Returns name of the node so if its path + then only last part is returned. + """ + org = safe_unicode(self.path.rstrip('/').split('/')[-1]) + return u'%s @ %s' % (org, self.changeset[:12]) diff --git a/rhodecode/public/css/style.css b/rhodecode/public/css/style.css --- a/rhodecode/public/css/style.css +++ b/rhodecode/public/css/style.css @@ -2718,6 +2718,14 @@ table.code-browser .browser-dir { text-align: left; } +table.code-browser .submodule-dir { + background: url("../images/icons/disconnect.png") no-repeat scroll 3px; + height: 16px; + padding-left: 20px; + text-align: left; +} + + .box .search { clear: both; overflow: hidden; diff --git a/rhodecode/templates/files/files_browser.html b/rhodecode/templates/files/files_browser.html --- a/rhodecode/templates/files/files_browser.html +++ b/rhodecode/templates/files/files_browser.html @@ -70,7 +70,11 @@ %for cnt,node in enumerate(c.file): - ${h.link_to(node.name,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=h.safe_unicode(node.path)),class_=file_class(node)+" ypjax-link")} + %if node.is_submodule(): + ${h.link_to(node.name,node.url or '#',class_="submodule-dir ypjax-link")} + %else: + ${h.link_to(node.name, h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id,f_path=h.safe_unicode(node.path)),class_=file_class(node)+" ypjax-link")} + %endif: %if node.is_file():