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
andAttachment.reparent_all
methods - added new
wiki_rename.html
template and the corresponding handler methods,WikiModule._render_confirm_rename
andWikiModule._do_rename
methods
Discussion
Feel free to provide feedback.
- Would be nice to have a HTTP 301 redirect from the old wiki page to the new one, to keep searchengine rankings etc.
- (cboos) see ticket:3718#comment:3 (rather than #976)
- Another TODO optionally rename sub-pages as well, and more generally, have the possibility to do batch renames
- (cboos) yes, see comment:8:ticket:4412
- Another TODO would be nice to have an entry in the history of the page including the name, date and optional comment of the rename event.
- Looking at existing code from WikiRenamePlugin could help, see: http://trac-hacks.org/browser/wikirenameplugin/0.11/wikirename/util.py#L55
- 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 ;-)
- 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)
- 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:
- before the DB transaction: copy all the attachments to the new location in the FS
- only if 1. succeeds, perform the DB transaction
- 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 ;-)
- Yes, what about the following approach in 3 steps:
- 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.
- 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)
- (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?
- 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
- there is support for this already, see:
- 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.
- both are possible: for TracAdmin it's
See also: #1106, TracDev/Proposals/AdvancedWikiOperations