Edgewall Software

Wiki Rename

The base feature has now landed on trunk for 0.12, see r9362 and r9363.

Among the various possibilities for performing a rename, this implementation aims at simplicity. The page name is modified "in-place", i.e. the object identity is mutated and as such, the whole history is kept and becomes associated to the renamed wiki page.

You need to be a WIKI_ADMIN in order to be able to rename a page (or at the very least, have the new WIKI_RENAME permission).

How it works

Example: renaming WikiStart to ProjectHome

  • before the rename:
pagename text comment
WikiStart version1 comment1
WikiStart version2 comment2
WikiStart version3 comment3
  • after the rename:
pagename text comment
ProjectHome version1 comment1
ProjectHome version2 comment2
ProjectHome version3 comment3

the WikiStart page will be (optionally) recreated with a redirection to the new page:

pagename text comment
WikiStart See ProjectHome WikiStart → ProjectHome

Note that this is very similar to how moving a page in MediaWiki works.

Overview of the changes

  • added new WikiPage.rename and Attachment.reparent_all methods
  • added new wiki_rename.html template and the corresponding handler methods, WikiModule._render_confirm_rename and WikiModule._do_rename methods

Discussion

Feel free to provide feedback.

  • Another TODO optionally rename sub-pages as well, and more generally, have the possibility to do batch renames
  • Another TODO also rename all links to renamed pages on all other pages and create for this a new version for all affected pages
    • Cabbiepete: This sounds like an excellent idea currently re-organising the wiki structure is quite painful.
    • Before re-inventing the wheel again a hint to look at WikiRenamePlugin, this is done here: http://trac-hacks.org/browser/wikirenameplugin/0.11/wikirename/util.py#L76
      • cboos: well, that's rather an example of how to not implement this. To do it correctly, the wiki parser has to provide some direct support for this (#4431, with an eye on keeping enough information in the syntax nodes for being able to modify the original text in place, or alternatively have a wiki source formatter that can be specialized)
        • mitar: but it works, quite well ;-)
  • More robust error handling: what happens if a reparent fails mid-way (e.g. permission issue for one attachment)? The whole transaction is rolled back, but some attachment files could have been moved already. Should we try to move them back? Should we warn the user about what already got moved? After fixing the permission issue, a new rename should work, which might not be the case if the attachment table and the files are not in sync.
    • We have the same issue when deleting pages. Actually, any time a filesystem change must be atomic with a DB change. I thought about adding some kind of "post-commit task list" where e.g. the attachment reparenting method registers a callable with the transaction to be executed after a successful commit. So the transaction would complete, and only then would all the items in the list be called to execute FS operations.
      • Yes, what about the following approach in 3 steps:
        1. before the DB transaction: copy all the attachments to the new location in the FS
        2. only if 1. succeeds, perform the DB transaction
        3. if 1. succeeded, perform a clean-up step:
          • post-commit if 2. has also succeeded, we can try to remove the files at their old location.
          • post-rollback: if 2. has failed, we can try to undo step 1. by removing the copied files. This depends on the actual reason of the failure, don't do that if the failure is due to a concurrent rename attempt which succeeded ;-)
          If either of these FS clean-up task failed, bad luck but at least the DB and FS are consistent, the FS can eventually be cleaned manually afterwards.
  • Making the whole rename process more modular by introducing a WikiPageRename ExtensionPoint would be critical for some plugins. This was suggested (by coderanger) for WikiRenamePlugin before and discussed as key element for any plugin support (see ticket:457th-ticket 457). Since TagsPlugin, FlexibleWikiPlugin and certainly others are both, popular and depending on their own db table with references to wiki pages by name, helping them to keep their db tables in sync should be mandatory.
    • there is support for this already, see:
      • WikiChangeListener.wiki_page_renamed(page, old_page_name)
      • IAttachmentChangeListener.attachment_reparented(attachment, old_parent_realm, old_parent_id)
      (to be documented)
    • (rblank) Considering the discussion above about transactions, maybe we should also move the calls to the listeners into the transaction, instead of after the commit, so that DB updates by plugins are also done in the context of the transaction?
      • I agree, and even more: if any plugin not only uses wiki page names as reference in db table(s) but in any filesystem-related form there would be the need to allow the same two-staged change process with signal (commit|roll-back); however, I don't know of such a plugin by now, so maybe this is irrelevant and we really just need to integrate changes for db tables via the WikiChangeListener.
      • I doubt the current WikiChangeListener will allow for sending signal (commit|roll-back) after the first call, so you think of modifying this extension point?
  • This is great, but how does the user actually do it? E.g., is it by a command in trac-admin, or is there a "Rename Page" link at the bottom of the page, or both?
    • both are possible: for TracAdmin it's
      wiki rename <page> <new_name>
      
          Rename wiki page
      
      
      and for the interface, it depends on having the WIKI_RENAME permission (and the WIKI_CREATE for the target page). That's mentioned in TracPermissions, but maybe TracWiki could be expanded a bit.

See also: #1106, TracDev/Proposals/AdvancedWikiOperations

Last modified 5 years ago Last modified on Feb 16, 2011, 3:14:30 PM