changeset 1478:53e9c1db5ace

support for page/attachment removal and renaming (preliminary commit to show activity, needs more testing)
author Franz Pletz <fpletz AT franz-pletz DOT org>
date Thu, 24 Aug 2006 15:25:15 +0200
parents 7f5a6374e0e1
children b1562b232683
files MoinMoin/PageEditor.py MoinMoin/search/Xapian.py MoinMoin/search/builtin.py
diffstat 3 files changed, 93 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/PageEditor.py	Thu Aug 24 13:46:12 2006 +0200
+++ b/MoinMoin/PageEditor.py	Thu Aug 24 15:25:15 2006 +0200
@@ -488,7 +488,15 @@
             self.error = None
             # Save page text with a comment about the old name
             savetext = u"## page was renamed from %s\n%s" % (self.page_name, savetext)
-            newpage.saveText(savetext, 0, comment=comment)
+            newpage.saveText(savetext, 0, comment=comment, index=0)
+
+            if self.request.cfg.xapian_search:
+                from MoinMoin.search.Xapian import Index
+                index = Index(self.request)
+                if index.exists():
+                    index.remove_item(self.page_name)
+                    index.update_page(newpagename)
+
             return True, None
         except OSError, err:
             # Try to understand what happened. Maybe its better to check
@@ -517,10 +525,18 @@
         try:
             # First save a final backup copy of the current page
             # (recreating the page allows access to the backups again)
-            msg = self.saveText(u"deleted\n", 0, comment=comment or u'')
+            msg = self.saveText(u"deleted\n", 0, comment=comment or u'',
+                    index=0)
             msg = msg.replace(
                 _("Thank you for your changes. Your attention to detail is appreciated."),
                 _('Page "%s" was successfully deleted!') % (self.page_name,))
+            
+            if self.request.cfg.xapian_search:
+                from MoinMoin.search.Xapian import Index
+                index = Index(self.request)
+                if index.exists():
+                    index.remove_item(self.page_name)
+
             # Then really delete it
             try:
                 os.remove(self._text_filename())
@@ -915,6 +931,7 @@
         @keyword extra: extra info field (e.g. for SAVE/REVERT with revno)
         @keyword comment: comment field (when preview is true)
         @keyword action: action for editlog (default: SAVE)
+        @keyword index: needs indexing, not already handled (default: 1)
         @rtype: unicode
         @return: error msg
         """
@@ -981,7 +998,7 @@
                 action != "SAVE/REVERT"):
                 msg = _("You can't change ACLs on this page since you have no admin rights on it!")
                 raise self.NoAdmin, msg
-            
+        
         # save only if no error occurred (msg is empty)
         if not msg:
             # set success msg
@@ -1002,11 +1019,9 @@
             if self.request.cfg.mail_enabled:
                 msg = msg + self._notifySubscribers(comment, trivial)
           
-            if self.request.cfg.xapian_search:
+            if kw.get('index', 1) and self.request.cfg.xapian_search:
                 from MoinMoin.search.Xapian import Index
                 index = Index(self.request)
-                # When we have automatic index building, we can add to
-                # the queue even if the index is missing.
                 if index.exists():
                     index.update_page(self.page_name)
 
--- a/MoinMoin/search/Xapian.py	Thu Aug 24 13:46:12 2006 +0200
+++ b/MoinMoin/search/Xapian.py	Thu Aug 24 15:25:15 2006 +0200
@@ -190,7 +190,7 @@
         'linkto': 'XLINKTO', # this document links to that document
         'stem_lang': 'XSTEMLANG', # ISO Language code this document was stemmed in
         'category': 'XCAT', # category this document belongs to
-        'full_title': 'XFT', # full title (for regex)
+        'fulltitle': 'XFT', # full title
         'domain': 'XDOMAIN', # standard or underlay
         'revision': 'XREV', # revision of page
                        #Y   year (four digits)
@@ -262,11 +262,22 @@
         self.touch()
         writer = xapidx.Index(self.dir, True)
         writer.configure(self.prefixMap, self.indexValueMap)
-        pages = self.queue.pages()[:amount]
+
+        # do all page updates
+        pages = self.update_queue.pages()[:amount]
         for name in pages:
             p = Page(request, name)
             self._index_page(writer, p, mode='update')
-            self.queue.remove([name])
+            self.update_queue.remove([name])
+
+        # do page/attachment removals
+        items = self.remove_queue.pages()[:amount]
+        for item in items:
+            _item = item.split('//')
+            p = Page(request, _item[0])
+            self._remove_item(writer, p, _item[1])
+            self.remove_queue.remove([item])
+
         writer.close()
 
     def allterms(self):
@@ -450,7 +461,7 @@
             updated = True
         if debug: request.log("%s %r" % (pagename, updated))
         if updated:
-            xwname = xapdoc.SortKey('wikiname', request.cfg.interwikiname or "Self")
+            xwname = xapdoc.SortKey('wikiname', wikiname)
             xpname = xapdoc.SortKey('pagename', pagename)
             xattachment = xapdoc.SortKey('attachment', '') # this is a real page, not an attachment
             xmtime = xapdoc.SortKey('mtime', str(mtime))
@@ -459,7 +470,7 @@
             xkeywords = [xapdoc.Keyword('itemid', itemid),
                     xapdoc.Keyword('lang', language),
                     xapdoc.Keyword('stem_lang', stem_language),
-                    xapdoc.Keyword('full_title', pagename.lower()),
+                    xapdoc.Keyword('fulltitle', pagename),
                     xapdoc.Keyword('revision', revision),
                     xapdoc.Keyword('author', author),
                 ]
@@ -491,7 +502,7 @@
         attachments = AttachFile._get_files(request, pagename)
         for att in attachments:
             filename = AttachFile.getFilename(request, pagename, att)
-            att_itemid = "%s//%s" % (itemid, att)
+            att_itemid = "%s:%s//%s" % (wikiname, pagename, att)
             mtime = wikiutil.timestamp2version(os.path.getmtime(filename))
             if mode == 'update':
                 query = xapidx.RawQuery(xapdoc.makePairForWrite('itemid', att_itemid))
@@ -521,12 +532,15 @@
                 mimetype, att_content = self.contentfilter(filename)
                 xmimetype = xapdoc.Keyword('mimetype', mimetype)
                 xcontent = xapdoc.TextField('content', att_content)
+                xtitle_txt = xapdoc.TextField('title',
+                        '%s/%s' % (pagename, att), True)
+                xfulltitle = xapdoc.Keyword('fulltitle', pagename)
                 xdomains = [xapdoc.Keyword('domain', domain)
                         for domain in domains]
-                doc = xapdoc.Document(textFields=(xcontent, ),
+                doc = xapdoc.Document(textFields=(xcontent, xtitle_txt),
                                       keywords=xdomains + [xatt_itemid,
                                           xtitle, xlanguage, xstem_language,
-                                          xmimetype, ],
+                                          xmimetype, xfulltitle, ],
                                       sortFields=(xpname, xattachment, xmtime,
                                           xwname, xrev, ),
                                      )
@@ -541,6 +555,33 @@
                     id = writer.index(doc)
         #writer.flush()
 
+    def _remove_item(self, writer, page, attachment=None):
+        request = page.request
+        wikiname = request.cfg.interwikiname or 'Self'
+        pagename = page.page_name
+
+        if not attachment:
+            # Remove all revisions and attachments from the index
+            query = xapidx.RawQuery(xapidx.makePairForWrite(
+                self.prefixMap['fulltitle'], pagename))
+            enq, mset, docs = writer.search(query, valuesWanted=['pagename',
+                'attachment', ])
+            for doc in docs:
+                writer.delete_document(doc['uid'])
+                request.log('%s removed from xapian index' %
+                        doc['values']['pagename'])
+        else:
+            # Only remove a single attachment
+            query = xapidx.RawQuery(xapidx.makePairForWrite('itemid',
+                "%s:%s//%s" % (wikiname, pagename, att)))
+            enq, mset, docs = writer.search(query, valuesWanted=['pagename',
+                'attachment', ])
+            if docs:
+                doc = docs[0]   # there should be only one
+                writer.delete_document(doc['uid'])
+                request.log('attachment %s from %s removed from index' %
+                    (doc['values']['attachment'], doc['values']['pagename']))
+
     def _index_pages(self, request, files=None, mode='update'):
         """ Index all pages (and all given files)
         
--- a/MoinMoin/search/builtin.py	Thu Aug 24 13:46:12 2006 +0200
+++ b/MoinMoin/search/builtin.py	Thu Aug 24 15:25:15 2006 +0200
@@ -156,8 +156,10 @@
         self.lock = lock.WriteLock(lock_dir,
                                    timeout=3600.0, readlocktimeout=60.0)
         #self.read_lock = lock.ReadLock(lock_dir, timeout=3600.0)
-        self.queue = UpdateQueue(os.path.join(main_dir, 'update-queue'),
-                                 os.path.join(main_dir, 'update-queue-lock'))
+        self.update_queue = UpdateQueue(os.path.join(main_dir, 'update-queue'),
+                                os.path.join(main_dir, 'update-queue-lock'))
+        self.remove_queue = UpdateQueue(os.path.join(main_dir, 'remove-queue'),
+                                os.path.join(main_dir, 'remove-queue-lock'))
 
         # Disabled until we have a sane way to build the index with a
         # queue in small steps.
@@ -200,7 +202,16 @@
 
         @param pagename: the name of the page to update
         """
-        self.queue.append(pagename)
+        self.update_queue.append(pagename)
+        self._do_queued_updates_InNewThread()
+
+    def remove_item(self, pagename, attachment=None):
+        """ Removes a page and all its revisions or a single attachment
+
+        @param pagename: name of the page to be removed
+        @param attachment: optional, only remove this attachment of the page
+        """
+        self.remove_queue.append('%s//%s' % (pagename, attachment or ''))
         self._do_queued_updates_InNewThread()
 
     def indexPages(self, files=None, mode='update'):
@@ -267,6 +278,15 @@
         """
         raise NotImplemented('...')
 
+    def _remove_item(self, writer, page, attachment=None):
+        """ Remove a page and all its revisions from the index or just
+            an attachment of that page
+
+        @param pagename: name of the page to remove
+        @keyword attachment: optionally, just remove this attachment
+        """
+        raise NotImplemented('...')
+
     def _do_queued_updates_InNewThread(self):
         """ do queued index updates in a new thread