def rename(self, new_name): """Rename wiki page in-place, keeping the history intact. Renaming a page this way will eventually leave dangling references to the old page - which litterally doesn't exist anymore. """ assert self.exists, "Cannot rename non-existent page" if not validate_page_name(new_name): raise TracError(_("Invalid Wiki page name '%(name)s'", name=new_name)) old_name = self.name with self.env.db_transaction as db: new_page = WikiPage(self.env, new_name) if new_page.exists: raise TracError(_("Can't rename to existing %(name)s page.", name=new_name)) db("UPDATE wiki SET name=%s WHERE name=%s", (new_name, old_name)) # Invalidate page name cache del WikiSystem(self.env).pages # Reparent attachments from trac.attachment import Attachment Attachment.reparent_all(self.env, 'wiki', old_name, 'wiki', new_name) self.name = new_name self.env.log.info('Renamed page %s to %s', old_name, new_name) for listener in WikiSystem(self.env).change_listeners: if hasattr(listener, 'wiki_page_renamed'): listener.wiki_page_renamed(self, old_name)
def rename(self, new_name): """Rename wiki page in-place, keeping the history intact. Renaming a page this way will eventually leave dangling references to the old page - which literally doesn't exist anymore. """ if not self.exists: raise TracError(_("Cannot rename non-existent page")) if not validate_page_name(new_name): raise TracError( _("Invalid Wiki page name '%(name)s'", name=new_name)) old_name = self.name with self.env.db_transaction as db: new_page = WikiPage(self.env, new_name) if new_page.exists: raise TracError( _("Can't rename to existing %(name)s page.", name=new_name)) db("UPDATE wiki SET name=%s WHERE name=%s", (new_name, old_name)) # Invalidate page name cache del WikiSystem(self.env).pages # Reparent attachments from trac.attachment import Attachment Attachment.reparent_all(self.env, self.realm, old_name, self.realm, new_name) self.name = new_name self.env.log.info("Renamed page %s to %s", old_name, new_name) for listener in WikiSystem(self.env).change_listeners: if hasattr(listener, 'wiki_page_renamed'): listener.wiki_page_renamed(self, old_name)
def _do_rename(self, req, page): if page.readonly: req.perm(page.resource).require('WIKI_ADMIN') else: req.perm(page.resource).require('WIKI_RENAME') if 'cancel' in req.args: req.redirect(get_resource_url(self.env, page.resource, req.href)) old_name, old_version = page.name, page.version new_name = req.args.get('new_name', '') new_name = re.sub(r'/{2,}', '/', new_name.strip('/')) redirect = req.args.get('redirect') # verify input parameters warn = None if not new_name: warn = _("A new name is mandatory for a rename.") elif not validate_page_name(new_name): warn = _("The new name is invalid (a name which is separated " "with slashes cannot be '.' or '..').") elif new_name == old_name: warn = _("The new name must be different from the old name.") elif WikiPage(self.env, new_name).exists: warn = _("The page %(name)s already exists.", name=new_name) if warn: add_warning(req, warn) return self._render_confirm_rename(req, page, new_name) with self.env.db_transaction as db: page.rename(new_name) if redirect: redirection = WikiPage(self.env, old_name, db=db) redirection.text = _('See [wiki:"%(name)s"].', name=new_name) author = get_reporter_id(req) comment = u'[wiki:"%s@%d" %s] \u2192 [wiki:"%s"].' % ( new_name, old_version, old_name, new_name) redirection.save(author, comment, req.remote_addr) add_notice( req, _("The page %(old_name)s has been renamed to " "%(new_name)s.", old_name=old_name, new_name=new_name)) if redirect: add_notice( req, _( "The page %(old_name)s has been recreated " "with a redirect to %(new_name)s.", old_name=old_name, new_name=new_name)) req.redirect(req.href.wiki(old_name if redirect else new_name))
def save(self, author, comment, remote_addr=None, t=None, db=None): """Save a new version of a page. :since 1.0: the `db` parameter is no longer needed and will be removed in version 1.1.1 :since 1.0.3: `remote_addr` is optional and deprecated, and will be removed in 1.3.1 """ if not validate_page_name(self.name): raise TracError(_("Invalid Wiki page name '%(name)s'", name=self.name)) new_text = self.text != self.old_text if not new_text and self.readonly == self.old_readonly: raise TracError(_("Page not modified")) t = t or datetime.now(utc) with self.env.db_transaction as db: if new_text: db("""INSERT INTO wiki (name, version, time, author, ipnr, text, comment, readonly) VALUES (%s,%s,%s,%s,%s,%s,%s,%s) """, (self.name, self.version + 1, to_utimestamp(t), author, remote_addr, self.text, comment, self.readonly)) self.version += 1 self.resource = self.resource(version=self.version) else: db("UPDATE wiki SET readonly=%s WHERE name=%s", (self.readonly, self.name)) if self.version == 1: # Invalidate page name cache del WikiSystem(self.env).pages self.author = author self.comment = comment self.time = t for listener in WikiSystem(self.env).change_listeners: if self.version == 1: listener.wiki_page_added(self) else: from trac.util import arity if arity(listener.wiki_page_changed) == 6: listener.wiki_page_changed(self, self.version, t, comment, author, remote_addr) else: listener.wiki_page_changed(self, self.version, t, comment, author) self.old_readonly = self.readonly self.old_text = self.text
def _do_rename(self, name, new_name): if new_name == name: return if not new_name: raise AdminCommandError(_("A new name is mandatory for a rename.")) if not validate_page_name(new_name): raise AdminCommandError(_("The new name is invalid.")) with self.env.db_transaction: if model.WikiPage(self.env, new_name).exists: raise AdminCommandError(_("The page %(name)s already exists.", name=new_name)) page = model.WikiPage(self.env, name) page.rename(new_name)
def _do_rename(self, name, new_name): if new_name == name: return if not new_name: raise AdminCommandError(_("A new name is mandatory for a rename.")) if not validate_page_name(new_name): raise AdminCommandError(_("The new name is invalid.")) with self.env.db_transaction: if model.WikiPage(self.env, new_name).exists: raise AdminCommandError( _("The page %(name)s already exists.", name=new_name)) page = model.WikiPage(self.env, name) page.rename(new_name)
def save(self, author, comment, remote_addr=None, t=None): """Save a new version of a page. :since 1.0.3: `remote_addr` is optional and deprecated, and will be removed in 1.3.1 """ if not validate_page_name(self.name): raise TracError( _("Invalid Wiki page name '%(name)s'", name=self.name)) new_text = self.text != self.old_text if not new_text and self.readonly == self.old_readonly: raise TracError(_("Page not modified")) t = t or datetime_now(utc) with self.env.db_transaction as db: if new_text: db( """INSERT INTO wiki (name, version, time, author, ipnr, text, comment, readonly) VALUES (%s,%s,%s,%s,%s,%s,%s,%s) """, (self.name, self.version + 1, to_utimestamp(t), author, remote_addr, self.text, comment, self.readonly)) self.version += 1 else: db("UPDATE wiki SET readonly=%s WHERE name=%s", (self.readonly, self.name)) if self.version == 1: # Invalidate page name cache del WikiSystem(self.env).pages self.author = author self.comment = comment self.time = t for listener in WikiSystem(self.env).change_listeners: if self.version == 1: listener.wiki_page_added(self) else: from trac.util import arity if arity(listener.wiki_page_changed) == 6: listener.wiki_page_changed(self, self.version, t, comment, author, remote_addr) else: listener.wiki_page_changed(self, self.version, t, comment, author) self.old_readonly = self.readonly self.old_text = self.text
def import_page(self, filename, title, create_only=[], replace=False): if not validate_page_name(title): raise AdminCommandError( _("Invalid Wiki page name '%(name)s'", name=title)) if filename: if not os.path.isfile(filename): raise AdminCommandError( _("'%(name)s' is not a file", name=path_to_unicode(filename))) data = read_file(filename) else: data = sys.stdin.read() data = to_unicode(data, 'utf-8') with self.env.db_transaction as db: # Make sure we don't insert the exact same page twice old = db( """SELECT text FROM wiki WHERE name=%s ORDER BY version DESC LIMIT 1 """, (title, )) if old and title in create_only: printout(_(" %(title)s already exists", title=title)) return False if old and data == old[0][0]: printout(_(" %(title)s is already up to date", title=title)) return False if replace and old: db( """UPDATE wiki SET text=%s WHERE name=%s AND version=(SELECT max(version) FROM wiki WHERE name=%s) """, (data, title, title)) else: db( """INSERT INTO wiki (version, readonly, name, time, author, text) SELECT 1 + COALESCE(max(version), 0), COALESCE(max(readonly), 0), %s, %s, 'trac', %s FROM wiki WHERE name=%s AND version=(SELECT max(version) FROM wiki WHERE name=%s) """, (title, to_utimestamp( datetime_now(utc)), data, title, title)) if not old: del WikiSystem(self.env).pages return True
def _do_rename(self, req, page): if page.readonly: req.perm(page.resource).require('WIKI_ADMIN') else: req.perm(page.resource).require('WIKI_RENAME') if 'cancel' in req.args: req.redirect(get_resource_url(self.env, page.resource, req.href)) old_name, old_version = page.name, page.version new_name = req.args.get('new_name', '') new_name = re.sub(r'/{2,}', '/', new_name.strip('/')) redirect = req.args.get('redirect') # verify input parameters warn = None if not new_name: warn = _("A new name is mandatory for a rename.") elif not validate_page_name(new_name): warn = _("The new name is invalid (a name which is separated " "with slashes cannot be '.' or '..').") elif new_name == old_name: warn = _("The new name must be different from the old name.") elif WikiPage(self.env, new_name).exists: warn = _("The page %(name)s already exists.", name=new_name) if warn: add_warning(req, warn) return self._render_confirm_rename(req, page, new_name) with self.env.db_transaction as db: page.rename(new_name) if redirect: redirection = WikiPage(self.env, old_name, db=db) redirection.text = _('See [wiki:"%(name)s"].', name=new_name) author = get_reporter_id(req) comment = u'[wiki:"%s@%d" %s] \u2192 [wiki:"%s"].' % ( new_name, old_version, old_name, new_name) redirection.save(author, comment, req.remote_addr) add_notice(req, _("The page %(old_name)s has been renamed to " "%(new_name)s.", old_name=old_name, new_name=new_name)) if redirect: add_notice(req, _("The page %(old_name)s has been recreated " "with a redirect to %(new_name)s.", old_name=old_name, new_name=new_name)) req.redirect(req.href.wiki(old_name if redirect else new_name))
def save(self, author, comment, t=None, replace=False): """Save a new version of a page.""" if not validate_page_name(self.name): raise TracError( _("Invalid Wiki page name '%(name)s'", name=self.name)) new_text = self.text != self.old_text if not new_text and self.readonly == self.old_readonly: raise TracError(_("Page not modified")) t = t or datetime_now(utc) with self.env.db_transaction as db: if new_text: if replace and self.version != 0: db( """ UPDATE wiki SET text=%s WHERE name=%s AND version=%s """, (self.text, self.name, self.version)) else: self.version += 1 db( """INSERT INTO wiki (name,version,time,author,text,comment,readonly) VALUES (%s,%s,%s,%s,%s,%s,%s) """, (self.name, self.version, to_utimestamp(t), author, self.text, comment, self.readonly)) else: db("UPDATE wiki SET readonly=%s WHERE name=%s", (self.readonly, self.name)) if self.version == 1: # Invalidate page name cache del WikiSystem(self.env).pages self.author = author self.comment = comment self.time = t for listener in WikiSystem(self.env).change_listeners: with self.env.component_guard(listener): if self.version == 1: listener.wiki_page_added(self) else: listener.wiki_page_changed(self, self.version, t, comment, author) self.old_readonly = self.readonly self.old_text = self.text
def save(self, author, comment, remote_addr, t=None, db=None): """Save a new version of a page. :since 0.13: the `db` parameter is no longer needed and will be removed in version 0.14 """ if not validate_page_name(self.name): raise TracError( _("Invalid Wiki page name '%(name)s'", name=self.name)) new_text = self.text != self.old_text if not new_text and self.readonly == self.old_readonly: raise TracError(_("Page not modified")) t = t or datetime.now(utc) with self.env.db_transaction as db: if new_text: db( """INSERT INTO wiki (name, version, time, author, ipnr, text, comment, readonly) VALUES (%s,%s,%s,%s,%s,%s,%s,%s) """, (self.name, self.version + 1, to_utimestamp(t), author, remote_addr, self.text, comment, self.readonly)) self.version += 1 self.resource = self.resource(version=self.version) else: db("UPDATE wiki SET readonly=%s WHERE name=%s", (self.readonly, self.name)) if self.version == 1: # Invalidate page name cache del WikiSystem(self.env).pages self.author = author self.comment = comment self.time = t for listener in WikiSystem(self.env).change_listeners: if self.version == 1: listener.wiki_page_added(self) else: listener.wiki_page_changed(self, self.version, t, comment, author, remote_addr) self.old_readonly = self.readonly self.old_text = self.text
def import_page(self, filename, title, create_only=[], replace=False): if not validate_page_name(title): raise AdminCommandError(_("Invalid Wiki page name '%(name)s'", name=title)) if filename: if not os.path.isfile(filename): raise AdminCommandError(_("'%(name)s' is not a file", name=path_to_unicode(filename))) data = read_file(filename) else: data = sys.stdin.read() data = to_unicode(data, 'utf-8') with self.env.db_transaction as db: # Make sure we don't insert the exact same page twice old = db("""SELECT text FROM wiki WHERE name=%s ORDER BY version DESC LIMIT 1 """, (title,)) if old and title in create_only: printout(_(" %(title)s already exists", title=title)) return False if old and data == old[0][0]: printout(_(" %(title)s is already up to date", title=title)) return False if replace and old: db("""UPDATE wiki SET text=%s WHERE name=%s AND version=(SELECT max(version) FROM wiki WHERE name=%s) """, (data, title, title)) else: db("""INSERT INTO wiki(version, name, time, author, ipnr, text) SELECT 1 + COALESCE(max(version), 0), %s, %s, 'trac', '127.0.0.1', %s FROM wiki WHERE name=%s """, (title, to_utimestamp(datetime.now(utc)), data, title)) if not old: del WikiSystem(self.env).pages return True
def process_request(self, req): action = req.args.get('action', 'view') pagename = req.args.get('page', self.START_PAGE) version = None if req.args.get('version'): # Allow version to be empty version = req.args.getint('version') old_version = req.args.getint('old_version') if pagename.startswith('/') or pagename.endswith('/') or \ '//' in pagename: pagename = re.sub(r'/{2,}', '/', pagename.strip('/')) req.redirect(req.href.wiki(pagename)) if not validate_page_name(pagename): raise TracError(_("Invalid Wiki page name '%(name)s'", name=pagename)) page = WikiPage(self.env, pagename) versioned_page = WikiPage(self.env, pagename, version) req.perm(versioned_page.resource).require('WIKI_VIEW') if version and versioned_page.version != version: raise ResourceNotFound( _('No version "%(num)s" for Wiki page "%(name)s"', num=version, name=page.name)) add_stylesheet(req, 'common/css/wiki.css') if req.method == 'POST': if action == 'edit': if 'cancel' in req.args: req.redirect(req.href.wiki(page.name)) has_collision = version != page.version for a in ('preview', 'diff', 'merge'): if a in req.args: action = a break versioned_page.text = req.args.get('text') valid = self._validate(req, versioned_page) if action == 'edit' and not has_collision and valid: return self._do_save(req, versioned_page) else: return self._render_editor(req, page, action, has_collision) elif action == 'edit_comment': self._do_edit_comment(req, versioned_page) elif action == 'delete': self._do_delete(req, versioned_page) elif action == 'rename': return self._do_rename(req, page) elif action == 'diff': style, options, diff_data = get_diff_options(req) contextall = diff_data['options']['contextall'] req.redirect(req.href.wiki(versioned_page.name, action='diff', old_version=old_version, version=version, contextall=contextall or None)) else: raise HTTPBadRequest(_("Invalid request arguments.")) elif action == 'delete': return self._render_confirm_delete(req, page) elif action == 'rename': return self._render_confirm_rename(req, page) elif action == 'edit': return self._render_editor(req, page) elif action == 'edit_comment': return self._render_edit_comment(req, versioned_page) elif action == 'diff': return self._render_diff(req, versioned_page) elif action == 'history': return self._render_history(req, versioned_page) else: format = req.args.get('format') if format: Mimeview(self.env).send_converted(req, 'text/x-trac-wiki', versioned_page.text, format, versioned_page.name) return self._render_view(req, versioned_page)
def process_request(self, req): action = req.args.get('action', 'view') pagename = req.args.get('page', 'WikiStart') version = req.args.get('version') old_version = req.args.get('old_version') if pagename.startswith('/') or pagename.endswith('/') or \ '//' in pagename: pagename = re.sub(r'/{2,}', '/', pagename.strip('/')) req.redirect(req.href.wiki(pagename)) if not validate_page_name(pagename): raise TracError(_("Invalid Wiki page name '%(name)s'", name=pagename)) page = WikiPage(self.env, pagename) versioned_page = WikiPage(self.env, pagename, version=version) req.perm(page.resource).require('WIKI_VIEW') req.perm(versioned_page.resource).require('WIKI_VIEW') if version and versioned_page.version != int(version): raise ResourceNotFound( _('No version "%(num)s" for Wiki page "%(name)s"', num=version, name=page.name)) add_stylesheet(req, 'common/css/wiki.css') if req.method == 'POST': if action == 'edit': if 'cancel' in req.args: req.redirect(req.href.wiki(page.name)) has_collision = int(version) != page.version for a in ('preview', 'diff', 'merge'): if a in req.args: action = a break versioned_page.text = req.args.get('text') valid = self._validate(req, versioned_page) if action == 'edit' and not has_collision and valid: return self._do_save(req, versioned_page) else: return self._render_editor(req, page, action, has_collision) elif action == 'delete': self._do_delete(req, versioned_page) elif action == 'rename': return self._do_rename(req, page) elif action == 'diff': style, options, diff_data = get_diff_options(req) contextall = diff_data['options']['contextall'] req.redirect(req.href.wiki(versioned_page.name, action='diff', old_version=old_version, version=version, contextall=contextall or None)) elif action == 'delete': return self._render_confirm_delete(req, page) elif action == 'rename': return self._render_confirm_rename(req, page) elif action == 'edit': return self._render_editor(req, page) elif action == 'diff': return self._render_diff(req, versioned_page) elif action == 'history': return self._render_history(req, versioned_page) else: format = req.args.get('format') if format: Mimeview(self.env).send_converted(req, 'text/x-trac-wiki', versioned_page.text, format, versioned_page.name) return self._render_view(req, versioned_page)
def save(self, author, comment, remote_addr=None, t=None, db=None): """Save a new version of a page. :since 1.0: the `db` parameter is no longer needed and will be removed in version 1.1.1 :since 1.0.3: `remote_addr` is optional and deprecated, and will be removed in 1.3.1 """ if not validate_page_name(self.name): raise TracError( _("Invalid Wiki page name '%(name)s'", name=self.name)) new_text = self.text != self.old_text if not new_text and self.readonly == self.old_readonly: raise TracError(_("Page not modified")) t = t or datetime_now(utc) with self.env.db_transaction as db: if new_text: db( """INSERT INTO wiki (name, version, time, author, ipnr, text, comment, readonly) VALUES (%s,%s,%s,%s,%s,%s,%s,%s) """, (self.name, self.version + 1, to_utimestamp(t), author, remote_addr, self.text, comment, self.readonly)) self.version += 1 self.resource = self.resource(version=self.version) else: db("UPDATE wiki SET readonly=%s WHERE name=%s", (self.readonly, self.name)) if self.version == 1: # Invalidate page name cache del WikiSystem(self.env).pages self.author = author self.comment = comment self.time = t for listener in WikiSystem(self.env).change_listeners: if self.version == 1: listener.wiki_page_added(self) else: listener.wiki_page_changed(page=self, version=self.version, t=t, comment=comment, author=author, ipnr=remote_addr) context = dict(version=self.version, comment=comment, author=author, remote_addr=remote_addr) if self.version == 1: ResourceSystem(self.env).resource_created(self, context) else: old_values = dict() if self.readonly != self.old_readonly: old_values["readonly"] = self.old_readonly if self.text != self.old_text: old_values["text"] = self.old_text ResourceSystem(self.env).resource_changed(self, old_values, context=context) self.old_readonly = self.readonly self.old_text = self.text