Commits

Marcin Kuzminski  committed dbec37a

Added submodule nodes type

  • Participants
  • Parent commits 294c5e8

Comments (0)

Files changed (3)

File vcs/backends/base.py

         :raises ``CommitError``: if any error occurs while committing
         """
         raise NotImplementedError
+
+
+class EmptyChangeset(BaseChangeset):
+    """
+    An dummy empty changeset. It's possible to pass hash when creating
+    an EmptyChangeset
+    """
+
+    def __init__(self, cs='0' * 40, repo=None, requested_revision=None,
+                 alias=None):
+        self._empty_cs = cs
+        self.revision = -1
+        self.message = ''
+        self.author = ''
+        self.date = ''
+        self.repository = repo
+        self.requested_revision = requested_revision
+        self.alias = alias
+
+    @LazyProperty
+    def raw_id(self):
+        """
+        Returns raw string identifying this changeset, useful for web
+        representation.
+        """
+
+        return self._empty_cs
+
+    @LazyProperty
+    def branch(self):
+        from vcs.backends import get_backend
+        return get_backend(self.alias).DEFAULT_BRANCH_NAME
+
+    @LazyProperty
+    def short_id(self):
+        return self.raw_id[:12]
+
+    def get_file_changeset(self, path):
+        return self
+
+    def get_file_content(self, path):
+        return u''
+
+    def get_file_size(self, path):
+        return 0

File vcs/nodes.py

     :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 vcs.utils.lazy import LazyProperty
 from vcs.utils import safe_unicode
 from vcs.exceptions import NodeError
 from vcs.exceptions import RemovedFileNodeError
-
-from pygments import lexers
+from vcs.backends.base import EmptyChangeset
 
 
 class NodeKind:
+    SUBMODULE = -1
     DIR = 1
     FILE = 2
 
         return None
 
     @LazyProperty
+    def unicode_path(self):
+        return safe_unicode(self.path)
+
+    @LazyProperty
     def name(self):
         """
         Returns name of the node so if its path
         """
         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
         attribute to indicate that type should *NOT* be calculated).
         """
         if hasattr(self, '_mimetype'):
-            if (isinstance(self._mimetype,(tuple,list,)) and
+            if (isinstance(self._mimetype, (tuple, list,)) and
                 len(self._mimetype) == 2):
                 return self._mimetype
             else:
                 raise NodeError('given _mimetype attribute must be an 2 '
                                'element list or tuple')
 
-        mtype,encoding = mimetypes.guess_type(self.name)
+        mtype, encoding = mimetypes.guess_type(self.name)
 
         if mtype is None:
             if self.is_binary:
             else:
                 mtype = 'text/plain'
                 encoding = None
-        return mtype,encoding
+        return mtype, encoding
 
     @LazyProperty
     def mimetype(self):
         """
         Returns True if file has binary content.
         """
-        bin = '\0' in self.content
-        return bin
+        _bin = '\0' in self.content
+        return _bin
 
     @LazyProperty
     def extension(self):
         """
         return bool(self.mode & stat.S_IXUSR)
 
+    def __repr__(self):
+        return '<%s %r @ %s>' % (self.__class__.__name__, self.path,
+                                 getattr(self.changeset, 'short_id', ''))
+
 
 class RemovedFileNode(FileNode):
     """
     name, kind or state (or methods/attributes checking those two) would raise
     RemovedFileNodeError.
     """
-    ALLOWED_ATTRIBUTES = ['name', 'path', 'state', 'is_root', 'is_file',
-        'is_dir', 'kind', 'added', 'changed', 'not_changed', 'removed']
+    ALLOWED_ATTRIBUTES = [
+        'name', 'path', 'state', 'is_root', 'is_file', 'is_dir', 'kind',
+        'added', 'changed', 'not_changed', 'removed'
+    ]
 
     def __init__(self, path):
         """
 
         return size
 
+    def __repr__(self):
+        return '<%s %r @ %s>' % (self.__class__.__name__, self.path,
+                                 getattr(self.changeset, 'short_id', ''))
+
 
 class RootNode(DirNode):
     """
 
     def __repr__(self):
         return '<%s>' % self.__class__.__name__
+
+
+class SubModuleNode(Node):
+    """
+    represents a SubModule of Git or SubRepo of Mercurial
+    """
+    is_binary = False
+    size = 0
+
+    def __init__(self, name, url=None, changeset=None, alias=None):
+        self.path = name
+        self.kind = NodeKind.SUBMODULE
+        self.alias = alias
+        # we have to use emptyChangeset here since this can point to svn/git/hg
+        # submodules we cannot get from repository
+        self.changeset = EmptyChangeset(str(changeset), alias=alias)
+        self.url = url or self._extract_submodule_url()
+
+    def __repr__(self):
+        return '<%s %r @ %s>' % (self.__class__.__name__, self.path,
+                                 getattr(self.changeset, 'short_id', ''))
+
+    def _extract_submodule_url(self):
+        if self.alias == 'git':
+            #TODO: find a way to parse gits submodule file and extract the
+            # linking URL
+            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.short_id)

File vcs/tests/test_nodes.py

 
     def test_file_node_stat(self):
         node = FileNode('foobar', 'empty... almost')
-        mode = node.mode # default should be 0100644
+        mode = node.mode  # default should be 0100644
         self.assertTrue(mode & stat.S_IRUSR)
         self.assertTrue(mode & stat.S_IWUSR)
         self.assertTrue(mode & stat.S_IRGRP)