def get_repository_id(self, repository):
        """
        Returns the repository id inside Trac. This is needed to support
        multi-repository since v0.12. However, in lower versions of Trac, by simply
        using 'default' as repository name, it should work just fine :)
        """
        # The default repository is the one that has no "name" value in repository table
        if (repository == "default"):
            sql_string = """
                SELECT id
                 FROM repository 
                 WHERE name = 'name' AND value = '';
            """
            self.cursor.execute(sql_string)
            row = self.cursor.fetchone()
            # Default is an special situation, we need to handle different
            # Default dir could be specified in repository table or in trac.ini
            self.default = True
            return row[0]

        # The repository can be a path to the root of the repository
        if os.path.isdir(repository):
            # The default repository is not in the repository table
            # We need to check it apart, against the Trac's config file
            default_repository_path = self.config.get("trac", "repository_dir", "") 
            contains = re.compile(repository)
            if contains.match(default_repository_path):
                self.default = True
                return 1

            sql_string = """
                SELECT id
                 FROM repository
                 WHERE name = 'dir' AND value LIKE %s
            """
            self.cursor.execute(sql_string, ("%%%s%%" % repository,))
            row = self.cursor.fetchone()
            
            # If the repository is not controlled by Trac
            # We exit with successful execution. This way we can make a generic 
            # Mercurial hook that will work with all repositories in the machine
            if not row:
                printout("[E] Path",repository,"was not found in repository table, neither in Trac's config. Sync will not be executed")
                sys.exit(0)

        # Otherwise it should be the name of the repository
        else:
            sql_string = """
                SELECT id
                 FROM repository
                 WHERE name = 'name' AND value LIKE %s
            """
            self.cursor.execute(sql_string, (repository,))
            row = self.cursor.fetchone()
        
            if not row:
                printout("[E] Sorry, repository name not found")
                sys.exit(1)
        
        return row[0]
Beispiel #2
0
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")
Beispiel #3
0
 def _do_changeset_modified(self, reponame, *revs):
     if is_default(reponame):
         reponame = ''
     rm = RepositoryManager(self.env)
     errors = rm.notify('changeset_modified', reponame, revs)
     for error in errors:
         printout(error)
Beispiel #4
0
 def _do_changeset_added(self, reponame, *revs):
     if is_default(reponame):
         reponame = ""
     rm = RepositoryManager(self.env)
     errors = rm.notify("changeset_added", reponame, revs)
     for error in errors:
         printout(error)
Beispiel #5
0
    def globally_get_command_help(self, *args):
        sys_home_project_name = self.config.get('multiproject', 'sys_home_project_name')
        for env_name, in self.projects_iterator(['env_name'], batch_size=1):
            if env_name == sys_home_project_name:
                continue
            env = None

            try:
                env_path = safe_path(self.config.get('multiproject', 'sys_projects_root'),
                    env_name)
                env = open_environment(env_path, True)
            except TracError as e:
                printout(_('ERROR: Opening environment %(env_name)s failed', env_name=env_name))
                continue

            try:
                command_manager = AdminCommandManager(env)
                helps = command_manager.get_command_help(list(args))
                if not args:
                    TracAdmin.print_doc(helps, short=True)
                elif len(helps) == 1:
                    TracAdmin.print_doc(helps, long=True)
                else:
                    TracAdmin.print_doc(helps)

            except AdminCommandError as e:
                printout(_('ERROR: Getting command help in environment %(env_name)s failed: ',
                    env_name=env_name) + e)
            break
Beispiel #6
0
 def do_import(db):
     cursor = db.cursor()
     # Make sure we don't insert the exact same page twice
     cursor.execute("SELECT text FROM wiki WHERE name=%s "
                    "ORDER BY version DESC LIMIT 1",
                    (title,))
     old = list(cursor)
     if old and title in create_only:
         printout(_('  %(title)s already exists', title=title))
         result[0] = False
         return
     if old and data == old[0][0]:
         printout(_('  %(title)s is already up to date', title=title))
         result[0] = False
         return
 
     if replace and old:
         cursor.execute("UPDATE wiki SET text=%s WHERE name=%s "
                        "  AND version=(SELECT max(version) FROM wiki "
                        "               WHERE name=%s)",
                        (data, title, title))
     else:
         cursor.execute("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
Beispiel #7
0
def main():
    names = sorted(name for name in resource_listdir('trac.wiki',
                                                     'default-pages')
                        if not name.startswith('.'))

    env = EnvironmentStub()
    load_components(env)
    with env.db_transaction:
        for name in names:
            wiki = WikiPage(env, name)
            wiki.text = resource_string('trac.wiki', 'default-pages/' +
                                        name).decode('utf-8')
            if wiki.text:
                wiki.save('trac', '')
            else:
                printout('%s: Skipped empty page' % name)

    req = Mock(href=Href('/'), abs_href=Href('http://trac.edgewall.org/'),
               perm=MockPerm(), chrome={})
    for name in sys.argv[1:]:
        name = os.path.basename(name)
        wiki = WikiPage(env, name)
        if not wiki.exists:
            continue
        context = web_context(req, wiki.resource, absurls=True)
        rst = wiki2rest(env, context, wiki)
        sys.stdout.write(rst)
Beispiel #8
0
def main():
    options, args = parse_args()
    names = sorted(name for name in resource_listdir('trac.wiki',
                                                     'default-pages')
                        if not name.startswith('.'))
    if args:
        args = sorted(set(names) & set(map(os.path.basename, args)))
    else:
        args = names

    if options.download:
        download_default_pages(args, options.prefix)

    env = EnvironmentStub()
    load_components(env)
    with env.db_transaction:
        for name in names:
            wiki = WikiPage(env, name)
            wiki.text = resource_string('trac.wiki', 'default-pages/' +
                                        name).decode('utf-8')
            if wiki.text:
                wiki.save('trac', '')
            else:
                printout('%s: Skipped empty page' % name)

    req = Mock(href=Href('/'), abs_href=Href('http://localhost/'),
               perm=MockPerm())
    for name in args:
        wiki = WikiPage(env, name)
        if not wiki.exists:
            continue
        context = web_context(req, wiki.resource)
        out = DummyIO()
        DefaultWikiChecker(env, context, name).format(wiki.text, out)
Beispiel #9
0
 def _do_wiki_upgrade(self):
     """Move all wiki pages starting with Trac prefix to unbranded user
     guide pages.
     """
     wiki_admin = WikiAdmin(self.env)
     pages = wiki_admin.get_wiki_list()
     for old_name in pages:
         if old_name.startswith('Trac'):
             new_name = wiki.new_name(old_name)
             if not new_name:
                 continue
             if new_name in pages:
                 printout(_('Ignoring %(page)s : '
                            'The page %(new_page)s already exists',
                            page=old_name, new_page=new_name))
                 continue
             try:
                 wiki_admin._do_rename(old_name, new_name)
             except AdminCommandError, exc:
                 printout(_('Error moving %(page)s : %(message)s',
                            page=old_name, message=unicode(exc)))
             else:
                 # On success, rename links in other pages
                 self._do_wiki_rename_links(old_name, new_name)
                 # On success, insert redirection page
                 redirection = WikiPage(self.env, old_name)
                 redirection.text = _('See [wiki:"%(name)s"].', name=new_name)
                 comment = 'Bloodhound guide update'
                 redirection.save('bloodhound', comment, '0.0.0.0')
Beispiel #10
0
 def _load_fixture_from_file(self, fname):
     """Calls _load_fixture with an open file"""
     try:
         fp = open(fname, mode='r')
         self._load_fixture(fp)
         fp.close()
     except IOError:
         printout(_("The file '%(fname)s' does not exist", fname=fname))
Beispiel #11
0
    def run(self):
        self.interactive = True
        printout(_("""Welcome to trac-admin %(version)s
Interactive Trac administration console.
Copyright (C) 2003-2013 Edgewall Software

Type:  '?' or 'help' for help on commands.
        """, version=TRAC_VERSION))
        self.cmdloop()
Beispiel #12
0
 def _do_remove(self, number):
     try:
         number = int(number)
     except ValueError:
         raise AdminCommandError(_('<number> must be a number'))
     with self.env.db_transaction:
         model.Ticket(self.env, number).delete()
     printout(_('Ticket #%(num)s and all associated data removed.',
                num=number))
Beispiel #13
0
    def _add_comment(self, ticket_id, user, comment):
        """Add a comment to a ticket"""

        try:
            ticket = Ticket(self.env, ticket_id)
            self._save_ticket(ticket, user, comment)
            printout('Added comment to ticket %s' % ticket_id)
        except:
            # if no such ticket then add comment.
            printout('Unable to add comment.')
Beispiel #14
0
 def do_transaction(db):
     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, page=page))
Beispiel #15
0
 def do_load(db):
     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=filename, page=page))
Beispiel #16
0
    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),
            )
        )
Beispiel #17
0
 def _do_add(self, user, *actions):
     permsys = PermissionSystem(self.env)
     if user.isupper():
         raise AdminCommandError(_('All upper-cased tokens are reserved '
                                   'for permission names'))
     for action in actions:
         try:
             permsys.grant_permission(user, action)
         except self.env.db_exc.IntegrityError:
             printout(_("The user %(user)s already has permission "
                        "%(action)s.", user=user, action=action))
Beispiel #18
0
 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))
Beispiel #19
0
 def _do_remove(self, number):
     try:
         number = int(number)
     except ValueError:
         raise AdminCommandError(_('<number> must be a number'))
     @self.env.with_transaction()
     def do_remove(db):
         ticket = model.Ticket(self.env, number, db=db)
         ticket.delete()
     printout(_('Ticket #%(num)s and all associated data removed.',
                num=number))
Beispiel #20
0
 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))
Beispiel #21
0
    def upgrade_environment(self, db):
        printout("Upgrading SimpleMultiProject database schema")
        cursor = db.cursor()

        db_installed_version = 0
        sqlGetInstalledVersion = """SELECT value FROM system WHERE name = %s"""
        cursor.execute(sqlGetInstalledVersion, [db_version_key])
        for row in cursor:
            db_installed_version = int(row[0])
        printout("SimpleMultiProject database schema version is %s, should be %s" %
                 (db_installed_version, db_version))

        db_connector, _ = DatabaseManager(self.env)._get_connector()

        if db_installed_version < 1:
            # Create tables
            for table in tables:
                for statement in db_connector.to_sql(table):
                    cursor.execute(statement)
                    
            sqlInsertVersion = """INSERT INTO system (name, value) VALUES (%s,%s)"""
            cursor.execute(sqlInsertVersion, [db_version_key, db_version])
            db_installed_version = 1
            
        if db_installed_version < 2:
            # Create tables
            for table in tables_v2:
                for statement in db_connector.to_sql(table):
                    cursor.execute(statement)
                    
            sqlInsertVersion = """UPDATE system SET value=%s WHERE name=%s"""
            cursor.execute(sqlInsertVersion, [db_version, db_version_key])
            db_installed_version = 2

        if db_installed_version < 3:
            # Create tables
            for table in tables_v3:
                for statement in db_connector.to_sql(table):
                    cursor.execute(statement)
                    
            sqlInsertVersion = """UPDATE system SET value=%s WHERE name=%s"""
            cursor.execute(sqlInsertVersion, [db_version, db_version_key])
            db_installed_version = 3

        if db_installed_version < 4:
            # Insert new column
            cursor.execute("""ALTER TABLE smp_project ADD summary varchar(255)""")
            
            sqlInsertVersion = """UPDATE system SET value=%s WHERE name=%s"""
            cursor.execute(sqlInsertVersion, [db_version, db_version_key])
            db_installed_version = 4
Beispiel #22
0
 def _do_set(self, reponame, key, value):
     if key not in self.repository_attrs:
         raise AdminCommandError(_('Invalid key "%(key)s"', key=key))
     if key == 'dir':
         value = os.path.abspath(value)
     self.modify_repository(reponame, {key: value})
     if not reponame:
         reponame = '(default)'
     if key == 'dir':
         printout(_('You should now run "repository resync %(name)s".',
                    name=reponame))
     elif key == 'type':
         printout(_('You may have to run "repository resync %(name)s".',
                    name=reponame))
Beispiel #23
0
 def next_callback(self, line, idx):
     marks = self.__marks
     if marks:
         buf = []
         prev = 0
         for start, end in self.__marks:
             buf.append(line[prev:start])
             buf.append(TURN_ON)
             buf.append(line[start:end])
             buf.append(TURN_OFF)
             prev = end
         buf.append(line[prev:])
         printout('%s:%d:%s' % (self.__name, idx + 1, ''.join(buf)))
         self.__marks[:] = ()
Beispiel #24
0
    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)))
Beispiel #25
0
    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:
                if not root:
                    continue
                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)
            with open(dest, "w") as out:
                stream.render("text", out=out, encoding="utf-8")
 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)
Beispiel #27
0
 def _sync(self, reponame, rev, clean):
     rm = RepositoryManager(self.env)
     if reponame == '*':
         if rev is not None:
             raise TracError(_('Cannot synchronize a single revision '
                               'on multiple repositories'))
         repositories = rm.get_real_repositories()
     else:
         if is_default(reponame):
             reponame = ''
         repos = rm.get_repository(reponame)
         if repos is None:
             raise TracError(_("Repository '%(repo)s' not found",
                               repo=reponame or '(default)'))
         if rev is not None:
             repos.sync_changeset(rev)
             printout(_('%(rev)s resynced on %(reponame)s.', rev=rev,
                        reponame=repos.reponame or '(default)'))
             return
         repositories = [repos]
     
     db = self.env.get_db_cnx()
     for repos in sorted(repositories, key=lambda r: r.reponame):
         printout(_('Resyncing repository history for %(reponame)s... ',
                    reponame=repos.reponame or '(default)'))
         repos.sync(self._sync_feedback, clean=clean)
         cursor = db.cursor()
         cursor.execute("SELECT count(rev) FROM revision WHERE repos=%s",
                        (repos.id,))
         for cnt, in cursor:
             printout(ngettext('%(num)s revision cached.',
                               '%(num)s revisions cached.', num=cnt))
     printout(_('Done.'))
Beispiel #28
0
    def _scan_ticket_commit_messages(self, reformat=False):
        """Convert commit messages from old to new format. (DANGEROUS)"""

        if reformat:
            printout('Reformatting ticket commit messages...')
        else:
            printout('diff ticket commit messages to be reformatted')
        
        n_matches = [0]
                         
        @self.env.with_transaction()
        def do_update(db):
            cursor = db.cursor()
            # Iterate over current ticket comments
            cursor.execute('SELECT ticket,time,oldvalue,newvalue '
                           'FROM ticket_change WHERE field=%s', ['comment'])
            for row in cursor.fetchall():
                ticket, time, oldvalue, oldmessage = row
                if oldvalue.isnumeric(): # ticket comment number
                    newmessage = _reformat_message(oldmessage)
                    if newmessage:
                        n_matches[0] += 1
                        if reformat:
                            cursor.execute(
                                    'UPDATE ticket_change SET newvalue=%s '
                                    'WHERE ticket=%s and time=%s and '
                                    'oldvalue=%s',
                                    [newmessage, ticket, time, oldvalue])
                        else:
                            printout('@@ comment:%s:ticket:%d (db time %d) @@'
                                     % (oldvalue, ticket, time))
                            printout('-' + oldmessage.replace('\n', '\n-'))
                            printout('+' + newmessage.replace('\n', '\n+'))
            # Iterate over changed (edited) ticket comments
            cursor.execute('SELECT ticket,time,oldvalue,newvalue '
                           'FROM ticket_change WHERE field LIKE %s',
                           ['_comment_%'])
            for row in cursor.fetchall():
                ticket, time, oldmessage, edit_time = row
                if edit_time.isnumeric(): # ticket comment change time
                    newmessage = _reformat_message(oldmessage)
                    if newmessage:
                        n_matches[0] += 1
                        if reformat:
                            cursor.execute(
                                    'UPDATE ticket_change SET oldvalue=%s '
                                    'WHERE ticket=%s and time=%s and '
                                    'newvalue=%s',
                                    [newmessage, ticket, time, edit_time])
                        else:
                            printout('@@ comment:(edit):ticket:%d (db time %d) @@'
                                     % (ticket, edit_time))
                            printout('-' + oldmessage.replace('\n', '\n-'))
                            printout('+' + newmessage.replace('\n', '\n+'))
        if reformat:
            printout('%d messages reformatted' % n_matches[0])
        else:
            printout('%d messages to be reformatted' % n_matches[0])
            
    def get_mercurial_repository(self):
        """
        Returns a Mercurial repository API object pointing at the repository directory
        associated to self.repository_id
        """
        try:
            repository_dir = None
            if (self.default):
                repository_dir = self.config.get("trac", "repository_dir", False)

            # If repository is "default" but the dir is not in config then
            # repository_dir will be False, so we look in repository table
            if not self.default or repository_dir is False:
                sql_string = """
                    SELECT value
                     FROM repository
                     WHERE name = 'dir' AND id = %s
                """
                self.cursor.execute(sql_string, (self.repository_id,))
                row = self.cursor.fetchone()

                if row[0] is None:
                    # It could be an alias
                    # We get the id of the repository it points to if it's an alias
                    # We are not supporting recursive alias (they are unnecessary) 
                    sql_string = """
                        SELECT id
                         FROM repository
                         WHERE name = 'name' AND value = (SELECT value FROM repository WHERE name = 'alias' AND id = %s)
                    """
                    self.cursor.execute(sql_string, (self.repository_id,))
                    row = self.cursor.fetchone()

                    if row[0] is None:
                        printout("[E] Sorry, but repository name is not defined in repository table")
                        sys.exit(1)
                    else:
                        # We need to update the id, to sync the repository the alias is pointing
                        self.repository_id = row[0]
                        sql_string = """
                            SELECT value
                             FROM repository
                             WHERE name = 'dir' AND id = %s
                        """
                        self.cursor.execute(sql_string, (self.repository_id,))
                        row = self.cursor.fetchone()

                        if row[0] is None:
                            printout("[E] Sorry, but alias directory was not found, this plugin does not support recursive alias")
                            sys.exit(1)

                repository_dir = row[0]

            return hg.repository(ui.ui(), repository_dir)

        except Exception, error:
            printout("Error:", error)
            printout("Error: Impossible to connect to Mercurial repository at", repository_dir)
            sys.exit(1)
Beispiel #30
0
    def _downloads_dir_check(self):
        try:
            env_name = self.env.project_identifier
        except AttributeError as e:
            # In case of trac admin commands, project_identifier is not found
            env_name = self.env.path.split("/")[-1]
            self.env.project_identifier = env_name

        download_config = FilesDownloadConfig(env_name)
        node_factory = FileSystemNode(download_config.base_path)
        node, dir_exists = self.get_dir_data(download_config, node_factory)
        if dir_exists:
            printout("[+] {0:<30} '{1:}'".format(env_name, download_config.downloads_dir))
        else:
            printout("[-] {0:<30} '{1:}'".format(env_name, download_config.downloads_dir))
Beispiel #31
0
    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
Beispiel #32
0
def do_upgrade(env, ver, cursor):
    """Upgrade the workflow."""

    # Upgrade the reports to better handle the new workflow capabilities.
    with env.db_query as db:
        owner = db.concat('owner', "' *'")
    cursor.execute('SELECT id, query, description FROM report')
    reports = cursor.fetchall()
    for report, query, description in reports:
        q, d = query, description
        if query:
            # All states other than 'closed' are "active".
            q = q.replace("IN ('new', 'assigned', 'reopened')", "<> 'closed'")
            # Add a status column instead of adding an '*' to the owner's name
            # for the 'assigned' state.
            q = q.replace(
                "(CASE status WHEN 'assigned' THEN %s "
                "ELSE owner END) AS owner" % owner, "owner, status")
        if description:
            d = d.replace(
                " * If a ticket has been accepted, a '*' is"
                " appended after the owner's name\n", '')
        if q != query or d != description:
            cursor.execute(
                """
                UPDATE report SET query=%s, description=%s WHERE id=%s
                """, (q, d, report))

    # Upgrade the workflow.
    if 'ticket-workflow' not in env.config:
        load_workflow_config_snippet(env.config, 'original-workflow.ini')
        env.config.save()
        info_message = """

==== Upgrade Notice ====

The ticket Workflow is now configurable.

Your environment has been upgraded, but configured to use the original
workflow. It is recommended that you look at changing this configuration
to use basic-workflow.

Read TracWorkflow for more information
(don't forget to 'wiki upgrade' as well)

"""
        env.log.info(info_message.replace('\n', ' ').replace('==', ''))
        printout(info_message)
Beispiel #33
0
    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)))
Beispiel #34
0
 def _do_add(self, user, *actions):
     permsys = PermissionSystem(self.env)
     if user.isupper():
         raise AdminCommandError(
             _('All upper-cased tokens are reserved '
               'for permission names'))
     for action in actions:
         try:
             permsys.grant_permission(user, action)
         except self.env.db_exc.IntegrityError:
             printout(
                 _(
                     "The user %(user)s already has permission "
                     "%(action)s.",
                     user=user,
                     action=action))
Beispiel #35
0
 def _do_set(self, reponame, key, value):
     if key not in self.repository_attrs:
         raise AdminCommandError(_('Invalid key "%(key)s"', key=key))
     if key == 'dir':
         value = os.path.abspath(value)
     self.modify_repository(reponame, {key: value})
     if not reponame:
         reponame = '(default)'
     if key == 'dir':
         printout(
             _('You should now run "repository resync %(name)s".',
               name=reponame))
     elif key == 'type':
         printout(
             _('You may have to run "repository resync %(name)s".',
               name=reponame))
Beispiel #36
0
 def _do_remove_comment(self, ticket_number, comment_number):
     ticket_number = as_int(ticket_number, None)
     if ticket_number is None:
         raise AdminCommandError(_('<ticket#> must be a number'))
     comment_number = as_int(comment_number, None)
     if comment_number is None:
         raise AdminCommandError(_('<comment#> must be a number'))
     with self.env.db_transaction:
         ticket = model.Ticket(self.env, ticket_number)
         change = ticket.get_change(comment_number)
         if not change:
             raise AdminCommandError(_("Comment %(num)s not found",
                                       num=comment_number))
         ticket.delete_change(comment_number)
     printout(_("The ticket comment %(num)s on ticket #%(id)s has been "
                "deleted.", num=comment_number, id=ticket_number))
Beispiel #37
0
    def _downloads_dir_check(self):
        try:
            env_name = self.env.project_identifier
        except AttributeError as e:
            # In case of trac admin commands, project_identifier is not found
            env_name = self.env.path.split('/')[-1]
            self.env.project_identifier = env_name

        download_config = FilesDownloadConfig(env_name)
        node_factory = FileSystemNode(download_config.base_path)
        node, dir_exists = self.get_dir_data(download_config, node_factory)
        if dir_exists:
            printout("[+] {0:<30} '{1:}'".format(
                env_name, download_config.downloads_dir))
        else:
            printout("[-] {0:<30} '{1:}'".format(
                env_name, download_config.downloads_dir))
Beispiel #38
0
 def copy(db):
     cursor = db.cursor()
     printout('  %s table... ' % table, newline=False)
     src_cursor.execute('SELECT * FROM ' + src_db.quote(table))
     columns = get_column_names(src_cursor)
     query = 'INSERT INTO ' + db.quote(table) + \
             ' (' + ','.join(db.quote(c) for c in columns) + ')' + \
             ' VALUES (' + ','.join(['%s'] * len(columns)) + ')'
     cursor.execute('DELETE FROM ' + db.quote(table))
     count = 0
     while True:
         rows = src_cursor.fetchmany(100)
         if not rows:
             break
         cursor.executemany(query, rows)
         count += len(rows)
     printout('%d records.' % count)
Beispiel #39
0
    def _do_deploy(self, dest):
        from trac.web.chrome import Chrome

        target = os.path.normpath(dest)
        chrome_target = os.path.join(target, 'htdocs')
        script_target = os.path.join(target, 'cgi-bin')

        # Check source and destination to avoid recursively copying files
        for provider in Chrome(self.env).template_providers:
            paths = list(provider.get_htdocs_dirs() or [])
            if not paths:
                continue
            for key, root in paths:
                if not root:
                    continue
                source = os.path.normpath(root)
                dest = os.path.join(chrome_target, key)
                if os.path.exists(source) and is_path_below(dest, source):
                    raise AdminCommandError(
                        _(
                            "Resources cannot be deployed to a target "
                            "directory that is equal to or below the source "
                            "directory '%(source)s'.\n\nPlease choose a "
                            "different target directory and try again.",
                            source=source))

        # Copy static content
        makedirs(target, overwrite=True)
        makedirs(chrome_target, overwrite=True)
        printout(_("Copying resources from:"))
        for provider in Chrome(self.env).template_providers:
            paths = list(provider.get_htdocs_dirs() or [])
            if not paths:
                continue
            printout('  %s.%s' %
                     (provider.__module__, provider.__class__.__name__))
            for key, root in paths:
                if not root:
                    continue
                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)
            with open(dest, 'w') as out:
                stream.render('text', out=out, encoding='utf-8')
Beispiel #40
0
 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=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)
Beispiel #41
0
    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))
Beispiel #42
0
Datei: env.py Projekt: t2y/trac
    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)))
Beispiel #43
0
    def _sync(self, reponame, rev, clean):
        rm = RepositoryManager(self.env)
        if reponame == '*':
            if rev is not None:
                raise TracError(
                    _('Cannot synchronize a single revision '
                      'on multiple repositories'))
            repositories = rm.get_real_repositories()
        else:
            if is_default(reponame):
                reponame = ''
            repos = rm.get_repository(reponame)
            if repos is None:
                raise TracError(
                    _("Repository \"%(repo)s\" doesn't exist",
                      repo=reponame or '(default)'))
            repositories = [repos]

        for repos in sorted(repositories, key=lambda r: r.reponame):
            pretty_name = repos.reponame or '(default)'
            if not isinstance(repos, CachedRepository):
                printout(
                    _("%(reponame)s is not a cached repository.",
                      reponame=pretty_name))
            elif rev is not None:
                repos.sync_changeset(rev)
                printout(
                    _('%(rev)s resynced on %(reponame)s.',
                      rev=rev,
                      reponame=pretty_name))
            else:
                printout(
                    _('Resyncing repository history for %(reponame)s... ',
                      reponame=pretty_name))
                repos.sync(self._sync_feedback, clean=clean)
                for cnt, in self.env.db_query(
                        "SELECT count(rev) FROM revision WHERE repos=%s",
                    (repos.id, )):
                    printout(
                        ngettext('%(num)s revision cached.',
                                 '%(num)s revisions cached.',
                                 num=cnt))
        printout(_('Done.'))
Beispiel #44
0
    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
Beispiel #45
0
    def _do_org_update(self):
        """
        Updates organizations from project.ini to database
        Organizations are in format::

            org.<type>.<identifier> = <backend>, <organization>

        Where:

        - type: Organization type: auths | email
        - identifier: Identifier for organization. Id for auths and mail domain for email
        - backend: Authentication backend
        - organization: Organization name

        """
        orgman = self.env[OrganizationManager]
        organizations = orgman.get_organizations()

        if not orgman.use_organizations:
            printout('Organizations are disabled. Nothing to do.')
            return

        if not organizations:
            printout(
                'No organizations were found from configuration. Nothing to do.'
            )
            return

        # Surround organizations with '
        organizations_sql = []
        for organization in sorted(organizations,
                                   key=lambda org: org['position']):
            organizations_sql.append("('{0}', {1})".format(
                safe_string(organization['name']),
                safe_int(organization['position'])))

        query = """
        INSERT IGNORE INTO organization (organization_name, sorting)
        VALUES {0}
        ON DUPLICATE KEY UPDATE sorting=VALUES(sorting)
        """.format(','.join(organizations_sql))

        with admin_transaction() as cursor:
            try:
                cursor.execute(query)
            except:
                logging.exception(
                    "Organization update failed (conf -> db) with query %s" %
                    query)
                printout('Failed to update organization info. Check the logs')
                return

        printout('Updated organization info into db successfully')
Beispiel #46
0
 def get_revs(self, tkt_id=None):
     r = {}
     if tkt_id is None:
         # Get tickets from db
         db = self.env.get_read_db()
         cursor = db.cursor()
         cursor.execute('SELECT ticket FROM ticket_changesets')
         for tkt_id, in cursor:
             csets = TicketChangesets(self.env).get(tkt_id)
             for (reponame, changesets) in csets:
                 r[tkt_id] = changesets.list_revs(reponame)
     else:
         csets = TicketChangesets(self.env).get(tkt_id)
         for (reponame, changesets) in csets:
             r[tkt_id] = changesets.list_revs(reponame)
     if r:
         for tkt_id, revs in r.iteritems():
             printout('#%s: %s' % (tkt_id, ','.join(revs)))
     else:
         printout('None')
Beispiel #47
0
 def _do_list(self, user=None):
     permsys = PermissionSystem(self.env)
     if user:
         rows = []
         perms = permsys.get_user_permissions(user)
         for action in perms:
             if perms[action]:
                 rows.append((user, action))
     else:
         rows = permsys.get_all_permissions()
     rows.sort()
     print_table(rows, [_('User'), _('Action')])
     print
     printout(_("Available actions:"))
     actions = permsys.get_actions()
     actions.sort()
     text = ', '.join(actions)
     printout(wrap(text, initial_indent=' ', subsequent_indent=' ', 
                   linesep='\n'))
     print
Beispiel #48
0
 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=filename))
             with open(filename, 'w') as f:
                 f.write(text.encode('utf-8'))
         break
     else:
         raise AdminCommandError(_("Page '%(page)s' not found", page=page))
Beispiel #49
0
 def export_page(self, page, filename, cursor=None):
     if cursor is None:
         db = self.env.get_db_cnx()
         cursor = db.cursor()
     cursor.execute("SELECT text FROM wiki WHERE name=%s "
                    "ORDER BY version DESC LIMIT 1", (page,))
     for text, in cursor:
         break
     else:
         raise AdminCommandError(_("Page '%(page)s' not found", page=page))
     if not filename:
         printout(text)
     else:
         if os.path.isfile(filename):
             raise AdminCommandError(_("File '%(name)s' exists",
                                       name=filename))
         f = open(filename, 'w')
         try:
             f.write(text.encode('utf-8'))
         finally:
             f.close()
Beispiel #50
0
def _run(args):
    if args is None:
        args = sys.argv[1:]
    admin = TracAdmin()
    if args:
        if args[0] in ('-h', '--help', 'help'):
            return admin.onecmd(' '.join(_quote_args(['help'] + args[1:])))
        elif args[0] in ('-v', '--version'):
            printout(os.path.basename(sys.argv[0]), TRAC_VERSION)
        else:
            admin.env_set(os.path.abspath(args[0]))
            if len(args) > 1:
                return admin.onecmd(' '.join(_quote_args(args[1:])))
            else:
                while True:
                    try:
                        admin.run()
                    except KeyboardInterrupt:
                        admin.do_quit('')
    else:
        return admin.onecmd("help")
Beispiel #51
0
    def get_initenv_args(self):
        returnvals = []
        printout(_("Creating a new Trac environment at %(envname)s",
                   envname=self.envname))
        printout(_("""
Trac will first ask a few questions about your environment
in order to initialize and prepare the project database.

 Please enter the name of your project.
 This name will be used in page titles and descriptions.
"""))
        dp = 'My Project'
        returnvals.append(raw_input(_("Project Name [%(default)s]> ",
                                      default=dp)).strip() or dp)
        printout(_("""
 Please specify the connection string for the database to use.
 By default, a local SQLite database is created in the environment
 directory. It is also possible to use an already existing
 PostgreSQL database (check the Trac documentation for the exact
 connection string syntax).
"""))
        ddb = 'sqlite:db/trac.db'
        prompt = _("Database connection string [%(default)s]> ", default=ddb)
        returnvals.append(raw_input(prompt).strip() or ddb)
        print()
        return returnvals
Beispiel #52
0
    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)
Beispiel #53
0
    def _do_wiki_upgrade(self):
        """Move all wiki pages starting with Trac prefix to unbranded user
        guide pages.
        """
        get_new_name = self.RENAME_MAP.get

        wiki_admin = WikiAdmin(self.env)
        pages = wiki_admin.get_wiki_list()
        for old_name in pages:
            if old_name.startswith('Trac'):
                new_name = get_new_name(old_name,
                                        GUIDE_NAME + '/' + old_name[4:])
                if not new_name:
                    continue
                if new_name in pages:
                    printout(
                        _(
                            'Ignoring %(page)s : '
                            'The page %(new_page)s already exists',
                            page=old_name,
                            new_page=new_name))
                    continue
                try:
                    wiki_admin._do_rename(old_name, new_name)
                except AdminCommandError, exc:
                    printout(
                        _('Error moving %(page)s : %(message)s',
                          page=old_name,
                          message=unicode(exc)))
                else:
                    # On success, rename links in other pages
                    self._do_wiki_rename_links(old_name, new_name)
                    # On success, insert redirection page
                    redirection = WikiPage(self.env, old_name)
                    redirection.text = _('See [wiki:"%(name)s"].',
                                         name=new_name)
                    comment = 'Bloodhound guide update'
                    redirection.save('bloodhound', comment, '0.0.0.0')
Beispiel #54
0
    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)))
Beispiel #55
0
    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
Beispiel #56
0
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")
Beispiel #57
0
    def resync(self):
        """Resync ticket changesets from commit messages in all repos.
        """
        printout('Resyncing ticket changesets...')
        ticket_changesets = TicketChangesets(self.env)
        ticket_updater = CommitTicketUpdater(self.env)
        repositories = RepositoryManager(self.env).get_real_repositories()
        n_changesets = 0

        @self.env.with_transaction()
        def do_clean(db):
            cursor = db.cursor()
            cursor.execute('DELETE FROM ticket_changesets')

        def _count_affected_tickets():
            db = self.env.get_read_db()
            cursor = db.cursor()
            cursor.execute('SELECT COUNT(*) FROM ticket_changesets')
            row = cursor.fetchone()
            return row and int(row[0]) or 0

        for repos in repositories:
            rev = repos.get_oldest_rev()
            while True:
                changeset = repos.get_changeset(rev)
                tickets = ticket_updater.parse_message(changeset.message)
                match = False
                for tkt_id, cmds in tickets.iteritems():
                    ticket_changesets.add(tkt_id, repos.id, rev)
                    match = True
                if match:
                    n_changesets += 1
                if rev == repos.get_youngest_rev():
                    break
                rev = repos.next_rev(rev)
        printout('Done, %d tickets related to %d changesets' %
                 (_count_affected_tickets(), n_changesets))
Beispiel #58
0
def do_upgrade(env, version, cursor):
    """Automatically append ReadonlyWikiPolicy if permission_policies is
    the default value. Otherwise, echo a message about the need to manually
    add ReadonlyWikiPolicy to the list of permission_policies."""

    policies = env.config.getlist('trac', 'permission_policies')
    if policies == _old_default:
        backup_config_file(env, '.db30.bak')
        env.config.set('trac', 'permission_policies', ', '.join(_new_default))
        env.config.save()
        env.log.info("Enabled ReadonlyWikiPolicy.")
    elif 'ReadonlyWikiPolicy' not in policies:
        env.log.info("ReadonlyWikiPolicy must be manually enabled.")
        # TRANSLATOR: Wrap message to 80 columns
        printout(
            _("""\
Notice: To enable the readonly wiki attribute, trac.ini must be manually
edited to add ReadonlyWikiPolicy to the list of permission_policies in
the [trac] section.

For more details see: https://trac.edgewall.org/wiki/ReadonlyWikiPolicy
"""))
    else:
        env.log.info("ReadonlyWikiPolicy already enabled.")
Beispiel #59
0
def do_upgrade(env, version, cursor):
    """Add `description` column to `enum` table."""
    new_schema = [
        Table('enum', key=('type', 'name'))[Column('type'),
                                            Column('name'),
                                            Column('value'),
                                            Column('description'), ]
    ]

    with env.db_transaction:
        DatabaseManager(env).upgrade_tables(new_schema)
        failures = []
        for id_ in [1, 2, 3, 4, 5, 7, 8]:
            try:
                r = Report(env, id_)
            except ResourceNotFound:
                pass
            else:
                query = replace_sql_fragment(r.query)
                if query:
                    r.query = query
                    r.update()
                else:
                    failures.append(unicode(id_))

    if failures:
        failures = ', '.join(failures)
        # TRANSLATOR: Wrap message to 80 columns
        printout(
            _("""\
Report(s) %(ids)s could not be upgraded and may need to be manually
edited to avoid an "ambiguous column name" error. See %(url)s for more
information.
""",
              ids=failures,
              url=url))
Beispiel #60
0
    def _sync(self, reponame, rev, clean):
        rm = RepositoryManager(self.env)
        if reponame == '*':
            if rev is not None:
                raise TracError(
                    _('Cannot synchronize a single revision '
                      'on multiple repositories'))
            repositories = rm.get_real_repositories()
        else:
            if is_default(reponame):
                reponame = ''
            repos = rm.get_repository(reponame)
            if repos is None:
                raise TracError(
                    _("Repository '%(repo)s' not found",
                      repo=reponame or '(default)'))
            if rev is not None:
                repos.sync_changeset(rev)
                printout(
                    _('%(rev)s resynced on %(reponame)s.',
                      rev=rev,
                      reponame=repos.reponame or '(default)'))
                return
            repositories = [repos]

        db = self.env.get_db_cnx()
        for repos in sorted(repositories, key=lambda r: r.reponame):
            printout(
                _('Resyncing repository history for %(reponame)s... ',
                  reponame=repos.reponame or '(default)'))
            repos.sync(self._sync_feedback, clean=clean)
            cursor = db.cursor()
            cursor.execute("SELECT count(rev) FROM revision WHERE repos=%s",
                           (repos.id, ))
            for cnt, in cursor:
                printout(
                    ngettext('%(num)s revision cached.',
                             '%(num)s revisions cached.',
                             num=cnt))
        printout(_('Done.'))