예제 #1
0
 def _set_kind(self, kind):
     if hasattr(self, '_kind'):
         raise NodeError("Cannot change node's kind")
     else:
         self._kind = kind
         # Post setter check (path's trailing slash)
         if self.path.endswith('/'):
             raise NodeError("Node's path cannot end with slash")
예제 #2
0
 def __init__(self, path, kind):
     if path.startswith('/'):
         raise NodeError("Cannot initialize Node objects with slash at "
                         "the beginning as only relative paths are supported")
     self.path = safe_str(path.rstrip('/'))  # we store paths as str
     if path == '' and kind != NodeKind.DIR:
         raise NodeError("Only DirNode and its subclasses may be "
                         "initialized with empty path")
     self.kind = kind
     #self.dirs, self.files = [], []
     if self.is_root() and not self.is_dir():
         raise NodeError("Root node cannot be FILE kind")
예제 #3
0
 def annotate(self):
     """
     Returns a list of three element tuples with lineno,changeset and line
     """
     if self.changeset is None:
         raise NodeError('Unable to get changeset for this FileNode')
     return self.changeset.get_file_annotate(self.path)
예제 #4
0
 def history(self):
     """
     Returns a list of changeset for this file in which the file was changed
     """
     if self.changeset is None:
         raise NodeError('Unable to get changeset for this FileNode')
     return self.changeset.get_file_history(self.path)
예제 #5
0
    def diff_2way(self, repo_name, f_path):
        diff1 = request.GET.get('diff1', '')
        diff2 = request.GET.get('diff2', '')
        try:
            if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
                c.changeset_1 = c.db_repo_scm_instance.get_changeset(diff1)
                try:
                    node1 = c.changeset_1.get_node(f_path)
                    if node1.is_dir():
                        raise NodeError('%s path is a %s not a file' %
                                        (node1, type(node1)))
                except NodeDoesNotExistError:
                    c.changeset_1 = EmptyChangeset(
                        cs=diff1,
                        revision=c.changeset_1.revision,
                        repo=c.db_repo_scm_instance)
                    node1 = FileNode(f_path, '', changeset=c.changeset_1)
            else:
                c.changeset_1 = EmptyChangeset(repo=c.db_repo_scm_instance)
                node1 = FileNode(f_path, '', changeset=c.changeset_1)

            if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
                c.changeset_2 = c.db_repo_scm_instance.get_changeset(diff2)
                try:
                    node2 = c.changeset_2.get_node(f_path)
                    if node2.is_dir():
                        raise NodeError('%s path is a %s not a file' %
                                        (node2, type(node2)))
                except NodeDoesNotExistError:
                    c.changeset_2 = EmptyChangeset(
                        cs=diff2,
                        revision=c.changeset_2.revision,
                        repo=c.db_repo_scm_instance)
                    node2 = FileNode(f_path, '', changeset=c.changeset_2)
            else:
                c.changeset_2 = EmptyChangeset(repo=c.db_repo_scm_instance)
                node2 = FileNode(f_path, '', changeset=c.changeset_2)
        except ChangesetDoesNotExistError as e:
            msg = _('Such revision does not exist for this repository')
            h.flash(msg, category='error')
            raise HTTPNotFound()
        c.node1 = node1
        c.node2 = node2
        c.cs1 = c.changeset_1
        c.cs2 = c.changeset_2

        return render('files/diff_2way.html')
예제 #6
0
 def state(self):
     if not self.changeset:
         raise NodeError("Cannot check state of the node if it's not "
                         "linked with changeset")
     elif self.path in (node.path for node in self.changeset.added):
         return NodeState.ADDED
     elif self.path in (node.path for node in self.changeset.changed):
         return NodeState.CHANGED
     else:
         return NodeState.NOT_CHANGED
예제 #7
0
    def get_node(self, path):
        """
        Returns node from within this particular ``DirNode``, so it is now
        allowed to fetch, i.e. node located at 'docs/api/index.rst' from node
        'docs'. In order to access deeper nodes one must fetch nodes between
        them first - this would work::

           docs = root.get_node('docs')
           docs.get_node('api').get_node('index.rst')

        :param: path - relative to the current node

        .. note::
           To access lazily (as in example above) node have to be initialized
           with related changeset object - without it node is out of
           context and may know nothing about anything else than nearest
           (located at same level) nodes.
        """
        try:
            path = path.rstrip('/')
            if path == '':
                raise NodeError("Cannot retrieve node without path")
            self.nodes  # access nodes first in order to set _nodes_dict
            paths = path.split('/')
            if len(paths) == 1:
                if not self.is_root():
                    path = '/'.join((self.path, paths[0]))
                else:
                    path = paths[0]
                return self._nodes_dict[path]
            elif len(paths) > 1:
                if self.changeset is None:
                    raise NodeError("Cannot access deeper "
                                    "nodes without changeset")
                else:
                    path1, path2 = paths[0], '/'.join(paths[1:])
                    return self.get_node(path1).get_node(path2)
            else:
                raise KeyError
        except KeyError:
            raise NodeError("Node does not exist at %s" % path)
예제 #8
0
    def __init__(self, path, nodes=(), changeset=None):
        """
        Only one of ``nodes`` and ``changeset`` may be given. Passing both
        would raise ``NodeError`` exception.

        :param path: relative path to the node
        :param nodes: content may be passed to constructor
        :param changeset: if given, will use it to lazily fetch content
        :param size: always 0 for ``DirNode``
        """
        if nodes and changeset:
            raise NodeError("Cannot use both nodes and changeset")
        super(DirNode, self).__init__(path, NodeKind.DIR)
        self.changeset = changeset
        self._nodes = nodes
예제 #9
0
    def __init__(self, path, content=None, changeset=None, mode=None):
        """
        Only one of ``content`` and ``changeset`` may be given. Passing both
        would raise ``NodeError`` exception.

        :param path: relative path to the node
        :param content: content may be passed to constructor
        :param changeset: if given, will use it to lazily fetch content
        :param mode: octal representation of ST_MODE (i.e. 0100644)
        """

        if content and changeset:
            raise NodeError("Cannot use both content and changeset")
        super(FileNode, self).__init__(path, kind=NodeKind.FILE)
        self.changeset = changeset
        self._content = content
        self._mode = mode or 0100644
예제 #10
0
    def __init__(self, path, content=None, changeset=None, mode=None):
        """
        Only one of ``content`` and ``changeset`` may be given. Passing both
        would raise ``NodeError`` exception.

        :param path: relative path to the node
        :param content: content may be passed to constructor
        :param changeset: if given, will use it to lazily fetch content
        :param mode: octal representation of ST_MODE (i.e. 0100644)
        """

        if content and changeset:
            raise NodeError("Cannot use both content and changeset")
        super(FileNode, self).__init__(path, kind=NodeKind.FILE)
        self.changeset = changeset
        if not isinstance(content, bytes) and content is not None:
            # File content is one thing that inherently must be bytes ... but
            # VCS module tries to be "user friendly" and support unicode ...
            content = safe_bytes(content)
        self._content = content
        self._mode = mode or 0o100644
예제 #11
0
    def get_mimetype(self):
        """
        Mimetype is calculated based on the file's content. If ``_mimetype``
        attribute is available, it will be returned (backends which store
        mimetypes or can easily recognize them, should set this private
        attribute to indicate that type should *NOT* be calculated).
        """
        if hasattr(self, '_mimetype'):
            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)

        if mtype is None:
            if self.is_binary:
                mtype = 'application/octet-stream'
                encoding = None
            else:
                mtype = 'text/plain'
                encoding = None

                #try with pygments
                try:
                    from pygments import lexers
                    mt = lexers.get_lexer_for_filename(self.name).mimetypes
                except lexers.ClassNotFound:
                    mt = None

                if mt:
                    mtype = mt[0]

        return mtype, encoding
예제 #12
0
 def content(self):
     raise NodeError(
         "%s represents a dir and has no ``content`` attribute" % self)
예제 #13
0
 def last_changeset(self):
     if self.changeset:
         return self.changeset.get_file_changeset(self.path)
     raise NodeError("Cannot retrieve last changeset of the file without "
                     "related changeset attribute")
예제 #14
0
 def size(self):
     if self.changeset:
         return self.changeset.get_file_size(self.path)
     raise NodeError("Cannot retrieve size of the file without related "
                     "changeset attribute")
예제 #15
0
    def diff(self, repo_name, f_path):
        ignore_whitespace = request.GET.get('ignorews') == '1'
        line_context = safe_int(request.GET.get('context'), 3)
        diff2 = request.GET.get('diff2', '')
        diff1 = request.GET.get('diff1', '') or diff2
        c.action = request.GET.get('diff')
        c.no_changes = diff1 == diff2
        c.f_path = f_path
        c.big_diff = False
        fulldiff = request.GET.get('fulldiff')
        c.anchor_url = anchor_url
        c.ignorews_url = _ignorews_url
        c.context_url = _context_url
        c.changes = OrderedDict()
        c.changes[diff2] = []

        # special case if we want a show rev only, it's impl here
        # to reduce JS and callbacks

        if request.GET.get('show_rev'):
            if str2bool(request.GET.get('annotate', 'False')):
                _url = url('files_annotate_home',
                           repo_name=c.repo_name,
                           revision=diff1,
                           f_path=c.f_path)
            else:
                _url = url('files_home',
                           repo_name=c.repo_name,
                           revision=diff1,
                           f_path=c.f_path)

            raise HTTPFound(location=_url)
        try:
            if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]:
                c.changeset_1 = c.db_repo_scm_instance.get_changeset(diff1)
                try:
                    node1 = c.changeset_1.get_node(f_path)
                    if node1.is_dir():
                        raise NodeError('%s path is a %s not a file' %
                                        (node1, type(node1)))
                except NodeDoesNotExistError:
                    c.changeset_1 = EmptyChangeset(
                        cs=diff1,
                        revision=c.changeset_1.revision,
                        repo=c.db_repo_scm_instance)
                    node1 = FileNode(f_path, '', changeset=c.changeset_1)
            else:
                c.changeset_1 = EmptyChangeset(repo=c.db_repo_scm_instance)
                node1 = FileNode(f_path, '', changeset=c.changeset_1)

            if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]:
                c.changeset_2 = c.db_repo_scm_instance.get_changeset(diff2)
                try:
                    node2 = c.changeset_2.get_node(f_path)
                    if node2.is_dir():
                        raise NodeError('%s path is a %s not a file' %
                                        (node2, type(node2)))
                except NodeDoesNotExistError:
                    c.changeset_2 = EmptyChangeset(
                        cs=diff2,
                        revision=c.changeset_2.revision,
                        repo=c.db_repo_scm_instance)
                    node2 = FileNode(f_path, '', changeset=c.changeset_2)
            else:
                c.changeset_2 = EmptyChangeset(repo=c.db_repo_scm_instance)
                node2 = FileNode(f_path, '', changeset=c.changeset_2)
        except (RepositoryError, NodeError):
            log.error(traceback.format_exc())
            raise HTTPFound(location=url(
                'files_home', repo_name=c.repo_name, f_path=f_path))

        if c.action == 'download':
            raw_diff = diffs.get_gitdiff(node1,
                                         node2,
                                         ignore_whitespace=ignore_whitespace,
                                         context=line_context)
            diff_name = '%s_vs_%s.diff' % (diff1, diff2)
            response.content_type = 'text/plain'
            response.content_disposition = ('attachment; filename=%s' %
                                            diff_name)
            return raw_diff

        elif c.action == 'raw':
            raw_diff = diffs.get_gitdiff(node1,
                                         node2,
                                         ignore_whitespace=ignore_whitespace,
                                         context=line_context)
            response.content_type = 'text/plain'
            return raw_diff

        else:
            fid = h.FID(diff2, node2.path)
            line_context_lcl = get_line_ctx(fid, request.GET)
            ign_whitespace_lcl = get_ignore_ws(fid, request.GET)

            diff_limit = None if fulldiff else self.cut_off_limit
            c.a_rev, c.cs_rev, a_path, diff, st, op = diffs.wrapped_diff(
                filenode_old=node1,
                filenode_new=node2,
                diff_limit=diff_limit,
                ignore_whitespace=ign_whitespace_lcl,
                line_context=line_context_lcl,
                enable_comments=False)
            c.file_diff_data = [(fid, fid, op, a_path, node2.path, diff, st)]

            return render('files/file_diff.html')
예제 #16
0
 def state(self):
     raise NodeError("Cannot access state of DirNode")
예제 #17
0
 def message(self):
     if self.changeset:
         return self.last_changeset.message
     raise NodeError("Cannot retrieve message of the file without related "
                     "changeset attribute")