def _do_import(self, filename=None): permsys = PermissionSystem(self.env) try: with file_or_std(filename, 'rb') as f: encoding = stream_encoding(f) linesep = os.linesep if filename else '\n' reader = csv.reader(f, lineterminator=linesep) for row in reader: if len(row) < 2: raise AdminCommandError( _("Invalid row %(line)d. Expected <user>, " "<action>, [action], [...]", line=reader.line_num)) user = to_unicode(row[0], encoding) actions = [to_unicode(action, encoding) for action in row[1:]] if user.isupper(): raise AdminCommandError( _("Invalid user %(user)s on line %(line)d: All " "upper-cased tokens are reserved for permission " "names.", user=user, line=reader.line_num)) old_actions = self.get_user_perms(user) for action in set(actions) - set(old_actions): permsys.grant_permission(user, action) except csv.Error as e: raise AdminCommandError( _("Cannot import from %(filename)s line %(line)d: %(error)s ", filename=path_to_unicode(filename or 'stdin'), line=reader.line_num, error=e)) except IOError as e: raise AdminCommandError( _("Cannot import from %(filename)s: %(error)s", filename=path_to_unicode(filename or 'stdin'), error=e.strerror))
def _do_import(self, filename=None): permsys = PermissionSystem(self.env) linesep = os.linesep if filename else '\n' try: with file_or_std(filename, 'rb') as f: encoding = stream_encoding(f) reader = csv.reader(f, lineterminator=linesep) for row in reader: if len(row) < 2: raise AdminCommandError( _("Invalid row %(line)d. Expected <user>, " "<action>, [action], [...]", line=reader.line_num)) user = to_unicode(row[0], encoding) actions = [to_unicode(action, encoding) for action in row[1:]] if user.isupper(): raise AdminCommandError( _("Invalid user %(user)s on line %(line)d: All " "upper-cased tokens are reserved for " "permission names.", user=user, line=reader.line_num)) old_actions = self.get_user_perms(user) for action in set(actions) - set(old_actions): permsys.grant_permission(user, action) except csv.Error as e: raise AdminCommandError( _("Cannot import from %(filename)s line %(line)d: %(error)s ", filename=path_to_unicode(filename or 'stdin'), line=reader.line_num, error=e)) except IOError as e: raise AdminCommandError( _("Cannot import from %(filename)s: %(error)s", filename=path_to_unicode(filename or 'stdin'), error=e.strerror))
def import_page(self, filename, title, create_only=[], replace=False): 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') name = unicode_unquote(title.encode('utf-8')) page = model.WikiPage(self.env, name) if page.exists: if name in create_only: self.log.info("%s already exists", name) return False if data == page.text: self.log.info("%s is already up to date", name) return False page.text = data try: page.save('trac', None, replace=replace) except TracError as e: raise AdminCommandError(e) self.log.info("%s imported from %s", name, path_to_unicode(filename)) return True
def _do_hotcopy(self, dest, no_db=None): if no_db not in (None, '--no-database'): raise AdminCommandError(_("Invalid argument '%(arg)s'", arg=no_db), show_usage=True) if os.path.exists(dest): raise TracError( _("hotcopy can't overwrite existing '%(dest)s'", dest=path_to_unicode(dest))) import shutil # Bogus statement to lock the database while copying files with self.env.db_transaction as db: db("UPDATE system SET name=NULL WHERE name IS NULL") printout( _("Hotcopying %(src)s to %(dst)s ...", src=path_to_unicode(self.env.path), dst=path_to_unicode(dest))) db_str = self.env.config.get('trac', 'database') prefix, db_path = db_str.split(':', 1) skip = [] if prefix == 'sqlite': db_path = os.path.join(self.env.path, os.path.normpath(db_path)) # don't copy the journal (also, this would fail on Windows) skip = [ db_path + '-journal', db_path + '-stmtjrnl', db_path + '-shm', db_path + '-wal' ] if no_db: skip.append(db_path) try: copytree(self.env.path, dest, symlinks=1, skip=skip) retval = 0 except shutil.Error as e: retval = 1 printerr( _("The following errors happened while copying " "the environment:")) for (src, dst, err) in e.args[0]: if src in err: printerr(' %s' % err) else: printerr(" %s: '%s'" % (err, path_to_unicode(src))) # db backup for non-sqlite if prefix != 'sqlite' and not no_db: printout(_("Backing up database ...")) sql_backup = os.path.join(dest, 'db', '%s-db-backup.sql' % prefix) self.env.backup(sql_backup) printout(_("Hotcopy done.")) return retval
def _do_hotcopy(self, dest, no_db=None): if no_db not in (None, '--no-database'): raise AdminCommandError(_("Invalid argument '%(arg)s'", arg=no_db), show_usage=True) if os.path.exists(dest): raise TracError(_("hotcopy can't overwrite existing '%(dest)s'", dest=path_to_unicode(dest))) # Bogus statement to lock the database while copying files with self.env.db_transaction as db: db("UPDATE system SET name=NULL WHERE name IS NULL") printout(_("Hotcopying %(src)s to %(dst)s ...", src=path_to_unicode(self.env.path), dst=path_to_unicode(dest))) db_str = self.env.config.get('trac', 'database') prefix, db_path = db_str.split(':', 1) skip = [] if prefix == 'sqlite': db_path = os.path.join(self.env.path, os.path.normpath(db_path)) # don't copy the journal (also, this would fail on Windows) skip = [db_path + '-journal', db_path + '-stmtjrnl', db_path + '-shm', db_path + '-wal'] if no_db: skip.append(db_path) try: copytree(self.env.path, dest, symlinks=1, skip=skip) retval = 0 except shutil.Error as e: retval = 1 printerr(_("The following errors happened while copying " "the environment:")) for (src, dst, err) in e.args[0]: if src in err: printerr(' %s' % err) else: printerr(" %s: '%s'" % (err, path_to_unicode(src))) # db backup for non-sqlite if prefix != 'sqlite' and not no_db: printout(_("Backing up database ...")) sql_backup = os.path.join(dest, 'db', '%s-db-backup.sql' % prefix) self.env.backup(sql_backup) printout(_("Hotcopy done.")) return retval
def _do_upgrade(self, no_backup=None): if no_backup not in (None, '-b', '--no-backup'): raise AdminCommandError(_("Invalid arguments"), show_usage=True) if not self.env.needs_upgrade(): printout(_("Database is up to date, no upgrade necessary.")) return try: self.env.upgrade(backup=no_backup is None) except BackupError as e: printerr( _("The pre-upgrade backup failed.\nUse '--no-backup' to " "upgrade without doing a backup.\n")) raise e.args[0] except Exception: printerr( _("The upgrade failed. Please fix the issue and try " "again.\n")) raise printout( _( 'Upgrade done.\n\n' 'You may want to upgrade the Trac documentation now by ' 'running:\n\n trac-admin "%(path)s" wiki upgrade', path=path_to_unicode(self.env.path)))
def _load_or_replace(self, paths, replace): with self.env.db_transaction: for path in paths: if os.path.isdir(path): self.load_pages(path, replace=replace) else: page = os.path.basename(path) page = unicode_unquote(page.encode('utf-8')) if self.import_page(path, page, replace=replace): printout(_(" %(page)s imported from %(filename)s", filename=path_to_unicode(path), page=page))
def _do_upgrade(self, no_backup=None): if no_backup not in (None, "-b", "--no-backup"): raise AdminCommandError(_("Invalid arguments"), show_usage=True) if not self.env.needs_upgrade(): printout(_("Database is up to date, no upgrade necessary.")) return try: self.env.upgrade(backup=no_backup is None) except BackupError as e: printerr(_("The pre-upgrade backup failed.\nUse '--no-backup' to " "upgrade without doing a backup.\n")) raise e.args[0] except Exception: printerr(_("The upgrade failed. Please fix the issue and try " "again.\n")) raise # Remove wiki-macros if it is empty and warn if it isn't wiki_macros = os.path.join(self.env.path, "wiki-macros") try: entries = os.listdir(wiki_macros) except OSError: pass else: if entries: printerr( _( "Warning: the wiki-macros directory in the " "environment is non-empty, but Trac\n" "doesn't load plugins from there anymore. " "Please remove it by hand." ) ) else: try: os.rmdir(wiki_macros) except OSError as e: printerr( _( "Error while removing wiki-macros: %(err)s\n" "Trac doesn't load plugins from wiki-macros " "anymore. Please remove it by hand.", err=exception_to_unicode(e), ) ) printout( _( "Upgrade done.\n\n" "You may want to upgrade the Trac documentation now by " "running:\n\n trac-admin %(path)s wiki upgrade", path=path_to_unicode(self.env.path), ) )
def load_pages(self, dir, ignore=[], create_only=[], replace=False): with self.env.db_transaction: for page in os.listdir(dir): if page in ignore: continue filename = os.path.join(dir, page) page = unicode_unquote(page.encode('utf-8')) if os.path.isfile(filename): if self.import_page(filename, page, create_only, replace): self.log.info("%s imported from %s", page, path_to_unicode(filename))
def _do_export(self, resource, name, destination=None): realm, id_ = self.split_resource(resource) attachment = Attachment(self.env, realm, id_, name) if destination is not None: if os.path.isdir(destination): destination = os.path.join(destination, name) if os.path.isfile(destination): raise AdminCommandError(_("File '%(name)s' exists", name=path_to_unicode(destination))) with attachment.open() as input: with file_or_std(destination, 'wb') as output: shutil.copyfileobj(input, output)
def load_pages(self, dir, ignore=[], create_only=[], replace=False): with self.env.db_transaction: for page in os.listdir(dir): if page in ignore: continue filename = os.path.join(dir, page) page = unicode_unquote(page.encode('utf-8')) if os.path.isfile(filename): if self.import_page(filename, page, create_only, replace): printout(_(" %(page)s imported from %(filename)s", filename=path_to_unicode(filename), page=page))
def _do_upgrade(self, no_backup=None): if no_backup not in (None, '-b', '--no-backup'): raise AdminCommandError(_("Invalid arguments"), show_usage=True) if not self.env.needs_upgrade(): printout(_("Database is up to date, no upgrade necessary.")) return try: self.env.upgrade(backup=no_backup is None) except BackupError as e: printerr( _("The pre-upgrade backup failed.\nUse '--no-backup' to " "upgrade without doing a backup.\n")) raise e.args[0] except Exception: printerr( _("The upgrade failed. Please fix the issue and try " "again.\n")) raise # Remove wiki-macros if it is empty and warn if it isn't wiki_macros = os.path.join(self.env.path, 'wiki-macros') try: entries = os.listdir(wiki_macros) except OSError: pass else: if entries: printerr( _("Warning: the wiki-macros directory in the " "environment is non-empty, but Trac\n" "doesn't load plugins from there anymore. " "Please remove it by hand.")) else: try: os.rmdir(wiki_macros) except OSError as e: printerr( _( "Error while removing wiki-macros: %(err)s\n" "Trac doesn't load plugins from wiki-macros " "anymore. Please remove it by hand.", err=exception_to_unicode(e))) printout( _( "Upgrade done.\n\n" "You may want to upgrade the Trac documentation now by " "running:\n\n trac-admin %(path)s wiki upgrade", path=path_to_unicode(self.env.path)))
def export_page(self, page, filename): wikipage = model.WikiPage(self.env, page) if wikipage.exists: if not filename: printout(wikipage.text) else: if os.path.isfile(filename): raise AdminCommandError( _("File '%(name)s' exists", name=path_to_unicode(filename))) with open(filename, 'w', encoding='utf-8') as f: f.write(wikipage.text) else: raise AdminCommandError(_("Page '%(page)s' not found", page=page))
def _do_export(self, filename=None): try: with file_or_std(filename, 'w') as f: linesep = os.linesep if filename else '\n' writer = csv.writer(f, lineterminator=linesep) users = self.get_user_list() for user in sorted(users): actions = sorted(self.get_user_perms(user)) writer.writerow([s for s in [user] + actions]) f.flush() except IOError as e: raise AdminCommandError( _("Cannot export to %(filename)s: %(error)s", filename=path_to_unicode(filename or 'stdout'), error=e.strerror))
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_export(self, filename=None): try: with file_or_std(filename, 'wb') as f: encoding = stream_encoding(f) linesep = os.linesep if filename else '\n' writer = csv.writer(f, lineterminator=linesep) users = self.get_user_list() for user in sorted(users): actions = sorted(self.get_user_perms(user)) writer.writerow([s.encode(encoding, 'replace') for s in [user] + actions]) except IOError as e: raise AdminCommandError( _("Cannot export to %(filename)s: %(error)s", filename=path_to_unicode(filename or 'stdout'), error=e.strerror))
def _do_export(self, resource, name, destination=None): (realm, id) = self.split_resource(resource) attachment = Attachment(self.env, realm, id, name) if destination is not None: if os.path.isdir(destination): destination = os.path.join(destination, name) if os.path.isfile(destination): raise AdminCommandError(_("File '%(name)s' exists", name=path_to_unicode(destination))) with attachment.open() as input: output = open(destination, "wb") if destination is not None \ else sys.stdout try: shutil.copyfileobj(input, output) finally: if destination is not None: output.close()
def _do_dump(self, directory, *names): if not names: names = ['*'] pages = self.get_wiki_list() if not os.path.isdir(directory): if not os.path.exists(directory): os.mkdir(directory) else: raise AdminCommandError(_("'%(name)s' is not a directory", name=path_to_unicode(directory))) for p in pages: if any(p == name or (name.endswith('*') and p.startswith(name[:-1])) for name in names): dst = os.path.join(directory, unicode_quote(p, '')) printout(' %s => %s' % (p, dst)) self.export_page(p, dst)
def export_page(self, page, filename): for text, in self.env.db_query(""" SELECT text FROM wiki WHERE name=%s ORDER BY version DESC LIMIT 1 """, (page,)): if not filename: printout(text) else: if os.path.isfile(filename): raise AdminCommandError(_("File '%(name)s' exists", name=path_to_unicode(filename))) with open(filename, 'w') as f: f.write(text.encode('utf-8')) break else: raise AdminCommandError(_("Page '%(page)s' not found", page=page))
def export_page(self, page, filename, cursor=None): """ :since 1.0: the `cursor` parameter is no longer needed and will be removed in version 1.1.1 """ for text, in self.env.db_query(""" SELECT text FROM wiki WHERE name=%s ORDER BY version DESC LIMIT 1 """, (page,)): if not filename: printout(text) else: if os.path.isfile(filename): raise AdminCommandError(_("File '%(name)s' exists", name=path_to_unicode(filename))) with open(filename, 'w') as f: f.write(text.encode('utf-8')) break else: raise AdminCommandError(_("Page '%(page)s' not found", page=page))
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 export_page(self, page, filename, cursor=None): """ :since 0.13: the `cursor` parameter is no longer needed and will be removed in version 0.14 """ for text, in self.env.db_query( """ SELECT text FROM wiki WHERE name=%s ORDER BY version DESC LIMIT 1 """, (page, )): if not filename: printout(text) else: if os.path.isfile(filename): raise AdminCommandError( _("File '%(name)s' exists", name=path_to_unicode(filename))) with open(filename, 'w') as f: f.write(text.encode('utf-8')) break else: raise AdminCommandError(_("Page '%(page)s' not found", page=page))
_( "Invalid row %(line)d. Expected <user>, " "<action>, [action], [...]", line=reader.line_num)) user = to_unicode(row[0], encoding) actions = [ to_unicode(action, encoding) for action in row[1:] ] if user.isupper(): raise AdminCommandError( _( "Invalid user %(user)s on line %(line)d: All " "upper-cased tokens are reserved for permission " "names.", user=user, line=reader.line_num)) old_actions = self.get_user_perms(user) for action in set(actions) - set(old_actions): permsys.grant_permission(user, action) except csv.Error, e: raise AdminCommandError( _("Cannot import from %(filename)s line %(line)d: %(error)s ", filename=path_to_unicode(filename or 'stdin'), line=reader.line_num, error=e)) except IOError, e: raise AdminCommandError( _("Cannot import from %(filename)s: %(error)s", filename=path_to_unicode(filename or 'stdin'), error=e.strerror))
def _import(self, filename, title, replace=False): if self.import_page(filename, title, replace=replace): printout(" '%s' => '%s'" % (path_to_unicode(filename), title)) else: printout(_(" '%(title)s' is already up to date", title=title))
except TracError, e: raise TracError(_("Backup failed: %(msg)s.\nUse '--no-backup' to " "upgrade without doing a backup.", msg=unicode(e))) # Remove wiki-macros if it is empty and warn if it isn't wiki_macros = os.path.join(self.env.path, 'wiki-macros') try: entries = os.listdir(wiki_macros) except OSError: pass else: if entries: printerr(_("Warning: the wiki-macros directory in the " "environment is non-empty, but Trac\n" "doesn't load plugins from there anymore. " "Please remove it by hand.")) else: try: os.rmdir(wiki_macros) except OSError, e: printerr(_("Error while removing wiki-macros: %(err)s\n" "Trac doesn't load plugins from wiki-macros " "anymore. Please remove it by hand.", err=exception_to_unicode(e))) printout(_("Upgrade done.\n\n" "You may want to upgrade the Trac documentation now by " "running:\n\n trac-admin %(path)s wiki upgrade", path=path_to_unicode(self.env.path)))
encoding = stream_encoding(f) linesep = os.linesep if filename else '\n' reader = csv.reader(f, lineterminator=linesep) for row in reader: if len(row) < 2: raise AdminCommandError( _("Invalid row %(line)d. Expected <user>, " "<action>, [action], [...]", line=reader.line_num)) user = to_unicode(row[0], encoding) actions = [to_unicode(action, encoding) for action in row[1:]] if user.isupper(): raise AdminCommandError( _("Invalid user %(user)s on line %(line)d: All " "upper-cased tokens are reserved for permission " "names.", user=user, line=reader.line_num)) old_actions = self.get_user_perms(user) for action in set(actions) - set(old_actions): permsys.grant_permission(user, action) except csv.Error, e: raise AdminCommandError( _("Cannot import from %(filename)s line %(line)d: %(error)s ", filename=path_to_unicode(filename or 'stdin'), line=reader.line_num, error=e)) except IOError, e: raise AdminCommandError( _("Cannot import from %(filename)s: %(error)s", filename=path_to_unicode(filename or 'stdin'), error=e.strerror))
# Remove wiki-macros if it is empty and warn if it isn't wiki_macros = os.path.join(self.env.path, 'wiki-macros') try: entries = os.listdir(wiki_macros) except OSError: pass else: if entries: printerr( _("Warning: the wiki-macros directory in the " "environment is non-empty, but Trac\n" "doesn't load plugins from there anymore. " "Please remove it by hand.")) else: try: os.rmdir(wiki_macros) except OSError, e: printerr( _( "Error while removing wiki-macros: %(err)s\n" "Trac doesn't load plugins from wiki-macros " "anymore. Please remove it by hand.", err=exception_to_unicode(e))) printout( _( "Upgrade done.\n\n" "You may want to upgrade the Trac documentation now by " "running:\n\n trac-admin %(path)s wiki upgrade", path=path_to_unicode(self.env.path)))