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")
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")
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)
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)
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')
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
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)
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
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
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
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
def content(self): raise NodeError( "%s represents a dir and has no ``content`` attribute" % self)
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")
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")
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')
def state(self): raise NodeError("Cannot access state of DirNode")
def message(self): if self.changeset: return self.last_changeset.message raise NodeError("Cannot retrieve message of the file without related " "changeset attribute")