Commits

Thomas Waldmann committed 555defa Merge

merged

Comments (0)

Files changed (14)

MoinMoin/apps/admin/views.py

     """
     u = user.User(auth_username=user_name)
     if request.method == 'GET':
-        return _(u"User profile of %(username)s: %(email)r", username=user_name,
-                 email=(u.email, u.disabled))
+        return _(u"User profile of %(username)s: %(email)s %(disabled)s", username=user_name,
+                 email=u.email, disabled=u.disabled)
 
     if request.method == 'POST':
         key = request.form.get('key', '')

MoinMoin/apps/frontend/views.py

 from MoinMoin.util import crypto
 from MoinMoin.util.interwiki import url_for_item
 from MoinMoin.search import SearchForm
+from MoinMoin.search.analyzers import item_name_analyzer
 from MoinMoin.security.textcha import TextCha, TextChaizedForm
 from MoinMoin.signalling import item_displayed, item_modified
 from MoinMoin.storage.middleware.protecting import AccessDenied
     submit_label = L_('Lookup')
 
 
+def analyze(analyzer, text):
+    return [token.text for token in analyzer(text, mode='index')]
+
+
 @frontend.route('/+lookup', methods=['GET', 'POST'])
 def lookup():
     """
                     term = Term(key, value)
                 terms.append(term)
         if terms:
+            LookupEntry = namedtuple('LookupEntry', 'name revid wikiname')
+            name = lookup_form[NAME].value
+            name_exact = lookup_form[NAME_EXACT].value or u''
             terms.append(Term(WIKINAME, app.cfg.interwikiname))
             q = And(terms)
             with flaskg.storage.indexer.ix[idx_name].searcher() as searcher:
                 flaskg.clock.start('lookup')
                 results = searcher.search(q, limit=100)
                 flaskg.clock.stop('lookup')
-                num_results = results.scored_length()
-                if num_results == 1:
-                    result = results[0]
-                    rev = result[REVID] if history else CURRENT
-                    url = url_for('.show_item', item_name=result[NAME], rev=rev)
+                lookup_results = []
+                for result in results:
+                    analyzer = item_name_analyzer()
+                    lookup_results += [LookupEntry(n, result[REVID], result[WIKINAME])
+                                       for n in result[NAME]
+                                       if not name or name.lower() in analyze(analyzer, n)
+                                       if n.startswith(name_exact)]
+
+                if len(lookup_results) == 1:
+                    result = lookup_results[0]
+                    rev = result.revid if history else CURRENT
+                    url = url_for('.show_item', item_name=result.name, rev=rev)
                     return redirect(url)
                 else:
                     flaskg.clock.start('lookup render')
                     html = render_template('lookup.html',
                                            title_name=title_name,
                                            lookup_form=lookup_form,
-                                           results=results,
+                                           results=lookup_results,
                     )
                     flaskg.clock.stop('lookup render')
-                    if not num_results:
+                    if not lookup_results:
                         status = 404
                     return Response(html, status)
     html = render_template('lookup.html',
                             for name in new_names:
                                 if user.search_users(**{NAME_EXACT: name}):
                                     # duplicate name
-                                    response['flash'].append((_("The username %(name)r is already in use.", name=name),
+                                    response['flash'].append((_("The username '%(name)s' is already in use.", name=name),
                                                               "error"))
                                     success = False
                     if part == 'notification':

MoinMoin/items/__init__.py

         """
         raise NotImplementedError
 
-    def _save(self, meta, data=None, name=None, action=u'SAVE', contenttype_guessed=None, comment=u'',
+    def _save(self, meta, data=None, name=None, action=u'SAVE', contenttype_guessed=None, comment=None,
               overwrite=False, delete=False):
         backend = flaskg.storage
         storage_item = backend[self.name]
         else:
             meta[NAME] = [name]
 
-        if comment:
+        if comment is not None:
             meta[COMMENT] = unicode(comment)
 
         if not overwrite and REVID in meta:

MoinMoin/security/__init__.py

 
             +SomeUser:read -OtherUser:write
 
-        The acl line above will grant SomeUser read right, and OtherUser
+        The acl line above will grant SomeUser read right, and deny OtherUser
         write right, but will NOT block automatically all other rights
         for these users. For example, if SomeUser asks to write, the
         above acl line does not define if he can or can not write. He

MoinMoin/storage/backends/_tests/__init__.py

         assert m == meta
         assert d.read() == data
         d.close()
-        self.be.remove(metaid)
+        self.be.remove(metaid, destroy_data=True)
         with pytest.raises(KeyError):
             self.be.retrieve(metaid)
 

MoinMoin/storage/backends/stores.py

     def _del_data(self, dataid):
         del self.data_store[dataid]
 
-    def remove(self, metaid):
+    def remove(self, metaid, destroy_data):
         meta = self._get_meta(metaid)
         dataid = meta[DATAID]
         self._del_meta(metaid)
-        self._del_data(dataid)
+        if destroy_data:
+            self._del_data(dataid)

MoinMoin/storage/middleware/_tests/test_routing.py

     assert other_name.split(':')[1] == other_meta[NAME][0]
 
     # delete revs:
-    router.remove(default_backend_name, default_revid)
-    router.remove(other_backend_name, other_revid)
+    router.remove(default_backend_name, default_revid, destroy_data=True)
+    router.remove(other_backend_name, other_revid, destroy_data=True)
 
 
 def test_store_readonly_fails(router):

MoinMoin/storage/middleware/indexing.py

 from MoinMoin.constants.keys import (WIKINAME, NAMESPACE, NAME, NAME_EXACT, MTIME, CONTENTTYPE, TAGS, LANGUAGE,
                                      USERID, ADDRESS, HOSTNAME, SIZE, ACTION, COMMENT, SUMMARY, CONTENT,
                                      EXTERNALLINKS, ITEMLINKS, ITEMTRANSCLUSIONS, ACL, DISABLED, EMAIL, OPENID,
-                                     ITEMID, REVID, CURRENT, PARENTID, PTIME, LATEST_REVS, ALL_REVS, BACKENDNAME)
+                                     ITEMID, REVID, CURRENT, PARENTID, PTIME, LATEST_REVS, ALL_REVS, BACKENDNAME, DATAID)
 from MoinMoin.constants.contenttypes import CONTENTTYPE_USER
 from MoinMoin.constants.namespaces import NAMESPACE_DEFAULT
 from MoinMoin.constants import keys
             COMMENT: TEXT(stored=True),
             # SUMMARY from metadata
             SUMMARY: TEXT(stored=True),
+            # DATAID from metadata
+            DATAID: ID(stored=True),
             # data (content), converted to text/plain and tokenized
             CONTENT: TEXT(stored=True),
         }
         Destroy revision <revid>.
         """
         rev = Revision(self, revid)
-        self.backend.remove(rev.backend_name, revid)
+        query = {DATAID: rev.meta[DATAID]}
+        with flaskg.storage.indexer.ix[ALL_REVS].searcher() as searcher:
+            refcount = len(list(searcher.document_numbers(**query)))
+        self.backend.remove(rev.backend_name, revid, destroy_data=refcount == 1)
         self.indexer.remove_revision(revid)
 
     def destroy_all_revisions(self):

MoinMoin/storage/middleware/routing.py

         meta[BACKENDNAME] = backend_name
         return backend_name, revid
 
-    def remove(self, backend_name, revid):
+    def remove(self, backend_name, revid, destroy_data):
         backend = self.backends[backend_name]
         if not isinstance(backend, MutableBackendBase):
             raise TypeError('backend {0} is readonly'.format(backend_name))
-        backend.remove(revid)
+        backend.remove(revid, destroy_data)

MoinMoin/templates/destroy.html

     {{ gen.form.close() }}
     </div>
 {% else %}
-    <h1>{{ _("DESTROY REVISION '%(item_name)s' (rev %(rev_id)s)", item_name=item.name, rev_id=rev_id) }}</h1>
+    <h1>{{ _("DESTROY REVISION '%(item_name)s' (rev %(rev_id)s)", item_name=item.name, rev_id=rev_id | shorten_id) }}</h1>
     <div class="moin-form">
     {{ gen.form.open(form, method="post", action=url_for('frontend.destroy_item', item_name=item.name, rev=rev_id)) }}
       {{ forms.render_errors(form) }}

MoinMoin/templates/lookup.html

             {% for result in results %}
                 {% if result['wikiname'] == cfg.interwikiname %}
                     <tr>
-                        <td class="moin-wordbreak">{{ result.pos + 1 }}
-                        <a href="{{ url_for_item(item_name=result['name'], wiki_name='Self', rev=result['revid']) }}"><b>{{ result['name'] }}</b></a>
+                        <td class="moin-wordbreak">{{ loop.index }}
+                        <a href="{{ url_for_item(item_name=result.name, wiki_name='Self', rev=result.revid) }}"><b>{{ result.name }}</b></a>
                         </td>
                     </tr>
                 {% else %}
                     <tr>
-                        <td class="moin-wordbreak">{{ result.pos + 1 }}
-                        <a class="moin-interwiki" href="{{ url_for_item(item_name=result['name'], wiki_name=result['wikiname'], rev=result['revid']) }}"><b>{{ "%s:%s" % (result['wikiname'], result['name']) }}</b></a>
+                        <td class="moin-wordbreak">{{ loop.index }}
+                        <a class="moin-interwiki" href="{{ url_for_item(item_name=result.name, wiki_name=result.wikiname, rev=result.revid) }}"><b>{{ "%s:%s" % (result.wikiname, result.name) }}</b></a>
                         </td>
                     </tr>
                 {% endif %}

MoinMoin/templates/meta.html

 {% block content_data %}
 <h1>
     {{ title }}
-    {% if show_revision %}({{ _("Revision") }} {{ rev.revid }}){% endif %}
+    {% if show_revision %}({{ _("Revision") }} {{ rev.revid | shorten_id }}){% endif %}
 </h1>
 {% if meta_rendered %}
 <div id="moin-content-meta">

MoinMoin/templates/revert.html

 {% import "forms.html" as forms %}
 {% extends theme("layout.html") %}
 {% block content %}
-<h1>{{ _("Revert '%(item_name)s' (rev %(rev_id)s)", item_name=item.name, rev_id=rev_id) }}</h1>
+<h1>{{ _("Revert '%(item_name)s' (rev %(rev_id)s)", item_name=item.name, rev_id=rev_id | shorten_id) }}</h1>
 <div class="moin-form">
 {{ gen.form.open(form, method="post", action=url_for('frontend.revert_item', item_name=item.name, rev=rev_id)) }}
   {{ forms.render_errors(form) }}

MoinMoin/templates/search.html

                             {% endif %}
                             <tr>
                                 <td>
-                                    <p class="info searchhitinfobar">{{ _("Revision: %(revid)s Last Change: %(mtime)s", revid=result['revid'], mtime=result['mtime']|datetimeformat) }}</p>
+                                    <p class="info searchhitinfobar">{{ _("Revision: %(revid)s Last Change: %(mtime)s", revid=result['revid']|shorten_id, mtime=result['mtime']|datetimeformat) }}</p>
                                 </td>
                             </tr>
                             <tr>