changeset 124:6c261cb94631

Fixed wiki history page and API endpoint.
author Ludovic Chabant <ludovic@chabant.com>
date Sat, 23 Nov 2013 13:35:37 -0800
parents ac6166453d77
children 886f36b05e5f
files static/tpl/special-changes.html wikked/db.py wikked/fs.py wikked/page.py wikked/scm.py wikked/utils.py wikked/views.py
diffstat 7 files changed, 73 insertions(+), 50 deletions(-) [+]
line wrap: on
line diff
--- a/static/tpl/special-changes.html	Sat Nov 23 13:31:35 2013 -0800
+++ b/static/tpl/special-changes.html	Sat Nov 23 13:35:37 2013 -0800
@@ -27,7 +27,11 @@
                                     <ul class="unstyled">
                                         {{#each changes}}
                                         <li>
+                                            {{#if valid_url}}
                                             <a href="{{get_read_url url}}">{{url}}</a>
+                                            {{else}}
+                                            <code>{{url}}</code>
+                                            {{/if}}
                                             {{#if is_edit}}(edit) {{/if}}
                                             {{#if is_add}}(added) {{/if}}
                                             {{#if is_delete}}(deleted) {{/if}}
--- a/wikked/db.py	Sat Nov 23 13:31:35 2013 -0800
+++ b/wikked/db.py	Sat Nov 23 13:35:37 2013 -0800
@@ -40,10 +40,10 @@
     def getPages(self, subdir=None, meta_query=None):
         raise NotImplementedError()
 
-    def getPage(self, url):
+    def getPage(self, url=None, path=None):
         raise NotImplementedError()
 
-    def pageExists(self, url):
+    def pageExists(self, url=None, path=None):
         raise NotImplementedError()
 
     def getLinksTo(self, url):
@@ -260,13 +260,22 @@
             pages.append(p)
         return pages
 
-    def getPage(self, url):
-        q = db.session.query(SQLPage).filter_by(url=url)
-        page = q.first()
-        return page
+    def getPage(self, url=None, path=None):
+        if not url and not path:
+            raise ValueError("Either URL or path need to be specified.")
+        if url and path:
+            raise ValueError("Can't specify both URL and path.")
+        if url:
+            q = db.session.query(SQLPage).filter_by(url=url)
+            page = q.first()
+            return page
+        if path:
+            q = db.session.query(SQLPage).filter_by(path=path)
+            page = q.first()
+            return page
 
-    def pageExists(self, url):
-        return self.getPage(url) is not None
+    def pageExists(self, url=None, path=None):
+        return self.getPage(url, path) is not None
 
     def getLinksTo(self, url):
         q = db.session.query(SQLReadyLink).\
--- a/wikked/fs.py	Sat Nov 23 13:31:35 2013 -0800
+++ b/wikked/fs.py	Sat Nov 23 13:35:37 2013 -0800
@@ -4,14 +4,7 @@
 import string
 import codecs
 import logging
-from utils import title_to_url
-
-
-class PageNotFoundError(Exception):
-    """ An error raised when no physical file
-       is found for a given URL.
-    """
-    pass
+from utils import PageNotFoundError, title_to_url, path_to_url
 
 
 class PageInfo(object):
@@ -99,10 +92,7 @@
         if self.page_extensions is not None and ext not in self.page_extensions:
             return None
 
-        url = ''
-        parts = unicode(name).lower().split(os.sep)
-        for i, part in enumerate(parts):
-            url += '/' + title_to_url(part)
+        url = path_to_url(unicode(name), strip_ext=True)
         return PageInfo(url, path)
 
     def _getPhysicalPath(self, url, is_file):
--- a/wikked/page.py	Sat Nov 23 13:31:35 2013 -0800
+++ b/wikked/page.py	Sat Nov 23 13:35:37 2013 -0800
@@ -5,6 +5,7 @@
 import jinja2
 from formatter import PageFormatter, FormattingContext, SINGLE_METAS
 from resolver import PageResolver, CircularIncludeError
+from utils import PageNotFoundError
 
 
 class PageLoadingError(Exception):
@@ -240,7 +241,7 @@
     def _loadData(self):
         db_obj = self._db_obj or self.wiki.db.getPage(self.url)
         if db_obj is None:
-            raise Exception("Can't find page '%s' in the database. Please run `update` or `reset`." % self.url)
+            raise PageNotFoundError("Can't find page '%s' in the database. Please run `update` or `reset`." % self.url)
         data = self._loadFromDbObject(db_obj)
         self._db_obj = None
         return data
--- a/wikked/scm.py	Sat Nov 23 13:31:35 2013 -0800
+++ b/wikked/scm.py	Sat Nov 23 13:35:37 2013 -0800
@@ -112,7 +112,7 @@
         return subprocess.check_output(exe)
 
 
-class MercurialSourceControl(SourceControl):
+class MercurialSourceControl(MercurialBaseSourceControl):
     def __init__(self, root, logger=None):
         MercurialBaseSourceControl.__init__(self, root, logger)
 
@@ -235,7 +235,7 @@
     def getHistory(self, path=None):
         if path is not None:
             rel_path = os.path.relpath(path, self.root)
-            status = self.client.status(include=rel_path)
+            status = self.client.status(include=[rel_path])
             if len(status) > 0 and status[0] == '?':
                 return []
 
@@ -249,14 +249,14 @@
         for rev in repo_revs:
             r = Revision(rev.node)
             r.rev_name = rev.node[:12]
-            r.author = rev.author
+            r.author = unicode(rev.author)
             r.timestamp = time.mktime(rev.date.timetuple())
-            r.description = rev.desc
+            r.description = unicode(rev.desc)
             if needs_files:
                 rev_statuses = self.client.status(change=rev.node)
                 for rev_status in rev_statuses:
                     r.files.append({
-                        'path': rev_status[1],
+                        'path': rev_status[1].decode('utf-8', 'replace'),
                         'action': self.actions[rev_status[0]]
                         })
             revisions.append(r)
@@ -264,7 +264,7 @@
 
     def getState(self, path):
         rel_path = os.path.relpath(path, self.root)
-        statuses = self.client.status(include=rel_path)
+        statuses = self.client.status(include=[rel_path])
         if len(statuses) == 0:
             return STATE_COMMITTED
         status = statuses[0]
@@ -276,7 +276,7 @@
             
     def getRevision(self, path, rev):
         rel_path = os.path.relpath(path, self.root)
-        return self.client.cat(rel_path, rev=rev)
+        return self.client.cat([rel_path], rev=rev)
 
     def diff(self, path, rev1, rev2):
         rel_path = os.path.relpath(path, self.root)
@@ -298,7 +298,7 @@
             if s[1] in rel_paths:
                 add_paths.append(s[1])
         if len(add_paths) > 0:
-            self.client.add(*add_paths)
+            self.client.add(files=add_paths)
 
         # Commit!
         if 'author' in op_meta:
@@ -309,9 +309,9 @@
     def revert(self, paths=None):
         if paths is not None:
             rel_paths = [os.path.relpath(p, self.root) for p in paths]
-            self.client.revert(*rel_paths, clean=True)
+            self.client.revert(files=rel_paths, nobackup=True)
         else:
-            self.client.revert(all=True, clean=True)
+            self.client.revert(all=True, nobackup=True)
 
 
 class GitBaseSourceControl(SourceControl):
--- a/wikked/utils.py	Sat Nov 23 13:31:35 2013 -0800
+++ b/wikked/utils.py	Sat Nov 23 13:35:37 2013 -0800
@@ -5,6 +5,13 @@
 from xml.sax.saxutils import escape, unescape
 
 
+class PageNotFoundError(Exception):
+    """ An error raised when no physical file
+       is found for a given URL.
+    """
+    pass
+
+
 def find_wiki_root(path=None):
     if not path:
         path = os.getcwd()
@@ -62,6 +69,17 @@
     return re.sub(r'[^A-Za-z0-9_\.\-\(\)\{\}]+', '-', ansi_title.lower())
 
 
+def path_to_url(path, strip_ext=True):
+    if strip_ext:
+        path = os.path.splitext(path)[0]
+
+    url = ''
+    parts = path.lower().split(os.sep) # unicode(path)
+    for i, part in enumerate(parts):
+        url += '/' + title_to_url(part)
+    return url
+
+
 def url_to_title(url):
     def upperChar(m):
         return m.group(0).upper()
--- a/wikked/views.py	Sat Nov 23 13:31:35 2013 -0800
+++ b/wikked/views.py	Sat Nov 23 13:35:37 2013 -0800
@@ -8,10 +8,10 @@
 from pygments.lexers import get_lexer_by_name
 from pygments.formatters import get_formatter_by_name
 from web import app, login_manager
-from page import Page, PageData
+from page import Page, PageData, PageLoadingError
 from fs import PageNotFoundError
 from formatter import PageFormatter, FormattingContext
-from utils import title_to_url
+from utils import title_to_url, path_to_url
 import scm
 
 
@@ -120,24 +120,25 @@
         if needs_files:
             rev_data['pages'] = []
             for f in rev.files:
-                f_info = g.wiki.fs.getPageInfo(f['path'])
-                if f_info is None:
-                    continue
-                page = g.wiki.getPage(f_info.url)
-                try:
-                    if not is_page_readable(page):
-                        continue
-                except PageNotFoundError:
-                    pass
-                    continue
-                page = g.wiki.getPage(f_info.url)
-                try:
-                    if not is_page_readable(page):
-                        continue
-                except PageNotFoundError:
-                    pass
+                url = None
+                is_url_valid = True
+                page = g.wiki.db.getPage(path=f['path'])
+                if page is not None:
+                    try:
+                        # Hide pages that the user can't see.
+                        if not is_page_readable(page):
+                            continue
+                        url = page.url
+                    except PageNotFoundError:
+                        pass
+                    except PageLoadingError:
+                        pass
+                if not url:
+                    url = path_to_url(f['path'])
+                    is_url_valid = False
                 rev_data['pages'].append({
-                    'url': f_info.url,
+                    'url': url,
+                    'valid_url': is_url_valid,
                     'action': scm.ACTION_NAMES[f['action']]
                     })
             if len(rev_data['pages']) > 0: