def run(args=None): """Main entry point.""" if args is None: args = sys.argv[1:] if has_babel: translation.activate(get_console_locale()) warn_setuptools_issue() admin = TracAdmin() if len(args) > 0: if args[0] in ('-h', '--help', 'help'): return admin.onecmd(' '.join(['help'] + args[1:])) elif args[0] in ('-v','--version'): printout(os.path.basename(sys.argv[0]), TRAC_VERSION) else: env_path = os.path.abspath(args[0]) try: unicode(env_path, 'ascii') except UnicodeDecodeError: printerr(_("Non-ascii environment path '%(path)s' not " "supported.", path=to_unicode(env_path))) sys.exit(2) admin.env_set(env_path) if len(args) > 1: s_args = ' '.join(["'%s'" % c for c in args[2:]]) command = args[1] + ' ' + s_args return admin.onecmd(command) else: while True: try: admin.run() except KeyboardInterrupt: admin.do_quit('') else: return admin.onecmd("help")
def _do_product_admin(self, prefix, *args): mgr = self.product_admincmd_mgr(prefix) if args and args[0] in self.GLOBAL_COMMANDS: raise AdminCommandError('%s command not supported for products' % (args[0],)) if args and args[0] == 'help': help_args = args[1:] if help_args: doc = mgr.get_command_help(list(help_args)) if doc: TracAdmin.print_doc(doc) else: printerr(_("No documentation found for '%(cmd)s'." " Use 'help' to see the list of commands.", cmd=' '.join(help_args))) cmds = mgr.get_similar_commands(help_args[0]) if cmds: printout('') printout(ngettext("Did you mean this?", "Did you mean one of these?", len(cmds))) for cmd in cmds: printout(' ' + cmd) else: printout(_("trac-admin - The Trac Administration Console " "%(version)s", version=TRAC_VERSION)) env = mgr.env TracAdmin.print_doc(TracAdmin.all_docs(env), short=True) else: mgr.execute_command(*args)
def env(self): try: if not self.__env: self._init_env() return self.__env except Exception as e: printerr(_("Failed to open environment: %(err)s", err=exception_to_unicode(e, traceback=True))) sys.exit(1)
def do_upgrade(env, version, cursor): """Move attachments from the `attachments` directory into `files`, hashing the filenames in the process.""" path = env.path old_dir = os.path.join(path, 'attachments') if not os.path.exists(old_dir): return old_stat = os.stat(old_dir) new_dir = os.path.join(path, 'files', 'attachments') if not os.path.exists(new_dir): os.makedirs(new_dir) cursor.execute(""" SELECT type, id, filename FROM attachment ORDER BY type, id """) for row in cursor: move_attachment_file(env, *row) # Try to preserve permissions and ownerships of the attachments # directory for $ENV/files for dir, dirs, files in os.walk(os.path.join(path, 'files')): try: if hasattr(os, 'chmod'): os.chmod(dir, old_stat.st_mode) if hasattr(os, 'chflags') and hasattr(old_stat, 'st_flags'): os.chflags(dir, old_stat.st_flags) if hasattr(os, 'chown'): os.chown(dir, old_stat.st_uid, old_stat.st_gid) except OSError: pass # Remove empty directory hierarchy try: for dir, dirs, files in os.walk(old_dir, topdown=False): os.rmdir(dir) except OSError, e: env.log.warning("Can't delete old attachments directory %s: %s", old_dir, exception_to_unicode(e)) # TRANSLATOR: Wrap message to 80 columns printerr(_("""\ The upgrade of attachments was successful, but the old attachments directory: %(src_dir)s couldn't be removed, possibly due to the presence of files that weren't referenced in the database. The error was: %(exception)s This error can be ignored, but for keeping your environment clean you should backup any remaining files in that directory and remove it manually. """, src_dir=old_dir, exception=exception_to_unicode(e)))
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 move_attachment_file(env, parent_realm, parent_id, filename): old_path = os.path.join(env.path, 'attachments', parent_realm, unicode_quote(parent_id)) if filename: old_path = os.path.join(old_path, unicode_quote(filename)) old_path = os.path.normpath(old_path) if os.path.isfile(old_path): new_path = Attachment._get_path(env.path, parent_realm, parent_id, filename) try: os.renames(old_path, new_path) except OSError: printerr(_("Unable to move attachment from:\n\n" " %(old_path)s\n\nto:\n\n %(new_path)s\n", old_path=old_path, new_path=new_path)) raise else: env.log.warning("Can't find file for 'attachment:%s:%s:%s', ignoring", filename, parent_realm, parent_id)
def onecmd(self, line): """`line` may be a `str` or an `unicode` object""" try: if isinstance(line, str): if self.interactive: encoding = sys.stdin.encoding else: encoding = getpreferredencoding() # sys.argv line = to_unicode(line, encoding) if self.interactive: line = line.replace('\\', '\\\\') rv = cmd.Cmd.onecmd(self, line) or 0 except SystemExit: raise except AdminCommandError as e: printerr(_("Error: %(msg)s", msg=to_unicode(e))) if e.show_usage: print() self.do_help(e.cmd or self.arg_tokenize(line)[0]) rv = 2 except TracError as e: printerr(exception_to_unicode(e)) rv = 2 except Exception as e: printerr(exception_to_unicode(e)) rv = 2 if self.env_check(): self.env.log.error("Exception in trac-admin command: %s", exception_to_unicode(e, traceback=True)) if not self.interactive: return rv
def onecmd(self, line): """`line` may be a `str` or an `unicode` object""" if isinstance(line, str): if self.interactive: encoding = sys.stdin.encoding else: encoding = getpreferredencoding() # sys.argv line = to_unicode(line, encoding) if self.interactive: line = line.replace('\\', '\\\\') try: rv = cmd.Cmd.onecmd(self, line) or 0 except SystemExit: raise except AdminCommandError as e: printerr(_("Error: %(msg)s", msg=to_unicode(e))) if e.show_usage: print() self.do_help(e.cmd or self.arg_tokenize(line)[0]) rv = 2 except TracError as e: printerr(exception_to_unicode(e)) rv = 2 except Exception as e: printerr(exception_to_unicode(e)) rv = 2 if self.env_check(): self.env.log.error("Exception in trac-admin command: %r%s", line, exception_to_unicode(e, traceback=True)) if not self.interactive: return rv
def move_attachment_file(env, parent_realm, parent_id, filename): old_path = os.path.join(env.path, 'attachments', parent_realm, unicode_quote(parent_id)) if filename: old_path = os.path.join(old_path, unicode_quote(filename)) old_path = os.path.normpath(old_path) if os.path.isfile(old_path): new_path = Attachment._get_path(env.attachments_dir, parent_realm, parent_id, filename) try: os.renames(old_path, new_path) except OSError: printerr( _( "Unable to move attachment from:\n\n" " %(old_path)s\n\nto:\n\n %(new_path)s\n", old_path=old_path, new_path=new_path)) raise else: env.log.warning("Can't find file for 'attachment:%s:%s:%s', ignoring", filename, parent_realm, parent_id)
def complete_line(self, text, line, cmd_only=False): args = self.arg_tokenize(line) if line and line[-1] == ' ': # Space starts new argument args.append('') comp = [] if self.env_check(): try: comp = self.cmd_mgr.complete_command(args, cmd_only) except Exception as e: printerr() printerr( _('Completion error: %(err)s', err=exception_to_unicode(e))) self.env.log.error("trac-admin completion error: %s", exception_to_unicode(e, traceback=True)) if len(args) == 1: comp.extend(name[3:] for name in self.get_names() if name.startswith('do_')) try: return comp.complete(text) except AttributeError: return self.word_complete(text, comp)
def environment_created(self): """Index the repositories.""" for repos in RepositoryManager(self.env).get_real_repositories(): pretty_name = repos.reponame or '(default)' printout(_(" Indexing '%(name)s' repository", name=pretty_name)) try: repos.sync(self._sync_feedback) except TracError: printerr(_(""" --------------------------------------------------------------------- Warning: couldn't index '%(pretty_name)s' repository. This can happen for a variety of reasons: wrong repository type, no appropriate third party library for this repository type, no repository at the specified repository path... You can nevertheless start using your Trac environment, but you'll need to check your `%(name)s.type` and `%(name)s.dir` option values in the [repositories] section of your trac.ini file. """, pretty_name=pretty_name, name=repos.reponame or '')) else: self._sync_feedback(None)
def main(): """ %(prog)s [-c] passwordfile realm username %(prog)s -b[c] passwordfile realm username password\ """ parser = argparse.ArgumentParser(usage=main.__doc__) parser.add_argument('-b', action='store_true', dest='batch', help="batch mode; password is passed on the command " "line IN THE CLEAR") parser.add_argument('-c', action='store_true', dest='create', help="create a new htdigest file, overwriting any " "existing file") parser.add_argument('passwordfile', help=argparse.SUPPRESS) parser.add_argument('realm', help=argparse.SUPPRESS) parser.add_argument('username', help=argparse.SUPPRESS) parser.add_argument('password', nargs='?', help=argparse.SUPPRESS) args = parser.parse_args() if args.batch and args.password is None: parser.error("too few arguments") elif not args.batch and args.password is not None: parser.error("too many arguments") prefix = '%s:%s:' % (args.username, args.realm) if args.create: try: with open(args.passwordfile, 'w') as f: print(get_digest(prefix, args.password), file=f) except EnvironmentError as e: if e.errno == errno.EACCES: printerr("Unable to update file %s" % args.passwordfile) sys.exit(1) else: raise else: matched = False try: for line in fileinput.input(args.passwordfile, inplace=True): if line.startswith(prefix): if not matched: print(get_digest(prefix, args.password)) matched = True else: print(line.rstrip()) if not matched: with open(args.passwordfile, 'a') as f: print(get_digest(prefix, args.password), file=f) except EnvironmentError as e: if e.errno == errno.ENOENT: printerr("Could not open password file %s for reading. " "Use -c option to create a new one." % args.passwordfile) sys.exit(1) elif e.errno == errno.EACCES: printerr("Unable to update file %s" % args.passwordfile) sys.exit(1) else: raise
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 complete_line(self, text, line, cmd_only=False): if rl_completion_suppress_append is not None: rl_completion_suppress_append.value = 1 args = self.arg_tokenize(line) if line and line[-1] == ' ': # Space starts new argument args.append('') if self.env_check(): try: comp = self.cmd_mgr.complete_command(args, cmd_only) except Exception as e: printerr() printerr(_('Completion error: %(err)s', err=exception_to_unicode(e))) self.env.log.error("trac-admin completion error: %s", exception_to_unicode(e, traceback=True)) comp = [] if len(args) == 1: comp.extend(name[3:] for name in self.get_names() if name.startswith('do_')) try: return comp.complete(text) except AttributeError: return self.word_complete(text, comp)
def run(args=None): """Main entry point.""" if args is None: args = sys.argv[1:] if has_babel: translation.activate(get_console_locale()) warn_setuptools_issue() admin = TracAdmin() if len(args) > 0: if args[0] in ('-h', '--help', 'help'): return admin.onecmd(' '.join(['help'] + args[1:])) elif args[0] in ('-v', '--version'): printout(os.path.basename(sys.argv[0]), TRAC_VERSION) else: env_path = os.path.abspath(args[0]) try: unicode(env_path, 'ascii') except UnicodeDecodeError: printerr( _( "Non-ascii environment path '%(path)s' not " "supported.", path=to_unicode(env_path))) sys.exit(2) admin.env_set(env_path) if len(args) > 1: s_args = ' '.join(["'%s'" % c for c in args[2:]]) command = args[1] + ' ' + s_args return admin.onecmd(command) else: while True: try: admin.run() except KeyboardInterrupt: admin.do_quit('') else: return admin.onecmd("help")
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_product_admin(self, prefix, *args): mgr = self.product_admincmd_mgr(prefix) if args and args[0] in self.GLOBAL_COMMANDS: raise AdminCommandError('%s command not supported for products' % (args[0],)) if args and args[0] == 'help': help_args = args[1:] if help_args: doc = mgr.get_command_help(list(help_args)) if doc: TracAdmin.print_doc(doc) else: printerr(_("No documentation found for '%(cmd)s'." " Use 'help' to see the list of commands.", cmd=' '.join(help_args))) cmds = mgr.get_similar_commands(help_args[0]) if cmds: printout('') printout(ngettext("Did you mean this?", "Did you mean one of these?", len(cmds))) for cmd in cmds: printout(' ' + cmd) else: printout(_("trac-admin - The Trac Administration Console " "%(version)s", version=TRAC_VERSION)) env = mgr.env TracAdmin.print_doc(TracAdmin.all_docs(env), short=True) else: try: mgr.execute_command(*args) except AdminCommandError, e: printerr(_("Error: %(msg)s", msg=to_unicode(e))) if e.show_usage: print self._do_product_admin(prefix, 'help', *args[:2]) except:
def do_help(self, line=None): arg = self.arg_tokenize(line) if arg[0]: cmd_mgr = None doc = getattr(self, "_help_" + arg[0], None) if doc is None and self.env_check(): cmd_mgr = self.cmd_mgr doc = cmd_mgr.get_command_help(arg) if doc: self.print_doc(doc) else: printerr(_("No documentation found for '%(cmd)s'." " Use 'help' to see the list of commands.", cmd=' '.join(arg))) cmds = None if cmd_mgr: cmds = cmd_mgr.get_similar_commands(arg[0]) if cmds: printout('') printout(ngettext("Did you mean this?", "Did you mean one of these?", len(cmds))) for cmd in cmds: printout(' ' + cmd) else: printout(_("trac-admin - The Trac Administration Console " "%(version)s", version=TRAC_VERSION)) if not self.interactive: print() printout(_("Usage: trac-admin </path/to/projenv> " "[command [subcommand] [option ...]]\n") ) printout(_("Invoking trac-admin without command starts " "interactive mode.\n")) env = self.env if self.env_check() else None self.print_doc(self.all_docs(env), short=True)
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 _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_hotcopy(self, dest): if os.path.exists(dest): raise TracError( _("hotcopy can't overwrite existing '%(dest)s'", dest=dest)) import shutil # Bogus statement to lock the database while copying files cnx = self.env.get_db_cnx() cursor = cnx.cursor() cursor.execute("UPDATE system SET name=NULL WHERE name IS NULL") try: printout( _('Hotcopying %(src)s to %(dst)s ...', src=self.env.path, dst=dest)) db_str = self.env.config.get('trac', 'database') prefix, db_path = db_str.split(':', 1) if prefix == 'sqlite': # don't copy the journal (also, this would fail on Windows) db = os.path.join(self.env.path, os.path.normpath(db_path)) skip = [db + '-journal', db + '-stmtjrnl'] else: skip = [] try: copytree(self.env.path, dest, symlinks=1, skip=skip) retval = 0 except shutil.Error, 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, src)) finally: # Unlock database cnx.rollback() printout(_("Hotcopy done.")) return retval
def _do_hotcopy(self, dest): if os.path.exists(dest): raise TracError(_("hotcopy can't overwrite existing '%(dest)s'", dest=dest)) import shutil # Bogus statement to lock the database while copying files cnx = self.env.get_db_cnx() cursor = cnx.cursor() cursor.execute("UPDATE system SET name=NULL WHERE name IS NULL") try: printout(_('Hotcopying %(src)s to %(dst)s ...', src=self.env.path, dst=dest)) db_str = self.env.config.get('trac', 'database') prefix, db_path = db_str.split(':', 1) if prefix == 'sqlite': # don't copy the journal (also, this would fail on Windows) db = os.path.join(self.env.path, os.path.normpath(db_path)) skip = [db + '-journal', db + '-stmtjrnl'] else: skip = [] try: copytree(self.env.path, dest, symlinks=1, skip=skip) retval = 0 except shutil.Error, 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, src)) finally: # Unlock database cnx.rollback() printout(_("Hotcopy done.")) return retval
self.env.upgrade(backup=no_backup is None) 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)))
def _printerr(self, message, *args, **kwargs): if args: message %= args printerr(message, **kwargs) sys.stderr.flush()
from trac.admin.console import TracAdmin from trac.util.text import printout, printerr import sys if __name__ == "__main__": if len(sys.argv) != 2: printerr( "Usage: %s <path>\nSupply the path where to create the test environment" % (sys.argv[0])) sys.exit(-1) admin = TracAdmin(sys.argv[1]) admin.onecmd( "initenv \"trac-subcomponents test environment\" sqlite:db/trac.db") admin.onecmd("permission add anonymous TRAC_ADMIN") components = ("NoSubcomponents", "SuperComponent", "SuperComponent/SubComponent1", "SuperComponent/SubComponent2", "ForcedSubcomponent/ForcedSub1/ForcedSubSub", "LeafTest", "LeafTest/HasEmptyLeaf", "LeafTest/HasEmptyLeaf/Sub1", "LeafTest/HasEmptyLeaf/Sub2", "LeafTest/NoEmptyLeaf/Sub1", "LeafTest/NoEmptyLeaf/Sub2", "SixSubLevels/s1/s2/s3/s4/s5/s6") for component in components: admin.onecmd("component add %s nobody" % (component, )) printout(""" The test environment is set up at %s. You can run tracd to test this environment. Please make sure that the trac-subcomponents plugin is loaded, either by putting the plugin in %s/plugins, by making it available in general
class EnvironmentAdmin(Component): """trac-admin command provider for environment administration.""" implements(IAdminCommandProvider) # IAdminCommandProvider methods def get_admin_commands(self): yield ('deploy', '<directory>', 'Extract static resources from Trac and all plugins', None, self._do_deploy) yield ('hotcopy', '<backupdir>', 'Make a hot backup copy of an environment', None, self._do_hotcopy) yield ('upgrade', '', 'Upgrade database to current version', None, self._do_upgrade) def _do_deploy(self, dest): target = os.path.normpath(dest) chrome_target = os.path.join(target, 'htdocs') script_target = os.path.join(target, 'cgi-bin') # Copy static content makedirs(target, overwrite=True) makedirs(chrome_target, overwrite=True) from trac.web.chrome import Chrome printout(_("Copying resources from:")) for provider in Chrome(self.env).template_providers: paths = list(provider.get_htdocs_dirs() or []) if not len(paths): continue printout(' %s.%s' % (provider.__module__, provider.__class__.__name__)) for key, root in paths: source = os.path.normpath(root) printout(' ', source) if os.path.exists(source): dest = os.path.join(chrome_target, key) copytree(source, dest, overwrite=True) # Create and copy scripts makedirs(script_target, overwrite=True) printout(_("Creating scripts.")) data = {'env': self.env, 'executable': sys.executable} for script in ('cgi', 'fcgi', 'wsgi'): dest = os.path.join(script_target, 'trac.' + script) template = Chrome(self.env).load_template('deploy_trac.' + script, 'text') stream = template.generate(**data) out = file(dest, 'w') try: stream.render('text', out=out) finally: out.close() def _do_hotcopy(self, dest): if os.path.exists(dest): raise TracError( _("hotcopy can't overwrite existing '%(dest)s'", dest=dest)) import shutil # Bogus statement to lock the database while copying files cnx = self.env.get_db_cnx() cursor = cnx.cursor() cursor.execute("UPDATE system SET name=NULL WHERE name IS NULL") try: printout( _('Hotcopying %(src)s to %(dst)s ...', src=self.env.path, dst=dest)) db_str = self.env.config.get('trac', 'database') prefix, db_path = db_str.split(':', 1) if prefix == 'sqlite': # don't copy the journal (also, this would fail on Windows) db = os.path.join(self.env.path, os.path.normpath(db_path)) skip = [db + '-journal', db + '-stmtjrnl'] else: skip = [] try: copytree(self.env.path, dest, symlinks=1, skip=skip) retval = 0 except shutil.Error, 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, src)) finally: # Unlock database cnx.rollback() 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 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)))
def do_initenv(self, line): def initenv_error(msg): printerr(_("Initenv for '%(env)s' failed.", env=self.envname), "\n%s" % msg) if self.env_check(): initenv_error(_("Does an environment already exist?")) return 2 if os.path.exists(self.envname) and os.listdir(self.envname): initenv_error(_("Directory exists and is not empty.")) return 2 if not os.path.exists(os.path.dirname(self.envname)): initenv_error(_("Base directory '%(env)s' does not exist. Please " "create it manually and retry.", env=os.path.dirname(self.envname))) return 2 arg = self.arg_tokenize(line) inherit_paths = [] config_file_path = None i = 0 while i < len(arg): item = arg[i] if item.startswith('--inherit='): inherit_paths.append(arg.pop(i)[10:]) elif item.startswith('--config='): config_file_path = arg.pop(i)[9:] else: i += 1 config = None if config_file_path: if not os.path.exists(config_file_path): initenv_error(_("The file specified in the --config argument " "does not exist: %(path)s.", path=config_file_path)) return 2 try: config = Configuration(config_file_path) except TracError as e: initenv_error(e) return 2 arg = arg or [''] # Reset to usual empty in case we popped the only one project_name = None db_str = None repository_type = None repository_dir = None if len(arg) == 1 and not arg[0]: project_name, db_str = self.get_initenv_args() elif len(arg) == 2: project_name, db_str = arg elif len(arg) == 4: project_name, db_str, repository_type, repository_dir = arg else: initenv_error('Wrong number of arguments: %d' % len(arg)) return 2 try: printout(_("Creating and Initializing Project")) options = [] if config: for section in config.sections(defaults=False): options.extend((section, option, value) for option, value in config.options(section)) options.extend([ ('project', 'name', project_name), ('trac', 'database', db_str), ]) def add_nav_order_options(section, default): for i, name in enumerate(default, 1): options.append((section, name + '.order', float(i))) add_nav_order_options('mainnav', default_mainnav_order) add_nav_order_options('metanav', default_metanav_order) if repository_dir: options.extend([ ('repositories', '.type', repository_type), ('repositories', '.dir', repository_dir), ]) if inherit_paths: options.append(('inherit', 'file', ",\n ".join(inherit_paths))) try: self.__env = Environment(self.envname, create=True, options=options) except Exception as e: initenv_error(_('Failed to create environment.')) printerr(e) traceback.print_exc() sys.exit(1) # Add a few default wiki pages printout(_(" Installing default wiki pages")) pages_dir = pkg_resources.resource_filename('trac.wiki', 'default-pages') WikiAdmin(self.__env).load_pages(pages_dir) if repository_dir: try: repos = RepositoryManager(self.__env).get_repository('') if repos: printout(_(" Indexing default repository")) repos.sync(self._resync_feedback) except TracError as e: printerr(_(""" --------------------------------------------------------------------- Warning: couldn't index the default repository. This can happen for a variety of reasons: wrong repository type, no appropriate third party library for this repository type, no actual repository at the specified repository path... You can nevertheless start using your Trac environment, but you'll need to check again your trac.ini file and the [trac] repository_type and repository_path settings. """)) except Exception as e: initenv_error(to_unicode(e)) traceback.print_exc() return 2 printout(_(""" --------------------------------------------------------------------- Project environment for '%(project_name)s' created. You may now configure the environment by editing the file: %(config_path)s If you'd like to take this new project environment for a test drive, try running the Trac standalone web server `tracd`: tracd --port 8000 %(project_path)s Then point your browser to http://localhost:8000/%(project_dir)s. There you can also browse the documentation for your installed version of Trac, including information on further setup (such as deploying Trac to a real web server). The latest documentation can also always be found on the project website: http://trac.edgewall.org/ Congratulations! """, project_name=project_name, project_path=self.envname, project_dir=os.path.basename(self.envname), config_path=os.path.join(self.envname, 'conf', 'trac.ini')))
def initenv_error(msg): printerr(_("Initenv for '%(env)s' failed.", env=self.envname), "\n%s" % msg)
from trac.admin.console import TracAdmin from trac.util.text import printout, printerr import sys if __name__ == "__main__": if len(sys.argv) != 2: printerr("Usage: %s <path>\nSupply the path where to create the test environment" % (sys.argv[0])) sys.exit(-1) admin = TracAdmin(sys.argv[1]) admin.onecmd("initenv \"trac-subcomponents test environment\" sqlite:db/trac.db") admin.onecmd("permission add anonymous TRAC_ADMIN") components = ("NoSubcomponents", "SuperComponent", "SuperComponent/SubComponent1", "SuperComponent/SubComponent2", "ForcedSubcomponent/ForcedSub1/ForcedSubSub", "LeafTest", "LeafTest/HasEmptyLeaf", "LeafTest/HasEmptyLeaf/Sub1", "LeafTest/HasEmptyLeaf/Sub2", "LeafTest/NoEmptyLeaf/Sub1", "LeafTest/NoEmptyLeaf/Sub2", "SixSubLevels/s1/s2/s3/s4/s5/s6") for component in components: admin.onecmd("component add %s nobody" % (component,)) printout(""" The test environment is set up at %s. You can run tracd to test this environment. Please make sure that the trac-subcomponents plugin is loaded, either by putting the plugin in %s/plugins, by making it available in general or by manipulation PYTHON_PATH. """ % (sys.argv[1], sys.argv[1])) sys.exit(0)
def do_initenv(self, line): def initenv_error(msg): printerr(_("Initenv for '%(env)s' failed.", env=self.envname), "\n" + msg) if self.env_check(): initenv_error(_("Does an environment already exist?")) return 2 if os.path.exists(self.envname) and os.listdir(self.envname): initenv_error(_("Directory exists and is not empty.")) return 2 if not os.path.exists(os.path.dirname(self.envname)): initenv_error(_("Base directory '%(env)s' does not exist. Please " "create it manually and retry.", env=os.path.dirname(self.envname))) return 2 arg = self.arg_tokenize(line) inherit_paths = [] i = 0 while i < len(arg): item = arg[i] if item.startswith('--inherit='): inherit_paths.append(arg.pop(i)[10:]) else: i += 1 arg = arg or [''] # Reset to usual empty in case we popped the only one project_name = None db_str = None repository_type = None repository_dir = None if len(arg) == 1 and not arg[0]: project_name, db_str = self.get_initenv_args() elif len(arg) == 2: project_name, db_str = arg elif len(arg) == 4: project_name, db_str, repository_type, repository_dir = arg else: initenv_error('Wrong number of arguments: %d' % len(arg)) return 2 try: printout(_("Creating and Initializing Project")) options = [ ('project', 'name', project_name), ('trac', 'database', db_str), ] def add_nav_order_options(section, default): for i, name in enumerate(default, 1): options.append((section, name + '.order', float(i))) add_nav_order_options('mainnav', default_mainnav_order) add_nav_order_options('metanav', default_metanav_order) if repository_dir: options.extend([ ('repositories', '.type', repository_type), ('repositories', '.dir', repository_dir), ]) if inherit_paths: options.append(('inherit', 'file', ",\n ".join(inherit_paths))) try: self.__env = Environment(self.envname, create=True, options=options) except Exception as e: initenv_error(_('Failed to create environment.')) printerr(e) traceback.print_exc() sys.exit(1) # Add a few default wiki pages printout(_(" Installing default wiki pages")) pages_dir = pkg_resources.resource_filename('trac.wiki', 'default-pages') WikiAdmin(self.__env).load_pages(pages_dir) if repository_dir: try: repos = RepositoryManager(self.__env).get_repository('') if repos: printout(_(" Indexing default repository")) repos.sync(self._resync_feedback) except TracError as e: printerr(_(""" --------------------------------------------------------------------- Warning: couldn't index the default repository. This can happen for a variety of reasons: wrong repository type, no appropriate third party library for this repository type, no actual repository at the specified repository path... You can nevertheless start using your Trac environment, but you'll need to check again your trac.ini file and the [trac] repository_type and repository_path settings. """)) except Exception as e: initenv_error(to_unicode(e)) traceback.print_exc() return 2 printout(_(""" --------------------------------------------------------------------- Project environment for '%(project_name)s' created. You may now configure the environment by editing the file: %(config_path)s If you'd like to take this new project environment for a test drive, try running the Trac standalone web server `tracd`: tracd --port 8000 %(project_path)s Then point your browser to http://localhost:8000/%(project_dir)s. There you can also browse the documentation for your installed version of Trac, including information on further setup (such as deploying Trac to a real web server). The latest documentation can also always be found on the project website: http://trac.edgewall.org/ Congratulations! """, project_name=project_name, project_path=self.envname, project_dir=os.path.basename(self.envname), config_path=os.path.join(self.envname, 'conf', 'trac.ini')))
def do_initenv(self, line): def initenv_error(msg): printerr(_("Initenv for '%(env)s' failed.", env=self.envname), "\n%s" % msg) if self.env_check(): initenv_error(_("Does an environment already exist?")) return 2 printout( _("Creating a new Trac environment at %(envname)s", envname=self.envname)) arg = self.arg_tokenize(line) inherit_paths = [] config_file_path = None i = 0 while i < len(arg): item = arg[i] if item.startswith('--inherit='): inherit_paths.append(arg.pop(i)[10:]) elif item.startswith('--config='): config_file_path = arg.pop(i)[9:] else: i += 1 config = None if config_file_path: if not os.path.exists(config_file_path): initenv_error( _( "The file specified in the --config argument " "does not exist: %(path)s.", path=config_file_path)) return 2 try: config = Configuration(config_file_path) except TracError as e: initenv_error(e) return 2 arg = arg or ['' ] # Reset to usual empty in case we popped the only one if len(arg) == 1 and not arg[0] and not config: project_name, db_str = self.get_initenv_args() elif len(arg) < 2 and config: project_name = db_str = None if arg[0]: project_name = arg[0] elif len(arg) == 2: project_name, db_str = arg else: initenv_error('Wrong number of arguments: %d' % len(arg)) return 2 options = [] if config: for section in config.sections(defaults=False): options.extend((section, option, value) for option, value in config.options(section)) if project_name is not None: options.append(('project', 'name', project_name)) if db_str is not None: options.append(('trac', 'database', db_str)) if inherit_paths: options.append( ('inherit', 'file', ",\n ".join(inherit_paths))) try: self.__env = Environment(self.envname, create=True, options=options) except TracError as e: initenv_error(e) return 2 except Exception as e: initenv_error(_('Failed to create environment.')) printerr(e) traceback.print_exc() sys.exit(1) printout( _(""" Project environment for '%(project_name)s' created. You may configure the environment by editing the file: %(config_path)s You can run the Trac standalone web server `tracd` and point your browser to http://localhost:8000/%(project_dir)s. tracd --port 8000 %(project_path)s Navigate to "Help/Guide" to browse the documentation for Trac, including information on further setup (such as deploying Trac to a real web server). The latest documentation can also be found on the project website: http://trac.edgewall.org/ """, project_name=project_name, project_path=self.envname, project_dir=os.path.basename(self.envname), config_path=self.__env.config_file_path))
_( "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( _(
from cStringIO import StringIO from pkg_resources import resource_listdir, resource_string from trac.loader import load_components from trac.test import EnvironmentStub, Mock, MockPerm from trac.util.text import printerr, printout from trac.web.chrome import web_context from trac.web.href import Href from trac.wiki.formatter import format_to_html from trac.wiki.model import WikiPage try: import html2rest except ImportError: printerr("The html2rest package must be installed.") sys.exit(1) class Parser(html2rest.Parser): def __init__(self, writer=sys.stdout, encoding='utf8', relroot=None, relpath=None): html2rest.Parser.__init__(self, writer, encoding, relroot, relpath) self.links = {} def end_a(self): if '#pending' in self.hrefs: href = self.hrefs['#pending']
import sys from pkg_resources import resource_listdir, resource_string from trac.loader import load_components from trac.test import EnvironmentStub, Mock, MockPerm from trac.util.text import printerr, printout from trac.web.chrome import web_context from trac.web.href import Href from trac.wiki.formatter import format_to_html from trac.wiki.model import WikiPage try: import pypandoc except ImportError: printerr("The pypandoc package must be installed.") sys.exit(1) def wiki2rest(env, context, wiki): # Convert CRLF to LF and remove macros. text = re.sub('\r?\n', '\n', wiki.text) text = re.sub(r'\[\[TracGuideToc\]\]\r?\n?', '', text) text = re.sub(r'\[\[PageOutline\([^\)]*\)\]\]\r?\n?', '', text) html = str(format_to_html(env, context, text)) html = html.replace('<span class="icon">\u200b</span>', '') html = re.sub(r'<em>\s*([^<]*?)\s*</em>', r'<em>\1</em>', html) # Convert intra-document links from absolute to relative URLs. html = re.sub(r'(<a [^>]*href=")%s(#\w+")' % context.href.wiki(wiki.name), r'\1\2', html)
def modification_callback(file): printerr("Detected modification of %s, restarting." % file)
def main(): args = parse_args() wsgi_app = TracEnvironMiddleware(dispatch_request, args.env_parent_dir, args.envs, args.single_env) if args.auths: if args.single_env: project_name = os.path.basename(args.envs[0]) wsgi_app = AuthenticationMiddleware(wsgi_app, args.auths, project_name) else: wsgi_app = AuthenticationMiddleware(wsgi_app, args.auths) base_path = args.base_path.strip('/') if base_path: wsgi_app = BasePathMiddleware(wsgi_app, base_path) server_address = (args.hostname, args.port) if args.protocol in ('http', 'https'): def serve(): addr, port = server_address if not addr or addr == '0.0.0.0': loc = '0.0.0.0:%s view at %s://127.0.0.1:%s/%s' \ % (port, args.protocol, port, base_path) else: loc = '%s://%s:%s/%s' % (args.protocol, addr, port, base_path) try: httpd = TracHTTPServer(server_address, wsgi_app, args.env_parent_dir, args.envs, use_http_11=args.http11) except socket.error as e: print("Error starting Trac server on %s" % loc) print("[Errno %s] %s" % e.args) sys.exit(1) print("Server starting in PID %s." % os.getpid()) print("Serving on %s" % loc) if args.http11: print("Using HTTP/1.1 protocol version") if args.protocol == 'https': httpd.socket = ssl.wrap_socket(httpd.socket, server_side=True, certfile=args.certfile, keyfile=args.keyfile) httpd.serve_forever() elif args.protocol in ('scgi', 'ajp', 'fcgi'): def serve(): module = 'flup.server.%s' % args.protocol try: server_cls = importlib.import_module(module).WSGIServer except ImportError: printerr("Install the flup package to use the '%s' " "protocol" % args.protocol) sys.exit(1) flup_app = wsgi_app if args.unquote: from trac.web.fcgi_frontend import FlupMiddleware flup_app = FlupMiddleware(flup_app) ret = server_cls(flup_app, bindAddress=server_address).run() sys.exit(42 if ret else 0) # if SIGHUP exit with status 42 try: if args.daemonize: daemon.daemonize(pidfile=args.pidfile, progname='tracd', umask=args.umask) if args.group is not None: os.setgid(args.group) if args.user is not None: os.setuid(args.user) if args.auto_reload: def modification_callback(file): printerr("Detected modification of %s, restarting." % file) autoreload.main(serve, modification_callback) else: serve() except OSError as e: printerr("%s: %s" % (e.__class__.__name__, e)) sys.exit(1) except KeyboardInterrupt: pass
def initenv_error(msg): printerr(_("Initenv for '%(env)s' failed.", env=self.envname), "\n" + msg)
# are also available at http://trac.edgewall.com/license.html. # # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/. import argparse import getpass import sys from trac.util import salt from trac.util.compat import crypt, wait_for_file_mtime_change from trac.util.text import printerr if crypt is None: printerr("The crypt module is not found. Install the passlib package " "from PyPI.", newline=True) sys.exit(1) def ask_pass(): pass1 = getpass.getpass('New password: '******'Re-type new password: ') if pass1 != pass2: printerr("htpasswd: password verification error") sys.exit(1) return pass1 class HtpasswdFile(object): """A class for manipulating htpasswd files."""
# # This software consists of voluntary contributions made by many # individuals. For the exact contribution history, see the revision # history and logs, available at http://trac.edgewall.org/. import getpass import optparse import sys from trac.util import salt from trac.util.compat import crypt, wait_for_file_mtime_change from trac.util.text import printerr, printout if crypt is None: printerr( "The crypt module is not found. You may want to install " "fcrypt from PyPI.", newline=True) sys.exit(1) class HtpasswdFile: """A class for manipulating htpasswd files.""" def __init__(self, filename, create=False): self.entries = [] self.filename = filename if not create: self.load() def load(self): """Read the htpasswd file into memory.""" self.entries = []