示例#1
0
class EnvironmentTestCase(unittest.TestCase):

    def setUp(self):
        env_path = os.path.join(tempfile.gettempdir(), 'trac-tempenv')
        self.env = Environment(env_path, create=True)
        self.db = self.env.get_db_cnx()

    def tearDown(self):
        self.db.close()
        self.env.shutdown() # really closes the db connections
        shutil.rmtree(self.env.path)

    def test_get_version(self):
        """Testing env.get_version"""
        assert self.env.get_version() == db_default.db_version

    def test_get_known_users(self):
        """Testing env.get_known_users"""
        cursor = self.db.cursor()
        cursor.executemany("INSERT INTO session VALUES (%s,%s,0)",
                           [('123', 0),('tom', 1), ('joe', 1), ('jane', 1)])
        cursor.executemany("INSERT INTO session_attribute VALUES (%s,%s,%s,%s)",
                           [('123', 0, 'email', '*****@*****.**'),
                            ('tom', 1, 'name', 'Tom'),
                            ('tom', 1, 'email', '*****@*****.**'),
                            ('joe', 1, 'email', '*****@*****.**'),
                            ('jane', 1, 'name', 'Jane')])
        users = {}
        for username,name,email in self.env.get_known_users(self.db):
            users[username] = (name, email)

        assert not users.has_key('anonymous')
        self.assertEqual(('Tom', '*****@*****.**'), users['tom'])
        self.assertEqual((None, '*****@*****.**'), users['joe'])
        self.assertEqual(('Jane', None), users['jane'])
示例#2
0
class EnvironmentTestCase(unittest.TestCase):
    def setUp(self):
        env_path = os.path.join(tempfile.gettempdir(), 'trac-tempenv')
        self.env = Environment(env_path,
                               create=True,
                               db_str='sqlite:db/trac.db')
        self.db = self.env.get_db_cnx()

    def tearDown(self):
        self.db.close()
        self.env.shutdown()  # really closes the db connections
        shutil.rmtree(self.env.path)

    def test_get_version(self):
        """Testing env.get_version"""
        assert self.env.get_version() == db_default.db_version

    def test_get_known_users(self):
        """Testing env.get_known_users"""
        cursor = self.db.cursor()
        cursor.execute("INSERT INTO session "
                       "VALUES ('123',0,'email','*****@*****.**')")
        cursor.executemany("INSERT INTO session VALUES (%s,1,%s,%s)",
                           [('tom', 'name', 'Tom'),
                            ('tom', 'email', '*****@*****.**'),
                            ('joe', 'email', '*****@*****.**'),
                            ('jane', 'name', 'Jane')])
        users = {}
        for username, name, email in self.env.get_known_users(self.db):
            users[username] = (name, email)

        assert not users.has_key('anonymous')
        self.assertEqual(('Tom', '*****@*****.**'), users['tom'])
        self.assertEqual((None, '*****@*****.**'), users['joe'])
        self.assertEqual(('Jane', None), users['jane'])
示例#3
0
def rename_user(envpath, oldname, newname):
    """Deletes all watchlist DB entries => Uninstaller"""
    from  trac.env   import  Environment
    try:
        env = Environment(envpath)
    except:
        print "Given path '%s' seems not to be a Trac environment." % envpath
        sys.exit(3)

    db = env.get_db_cnx()
    cursor = db.cursor()

    try:
        cursor.execute("""
            UPDATE watchlist
            SET wluser=%s
            WHERE wluser=%s
        """, (newname,oldname))
        cursor.execute("""
            UPDATE watchlist_settings
            SET wluser=%s
            WHERE wluser=%s
        """, (newname,oldname))
        print "Renamed user '%s' to '%s'." % (oldname,newname)
        db.commit()
    except Exception as e:
        db.rollback()
        print "Could not rename user: "******"Does the new user already exists?"
        sys.exit(3)

    db.commit()
    print "Finished."
示例#4
0
def rename_user(envpath, oldname, newname):
    """Deletes all watchlist DB entries => Uninstaller"""
    from trac.env import Environment
    try:
        env = Environment(envpath)
    except:
        print "Given path '%s' seems not to be a Trac environment." % envpath
        sys.exit(3)

    db = env.get_db_cnx()
    cursor = db.cursor()

    try:
        cursor.execute(
            """
            UPDATE watchlist
            SET wluser=%s
            WHERE wluser=%s
        """, (newname, oldname))
        cursor.execute(
            """
            UPDATE watchlist_settings
            SET wluser=%s
            WHERE wluser=%s
        """, (newname, oldname))
        print "Renamed user '%s' to '%s'." % (oldname, newname)
        db.commit()
    except Exception as e:
        db.rollback()
        print "Could not rename user: "******"Does the new user already exists?"
        sys.exit(3)

    db.commit()
    print "Finished."
示例#5
0
def fetchRecipes(trac_env):
  env = Environment(trac_env)
  db = env.get_db_cnx()
  cursor = db.cursor()
  cursor.execute("SELECT path,active,recipe,min_rev,max_rev,label,description,name FROM bitten_config")
  for row in cursor:
    (path, active, recipe, min_rev, max_rev, label, description, name) = row
    writeFile(trac_env, name, (path, active, recipe, min_rev, max_rev, label, description))
def Main(opts):
    """ Cross your fingers and pray """
    env = Environment(opts.envpath)
    from tractags.api import TagSystem

    tlist = opts.tags or split_tags(env.config.get('blog', 'default_tag', 
                                                   'blog'))
    tags = TagSystem(env)
    req = Mock(perm=MockPerm())
    blog = tags.query(req, ' '.join(tlist + ['realm:wiki']))
                   
    cnx = env.get_db_cnx()
    for resource, page_tags in list(blog):
        try:
            page = WikiPage(env, version=1, name=resource.id)
            _, publish_time, author, _, _ =  page.get_history().next()
            if opts.deleteonly:
                page.delete()
                continue
            categories = ' '.join([t for t in page_tags if t not in tlist])
            page = WikiPage(env, name=resource.id)
            for version, version_time, version_author, version_comment, \
                _ in page.get_history():
                # Currently the basename of the post url is used due to 
                # http://trac-hacks.org/ticket/2956
                #name = resource.id.replace('/', '_')
                name = resource.id
                # extract title from text:
                fulltext = page.text
                match = _title_split_match(fulltext)
                if match:
                    title = match.group(1)
                    fulltext = match.group(2)
                else: 
                    title = name
                body = fulltext
                print "Adding post %s, v%s: %s" % (name, version, title)
                insert_blog_post(cnx, name, version, title, body,
                                 publish_time, version_time, 
                                 version_comment, version_author, author,
                                 categories)
                reparent_blog_attachments(env, resource.id, name)
                continue
            cnx.commit()
            if opts.delete:
                page.delete()
                continue
        except:
            env.log.debug("Error loading wiki page %s" % resource.id, 
                          exc_info=True)
            print "Failed to add post %s, v%s: %s" % (name, version, title)
            cnx.rollback()
            cnx.close()
            return 1
    cnx.close()
    return 0
示例#7
0
def get_trac_user(path, username):
    from trac.env import Environment

    env = Environment(path)
    db = env.get_db_cnx()
    cursor = db.cursor()
    cursor.execute(
        "SELECT name, value" " FROM session_attribute" " WHERE sid='%s'" " AND (name='email' OR name='name')" % username
    )
    return dict((name, value) for name, value in cursor)
示例#8
0
def Main(opts):
    """ Cross your fingers and pray """
    env = Environment(opts.envpath)
    from tractags.api import TagSystem

    tlist = opts.tags or split_tags(
        env.config.get('blog', 'default_tag', 'blog'))
    tags = TagSystem(env)
    req = Mock(perm=MockPerm())
    blog = tags.query(req, ' '.join(tlist + ['realm:wiki']))

    cnx = env.get_db_cnx()
    for resource, page_tags in list(blog):
        try:
            page = WikiPage(env, version=1, name=resource.id)
            _, publish_time, author, _, _ = page.get_history().next()
            if opts.deleteonly:
                page.delete()
                continue
            categories = ' '.join([t for t in page_tags if t not in tlist])
            page = WikiPage(env, name=resource.id)
            for version, version_time, version_author, version_comment, \
                _ in page.get_history():
                # Currently the basename of the post url is used due to
                # http://trac-hacks.org/ticket/2956
                #name = resource.id.replace('/', '_')
                name = resource.id
                # extract title from text:
                fulltext = page.text
                match = _title_split_match(fulltext)
                if match:
                    title = match.group(1)
                    fulltext = match.group(2)
                else:
                    title = name
                body = fulltext
                print "Adding post %s, v%s: %s" % (name, version, title)
                insert_blog_post(cnx, name, version, title, body, publish_time,
                                 version_time, version_comment, version_author,
                                 author, categories)
                reparent_blog_attachments(env, resource.id, name)
                continue
            cnx.commit()
            if opts.delete:
                page.delete()
                continue
        except:
            env.log.debug("Error loading wiki page %s" % resource.id,
                          exc_info=True)
            print "Failed to add post %s, v%s: %s" % (name, version, title)
            cnx.rollback()
            cnx.close()
            return 1
    cnx.close()
    return 0
示例#9
0
class TicketTemplateTestCase(unittest.TestCase):
    def setUp(self):
        #        self.env = EnvironmentStub()

        env_path = os.path.join(tempfile.gettempdir(), 'trac-tempenv')
        self.env = Environment(env_path, create=True)
        self.db = self.env.get_db_cnx()

        self.compmgr = ComponentManager()

        # init TicketTemplateModule
        self.tt = ttadmin.TicketTemplateModule(self.compmgr)
        setattr(self.tt, "env", self.env)

    def tearDown(self):
        self.db.close()
        self.env.shutdown()  # really closes the db connections
        shutil.rmtree(self.env.path)

    def test_get_active_navigation_item(self):
        req = Mock(path_info='/tickettemplate')
        self.assertEqual('tickettemplate',
                         self.tt.get_active_navigation_item(req))

        req = Mock(path_info='/something')
        self.assertNotEqual('tickettemplate', self.tt.match_request(req))

    def test_get_navigation_items(self):
        req = Mock(href=Mock(
            tickettemplate=lambda: "/trac-tempenv/tickettemplate"))
        a, b, c = self.tt.get_navigation_items(req).next()
        self.assertEqual('mainnav', a)
        self.assertEqual('tickettemplate', b)

    def test_match_request(self):
        req = Mock(path_info='/tickettemplate')
        self.assertEqual(True, self.tt.match_request(req))

        req = Mock(path_info='/something')
        self.assertEqual(False, self.tt.match_request(req))

    def test_getTicketTypeNames(self):
        options = self.tt._getTicketTypeNames()
        self.assertEqual(["default", "defect", "enhancement", "task"], options)

    def test_loadSaveTemplateText(self):
        for tt_name, tt_text in [
            ("default", "default text"),
            ("defect", "defect text"),
            ("enhancement", "enhancement text"),
            ("task", "task text"),
        ]:
            self.tt._saveTemplateText(tt_name, tt_text)
            self.assertEqual(tt_name + " text",
                             self.tt._loadTemplateText(tt_name))
示例#10
0
class TracDatabase(object):
    def __init__(self, path):
        self.env = Environment(path)
        self._db = self.env.get_db_cnx()

    def db(self):
        return self._db

    def hasTickets(self):
        c = self.db().cursor()
        c.execute("SELECT count(*) FROM Ticket")
        return int(c.fetchall()[0][0]) > 0

    def setList(self, name, values):
        c = self.db().cursor()
        c.execute("DELETE FROM %s" % name)
        for v in values:
            print "  inserting %s '%s'" % (name, v)
            c.execute("INSERT INTO " + name + " (name) VALUES (%s)", (v,))
        self.db().commit()

    def setEnumList(self, name, values):
        c = self.db().cursor()
        c.execute("DELETE FROM enum WHERE type=%s", (name,))
        for n, v in enumerate(values):
            print "  inserting %s '%s'" % (name, v)
            c.execute("INSERT INTO enum (type, name, value) VALUES (%s,%s,%s)",
                      (name, v, n))
        self.db().commit()

    def clean(self):
        print "\nCleaning all tickets..."
        c = self.db().cursor()
        c.execute("DELETE FROM ticket_change")
        c.execute("DELETE FROM ticket")
        c.execute("DELETE FROM attachment")
        c.execute("DELETE FROM ticket_custom")
        self.db().commit()

        attachments_dir = os.path.join(os.path.normpath(self.env.path),
                                       "attachments")
        remove_recursively(attachments_dir)
        if not os.path.isdir(attachments_dir):
            os.mkdir(attachments_dir)

    def addAttachment(self, ticket_id, filename, datafile, filesize,
                      author, description, upload_time):
        # copied from bugzilla2trac
        attachment = Attachment(self.env, 'ticket', ticket_id)
        attachment.author = author
        attachment.description = description
        attachment.insert(filename, datafile, filesize, upload_time)
        del attachment
示例#11
0
def fetchRecipes(trac_env):
    env = Environment(trac_env)
    db = env.get_db_cnx()
    cursor = db.cursor()
    cursor.execute(
        "SELECT path,active,recipe,min_rev,max_rev,label,description,name FROM bitten_config"
    )
    for row in cursor:
        (path, active, recipe, min_rev, max_rev, label, description,
         name) = row
        writeFile(trac_env, name,
                  (path, active, recipe, min_rev, max_rev, label, description))
示例#12
0
class TracDatabase(object):
    def __init__(self, path):
        self.env = Environment(path)
        self._db = self.env.get_db_cnx()

    def db(self):
        return self._db

    def hasTickets(self):
        c = self.db().cursor()
        c.execute("SELECT count(*) FROM Ticket")
        return int(c.fetchall()[0][0]) > 0

    def setList(self, name, values):
        c = self.db().cursor()
        c.execute("DELETE FROM %s" % name)
        for v in values:
            print "  inserting %s '%s'" % (name, v)
            c.execute("INSERT INTO " + name + " (name) VALUES (%s)", (v, ))
        self.db().commit()

    def setEnumList(self, name, values):
        c = self.db().cursor()
        c.execute("DELETE FROM enum WHERE type=%s", (name, ))
        for n, v in enumerate(values):
            print "  inserting %s '%s'" % (name, v)
            c.execute("INSERT INTO enum (type, name, value) VALUES (%s,%s,%s)",
                      (name, v, n))
        self.db().commit()

    def clean(self):
        print "\nCleaning all tickets..."
        c = self.db().cursor()
        c.execute("DELETE FROM ticket_change")
        c.execute("DELETE FROM ticket")
        c.execute("DELETE FROM attachment")
        c.execute("DELETE FROM ticket_custom")
        self.db().commit()

        attachments_dir = os.path.join(os.path.normpath(self.env.path),
                                       "attachments")
        remove_recursively(attachments_dir)
        if not os.path.isdir(attachments_dir):
            os.mkdir(attachments_dir)

    def addAttachment(self, ticket_id, filename, datafile, filesize, author,
                      description, upload_time):
        # copied from bugzilla2trac
        attachment = Attachment(self.env, 'ticket', ticket_id)
        attachment.author = author
        attachment.description = description
        attachment.insert(filename, datafile, filesize, upload_time)
        del attachment
示例#13
0
文件: api.py 项目: nyuhuhuu/trachacks
  def do_purge(self, req, path, users):
    """Purge obsolete data - i.e. environment data (sessions, preferences,
    permissions) from users no longer existing
    @param req
    @param path path to the trac env to purge
    @param users users to keep
    @return boolean success
    @return msg info
    """
    self.env.log.debug('+ Purging obsolete data')
    dryrun = self.env.config.getbool('user_sync','dryrun',True)
    sql = []
    envpath, tracenv = os.path.split(path)
    try:
      env = Environment(path)
    except IOError:
      self.env.log.debug('Could not initialize environment at %s' % (path,))
      return False, 'Could not initialize environment at %s' % (path,)
    perm = PermissionSystem(env)
    if not 'TRAC_ADMIN' in perm.get_user_permissions(req.perm.username):
      raise PermissionError
    excludes = self.get_perm_groups(path)+users
    protect = "'"+"','".join(excludes)+"'"
    self.env.log.debug("Excluding from purge: %s" % (protect,))
    db = env.get_db_cnx()
    cursor = db.cursor()
    if not dryrun:
      self.env.log.debug('Updating database for %s' % (tracenv,))
      cursor.execute('DELETE FROM auth_cookie WHERE name NOT IN (%s)' % (protect,))
      cursor.execute('DELETE FROM session WHERE sid NOT IN (%s)' % (protect,))
      cursor.execute('DELETE FROM session_attribute WHERE sid NOT IN (%s)' % (protect,))
      cursor.execute('DELETE FROM permission WHERE username NOT IN (%s)' % (protect,))
      db.commit()

    sql_file_path = self.env.config.get('user_sync','sql_file_path') or os.path.join(self.env.path,'log')
    if sql_file_path.lower() == 'none':
      self.env.log.debug('SQLFile disabled (sql_file_path is "none")')
    else:
      sqlfile = '%s.sql' % (tracenv,)
      sqlfile = os.path.join(sql_file_path,sqlfile)
      self.env.log.debug('Writing SQL to %s' % (sqlfile,))
      try:
          f = open(sqlfile,'a')
          f.write('\n--- SQL for purging Trac environment %s\n' % (tracenv,));
          f.write('DELETE FROM auth_cookie WHERE name NOT IN (%s);\n' % (protect,))
          f.write('DELETE FROM session WHERE sid NOT IN (%s);\n' % (protect,))
          f.write('DELETE FROM session_attribute WHERE sid NOT IN (%s);\n' % (protect,))
          f.write('DELETE FROM permission WHERE username NOT IN (%s);\n' % (protect,))
      except IOError:
          self.env.log.debug('Could not write SQL file %s!' % (sqlfile,))
          return False, 'Could not write SQL file %s!' % (sqlfile,)

    return True, 'Successfully purged environment %s' % (tracenv,)
示例#14
0
class TicketTemplateTestCase(unittest.TestCase):

    def setUp(self):
#        self.env = EnvironmentStub()

        env_path = os.path.join(tempfile.gettempdir(), 'trac-tempenv')
        self.env = Environment(env_path, create=True)
        self.db = self.env.get_db_cnx()
        
        self.compmgr = ComponentManager()

        # init TicketTemplateModule
        self.tt = ttadmin.TicketTemplateModule(self.compmgr)
        setattr(self.tt, "env", self.env)

    def tearDown(self):
        self.db.close()
        self.env.shutdown() # really closes the db connections
        shutil.rmtree(self.env.path)

    def test_get_active_navigation_item(self):
        req = Mock(path_info='/tickettemplate')
        self.assertEqual('tickettemplate', self.tt.get_active_navigation_item(req))

        req = Mock(path_info='/something')
        self.assertNotEqual('tickettemplate', self.tt.match_request(req))

    def test_get_navigation_items(self):
        req = Mock(href=Mock(tickettemplate=lambda:"/trac-tempenv/tickettemplate"))
        a, b, c= self.tt.get_navigation_items(req).next()
        self.assertEqual('mainnav', a)
        self.assertEqual('tickettemplate', b)

    def test_match_request(self):
        req = Mock(path_info='/tickettemplate')
        self.assertEqual(True, self.tt.match_request(req))

        req = Mock(path_info='/something')
        self.assertEqual(False, self.tt.match_request(req))

    def test_getTicketTypeNames(self):
        options = self.tt._getTicketTypeNames()
        self.assertEqual(["default", "defect", "enhancement", "task"], options)

    def test_loadSaveTemplateText(self):
        for tt_name, tt_text in [("default", "default text"), 
                                ("defect", "defect text"), 
                                ("enhancement", "enhancement text"), 
                                ("task", "task text"),
                                ]:
            self.tt._saveTemplateText(tt_name, tt_text)
            self.assertEqual(tt_name + " text", self.tt._loadTemplateText(tt_name))
示例#15
0
    def _setup(self, configuration = None):
        configuration = configuration or '[ticket-custom]\nmycustomfield = text\nmycustomfield.label = My Custom Field\nmycustomfield.order = 1'

        instancedir = os.path.join(tempfile.gettempdir(), 'test-importer._preview')
        if os.path.exists(instancedir):
           shutil.rmtree(instancedir, False)
        env = Environment(instancedir, create=True)
        open(os.path.join(os.path.join(instancedir, 'conf'), 'trac.ini'), 'a').write('\n' + configuration + '\n')
        db = env.get_db_cnx()
        _exec(db.cursor(), "INSERT INTO permission VALUES ('anonymous', 'REPORT_ADMIN')        ")
        _exec(db.cursor(), "INSERT INTO permission VALUES ('anonymous', 'IMPORT_EXECUTE')        ")
        db.commit()
        ImporterTestCase.TICKET_TIME = 1190909220
        return Environment(instancedir)
示例#16
0
    def get_number_of_tickets_per_cr(self, project):
        settings = get_current_registry().settings
        if not settings:
            return

        tracenvs = settings.get('penelope.trac.envs')

        for trac in project.tracs:
            env = Environment('%s/%s' % (tracenvs, trac.trac_name))
            db = env.get_db_cnx()
            cursor = db.cursor()
            cursor.execute("""SELECT c.value as cr, count(t.id) AS number FROM ticket t INNER JOIN ticket_custom c ON (t.id = c.ticket AND c.name = 'customerrequest') group by cr;""")
            tickets = cursor.fetchall()
            db.rollback()
            return dict(tickets)
示例#17
0
文件: api.py 项目: nyuhuhuu/trachacks
 def get_perm_groups(self,path):
    """Get array of permission groups (e.g. anonymous,authenticated) defined in the given environment.
    These 'users' should e.g. never be purged on cleanup
    """
    users = []
    env = Environment(path)
    sids = []
    self.env.log.debug('Get users to keep from environment path %s' % (path,))
    db = env.get_db_cnx()
    cursor = db.cursor()
    cursor.execute('SELECT DISTINCT username FROM permission WHERE username NOT IN (SELECT DISTINCT sid FROM session_attribute UNION SELECT DISTINCT sid FROM session UNION SELECT DISTINCT name FROM auth_cookie)')
    for row in cursor: users.append(row[0])
    self.env.log.debug('Permission groups for %s: %s' % (path,','.join(users)))
    for user in env.config.getlist('user_sync','users_keep'):
      if not user in users: users.append(user)
    return users
示例#18
0
def getMySQLEnvironment(opts):
    dburi = opts.mysql_uri
    env = Environment(opts.tracenv)
    env.config.set('trac', 'database', dburi)
 
    try:
        cnx = env.get_db_cnx()
        cur = cnx.cursor()
        cur.execute("select value from system where name = 'database_version'");
    except ProgrammingError:
       cnx.rollback()
       DatabaseManager(env).init_db()
       DatabaseManager(env).shutdown()
 
#    if env.needs_upgrade():
#        env.upgrade()
    return env
示例#19
0
文件: api.py 项目: nyuhuhuu/trachacks
 def get_tracenv_users(self, path, userlist=''):
    """Get array of users defined in the specified environment having data assigned
    @param path path to the environment
    @param userlist comma separated list of users to restrict the result to (e.g. the users from the password file), each user enclosed in single quotes (for SQL)
    @return array [0..n] of string users
    """
    env = Environment(path)
    sids = []
    self.env.log.debug('Get users from %s' % (path,))
    db = env.get_db_cnx()
    cursor = db.cursor()
    if userlist:
      cursor.execute("SELECT DISTINCT sid FROM session_attribute WHERE sid IN (%s) AND name != 'enabled'" % (userlist,))
    else:
      cursor.execute("SELECT DISTINCT sid FROM session_attribute WHERE name != 'enabled'")
    for row in cursor:
       sids.append(row[0])
    return sids
示例#20
0
文件: api.py 项目: nyuhuhuu/trachacks
 def get_tracenv_userdata(self, req, path, userlist=''):
    """Retrieve account data from the environment at the specified path
    @param path path to the environment
    @param userlist comma separated list of users to restrict the result to (e.g. the users from the password file), each user enclosed in single quotes (for SQL)
    @return array (empty array if the environment uses a different password file than the master env calling us)
    """
    self.env.log.debug('Get user data from %s' % (path,))
    data = {}
    env = Environment(path)
    # if this environment uses a different password file, we return an empty dataset
    if self.env.config.get('account-manager','password_file') != env.config.get('account-manager','password_file'):
      self.env.log.info('Password files do not match, skipping environment %s' % (path,))
      return data
    perm = PermissionSystem(env)
    if not 'TRAC_ADMIN' in perm.get_user_permissions(req.perm.username):
      raise PermissionError
    db = env.get_db_cnx()
    cursor = db.cursor()
    sync_fields = self.env.config.getlist('user_sync','sync_fields')
    attr = "'"+"','".join(sync_fields)+"','email_verification_sent_to','email_verification_token'"
    self.env.log.debug('* Checking attributes: %s' % (attr,))
    if userlist:
      cursor.execute("SELECT sid,name,value FROM session_attribute WHERE sid IN (%s) AND name IN (%s)" % (userlist,attr,))
    else:
      cursor.execute("SELECT sid,name,value FROM session_attribute WHERE name IN (%s)" % (attr,))
    for row in cursor:
      if not row[0] in data: data[row[0]] = {}
      data[row[0]][row[1]] = row[2]
    for sid in data.iterkeys():
       no_data = True
       for att in sync_fields:
          if att in data[sid]:
             no_data = False
             break
       if no_data:
             self.env.log.debug('No data for %s in %s' % (sid,path,))
             data[sid] = Null
             continue
       data[sid]['path'] = path
       cursor.execute("SELECT authenticated FROM session_attribute WHERE sid='%s'" % (sid,))
       for row in cursor: data[sid]['authenticated'] = row[0]
       cursor.execute("SELECT datetime(last_visit,'unixepoch') AS last_visit FROM session WHERE sid='%s'" % (sid,))
       for row in cursor: data[sid]['last_visit'] = row[0]
    return data
示例#21
0
 def get_perm_groups(self, path):
     """Get array of permission groups (e.g. anonymous,authenticated) defined in the given environment.
  These 'users' should e.g. never be purged on cleanup
  """
     users = []
     env = Environment(path)
     sids = []
     self.env.log.debug('Get users to keep from environment path %s' %
                        (path, ))
     db = env.get_db_cnx()
     cursor = db.cursor()
     cursor.execute(
         'SELECT DISTINCT username FROM permission WHERE username NOT IN (SELECT DISTINCT sid FROM session_attribute UNION SELECT DISTINCT sid FROM session UNION SELECT DISTINCT name FROM auth_cookie)'
     )
     for row in cursor:
         users.append(row[0])
     self.env.log.debug('Permission groups for %s: %s' %
                        (path, ','.join(users)))
     for user in env.config.getlist('user_sync', 'users_keep'):
         if not user in users: users.append(user)
     return users
示例#22
0
def getPostgreSQLEnvironment(opts):
    """ Create an Environment connected to the PostgreSQL database """

    dburi = opts.pg_uri
    env = Environment(opts.tracenv)
    env.config.set('trac', 'database', dburi)
    try:
        cnx = env.get_db_cnx()
        cur = cnx.cursor()
        cur.execute("select value from system where name = 'database_version'");
    except ProgrammingError:
        cnx.rollback()
        DatabaseManager(env).init_db()
        DatabaseManager(env).shutdown()
        for x in filter(None, [env.compmgr[cls] for cls in 
                        ComponentMeta._registry.get(
                        IEnvironmentSetupParticipant, [])]):
            if isinstance(x, EnvironmentSetup):
                x.environment_created()        
    if env.needs_upgrade():
        env.upgrade()
    return env
示例#23
0
    def _setup(self, configuration=None):
        configuration = configuration or '[ticket-custom]\nmycustomfield = text\nmycustomfield.label = My Custom Field\nmycustomfield.order = 1'

        instancedir = os.path.join(tempfile.gettempdir(),
                                   'test-importer._preview')
        if os.path.exists(instancedir):
            shutil.rmtree(instancedir, False)
        env = Environment(instancedir, create=True)
        open(os.path.join(os.path.join(instancedir, 'conf'), 'trac.ini'),
             'a').write('\n' + configuration + '\n')
        db = env.get_db_cnx()
        _exec(
            db.cursor(),
            "INSERT INTO permission VALUES ('anonymous', 'REPORT_ADMIN')        "
        )
        _exec(
            db.cursor(),
            "INSERT INTO permission VALUES ('anonymous', 'IMPORT_EXECUTE')        "
        )
        db.commit()
        ImporterTestCase.TICKET_TIME = 1190909220
        return Environment(instancedir)
示例#24
0
 def _create_a_project(self,owner,proj_name,proj_full_name,description,req):
     if "PROJECT_CREATE" in req.perm:
         inherit_file=self.env.config.get('projectsmanager','inherit_file')
         options=[
                   ('project','name',proj_full_name),
                   ('project','descr',description),
                   ('inherit','file',inherit_file)
                   ]
         (projects_root_dir,_)=os.path.split(self.env.path)
         path = os.path.join(projects_root_dir,proj_name)
         self.log.debug('starting to create the environment.')
         Environment(path,True,options)
         env=Environment(path)# cmd: trac-admin path permission add XX TRAC_ADMIN
         cnx=env.get_db_cnx()
         cur=cnx.cursor()
         cur.execute("insert into permission values ('%s','TRAC_ADMIN');"%\
                         owner)
         cur.close()
         cnx.commit()
         cnx.close()
     else:
         pass
示例#25
0
 def get_tracenv_users(self, path, userlist=''):
     """Get array of users defined in the specified environment having data assigned
  @param path path to the environment
  @param userlist comma separated list of users to restrict the result to (e.g. the users from the password file), each user enclosed in single quotes (for SQL)
  @return array [0..n] of string users
  """
     env = Environment(path)
     sids = []
     self.env.log.debug('Get users from %s' % (path, ))
     db = env.get_db_cnx()
     cursor = db.cursor()
     if userlist:
         cursor.execute(
             "SELECT DISTINCT sid FROM session_attribute WHERE sid IN (%s) AND name != 'enabled'"
             % (userlist, ))
     else:
         cursor.execute(
             "SELECT DISTINCT sid FROM session_attribute WHERE name != 'enabled'"
         )
     for row in cursor:
         sids.append(row[0])
     return sids
示例#26
0
def getPostgreSQLEnvironment(opts):
    """ Create an Environment connected to the PostgreSQL database """

    dburi = opts.pg_uri
    env = Environment(opts.tracenv)
    env.config.set('trac', 'database', dburi)
    try:
        cnx = env.get_db_cnx()
        cur = cnx.cursor()
        cur.execute("select value from system where name = 'database_version'")
    except ProgrammingError:
        cnx.rollback()
        DatabaseManager(env).init_db()
        DatabaseManager(env).shutdown()
        for x in filter(None, [
                env.compmgr[cls] for cls in ComponentMeta._registry.get(
                    IEnvironmentSetupParticipant, [])
        ]):
            if isinstance(x, EnvironmentSetup):
                x.environment_created()
    if env.needs_upgrade():
        env.upgrade()
    return env
示例#27
0
class EnvironmentTestCase(unittest.TestCase):
    def setUp(self):
        env_path = os.path.join(tempfile.gettempdir(), "trac-tempenv")
        self.env = Environment(env_path, create=True)
        self.db = self.env.get_db_cnx()

    def tearDown(self):
        self.db.close()
        self.env.shutdown()  # really closes the db connections
        shutil.rmtree(self.env.path)

    def test_get_version(self):
        """Testing env.get_version"""
        assert self.env.get_version() == db_default.db_version

    def test_get_known_users(self):
        """Testing env.get_known_users"""
        cursor = self.db.cursor()
        cursor.executemany("INSERT INTO session VALUES (%s,%s,0)", [("123", 0), ("tom", 1), ("joe", 1), ("jane", 1)])
        cursor.executemany(
            "INSERT INTO session_attribute VALUES (%s,%s,%s,%s)",
            [
                ("123", 0, "email", "*****@*****.**"),
                ("tom", 1, "name", "Tom"),
                ("tom", 1, "email", "*****@*****.**"),
                ("joe", 1, "email", "*****@*****.**"),
                ("jane", 1, "name", "Jane"),
            ],
        )
        users = {}
        for username, name, email in self.env.get_known_users(self.db):
            users[username] = (name, email)

        assert not users.has_key("anonymous")
        self.assertEqual(("Tom", "*****@*****.**"), users["tom"])
        self.assertEqual((None, "*****@*****.**"), users["joe"])
        self.assertEqual(("Jane", None), users["jane"])
示例#28
0
    def _setup(self, configuration = None, plugin_dir=None):
        configuration = configuration or '[ticket-custom]\nmycustomfield = text\nmycustomfield.label = My Custom Field\nmycustomfield.order = 1\n'

        configuration += '\n[ticket]\ndefault_type = task\n'


        instancedir = os.path.join(tempfile.gettempdir(), 'test-importer._preview_%d' % self.index[0])
        self.index[0] += 1
        if os.path.exists(instancedir):
           shutil.rmtree(instancedir, False)
        env = Environment(instancedir, create=True)
        if plugin_dir:
            for file in os.listdir(plugin_dir):
                if file[0] == '.':
                    continue
                shutil.copyfile(os.path.join(plugin_dir, file), os.path.join(instancedir, 'plugins', file))

        open(os.path.join(os.path.join(instancedir, 'conf'), 'trac.ini'), 'a').write('\n' + configuration + '\n')
        db = env.get_db_cnx()
        _exec(db.cursor(), "INSERT INTO permission VALUES ('anonymous', 'REPORT_ADMIN')        ")
        _exec(db.cursor(), "INSERT INTO permission VALUES ('anonymous', 'IMPORT_EXECUTE')        ")
        db.commit()
        ImporterTestCase.TICKET_TIME = 1190909220
        return Environment(instancedir)
示例#29
0
def delete_watchlist_tables(envpath, tables=('watchlist','watchlist_settings','system'), user=None):
    """Deletes all watchlist DB entries => Uninstaller"""
    from  trac.env   import  Environment
    try:
        env = Environment(envpath)
    except:
        print "Given path '%s' seems not to be a Trac environment." % envpath
        sys.exit(3)

    db = env.get_db_cnx()

    if user is not None:
        cursor = db.cursor()
        if 'watchlist' in tables:
            try:
                cursor.execute("DELETE FROM watchlist WHERE wluser=%s", (user,))
                print "Deleted user entries from 'watchlist' table."
            except Exception as e:
                db.rollback()
                print "Could not delete user entry from 'watchlist' table: "\
                    + unicode(e)
        cursor = db.cursor()
        if 'watchlist_settings' in tables:
            try:
                cursor.execute("DELETE FROM watchlist_settings WHERE wluser=%s", (user,))
                print "Deleted user entries from 'watchlist_settings' table."
            except Exception as e:
                db.rollback()
                print "Could not delete user entry from 'watchlist_settings' table: "\
                    + unicode(e)

        db.commit()
        print "Finished."
        return


    if 'watchlist' in tables:
        cursor = db.cursor()
        try:
            cursor.execute("DROP TABLE watchlist")
            print "Deleted 'watchlist' table."
        except:
            db.rollback()
            print "No 'watchlist' table for deletion found."

    if 'watchlist_settings' in tables:
        cursor = db.cursor()
        try:
            cursor.execute("DROP TABLE watchlist_settings")
            print "Deleted 'watchlist_settings' table."
        except:
            db.rollback()
            print "No 'watchlist_settings' table for deletion found."

    if 'system' in tables:
        cursor = db.cursor()
        try:
            cursor.execute("DELETE FROM system WHERE name='watchlist_version'")
            print "Deleted watchlist version entry from system table."
        except Exception as e:
            db.rollback()
            print "Could not delete 'watchlist_version' from 'system' table: "\
                  + unicode(e)

    db.commit()
    print "Finished."
示例#30
0
文件: api.py 项目: nyuhuhuu/trachacks
 def update_tracenv_userdata(self, req, path, userdata):
   """Update the userdata in the specified environment using the records passed
   by userdata.
   @param path     : path to the trac environment to update
   @param userdata : collection of userdata as returned from merge()
   @return success : boolean
   @return msg     : details
   """
   sql = []
   exists = ''
   msg = ''
   envpath, tracenv = os.path.split(path)
   self.env.log.debug('Updating userdata in environment %s' % (path,))
   dryrun = self.env.config.getbool('user_sync','dryrun',True)
   if not dryrun:
     self.env.log.debug('HOT!!! We are NOT in dryrun mode!')
   else: self.env.log.debug('TESTING - we ARE in dryrun mode.')
   try:
     env = Environment(path)
   except IOError:
     self.env.log.debug('Could not initialize environment at %s' % (path,))
     return False, 'Could not initialize environment at %s' % (path,)
   perm = PermissionSystem(env)
   if not 'TRAC_ADMIN' in perm.get_user_permissions(req.perm.username):
     raise PermissionError
   db = env.get_db_cnx()
   cursor = db.cursor()
   if not dryrun: self.env.log.debug('Updating database for %s' % (tracenv,))
   for user in userdata:
     authenticated = userdata[user]['authenticated'] or 0
     for att in userdata[user]:
       if att in ['path','authenticated','last_visit']: continue
       cursor.execute("SELECT value FROM session_attribute WHERE sid='%s' AND name='%s' AND authenticated=%s" % (user,att,authenticated,))
       for row in cursor: exists = row[0]
       if exists:
         if exists == userdata[user][att]: continue
         if not dryrun: cursor.execute("UPDATE session_attribute SET value='%s' WHERE sid='%s' AND name='%s' AND authenticated=%s;\n" % (userdata[user][att],user,att,authenticated,))
         sql.append("UPDATE session_attribute SET value='%s' WHERE sid='%s' AND name='%s' AND authenticated=%s;\n" % (userdata[user][att],user,att,authenticated,))
       else:
         if not dryrun: cursor.execute("INSERT INTO session_attribute (sid,authenticated,name,value) VALUES('%s',%s,'%s','%s');\n" % (user,authenticated,att,userdata[user][att]))
         sql.append("INSERT INTO session_attribute (sid,authenticated,name,att) VALUES('%s',%s,'%s','%s');\n" % (user,authenticated,att,userdata[user][att]))
   if len(sql):
     if not dryrun: db.commit()
     sql_file_path = self.env.config.get('user_sync','sql_file_path') or os.path.join(self.env.path,'log')
     if sql_file_path.lower() == 'none':
       self.env.log.debug('SQLFile disabled (sql_file_path is "none")')
     else:
       sqlfile = '%s.sql' % (tracenv,)
       sqlfile = os.path.join(sql_file_path,sqlfile)
       try:
         if os.path.exists(sqlfile): os.unlink(sqlfile)
         self.env.log.debug('Writing SQL to %s' % (sqlfile,))
         f = open(sqlfile,'a')
         f.write('--- SQL for Trac environment %s\n' % (tracenv,));
         f.writelines(sql)
         f.close()
       except IOError:
         self.env.log.debug('Could not write SQL file %s!' % (sqlfile,))
         return False, 'Could not write SQL file %s!' % (sqlfile,)
       except ValueError:
         self.env.log.debug('No value for sqlfile?')
       if dryrun: msg = 'Wrote SQL for Trac environment %s to %s' % (tracenv,sqlfile,)
       else: msg = 'Updated userdata in environment %s. SQL was additionally written to %s' % (tracenv,sqlfile,)
   else:
     msg = 'No updates for Trac environment %s' % (tracenv)
   self.env.log.debug('Done updating userdata in environment %s' % (path,))
   return True, msg
示例#31
0
import os, sys

if os.environ['TRAC_VERSION'] in ('trunk', 'renderfilter'):
    import pkg_resources
    pkg_resources.require('Trac >= 0.11dev')

from trac.core import *
from trac.env import Environment
from trac.wiki.model import WikiPage
from trac.ticket.model import Ticket
from trac.web.href import Href
from genshi.core import *
from genshi.builder import tag

env = Environment(os.environ['TRAC'])
db = env.get_db_cnx()
cursor = db.cursor()

class FakeReq(object):
    def __init__(self):
        self.href = Href(os.environ['TRAC_VERSION'] + '/' + os.environ['TRAC'])
        self.authname = 'anonymous'
req = FakeReq()

from tracforge.admin.query import MultiQuery, TracForgeQueryModule
from trac.ticket.query import QueryModule
q = MultiQuery(env, 'id!=0')
d = q.execute(req)

示例#32
0
class Trac(object):
    def __init__(self, path):
        '''Basic object that supports the wiki and all that jazz'''
        self._env = Environment(os.path.abspath(path))
        purl = self._env.project_url
        if purl.endswith('/'):
            purl = purl[:-1]
        if purl:
            self.name = purl.split('/')[-1]
        else:
            self.name = self._env.project_name

    def listWikiPages(self):
        '''Return a list of all wiki pages that were not written by the 'trac' user'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        wikiPagesQuery = "select distinct name from wiki where author != 'trac'"
        res = cursor.execute(wikiPagesQuery)
        pages = res.fetchall()
        names = [x[0] for x in pages]
        return names

    def listTickets(self):
        '''Return a list of all ticket numbers'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        ticketsQuery = 'select distinct id from ticket'
        res = cursor.execute(ticketsQuery)
        ticketsRes = res.fetchall()
        tickets = [x[0] for x in ticketsRes]
        return tickets

    def maxTicket(self):
        '''Return the largest ticket number'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        maxTicketQuery = 'select max(id) from ticket'
        res = cursor.execute(maxTicketQuery)
        (maxTicket, ) = res.fetchone()
        return maxTicket

    def listVersions(self):
        '''List all the versions'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        versionsQuery = "select name from version"
        res = cursor.execute(versionsQuery)
        versions = [x[0] for x in res.fetchall()]
        return versions

    def listComponents(self):
        '''List all the ticket components'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        componentsQuery = "select name from component"
        res = cursor.execute(componentsQuery)
        components = [x[0] for x in res.fetchall()]
        return components

    def listEnums(self):
        '''List all the enums'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        enumsQuery = "select name, type from enum"
        res = cursor.execute(enumsQuery)
        return res.fetchall()

    def listMilestones(self):
        '''List all the milestones'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        milestonesQuery = "select name from milestone"
        res = cursor.execute(milestonesQuery)
        milestones = [x[0] for x in res.fetchall()]
        return milestones

    def getAllInfo(self):
        all = {}
        all['wikiNames'] = self.listWikiPages()
        all['maxTicket'] = self.maxTicket()
        all['versions'] = self.listVersions()
        all['components'] = self.listComponents()
        all['enums'] = self.listEnums()
        all['milestones'] = self.listMilestones()
        return all

    def getWikiPageAll(self, page):
        '''Get all the versions of a wiki page as a list of dicts and a list of attachments'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        pageCountRes = cursor.execute(
            'select count(*) as count from wiki where name = %s', (page, ))
        pageCount = pageCountRes.fetchone()[0]
        assert pageCount >= 1, 'Page %s not found in %s' % (page, self.name)

        attachments = []
        pageAttachmentQuery = "select type, id, filename, size, time, description, author, ipnr from attachment where type = 'wiki' and id = %s"
        pageAttachmentRes = cursor.execute(pageAttachmentQuery, (page, ))
        for attachment in pageAttachmentRes:
            thisAttachment = dict(
                zip([d[0] for d in pageAttachmentRes.description], attachment))
            thisAttachment['fileobj'] = Attachment(
                self._env, 'wiki', page, thisAttachment['filename']).open()
            attachments.append(thisAttachment)

        baseQuery = 'select name, version, time, author, ipnr, text, comment, readonly from wiki where name = %s'
        res = cursor.execute(baseQuery, (page, ))
        wikiData = []
        for row in res:
            wikiData.append(dict(zip([d[0] for d in res.description], row)))
        return wikiData, attachments

    def getWikiPageCurrent(self, page):
        '''Get the current version of a wiki page as a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        pageCountRes = cursor.execute(
            'select count(*) as count from wiki where name = %s', (page, ))
        pageCount = pageCountRes.fetchone()[0]
        assert pageCount >= 1, 'Page %s not found in %s' % (page, self.name)
        pageQuery = 'select name, version, time, author, ipnr, text, comment, readonly from wiki where name = %s and version = (select max(version) from wiki where name = %s)'
        pageRes = cursor.execute(pageQuery, (page, page))
        wikiPage = dict(
            zip([d[0] for d in pageRes.description], pageRes.fetchone()))

        wikiPage['attachment'] = []
        pageAttachmentQuery = "select type, id, filename, size, time, description, author, ipnr from attachment where type = 'wiki' and id = %s"
        pageAttachmentRes = cursor.execute(pageAttachmentQuery, (page, ))
        for attachment in pageAttachmentRes:
            thisAttachment = dict(
                zip([d[0] for d in pageAttachmentRes.description], attachment))
            thisAttachment['fileobj'] = Attachment(
                self._env, 'wiki', page, thisAttachment['filename']).open()
            wikiPage['attachment'].append(thisAttachment)
        return wikiPage

    def addWikiPage(self, page, attachments):
        '''Add a wiki page as a list of dictionaries'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        pageCountRes = cursor.execute(
            'select count(*) as count from wiki where name = %s',
            (page[0]['name'], ))
        pageCount = pageCountRes.fetchone()[0]
        assert pageCount == 0, 'Page %s found in %s' % (page[0]['name'],
                                                        self.name)

        insertWikiQuery = 'insert into wiki (name, version, time, author, ipnr, text, comment, readonly) values (%s, %s, %s, %s, %s, %s, %s, %s)'
        for pV in page:
            insertValues = (pV['name'], pV['version'], pV['time'],
                            pV['author'], pV['ipnr'], pV['text'],
                            pV['comment'], pV['readonly'])
            insertRes = cursor.execute(insertWikiQuery, insertValues)
        for a in attachments:
            pageAttach = Attachment(self._env, 'wiki', pV['name'])
            pageAttach.description = a['description']
            pageAttach.author = a['author']
            pageAttach.ipnr = a['ipnr']
            pageAttach.insert(a['filename'],
                              a['fileobj'],
                              a['size'],
                              t=a['time'])
        db.commit()

    def getTicket(self, id):
        '''Get a ticket id as a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        idCountRes = cursor.execute(
            'select count(*) as count from ticket where id = %s', (id, ))
        idCount = idCountRes.fetchone()[0]
        assert idCount >= 1, 'Page %s not found in %s' % (id, self.id)

        mainTicketQuery = 'select id, type, time, changetime, component, severity, priority, owner, \
			reporter, cc, version, milestone, status, resolution, summary, description, keywords from ticket where id = %s'

        mainTicketRes = cursor.execute(mainTicketQuery, (id, ))
        ticket = dict(
            zip([d[0] for d in mainTicketRes.description],
                mainTicketRes.fetchone()))

        ticket['ticket_change'] = []
        ticketChangeQuery = 'select time, author, field, oldvalue, newvalue from ticket_change where ticket = %s'
        ticketChangeRes = cursor.execute(ticketChangeQuery, (id, ))
        for ticket_change in ticketChangeRes:
            ticket['ticket_change'].append(
                dict(
                    zip([d[0] for d in ticketChangeRes.description],
                        ticket_change)))

        ticket['attachment'] = []
        ticketAttachmentQuery = 'select type, id, filename, size, time, description, author, ipnr from attachment where type = \'ticket\' and id = %s'
        ticketAttachmentRes = cursor.execute(ticketAttachmentQuery, (id, ))
        for attachment in ticketAttachmentRes:
            thisAttachment = dict(
                zip([d[0] for d in ticketAttachmentRes.description],
                    attachment))
            thisAttachment['fileobj'] = Attachment(
                self._env, 'ticket', id, thisAttachment['filename']).open()
            ticket['attachment'].append(thisAttachment)
        return ticket

    def addTicket(self, ticket, source):
        '''Add a ticket from a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        idCountRes = cursor.execute(
            'select count(*) as count from ticket where id = %s',
            (ticket['id'], ))
        idCount = idCountRes.fetchone()[0]
        assert idCount == 0, 'Ticket %s found in %s' % (ticket['id'],
                                                        self.name)

        insertMainTicketQuery = 'insert into ticket (id, type, time, changetime, component, severity, priority, owner, \
			reporter, cc, version, milestone, status, resolution, summary, description, keywords) \
			values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'
        insertMainTicketValues = (ticket['id'], ticket['type'], ticket['time'], ticket['changetime'], ticket['component'], \
         ticket['severity'], ticket['priority'], ticket['owner'], ticket['reporter'], ticket['cc'], ticket['version'], \
         ticket['milestone'], ticket['status'], ticket['resolution'], ticket['summary'], ticket['description'], ticket['keywords'])
        insertMainTicketRes = cursor.execute(insertMainTicketQuery,
                                             insertMainTicketValues)

        #so we know where the ticket came from
        insertTicketSourceQuery = 'insert into ticket_custom (ticket, name, value) values (%s, %s, %s)'
        insertTicketSourceValues = (ticket['id'], 'project', source)
        insertTicketSourceRes = cursor.execute(insertTicketSourceQuery,
                                               insertTicketSourceValues)

        insertTicketChangeQuery = 'insert into ticket_change (ticket, time, author, field, oldvalue, newvalue) values (%s, %s, %s, %s, %s, %s)'
        for ticket_change in ticket['ticket_change']:
            insertTicketChangeValues = (ticket['id'], ticket_change['time'],
                                        ticket_change['author'],
                                        ticket_change['field'],
                                        ticket_change['oldvalue'],
                                        ticket_change['newvalue'])
            insertTicketChangeRes = cursor.execute(insertTicketChangeQuery,
                                                   insertTicketChangeValues)

        for a in ticket['attachment']:
            ticketAttach = Attachment(self._env, 'ticket', ticket['id'])
            ticketAttach.description = a['description']
            ticketAttach.author = a['author']
            ticketAttach.ipnr = a['ipnr']
            ticketAttach.insert(a['filename'],
                                a['fileobj'],
                                a['size'],
                                t=a['time'])
        db.commit()

    def getComponent(self, comp):
        '''Get a component as a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        compCountRes = cursor.execute(
            'select count(*) as count from component where name = %s',
            (comp, ))
        compCount = compCountRes.fetchone()[0]
        assert compCount >= 1, 'Component %s not found in %s' % (comp,
                                                                 self.name)
        baseQuery = 'select name, owner, description from component where name = %s'
        res = cursor.execute(baseQuery, (comp, ))
        return (dict(zip([d[0] for d in res.description], res.fetchone())))

    def addComponent(self, comp):
        '''Add a component from a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        assert comp['name'] != '', 'No name given'
        compCountRes = cursor.execute(
            'select count(*) as count from component where name = %s',
            (comp['name'], ))
        compCount = compCountRes.fetchone()[0]
        if compCount > 0:
            'Component %s found in %s. Skipping the re-insertion.' % (
                comp['name'], self.name)
        else:
            insertComponentQuery = 'insert into component (name, owner, description) values (%s, %s, %s)'
            insertComponentValues = (comp['name'], comp['owner'],
                                     comp['description'])
            res = cursor.execute(insertComponentQuery, insertComponentValues)
            db.commit()

    def getMilestone(self, mile):
        '''Get a milestone as a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        mileCountRes = cursor.execute(
            'select count(*) as count from milestone where name = %s',
            (mile, ))
        mileCount = mileCountRes.fetchone()[0]
        assert mileCount >= 1, 'Milestone %s not found in %s' % (mile,
                                                                 self.name)

        baseQuery = 'select name, due, completed, description from milestone where name = %s'
        res = cursor.execute(baseQuery, (mile, ))
        return (dict(zip([d[0] for d in res.description], res.fetchone())))

    def addMilestone(self, mile):
        '''Add a milestone from a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        assert mile['name'] != '', 'No name given'
        mileCountRes = cursor.execute(
            'select count(*) as count from milestone where name = %s',
            (mile['name'], ))
        mileCount = mileCountRes.fetchone()[0]
        if mileCount > 0:
            'Milestone %s found in %s. Skipping the re-insertion.' % (
                mile['name'], self.name)
        else:
            insertMilestoneQuery = 'insert into milestone (name, due, completed, description) values (%s, %s, %s, %s)'
            insertMilestoneValues = (mile['name'], mile['due'],
                                     mile['completed'], mile['description'])
            res = cursor.execute(insertMilestoneQuery, insertMilestoneValues)
            db.commit()

    def getEnum(self, enum):
        '''Get an enum as a dict. Enum should be a tupe of (name, type)'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        enumCountRes = cursor.execute(
            'select count(*) as count from enum where name = %s and type = %s',
            enum)
        enumCount = enumCountRes.fetchone()[0]
        assert enumCount >= 1, 'Enum %s not found in %s' % (enum, self.name)

        baseQuery = 'select name, type, value from enum where name = %s and type = %s'
        res = cursor.execute(baseQuery, enum)
        return (dict(zip([d[0] for d in res.description], res.fetchone())))

    def addEnum(self, enum):
        '''Add a enum from a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        assert enum['name'] != '', 'No name given'
        enumCountRes = cursor.execute(
            'select count(*) as count from enum where name = %s and type = %s',
            (enum['name'], enum['type']))
        enumCount = enumCountRes.fetchone()[0]
        if enumCount > 0:
            print 'Enum %s found in %s. Skipping the re-insertion.' % (
                enum['name'], self.name)
        else:
            insertEnumQuery = 'insert into enum (name, type, value) values (%s, %s, %s)'
            insertEnumValues = (enum['name'], enum['type'], enum['value'])
            res = cursor.execute(insertEnumQuery, insertEnumValues)
            db.commit()

    def getVersion(self, version):
        '''Get a version as a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        versionCountRes = cursor.execute(
            'select count(*) as count from version where name = %s',
            (version, ))
        versionCount = versionCountRes.fetchone()[0]
        assert versionCount >= 1, 'Version %s not found in %s' % (version,
                                                                  self.name)

        baseQuery = 'select name, time, description from version where name = %s'
        res = cursor.execute(baseQuery, (version, ))
        return (dict(zip([d[0] for d in res.description], res.fetchone())))

    def addVersion(self, version):
        '''Add a version from a dict'''
        db = self._env.get_db_cnx()
        cursor = db.cursor()
        assert version['name'] != '', 'No name given'
        versionCountRes = cursor.execute(
            'select count(*) as count from version where name = %',
            (version['name'], ))
        versionCount = versionCountRes.fetchone()[0]
        if versionCount > 0:
            print 'Version %s found in %s. Skipping the re-insertion.' % (
                version['name'], self.name)
        else:
            insertVersionQuery = 'insert into version (name, time, description) values (%s, %s, %s)'
            insertVersionValues = (version['name'], version['time'],
                                   version['description'])
            res = cursor.execute(insertVersionQuery, insertVersionValues)
            db.commit()

    def getRepository(self):
        '''Get the repository info, particularly the path and type'''
        repository = {}
        repository['type'] = self._env.config.get('trac', 'repository_type')
        repository['dir'] = self._env.config.get('trac', 'repository_dir')
        return repository

    def addRepository(self, repository):
        '''Add a repository from a dict specifying name, type and dir.
		This adds using the multiple repository functionality.'''
        assert repository.has_key('name') and repository.has_key(
            'type') and repository.has_key(
                'dir'), "Repository info not specified"
        self._env.config.set('repositories', '%s.dir' % repository['name'],
                             repository['dir'])
        if repository['type'] == 'svn':
            repotype = 'direct-svnfs'
        else:
            repotype = repository['type']
        self._env.config.set('repositories', '%s.type' % repository['name'],
                             repotype)
        self._env.config.save()
示例#33
0
class Client(object):
    def __init__(self, env_path):
        self.env_path = env_path
        self.env = Environment(env_path)
        self.db_cnx = self.env.get_db_cnx()
        self._registered_users_logins = []

    def get_project_description(self):
        return self.env.project_description

    def get_users(self):
        result = self.env.get_known_users()
        trac_users = list([])
        for user in result:
            user_login = user[0].lower()
            if user_login in self._registered_users_logins:
                continue
            u = TracUser(user_login)
            u.email = user[2]
            trac_users.append(u)
            self._registered_users_logins.append(user_login)
        # if we accept only authorised users, we don't have any more users to return
        # all of them were returned by "get_known_users" method
        if not tracLib.ACCEPT_NON_AUTHORISED_USERS:
            return trac_users
        # here we must to get component owners, issue reporters, owners and attachment authors
        # that are not registered users
        user_fields = [("owner", "component"), ("reporter", "ticket"),
                       ("owner", "ticket"), ("author", "attachment")]
        first = True
        request = ""
        for column_name, table_name in user_fields:
            if first:
                first = False
            else:
                request += "UNION "
            request += "SELECT DISTINCT lower(%s) FROM %s " % (column_name,
                                                               table_name)
        cursor = self.db_cnx.cursor()
        cursor.execute(request)
        for row in cursor:
            if row[0] not in self._registered_users_logins:
                trac_user = self._get_non_authorised_user(row[0])
                if trac_user is not None:
                    trac_users.append(trac_user)
                    self._registered_users_logins.append(trac_user.name)
        return trac_users

    def _get_non_authorised_user(self, user_name):
        if user_name is None:
            return None
        # non authorized users in trac are stored like this "name <email_address>"
        start = user_name.find("<")
        end = user_name.rfind(">")
        # we don't accept users who didn't leave the email
        if (start > -1) and (end > start + 1):
            if user_name.find("@", start, end) > 0:
                user = TracUser(user_name[start + 1:end].replace(" ", "_"))
                user.email = user_name[start + 1:end].replace(" ", "_")
                return user
        return None

    def _get_user_login(self, user_name):
        if user_name is None:
            return None
        if user_name in self._registered_users_logins:
            return user_name
        if not tracLib.ACCEPT_NON_AUTHORISED_USERS:
            return None
        user = self._get_non_authorised_user(user_name)
        if (user is None) or (user.name not in self._registered_users_logins):
            return None
        return user.name

    def get_severities(self):
        return self._get_data_from_enum("severity")

    def get_issue_types(self):
        return self._get_data_from_enum("ticket_type")

    def get_issue_priorities(self):
        return self._get_data_from_enum("priority")

    def get_issue_resolutions(self):
        return [
            TracResolution(name)
            for name in self._get_data_from_enum("resolution")
        ]

    def get_components(self):
        cursor = self.db_cnx.cursor()
        cursor.execute("SELECT name, owner, description FROM component")
        trac_components = list([])
        for row in cursor:
            component = TracComponent(row[0])
            component.owner = self._get_user_login(component.owner)
            if row[2] is not None:
                component.description = row[2]
            trac_components.append(component)
        return trac_components

    def get_versions(self):
        cursor = self.db_cnx.cursor()
        cursor.execute("SELECT name, time, description FROM version")
        trac_versions = list([])
        for row in cursor:
            version = TracVersion(row[0])
            if row[1]:
                version.time = self.to_unix_time(row[1])
            if row[2] is not None:
                version.description = row[2]
            trac_versions.append(version)
        return trac_versions

    def get_issues(self):
        cursor = self.db_cnx.cursor()
        cursor.execute(
            "SELECT id, type, time, changetime, component, severity, priority, owner, reporter,"
            "cc, version, status, resolution, summary, description, keywords FROM ticket"
        )
        trac_issues = list([])
        for row in cursor:
            issue = TracIssue(row[0])
            issue.time = self.to_unix_time(row[2])
            issue.changetime = self.to_unix_time(row[3])
            issue.reporter = self._get_user_login(row[8])
            if row[9] is not None:
                cc = row[9].split(",")
                for c in cc:
                    if len(c) > 0:
                        cc_name = self._get_user_login(c.strip())
                        if cc_name is not None:
                            issue.cc.add(cc_name)
            issue.summary = row[13]
            issue.description = row[14]
            issue.custom_fields["Type"] = row[1]
            issue.custom_fields["Component"] = row[4]
            issue.custom_fields["Severity"] = row[5]
            issue.custom_fields["Priority"] = row[6]
            issue.custom_fields["Owner"] = self._get_user_login(row[7])
            issue.custom_fields["Version"] = row[10]
            issue.custom_fields["Status"] = row[11]
            issue.custom_fields["Resolution"] = row[12]
            if row[15] is not None:
                keywords = row[15].rsplit(",")
                for kw in keywords:
                    if len(kw) > 0:
                        issue.keywords.add(kw.strip())
            #getting custom fields from ticket_custom table
            custom_field_cursor = self.db_cnx.cursor()
            custom_field_cursor.execute(
                "SELECT name, value FROM ticket_custom WHERE ticket=%s",
                (str(row[0]), ))
            for cf in custom_field_cursor:
                issue.custom_fields[cf[0].capitalize()] = cf[1]
            # getting attachments from attachment table
            attachment_cursor = self.db_cnx.cursor()
            attachment_cursor.execute(
                "SELECT filename, size, time, description, author FROM attachment WHERE "
                "type = %s AND id = %s", ("ticket", str(issue.id)))
            #path = self.env_path + "/attachments/ticket/" + str(issue.id) + "/"
            for elem in attachment_cursor:
                #at = TracAttachment(path + elem[0])
                at = TracAttachment(
                    Attachment._get_path(self.env.path, 'ticket',
                                         str(issue.id), elem[0]))
                at.name = elem[0]
                at.size = elem[1]
                at.time = self.to_unix_time(elem[2])
                at.description = elem[3]
                at.author_name = elem[4]
                issue.attachment.add(at)
            trac_issues.append(issue)
            #getting comments
            change_cursor = self.db_cnx.cursor()
            change_cursor.execute(
                "SELECT time, author, newvalue, oldvalue FROM ticket_change WHERE ticket = %s AND field = %s ORDER BY time DESC",
                (
                    str(row[0]),
                    "comment",
                ))
            for elem in change_cursor:
                if (elem[2] is None) or (not len(elem[2].lstrip())):
                    continue
                comment = TracComment(self.to_unix_time(elem[0]))
                comment.author = str(elem[1])
                comment.content = unicode(elem[2])
                comment.id = elem[3]
                issue.comments.add(comment)
        return trac_issues

    def get_custom_fields_declared(self):
        ini_file_path = self.env_path + "/conf/trac.ini"
        parser = ConfigParser()
        parser.read(ini_file_path)
        if not ("ticket-custom" in parser.sections()):
            return set([])
        result = parser.items("ticket-custom")
        items = dict([])
        for elem in result:
            items[elem[0]] = elem[1]

        keys = items.keys()
        custom_fields = list([])
        for k in keys:
            if not ("." in k):
                field = TracCustomFieldDeclaration(k.capitalize())
                field.type = items[k]
                options_key = k + ".options"
                if options_key in items:
                    opts_str = items[options_key]
                    opts = opts_str.rsplit("|")
                    for o in opts:
                        field.options.append(o)
                value_key = k + ".value"
                if value_key in items:
                    field.value = items[value_key]
                label_key = k + ".label"
                if label_key in items:
                    field.label = items[label_key]
                custom_fields.append(field)

        return custom_fields

    def _get_data_from_enum(self, type_name):
        cursor = self.db_cnx.cursor()
        cursor.execute("SELECT name, value FROM enum WHERE type=%s",
                       (type_name, ))
        return [row[0] for row in cursor]

    def to_unix_time(self, time):
        return time / 1000
示例#34
0
class TracDatabase(object):
    def __init__(self, project_name, path, db, host, user, password, append):
        self.env = Environment(path)
        self._append = append

        self._tracdb = self.env.get_db_cnx()
        self._tracdb.autocommit = False
        self._trac_cursor = self._tracdb.cursor()
        self._mantis_con = MySQLdb.connect(
            host=host,
            user=user,
            passwd=password,
            db=db,
            compress=1,
            cursorclass=MySQLdb.cursors.DictCursor,
            use_unicode=1)
        self._mantis_cursor = self._mantis_con.cursor()

        sql = "SELECT id FROM mantis_project_table WHERE name = %s" % (
            project_name)
        print sql
        self.mantisCursor().execute(
            "SELECT id FROM mantis_project_table WHERE name = %s",
            (project_name))
        result = self.mantisCursor().fetchall()
        if len(result) > 1:
            raise Exception("Ambiguous project name %s" % project_name)
        elif len(result) == 0:
            sql = """INSERT INTO mantis_project_table (name) VALUES (%s)""" % (
                project_name)
            print sql
            self.mantisCursor().execute(
                """INSERT INTO mantis_project_table (name) VALUES (%s)""",
                (project_name))
            self.mantisCommit()
            self._project_id = int(self.mantisCursor().lastrowid)
        else:
            self._project_id = int(result[0]['id'])

        self._bug_map = {}
        self._user_map = {}
        self._category_map = {}

    def projectId(self):
        return self._project_id

    def tracCursor(self):
        return self._trac_cursor

    def tracCommit(self):
        self._tracdb.commit()

    def mantisCursor(self):
        return self._mantis_cursor

    def mantisCommit(self):
        self._mantis_con.commit()

    def hasTickets(self):
        c = self.mantisCursor()
        c.execute('''SELECT count(*) FROM mantis_bug_table WHERE 1''')
        return int(c.fetchall()[0]['count(*)']) > 0

    def clean(self, tablename):
        print 'TRUNCATE %s' % tablename
        self.mantisCursor().execute('TRUNCATE %s' % tablename)
        self.mantisCommit()

    def assertNoTickets(self):
        if not self._append and self.hasTickets():
            raise Exception("Will not modify database with existing tickets!")
            return

    # generate a random character string of given length
    def generateCookie(self, length):
        password = ''
        for i in range(int(length)):
            password += random.choice("abcdefghijklmnopqrstuvwxyz0123456789")
        return password

    # generate a random character string of given length
    def generatePassword(self, length):
        password = ''
        for i in range(int(length)):
            password += chr(random.randint(33, 126))
        return password

    def newBugId(self, tracId, mantisId):
        self._bug_map[tracId] = mantisId

    def bugId(self, tracId):
        return self._bug_map[tracId]

    def userId(self, username):
        if username == '' or username is None:
            return 0
        if username not in self._user_map:
            sql = """SELECT id, username FROM mantis_user_table WHERE username = %s""" % (
                username)
            print sql
            self.mantisCursor().execute(
                """SELECT id, username FROM mantis_user_table WHERE username = %s""",
                (username))
            result = self.mantisCursor().fetchall()
            print result
            if result:
                self._user_map[username] = int(result[0]['id'])
            else:
                result = ((1))
                while result:
                    cookie = self.generateCookie(64)
                    print cookie
                    self.mantisCursor().execute(
                        """SELECT cookie_string FROM mantis_user_table WHERE cookie_string = %s""",
                        (cookie))
                    result = self.mantisCursor().fetchall()

                sql = """INSERT INTO mantis_user_table (username, realname, email, password, cookie_string) VALUES (%s, %s, %s, Md5(%s), %s) """ % (
                    username, NN_NAME, NN_EMAIL, self.generatePassword(16),
                    cookie)
                print sql
                self.mantisCursor().execute(
                    """INSERT INTO mantis_user_table (username, realname, email, password, cookie_string) VALUES (%s, %s, %s, MD5(%s), %s) """,
                    (username, NN_NAME, NN_EMAIL, str(
                        self.generatePassword(16)), str(cookie)))
                self.mantisCommit()
                self._user_map[username] = int(self.mantisCursor().lastrowid)

        return self._user_map[username]

    def categoryId(self, category):
        if category not in self._category_map:
            sql = """SELECT id FROM mantis_category_table WHERE name = %s AND project_id = '%d'""" % (
                category, int(self.projectId()))
            print sql
            self.mantisCursor().execute(
                """SELECT id FROM mantis_category_table WHERE name = %s AND project_id = %s""",
                (category, self.projectId()))
            result = self.mantisCursor().fetchall()
            if result:
                self._category_map[category] = result[0]['id']
            else:
                sql = """INSERT INTO mantis_category_table 
                  (project_id, name) VALUES (%s, %s) """ % (self.projectId(),
                                                            category)
                print sql
                self.mantisCursor().execute(
                    """INSERT INTO mantis_category_table 
                  (project_id, name) VALUES (%s, %s) """,
                    (self.projectId(), category))
                self.mantisCommit()
                self._category_map[category] = self.mantisCursor().lastrowid

        return self._category_map[category]

    def convertMantisTime(self, time2):
        time2 = datetime.fromtimestamp(time2)
        return long(str(int(time.mktime(time2.timetuple()))) + '000000')

    def convertTracTime(self, time2):
        time2 = time2 / 1000000
        return time2
示例#35
0
 def update_tracenv_userdata(self, req, path, userdata):
     """Update the userdata in the specified environment using the records passed
 by userdata.
 @param path     : path to the trac environment to update
 @param userdata : collection of userdata as returned from merge()
 @return success : boolean
 @return msg     : details
 """
     sql = []
     exists = ''
     msg = ''
     envpath, tracenv = os.path.split(path)
     self.env.log.debug('Updating userdata in environment %s' % (path, ))
     dryrun = self.env.config.getbool('user_sync', 'dryrun', True)
     if not dryrun:
         self.env.log.debug('HOT!!! We are NOT in dryrun mode!')
     else:
         self.env.log.debug('TESTING - we ARE in dryrun mode.')
     try:
         env = Environment(path)
     except IOError:
         self.env.log.debug('Could not initialize environment at %s' %
                            (path, ))
         return False, 'Could not initialize environment at %s' % (path, )
     perm = PermissionSystem(env)
     if not 'TRAC_ADMIN' in perm.get_user_permissions(req.perm.username):
         raise PermissionError
     db = env.get_db_cnx()
     cursor = db.cursor()
     if not dryrun:
         self.env.log.debug('Updating database for %s' % (tracenv, ))
     for user in userdata:
         authenticated = userdata[user]['authenticated'] or 0
         for att in userdata[user]:
             if att in ['path', 'authenticated', 'last_visit']: continue
             cursor.execute(
                 "SELECT value FROM session_attribute WHERE sid='%s' AND name='%s' AND authenticated=%s"
                 % (
                     user,
                     att,
                     authenticated,
                 ))
             for row in cursor:
                 exists = row[0]
             if exists:
                 if exists == userdata[user][att]: continue
                 if not dryrun:
                     cursor.execute(
                         "UPDATE session_attribute SET value='%s' WHERE sid='%s' AND name='%s' AND authenticated=%s;\n"
                         % (
                             userdata[user][att],
                             user,
                             att,
                             authenticated,
                         ))
                 sql.append(
                     "UPDATE session_attribute SET value='%s' WHERE sid='%s' AND name='%s' AND authenticated=%s;\n"
                     % (
                         userdata[user][att],
                         user,
                         att,
                         authenticated,
                     ))
             else:
                 if not dryrun:
                     cursor.execute(
                         "INSERT INTO session_attribute (sid,authenticated,name,value) VALUES('%s',%s,'%s','%s');\n"
                         % (user, authenticated, att, userdata[user][att]))
                 sql.append(
                     "INSERT INTO session_attribute (sid,authenticated,name,att) VALUES('%s',%s,'%s','%s');\n"
                     % (user, authenticated, att, userdata[user][att]))
     if len(sql):
         if not dryrun: db.commit()
         sql_file_path = self.env.config.get(
             'user_sync', 'sql_file_path') or os.path.join(
                 self.env.path, 'log')
         if sql_file_path.lower() == 'none':
             self.env.log.debug(
                 'SQLFile disabled (sql_file_path is "none")')
         else:
             sqlfile = '%s.sql' % (tracenv, )
             sqlfile = os.path.join(sql_file_path, sqlfile)
             try:
                 if os.path.exists(sqlfile): os.unlink(sqlfile)
                 self.env.log.debug('Writing SQL to %s' % (sqlfile, ))
                 f = open(sqlfile, 'a')
                 f.write('--- SQL for Trac environment %s\n' % (tracenv, ))
                 f.writelines(sql)
                 f.close()
             except IOError:
                 self.env.log.debug('Could not write SQL file %s!' %
                                    (sqlfile, ))
                 return False, 'Could not write SQL file %s!' % (sqlfile, )
             except ValueError:
                 self.env.log.debug('No value for sqlfile?')
             if dryrun:
                 msg = 'Wrote SQL for Trac environment %s to %s' % (
                     tracenv,
                     sqlfile,
                 )
             else:
                 msg = 'Updated userdata in environment %s. SQL was additionally written to %s' % (
                     tracenv,
                     sqlfile,
                 )
     else:
         msg = 'No updates for Trac environment %s' % (tracenv)
     self.env.log.debug('Done updating userdata in environment %s' %
                        (path, ))
     return True, msg
示例#36
0
from acct_mgr.pwhash import HtPasswdHashMethod, HtDigestHashMethod

env = Environment(sys.argv[1])

store = AccountManager(env).password_store
if isinstance(store, HtPasswdStore):
    env.config.set('account-manager', 'hash_method', 'HtPasswdHashMethod')
    prefix = ''
elif isinstance(store, HtDigestStore):
    env.config.set('account-manager', 'hash_method', 'HtDigestHashMethod')
    prefix = store.realm + ':'
else:
    print >> sys.stderr, 'Unsupported password store:', store.__class__.__name__
    sys.exit(1)

password_file = os.path.join(
    env.path, env.config.get('account-manager', 'password_file'))
hashes = [line.strip().split(':', 1) for line in open(password_file)]
hashes = [(u, p) for u, p in hashes if p.startswith(prefix)]
if hashes:
    db = env.get_db_cnx()
    cursor = db.cursor()
    cursor.executemany(
        "INSERT INTO session_attribute "
        "(sid,authenticated,name,value) "
        "VALUES (%s,1,'password',%s)", hashes)
    db.commit()

env.config.set('account-manager', 'password_store', 'SessionStore')
env.config.save()
示例#37
0
class TracDatabase(object):
    def __init__(self, path):
        self.env = Environment(path)
        self._db = self.env.get_db_cnx()
        self._db.autocommit = False
        self.loginNameCache = {}
        self.fieldNameCache = {}
        from trac.db.api import DatabaseManager
        self.using_postgres = DatabaseManager(
            self.env).connection_uri.startswith("postgres:")

    def db(self):
        return self._db

    def hasTickets(self):
        c = self.db().cursor()
        c.execute("SELECT count(*) FROM ticket")
        return int(c.fetchall()[0][0]) > 0

    def assertNoTickets(self):
        if self.hasTickets():
            raise Exception("Will not modify database with existing tickets!")

    def setSeverityList(self, s):
        """Remove all severities, set them to `s`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("DELETE FROM enum WHERE type='severity'")
        for value, i in s:
            print "  inserting severity '%s' - '%s'" % (value, i)
            c.execute(
                """INSERT INTO enum (type, name, value)
                                   VALUES (%s, %s, %s)""",
                ("severity", value, i))
        self.db().commit()

    def setPriorityList(self, s):
        """Remove all priorities, set them to `s`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("DELETE FROM enum WHERE type='priority'")
        for value, i in s:
            print "  inserting priority '%s' - '%s'" % (value, i)
            c.execute(
                """INSERT INTO enum (type, name, value)
                                   VALUES (%s, %s, %s)""",
                ("priority", value, i))
        self.db().commit()

    def setComponentList(self, l, key):
        """Remove all components, set them to `l`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("DELETE FROM component")
        for comp in l:
            print "  inserting component '%s', owner '%s'" % \
                            (comp[key], comp['owner'])
            c.execute("INSERT INTO component (name, owner) VALUES (%s, %s)",
                      (comp[key], comp['owner']))
        self.db().commit()

    def setVersionList(self, v, key):
        """Remove all versions, set them to `v`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("DELETE FROM version")
        for vers in v:
            print "  inserting version '%s'" % (vers[key])
            c.execute("INSERT INTO version (name) VALUES (%s)", (vers[key], ))
        self.db().commit()

    def setMilestoneList(self, m, key):
        """Remove all milestones, set them to `m`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("DELETE FROM milestone")
        for ms in m:
            milestone = ms[key]
            print "  inserting milestone '%s'" % (milestone)
            c.execute("INSERT INTO milestone (name) VALUES (%s)",
                      (milestone, ))
        self.db().commit()

    def addTicket(self, id, time, changetime, component, severity, priority,
                  owner, reporter, cc, version, milestone, status, resolution,
                  summary, description, keywords, customfields):
        c = self.db().cursor()

        desc = description
        type = "defect"

        if SEVERITIES:
            if severity.lower() == "enhancement":
                severity = "minor"
                type = "enhancement"

        else:
            if priority.lower() == "enhancement":
                priority = "minor"
                type = "enhancement"

        if PREFORMAT_COMMENTS:
            desc = '{{{\n%s\n}}}' % desc

        if REPLACE_BUG_NO:
            if BUG_NO_RE.search(desc):
                desc = re.sub(BUG_NO_RE, BUG_NO_REPL, desc)

        if PRIORITIES_MAP.has_key(priority):
            priority = PRIORITIES_MAP[priority]

        print "  inserting ticket %s -- %s" % (id, summary)

        c.execute(
            """INSERT INTO ticket (id, type, time, changetime, component,
                                         severity, priority, owner, reporter,
                                         cc, version, milestone, status,
                                         resolution, summary, description,
                                         keywords)
                                 VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s,
                                         %s, %s, %s, %s, %s, %s, %s, %s)""",
            (id, type, datetime2epoch(time), datetime2epoch(changetime),
             component, severity, priority, owner, reporter, cc, version,
             milestone, status.lower(), resolution, summary, desc, keywords))

        self.db().commit()
        if self.using_postgres:
            c.execute("""SELECT SETVAL('ticket_id_seq', MAX(id)) FROM ticket;
              SELECT SETVAL('report_id_seq', MAX(id)) FROM report""")
        ticket_id = self.db().get_last_id(c, 'ticket')

        # add all custom fields to ticket
        for name, value in customfields.iteritems():
            self.addTicketCustomField(ticket_id, name, value)

        return ticket_id

    def addTicketCustomField(self, ticket_id, field_name, field_value):
        c = self.db().cursor()

        if field_value == None:
            return

        c.execute(
            """INSERT INTO ticket_custom (ticket, name, value)
                                 VALUES (%s, %s, %s)""",
            (ticket_id, field_name, field_value))

        self.db().commit()

    def addTicketComment(self, ticket, time, author, value):
        comment = value

        if PREFORMAT_COMMENTS:
            comment = '{{{\n%s\n}}}' % comment

        if REPLACE_BUG_NO:
            if BUG_NO_RE.search(comment):
                comment = re.sub(BUG_NO_RE, BUG_NO_REPL, comment)

        c = self.db().cursor()
        c.execute(
            """INSERT INTO ticket_change (ticket, time, author, field,
                                                oldvalue, newvalue)
                                        VALUES (%s, %s, %s, %s, %s, %s)""",
            (ticket, datetime2epoch(time), author, 'comment', '', comment))
        self.db().commit()

    def addTicketChange(self, ticket, time, author, field, oldvalue, newvalue):
        c = self.db().cursor()

        if field == "owner":
            if LOGIN_MAP.has_key(oldvalue):
                oldvalue = LOGIN_MAP[oldvalue]
            if LOGIN_MAP.has_key(newvalue):
                newvalue = LOGIN_MAP[newvalue]

        if field == "priority":
            if PRIORITIES_MAP.has_key(oldvalue.lower()):
                oldvalue = PRIORITIES_MAP[oldvalue.lower()]
            if PRIORITIES_MAP.has_key(newvalue.lower()):
                newvalue = PRIORITIES_MAP[newvalue.lower()]

        # Doesn't make sense if we go from highest -> highest, for example.
        if oldvalue == newvalue:
            return

        c.execute(
            """INSERT INTO ticket_change (ticket, time, author, field,
                                                oldvalue, newvalue)
                                        VALUES (%s, %s, %s, %s, %s, %s)""",
            (ticket, datetime2epoch(time), author, field, oldvalue, newvalue))
        self.db().commit()

    def addAttachment(self, author, a):
        if a['filename'] != '':
            description = a['description']
            id = a['bug_id']
            filename = a['filename']
            filedata = StringIO.StringIO(a['thedata'])
            filesize = len(filedata.getvalue())
            time = a['creation_ts']
            print "    ->inserting attachment '%s' for ticket %s -- %s" % \
                    (filename, id, description)
            attachment = Attachment(self.env, 'ticket', id)
            attachment.author = author
            attachment.description = description
            attachment.insert(filename, filedata, filesize,
                              datetime2epoch(time))
            del attachment

    def getLoginName(self, cursor, userid):
        if userid not in self.loginNameCache:
            cursor.execute("SELECT * FROM profiles WHERE userid = %s",
                           (userid))
            loginName = cursor.fetchall()

            if loginName:
                loginName = loginName[0]['login_name']
            else:
                print """WARNING: unknown bugzilla userid %d, recording as
                         anonymous""" % (userid)
                loginName = "anonymous"

            loginName = LOGIN_MAP.get(loginName, loginName)

            self.loginNameCache[userid] = loginName

        return self.loginNameCache[userid]

    def getFieldName(self, cursor, fieldid):
        if fieldid not in self.fieldNameCache:
            # fielddefs.fieldid got changed to fielddefs.id in Bugzilla
            # 2.23.3.
            if BZ_VERSION >= 2233:
                cursor.execute("SELECT * FROM fielddefs WHERE id = %s",
                               (fieldid))
            else:
                cursor.execute("SELECT * FROM fielddefs WHERE fieldid = %s",
                               (fieldid))
            fieldName = cursor.fetchall()

            if fieldName:
                fieldName = fieldName[0]['name'].lower()
            else:
                print "WARNING: unknown bugzilla fieldid %d, \
                                recording as unknown" % (userid)
                fieldName = "unknown"

            self.fieldNameCache[fieldid] = fieldName

        return self.fieldNameCache[fieldid]
示例#38
0
def emailer(req, fromPage,name, fromAddr, toAddr, subject, msg,jsoncallback):
	"""Perform sanity/security checks, look up usernames from trac and send message as [email protected].
req = CGI
name = Friendly
from = email address	
"""
	res = {}
	# bar access to everyone but this server
	#req.add_common_vars()
	#env_vars = req.subprocess_env.copy()
	#env_vars['']	
	config = loadConfig(req)
	text = msg.replace('%0A','\n')
	html = msg.replace('%0A','<br />')
	config['from'] = fromAddr
	config['name'] = name
	config['subject'] = subject
	list = []
	addresses = toAddr.split(',')
	for name in addresses:
		if not validateEmail(name):
			# look up DB
			env = Environment(config['tracRendersEnv'])
			db = env.get_db_cnx()
			cursor = db.cursor()
			sql = "SELECT value from session_attribute where sid = '%s' and name = 'email'" % name
			cursor.execute(sql)
			db.commit()
			for row in cursor:
				list.append(row[0])
		else:
			list.append(name)
	config['smtpserver'] = smtplib.SMTP(config['smtpserver'])
#	config['smtpserver'] = smtplib.SMTP('outbound.mailhop.org')
	config['smtpserver'].set_debuglevel(1)
#	config['smtpserver'].login('modfilms','f@milyman')
	
	toAddrFiltered = ','.join(list)	
	textMsg = """
This was sent from http://%s

%s says "%s"

Powered by http://modfilms.net | Contact us at [email protected]
""" % (config['httpServer'] + fromPage, config['name'], text)
	htmlMsg = """
<html>
<head>
<link rel="stylesheet" href="http://modfilms.com/js/themes/flora/flora.all.css" type="text/css" media="screen" title="Flora (Default)" />
<link rel="stylesheet" href="http://modfilms.com/js/demos/css/style.css" type="text/css" />
</head>
<body>
<p>This was sent from <a href="%s">http://%s</a></p>
<p>%s says: </p>
<p><i>"%s"</i></p>
<p>Email <a href="mailto:[email protected]">[email protected]</a> if you need assistance</p>
<p><a href="http://modfilms.net"><img border="0" src="http://modfilms.com/images/poweredby.gif" alt="Powered by the MOD Films network"></p>
</body>
</html>
""" % (config['httpServer'] + fromPage,config['httpServer'] + fromPage,config['name'], html)
	
#	theMsg = createhtmlmail(htmlMsg, textMsg, subject)
	theMsg = createtextmail(textMsg,subject)
	SENDER = config['from']
	RECIPIENT = toAddrFiltered
	headers = "From: %s\r\nTo: %s\r\n" % (SENDER, RECIPIENT)
	message = headers + theMsg
	try:
		smtpresult = config['smtpserver'].sendmail(SENDER, RECIPIENT, message)
		if smtpresult:
			errstr = ""
			for recip in smtpresult.keys():
				errstr = """Could not delivery mail to: %s

		Server said: %s
		%s

		%s""" % (recip, smtpresult[recip][0], smtpresult[recip][1], errstr)
			raise smtplib.SMTPException, errstr
		config['smtpserver'].quit()
		res['err'] = 'Email sent'
		res['good'] = True
	except smtplib.SMTPRecipientsRefused, recipients:
		res['err'] = 'Message not sent. Check the email addresses or studio usernames are valid.'
		res['good'] = False
示例#39
0
class BuildDeleter(object):
    """Class for deleting a build."""
    def __init__(self, env_path):
        self.env = Environment(env_path)
        self.logs_dir = self.env.config.get('bitten', 'logs_dir', 'log/bitten')

    def _log_files(self, cursor, build):
        """Return a list of log files."""
        cursor.execute("SELECT filename FROM bitten_log WHERE build=%s",
                       (build, ))
        rows = cursor.fetchall()

        all_files = []
        for row in rows:
            filename = row[0]
            file_prefix = os.path.join(self.logs_dir, filename)
            for suffix in ['', '.level', '.levels']:
                log_file = file_prefix + suffix
                if os.path.isfile(log_file):
                    all_files.append(log_file)

        return all_files

    def discover(self, build):
        """Print a summary of what is linked to the build."""
        print "Items to delete for build %r" % (build, )
        print "-------------------------------"

        db = self.env.get_db_cnx()
        cursor = db.cursor()

        print "Attachments for build resource:"
        cursor.execute("SELECT config FROM bitten_build WHERE id=%s",
                       (build, ))
        config = cursor.fetchone()[0]
        print "  %s/%s" % (config, build)

        print "Log files:"
        print " ", "\n  ".join(self._log_files(cursor, build))

        print "Rows from bitten_log with ids:"
        cursor.execute("SELECT id FROM bitten_log WHERE build=%s", (build, ))
        print " ", "\n  ".join(str(row[0]) for row in cursor.fetchall())

        print "Rows from bitten_report with ids:"
        cursor.execute("SELECT id FROM bitten_report WHERE build=%s",
                       (build, ))
        print " ", "\n  ".join(str(row[0]) for row in cursor.fetchall())
        print "Rows from bitten_report_item with report set to these ids will"
        print "also be deleted."

        print "Rows from bitten_step for this build with names:"
        cursor.execute("SELECT name FROM bitten_step WHERE build=%s",
                       (build, ))
        print " ", "\n  ".join(str(row[0]) for row in cursor.fetchall())

        print "Row from bitten_build with id:"
        cursor.execute("SELECT id FROM bitten_build WHERE id=%s", (build, ))
        print " ", "\n  ".join(str(row[0]) for row in cursor.fetchall())

    def remove(self, build):
        """Delete what is linked to the build."""
        print "Deleting items for build %r" % (build, )

        db = self.env.get_db_cnx()
        cursor = db.cursor()

        print "Determining associated config."
        cursor.execute("SELECT config FROM bitten_build WHERE id=%s",
                       (build, ))
        config = cursor.fetchone()[0]

        print "Collecting log files."
        filenames = self._log_files(cursor, build)

        try:
            print "Deleting bitten_log entries."
            cursor.execute("DELETE FROM bitten_log WHERE build=%s", (build, ))

            print "Deleting bitten_report_item_entries."
            cursor.execute(
                "DELETE FROM bitten_report_item WHERE report IN ("
                "SELECT bitten_report.id FROM bitten_report "
                "WHERE bitten_report.build=%s"
                ")", (build, ))

            print "Deleting bitten_report entires."
            cursor.execute("DELETE FROM bitten_report WHERE build=%s",
                           (build, ))

            print "Deleting bitten_step entries."
            cursor.execute("DELETE FROM bitten_step WHERE build=%s", (build, ))

            print "Delete bitten_build entry."
            cursor.execute("DELETE FROM bitten_build WHERE id=%s", (build, ))
        except:
            db.rollback()
            print "Build deletion failed. Database rolled back."
            raise

        print "Bitten database changes committed."
        db.commit()

        print "Removing log files."
        for filename in filenames:
            os.remove(filename)

        print "Removing attachments."
        resource = Resource('build', '%s/%s' % (config, build))
        Attachment.delete_all(self.env, 'build', resource.id, db)
示例#40
0
class TracDatabase(object):
    def __init__(self, project_name, path, db, host, user, password, append):
        self.env = Environment(path)
        self._append = append

        self._tracdb = self.env.get_db_cnx()
        self._tracdb.autocommit = False
        self._trac_cursor = self._tracdb.cursor()
        self._mantis_con = MySQLdb.connect(host=host, 
                user=user, passwd=password, db=db, compress=1, 
                cursorclass=MySQLdb.cursors.DictCursor, use_unicode=1)
        self._mantis_cursor = self._mantis_con.cursor()

        sql = "SELECT id FROM mantis_project_table WHERE name = %s" % (project_name)
        print sql
        self.mantisCursor().execute("SELECT id FROM mantis_project_table WHERE name = %s", (project_name))
        result = self.mantisCursor().fetchall()
        if len(result) > 1:
            raise Exception("Ambiguous project name %s" % project_name)
        elif len(result) == 0:
            sql = """INSERT INTO mantis_project_table (name) VALUES (%s)""" % (project_name)
            print sql
            self.mantisCursor().execute("""INSERT INTO mantis_project_table (name) VALUES (%s)""" , (project_name))
            self.mantisCommit()
            self._project_id = int(self.mantisCursor().lastrowid)
        else:
            self._project_id = int(result[0]['id'])

        self._bug_map = {}
        self._user_map = {}
        self._category_map = {}
        
    def projectId(self):
        return self._project_id

    def tracCursor(self):
        return self._trac_cursor

    def tracCommit(self):
        self._tracdb.commit()

    def mantisCursor(self):
        return self._mantis_cursor

    def mantisCommit(self):
        self._mantis_con.commit()
    
    def hasTickets(self):
        c = self.mantisCursor()
        c.execute('''SELECT count(*) FROM mantis_bug_table WHERE 1''')
        return int(c.fetchall()[0]['count(*)']) > 0

    def clean(self, tablename):
        print 'TRUNCATE %s' % tablename
        self.mantisCursor().execute('TRUNCATE %s' % tablename)
        self.mantisCommit()

    def assertNoTickets(self):
        if not self._append and self.hasTickets():
          raise Exception("Will not modify database with existing tickets!")
          return

    # generate a random character string of given length
    def generateCookie(self, length):
        password = ''
        for i in range(int(length)):
            password += random.choice("abcdefghijklmnopqrstuvwxyz0123456789")
        return password

    # generate a random character string of given length
    def generatePassword(self, length):
        password = ''
        for i in range(int(length)):
            password += chr(random.randint(33,126))
        return password

    def newBugId(self, tracId, mantisId):
        self._bug_map[tracId] = mantisId

    def bugId(self, tracId):
        return self._bug_map[tracId]

    def userId(self, username):
        if username == '' or username is None:
            return 0
        if username not in self._user_map:
            sql = """SELECT id, username FROM mantis_user_table WHERE username = %s""" % (username)
            print sql
            self.mantisCursor().execute("""SELECT id, username FROM mantis_user_table WHERE username = %s""" , (username))
            result = self.mantisCursor().fetchall()
            print result
            if result:
                self._user_map[username] = int(result[0]['id'])
            else:
                result = ((1))
                while result:
                    cookie = self.generateCookie(64)
                    print cookie
                    self.mantisCursor().execute("""SELECT cookie_string FROM mantis_user_table WHERE cookie_string = %s""" , (cookie))
                    result = self.mantisCursor().fetchall()

                sql = """INSERT INTO mantis_user_table (username, realname, email, password, cookie_string) VALUES (%s, %s, %s, Md5(%s), %s) """ % (username, NN_NAME, NN_EMAIL, self.generatePassword(16), cookie)
                print sql
                self.mantisCursor().execute("""INSERT INTO mantis_user_table (username, realname, email, password, cookie_string) VALUES (%s, %s, %s, MD5(%s), %s) """ , (username, NN_NAME, NN_EMAIL, str(self.generatePassword(16)), str(cookie)))
                self.mantisCommit()
                self._user_map[username] = int(self.mantisCursor().lastrowid)

        return self._user_map[username]
        
    def categoryId(self, category):
        if category not in self._category_map:
            sql = """SELECT id FROM mantis_category_table WHERE name = %s AND project_id = '%d'""" % (category, int(self.projectId()))
            print sql
            self.mantisCursor().execute("""SELECT id FROM mantis_category_table WHERE name = %s AND project_id = %s""" , (category, self.projectId()))
            result = self.mantisCursor().fetchall()
            if result:
                self._category_map[category] = result[0]['id']
            else:
                sql = """INSERT INTO mantis_category_table 
                  (project_id, name) VALUES (%s, %s) """ % (self.projectId(), category)
                print sql
                self.mantisCursor().execute("""INSERT INTO mantis_category_table 
                  (project_id, name) VALUES (%s, %s) """ , (self.projectId(), category))
                self.mantisCommit()
                self._category_map[category] = self.mantisCursor().lastrowid

        return self._category_map[category]
        
    def convertMantisTime(self,time2):
	time2 = datetime.fromtimestamp(time2)
	return long(str(int(time.mktime(time2.timetuple()))) + '000000')

    def convertTracTime(self,time2):
	time2 = time2 / 1000000
	return time2
示例#41
0
def add_trac_to_project(application,
        smtp_enabled=True,
        privatecomments=True,
        sensitivetickets=True,
        batchmod=True,
        autocompleteusers=True,
        customfieldadmin=True,
        qafields=True,
        privatetickets=False,
        tracwysiwyg=True,
        attachment_max_size=10485760,
        milestones=[],
        tickets=[],
        project_name=u'',
        ):

    from penelope.core.models.dashboard import Project

    project = DBSession.query(Project).get(application.project_id)

    settings = get_current_registry().settings or application.settings
    tracenvs = settings.get('penelope.trac.envs')

    if not os.path.exists(tracenvs):
        # TODO: logging bootstrap
        os.mkdir(tracenvs)

    tracname = None
    idx = ''
    while (not tracname):
        tracname = idnormalizer.normalize("%s%s" % (project.id, idx))
        trac_path = '%s/%s' % (tracenvs, tracname)
        if os.path.exists(trac_path):
            idx = idx and (idx+1) or 1
            tracname = None

    trac_perm = {
        'administrator': ['TRAC_ADMIN', 'EXTRA_TIMEENTRY'],
        'customer': ['TICKET_CREATE', 'TICKET_MODIFY', 'TICKET_VIEW',
            'WIKI_VIEW', 'XML_RPC',
            'CHANGESET_VIEW', 'FILE_VIEW',
            'LOG_VIEW', 'MILESTONE_VIEW',
            'REPORT_VIEW', 'REPORT_SQL_VIEW',
            'ROADMAP_VIEW', 'SEARCH_VIEW', 'TIMELINE_VIEW'],
        'developer': ['TICKET_CREATE', 'TICKET_MODIFY', 'TICKET_VIEW',
            'WIKI_VIEW', 'XML_RPC',
            'WIKI_CREATE', 'WIKI_MODIFY',
            'CHANGESET_VIEW', 'FILE_VIEW',
            'LOG_VIEW', 'MILESTONE_VIEW',
            'REPORT_VIEW', 'REPORT_SQL_VIEW',
            'ROADMAP_VIEW', 'SEARCH_VIEW',
            'TIMELINE_VIEW', 'REPORT_ADMIN'],
        'internal_developer': ['developer', 'TRAC_ADMIN', 'TIME_ENTRY_ADD'],
        'external_developer': ['developer'],
        'project_manager': ['administrator', 'TIME_ENTRY_ADD'],
    }


    pordb = str(DBSession.bind.url)
    run([trac_path, 'initenv "%s" "%s?schema=trac_%s"' % (
         tracname,
         pordb.replace('postgresql://', 'postgres://'),
         tracname)])

    tracenv = Environment(trac_path)

    # REPORTS
    cnx = tracenv.get_db_cnx().cnx
    cursor = cnx.cursor()
    cursor.executemany(\
        "INSERT INTO report (title, description, query) VALUES (%s, %s, %s)",
        get_reports(project_id=project.id))
    cursor.close()
    cnx.commit()

    # remove report 2
    cursor = cnx.cursor()
    cursor.execute("DELETE FROM report where id=2;")
    cursor.close()
    cnx.commit()

    # update reports
    cursor = cnx.cursor()
    cursor.execute("""UPDATE report set query='
        SELECT p.value AS __color__,
            t.id AS ticket, summary, t.type AS type, cr.name AS CR,
            owner, status,
            time AS created,
            changetime AS _changetime, t.description AS _description,
            reporter AS _reporter
        FROM ticket t
        LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority''
        LEFT JOIN ticket_custom tc ON t.id = tc.ticket
        LEFT JOIN public.customer_requests cr ON tc.value = cr.id
        WHERE status <> ''closed''
        AND tc.name = ''customerrequest''
        ORDER BY CAST(p.value AS int), milestone, t.type, time' where id=1;""")
    cursor.execute("""UPDATE report set query='
            SELECT p.value AS __color__,
               ''Milestone ''||milestone AS __group__,
               t.id AS ticket, summary, t.type AS type,
               cr.name AS CR,
               owner, status,
               time AS created,
               changetime AS _changetime, t.description AS _description,
               reporter AS _reporter
            FROM ticket t
            LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority''
            LEFT JOIN ticket_custom tc ON t.id = tc.ticket
            LEFT JOIN public.customer_requests cr ON tc.value = cr.id
            WHERE status <> ''closed''
            AND tc.name = ''customerrequest''
            ORDER BY (milestone IS NULL),milestone, CAST(p.value AS int), t.type, time' where id=3;""")
    cursor.execute("""UPDATE report set query='
            SELECT p.value AS __color__,
               owner AS __group__,
               t.id AS ticket, summary, milestone,  cr.name AS CR, t.type AS type, time AS created,
               changetime AS _changetime, t.description AS _description,
               reporter AS _reporter
            FROM ticket t
            LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority''
            LEFT JOIN ticket_custom tc ON t.id = tc.ticket
            LEFT JOIN public.customer_requests cr ON tc.value = cr.id
            WHERE status = ''accepted''
            AND tc.name = ''customerrequest''
            ORDER BY owner, CAST(p.value AS int), t.type, time'
            where id=4;""")
    cursor.execute("""UPDATE report set query='
            SELECT p.value AS __color__,
               owner AS __group__,
               t.id AS ticket, summary, milestone, t.type AS type, cr.name AS CR, time AS created,
               t.description AS _description_,
               changetime AS _changetime, reporter AS _reporter
            FROM ticket t
            LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority''
            LEFT JOIN ticket_custom tc ON t.id = tc.ticket
            LEFT JOIN public.customer_requests cr ON tc.value = cr.id
            WHERE status = ''accepted''
            AND tc.name = ''customerrequest''
            ORDER BY owner, CAST(p.value AS int), t.type, time'
            where id=5;""")
    cursor.execute("""UPDATE report set query='
            SELECT p.value AS __color__,
            (CASE status WHEN ''accepted'' THEN ''Accepted'' ELSE ''Owned'' END) AS __group__,
                 t.id AS ticket, summary, milestone, cr.name AS CR,
                 t.type AS type, priority, time AS created,
                 changetime AS _changetime, t.description AS _description,
                 reporter AS _reporter
            FROM ticket t
            LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority''
            LEFT JOIN ticket_custom tc ON t.id = tc.ticket
            LEFT JOIN public.customer_requests cr ON tc.value = cr.id
            WHERE t.status <> ''closed'' AND owner = $USER
            AND tc.name = ''customerrequest''
            ORDER BY (status = ''accepted'') DESC, CAST(p.value AS int), milestone, t.type, time'
            where id=7;""")
    cursor.execute("""UPDATE report set query='
            SELECT p.value AS __color__,
           (CASE owner
            WHEN $USER THEN ''My Tickets''
                ELSE ''Active Tickets''
            END) AS __group__,
                t.id AS ticket, summary, milestone, t.type AS type, cr.name AS CR,
                owner, status,
                time AS created,
                changetime AS _changetime, t.description AS _description,
                reporter AS _reporter
            FROM ticket t
            LEFT JOIN enum p ON p.name = t.priority AND p.type = ''priority''
            LEFT JOIN ticket_custom tc ON t.id = tc.ticket
            LEFT JOIN public.customer_requests cr ON tc.value = cr.id
            WHERE status <> ''closed''
            AND tc.name = ''customerrequest''
            ORDER BY (COALESCE(owner, '''') = $USER) DESC, CAST(p.value AS int), milestone, t.type, time'
            where id=8;""")
    cursor.close()
    cnx.commit()

    # remove default trac's milestones, components, versions
    cursor = cnx.cursor()
    cursor.execute("DELETE FROM milestone;")
    cursor.close()
    cnx.commit()

    cursor = cnx.cursor()
    cursor.execute("DELETE FROM component;")
    cursor.close()
    cnx.commit()

    cursor = cnx.cursor()
    cursor.execute("DELETE FROM version;")
    cursor.close()
    cnx.commit()


    # TODO: attualmente il riferimento dal trac al progetto dashboard è il project_id,
    #       considerando un'instalalzzione che condicide lo stesso stack wsgi,
    #       valutare se deve essere una uri (jsnorpc, xmlrpx, ...)
    #       o un dsn che punti al db, o ...
    tracenv.config.set('por-dashboard', 'project-id', application.project_id)

    # custom templates
    templates = settings.get('penelope.trac.templates')
    masterconfig = settings.get('penelope.trac.masterconfig')

    if templates:
        tracenv.config.set('inherit', 'templates_dir', templates)

    # master config
    if masterconfig:
        tracenv.config.set('inherit', 'file', masterconfig)

    # set name and description
    tracenv.config.set('project', 'name', project_name)
    tracenv.config.set('project', 'descr', application.name)

    tracenv.config.set('notification', 'smtp_enabled', smtp_enabled and 'true' or 'false')
    tracenv.config.set('notification', 'always_notify_owner', 'true')
    tracenv.config.set('notification', 'always_notify_reporter', 'true')
    manager_email = project.manager.email or ''
    tracenv.config.set('notification', 'smtp_always_cc', manager_email) # manager should always receiv CC

    tracenv.config.set('attachment', 'max_size', attachment_max_size)

    tracenv.config.set('components', 'penelope.trac.*', 'enabled')
    tracenv.config.set('components', 'themeengine.admin.*', 'enabled')
    tracenv.config.set('components', 'themeengine.api.*', 'enabled')
    tracenv.config.set('components', 'themeengine.web_ui.*', 'enabled')
    tracenv.config.set('components', 'ticketrelations.*', 'enabled')
    tracenv.config.set('components', 'tracopt.perm.config_perm_provider.extrapermissionsprovider', 'enabled')

    # All the custom permission names are converted to uppercase.
    # It is not possible to have lowercase and distinguish them from the standard permissions.
    tracenv.config.set('extra-permissions', 'extra_timeentry', 'TIME_ENTRY_ADD')

    tracenv.config.set('theme','theme', 'por')
    # ticket-custom
    tracenv.config.set('ticket-custom', 'customerrequest', 'select')
    tracenv.config.set('ticket-custom', 'customerrequest.label', 'Customer Request')
    tracenv.config.set('ticket-custom', 'blocking', 'text')
    tracenv.config.set('ticket-custom', 'blocking.label', 'Blocking')
    tracenv.config.set('ticket-custom', 'blockedby', 'text')
    tracenv.config.set('ticket-custom', 'blockedby.label', 'Blocked By')
    # BBB: ii valori di customerrequest vengono caricati ondemand
    tracenv.config.set('ticket-custom', 'customerrequest.options', '')

    # see ticket:80
    if qafields:
        tracenv.config.set('ticket-custom', 'issuetype', 'select')
        tracenv.config.set('ticket-custom', 'issuetype.label', 'Natura del problema')
        tracenv.config.set('ticket-custom', 'issuetype.options', '|'.join([u"",
                                u"sistemistica",
                                u"funzionalità",
                                u"design (grafica, layout...)",
                                u"prestazioni",
                                u"mi aspettavo che..."]))
        tracenv.config.set('ticket-custom', 'esogeno', 'checkbox')
        tracenv.config.set('ticket-custom', 'esogeno.label', 'Ticket aperto dal Cliente')
        tracenv.config.set('ticket-custom', 'esogeno.value', 'false')
        tracenv.config.set('ticket-custom', 'stats_exclude', 'checkbox')
        tracenv.config.set('ticket-custom', 'stats_exclude.label', 'Exclude from report stats')
        tracenv.config.set('ticket-custom', 'stats_exclude.value', 'false')
        tracenv.config.set('ticket-custom', 'fasesviluppo', 'select')
        tracenv.config.set('ticket-custom', 'fasesviluppo.label', 'Fase sviluppo')
        tracenv.config.set('ticket-custom', 'fasesviluppo.options', '|'.join([u"",
                                u"In lavorazione",
                                u"Per lo staging",
                                u"In staging",
                                u"Per la produzione",
                                u"In produzione"]))

    tracenv.config.set('ticket', 'restrict_owner', 'true')

    tracenv.config.set('ticket-custom', 'milestone.invalid_if', '')

    # WORKFLOW
    tracenv.config.set('ticket-workflow', 'accept', 'new,reviewing -> assigned')
    tracenv.config.set('ticket-workflow', 'accept.operations', 'set_owner_to_self')
    tracenv.config.set('ticket-workflow', 'accept.permissions', 'TICKET_MODIFY')
    tracenv.config.set('ticket-workflow', 'leave', '* -> *')
    tracenv.config.set('ticket-workflow', 'leave.default', '1')
    tracenv.config.set('ticket-workflow', 'leave.operations', 'leave_status')
    tracenv.config.set('ticket-workflow', 'reassign', 'new,assigned,accepted,reopened -> assigned')
    tracenv.config.set('ticket-workflow', 'reassign.operations', 'set_owner')
    tracenv.config.set('ticket-workflow', 'reassign.permissions', 'TICKET_MODIFY')
    tracenv.config.set('ticket-workflow', 'reassign_reviewing', 'reviewing -> *')
    tracenv.config.set('ticket-workflow', 'reassign_reviewing.name', 'reassign review')
    tracenv.config.set('ticket-workflow', 'reassign_reviewing.operations', 'set_owner')
    tracenv.config.set('ticket-workflow', 'reassign_reviewing.permissions', 'TICKET_MODIFY')
    tracenv.config.set('ticket-workflow', 'reopen', 'closed -> reopened')
    tracenv.config.set('ticket-workflow', 'reopen.operations', 'del_resolution')
    tracenv.config.set('ticket-workflow', 'reopen.permissions', 'TRAC_ADMIN')
    tracenv.config.set('ticket-workflow', 'resolve', 'new,assigned,reopened,reviewing -> closed')
    tracenv.config.set('ticket-workflow', 'resolve.operations', 'set_resolution')
    tracenv.config.set('ticket-workflow', 'resolve.permissions', 'TICKET_MODIFY')
    tracenv.config.set('ticket-workflow', 'review', 'new,assigned,reopened -> reviewing')
    tracenv.config.set('ticket-workflow', 'review.operations', 'set_owner')
    tracenv.config.set('ticket-workflow', 'review.permissions', 'TICKET_MODIFY')

    tracenv.config.set('milestone-groups', 'closed', 'closed')
    tracenv.config.set('milestone-groups', 'closed.order', '0')
    tracenv.config.set('milestone-groups', 'closed.query_args', 'group=resolution')
    tracenv.config.set('milestone-groups', 'closed.overall_completion', 'true')

    tracenv.config.set('milestone-groups', 'active', '*')
    tracenv.config.set('milestone-groups', 'active.order', '1')
    tracenv.config.set('milestone-groups', 'active.css_class', 'open')

    tracenv.config.set('milestone-groups', 'new', 'new,reopened')
    tracenv.config.set('milestone-groups', 'new.order', '2')


    # navigation
    tracenv.config.set('metanav', 'logout', 'disabled')

    # permissions
    tracenv.config.set('components', 'penelope.trac.users.*', 'enabled')
    tracenv.config.set('trac', 'permission_store', 'PorPermissionStore')
    tracenv.config.set('trac', 'show_email_addresses', 'true')

    # xmlrpc plugin
    tracenv.config.set('components', 'tracrpc.api.xmlrpcsystem', 'enabled')
    tracenv.config.set('components', 'tracrpc.xml_rpc.xmlrpcprotocol', 'enabled')
    tracenv.config.set('components', 'tracrpc.web_ui.rpcweb', 'enabled')
    tracenv.config.set('components', 'tracrpc.ticket.*', 'enabled')

    # DynamicFields Plugin
    tracenv.config.set('components', 'dynfields.rules.*','enabled')
    tracenv.config.set('components', 'dynfields.web_ui.*','enabled')

    # User & Roles (ReadOnly !!!)
    # tracenv.config.set('user_manager', 'user_store', 'PorUserStore')
    # tracenv.config.set('user_manager', 'attribute_provider', 'PorAttributeProvider')

    # BatchModifyPlugin
    if batchmod:
        tracenv.config.set('components', 'batchmod.web_ui.*', 'enabled')

    # Traccustomfieldadmin
    if customfieldadmin:
        tracenv.config.set('components', 'customfieldadmin.*', 'enabled')

    # PrivateCommentsPlugin
    if privatecomments:
        tracenv.config.set('components', 'privatecomments.privatecomments.*', 'enabled')

    # PrivateTicketPlugin
    if privatetickets:
        tracenv.config.set('components', 'privatetickets.policy.*', 'enabled')
        tracenv.config.set('trac', 'permission_policies',
            'PrivateTicketsPolicy, %s' % tracenv.config.get('trac', 'permission_policies'))
        trac_perm['customer'].append('TICKET_VIEW_SELF')

    # SensitiveTicketsPlugin
    if sensitivetickets:
        tracenv.config.set('components', 'sensitivetickets.*', 'enabled')
        tracenv.config.set('trac', 'permission_policies',
            'SensitiveTicketsPolicy, %s' % tracenv.config.get('trac', 'permission_policies'))
        tracenv.config.set('ticket-custom', 'sensitive.show_if_group', 'administrator|developer')
        # utilizzato se il default e' 1, se il default e' 0 non serve
        # tracenv.config.set('ticket-custom', 'sensitive.clear_on_hide', 'false')
        # tracenv.config.set('ticket-custom', 'sensitive.has_permission', 'SENSITIVE_VIEW')
        tracenv.config.set('ticket-custom', 'sensitive.value', '0')
        trac_perm['developer'].append('SENSITIVE_VIEW')

    # tracwysiwyg
    if tracwysiwyg:
        tracenv.config.set('components', 'tracwysiwyg.wysiwygmodule', 'enabled')

    # AutoCompleteUsers
    if autocompleteusers:
        tracenv.config.set('components', 'autocompleteusers.autocompleteusers', 'enabled')

    tracenv.config.set('wiki', 'max_size', 1048576)

    tracenv.config.set('logging', 'log_file', 'trac.log')
    tracenv.config.set('logging', 'log_level', 'INFO')
    tracenv.config.set('logging', 'log_type', 'file')

    tracenv.config.save()

    # let's remove notification config - it is set by the global config
    tracenv.config.remove('notification', 'smtp_from')
    tracenv.config.remove('notification', 'smtp_from_name')
    tracenv.config.remove('notification', 'replyto')
    tracenv.config.remove('notification', 'smtp_replyto')
    tracenv.config.remove('notification', 'email_sender')
    tracenv.config.remove('notification', 'smtp_enabled')
    tracenv.config.remove('notification', 'smtp_host')
    tracenv.config.remove('notification', 'smtp_port')
    tracenv.config.remove('notification', 'smtp_password')
    tracenv.config.remove('notification', 'smtp_username')

    tracenv.config.remove('trac', 'repository_sync_per_request')
    tracenv.config.save()

    run([trac_path, 'upgrade --no-backup'])

    run([trac_path, 'permission remove anonymous *'])
    run([trac_path, 'permission remove authenticated *'])
    for role, perms in trac_perm.items():
        for perm in perms:
            run([trac_path, "permission add %s %s" % (role, perm)])

    run([trac_path, "ticket_type add verification"])

    # hack to minimize config size
    run([trac_path, 'config set browser color_scale True'])

    # add properly milestones
    milestones.append({'title': 'Backlog', 'due_date': date.today().replace(year=date.today().year+1)})

    for milestone in milestones:
        due = milestone['due_date']
        if due:
            due = milestone['due_date'].strftime('%Y-%m-%d')
            run([trac_path, 'milestone add "%s" %s' % (milestone['title'], due)])
        else:
            run([trac_path, 'milestone add "%s"' % milestone['title']])

    tracenv = Environment(trac_path)
    for ticket in tickets:
        # in this moment the customer request has a proper id
        ticket['status'] = 'new'
        t = Ticket(tracenv)
        t.populate(ticket)
        t.insert()

    application.api_uri = 'trac://%s' % tracname
    application.trac_name = tracname
示例#42
0
class BuildDeleter(object):
    """Class for deleting a build."""

    def __init__(self, env_path):
        self.env = Environment(env_path)
        self.logs_dir = self.env.config.get('bitten', 'logs_dir', 'log/bitten')

    def _log_files(self, cursor, build):
        """Return a list of log files."""
        cursor.execute("SELECT filename FROM bitten_log WHERE build=%s",
            (build,))
        rows = cursor.fetchall()

        all_files = []
        for row in rows:
            filename = row[0]
            file_prefix = os.path.join(self.logs_dir, filename)
            for suffix in ['', '.level', '.levels']:
                log_file = file_prefix + suffix
                if os.path.isfile(log_file):
                    all_files.append(log_file)

        return all_files

    def discover(self, build):
        """Print a summary of what is linked to the build."""
        print "Items to delete for build %r" % (build,)
        print "-------------------------------"

        db = self.env.get_db_cnx()
        cursor = db.cursor()

        print "Attachments for build resource:"
        cursor.execute("SELECT config FROM bitten_build WHERE id=%s", (build,))
        config = cursor.fetchone()[0]
        print "  %s/%s" % (config, build)

        print "Log files:"
        print " ", "\n  ".join(self._log_files(cursor, build))

        print "Rows from bitten_log with ids:"
        cursor.execute("SELECT id FROM bitten_log WHERE build=%s", (build,))
        print " ", "\n  ".join(str(row[0]) for row in cursor.fetchall())

        print "Rows from bitten_report with ids:"
        cursor.execute("SELECT id FROM bitten_report WHERE build=%s", (build,))
        print " ", "\n  ".join(str(row[0]) for row in cursor.fetchall())
        print "Rows from bitten_report_item with report set to these ids will"
        print "also be deleted."

        print "Rows from bitten_step for this build with names:"
        cursor.execute("SELECT name FROM bitten_step WHERE build=%s", (build,))
        print " ", "\n  ".join(str(row[0]) for row in cursor.fetchall())

        print "Row from bitten_build with id:"
        cursor.execute("SELECT id FROM bitten_build WHERE id=%s", (build,))
        print " ", "\n  ".join(str(row[0]) for row in cursor.fetchall())

    def remove(self, build):
        """Delete what is linked to the build."""
        print "Deleting items for build %r" % (build,)

        db = self.env.get_db_cnx()
        cursor = db.cursor()

        print "Determining associated config."
        cursor.execute("SELECT config FROM bitten_build WHERE id=%s", (build,))
        config = cursor.fetchone()[0]

        print "Collecting log files."
        filenames = self._log_files(cursor, build)

        try:
            print "Deleting bitten_log entries."
            cursor.execute("DELETE FROM bitten_log WHERE build=%s", (build,))

            print "Deleting bitten_report_item_entries."
            cursor.execute("DELETE FROM bitten_report_item WHERE report IN ("
                "SELECT bitten_report.id FROM bitten_report "
                "WHERE bitten_report.build=%s"
                ")", (build,))

            print "Deleting bitten_report entires."
            cursor.execute("DELETE FROM bitten_report WHERE build=%s",
                (build,))

            print "Deleting bitten_step entries."
            cursor.execute("DELETE FROM bitten_step WHERE build=%s", (build,))

            print "Delete bitten_build entry."
            cursor.execute("DELETE FROM bitten_build WHERE id=%s", (build,))
        except:
            db.rollback()
            print "Build deletion failed. Database rolled back."
            raise

        print "Bitten database changes committed."
        db.commit()

        print "Removing log files."
        for filename in filenames:
            os.remove(filename)

        print "Removing attachments."
        resource = Resource('build', '%s/%s' % (config, build))
        Attachment.delete_all(self.env, 'build', resource.id, db)
示例#43
0
if "edit" not in mwsite.rights:
    raise Exception("%(mwiki_user)s does not have edit permissions on %(mwiki_host)s" % args)
if "createpage" not in mwsite.rights:
    raise Exception("%(mwiki_user)s does not have page creation permissions on %(mwiki_host)s" % args)

if args.sqlite_db is not None:
    import sqlite3

    sqliteconn = sqlite3.connect(args.sqlite_db)
    traccur = sqliteconn.cursor()
elif args.trac_path is not None:
    from trac.env import Environment

    tracenv = Environment(args.trac_path)
    tracdb = tracenv.get_db_cnx()
    traccur = tracdb.cursor()

if args.prefix != "":
    args.prefix = "%s - " % args.prefix

traccur.execute("SELECT `name`, `author`, `text`, `comment` FROM `wiki` ORDER BY `version` ASC")
for page in traccur:
    # Format the page from Trac to MW format
    formatter = WikiFormatter(page[2])

    newpage = {}
    newpage["name"] = "%s%s" % (args.prefix, page[0])
    newpage["author"] = page[1]
    newpage["text"] = formatter.parse()
    newpage["comment"] = page[3]
class TracDatabase(object):
    def __init__(self, path, append):
        self.append = _append
        self.env = Environment(path)
        self._db = self.env.get_db_cnx()
        self._db.autocommit = False
        self.loginNameCache = {}
        self.fieldNameCache = {}

    def db(self):
        return self._db

    def hasTickets(self):
        c = self.db().cursor()
        c.execute('''SELECT count(*) FROM ticket''')
        return int(c.fetchall()[0][0]) > 0

    def assertNoTickets(self):
        if not self._append or self.hasTickets():
            raise Exception("Will not modify database with existing tickets!")
            return

    def setSeverityList(self, s):
        """Remove all severities, set them to `s`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("""DELETE FROM enum WHERE type='severity'""")
        for value, i in s:
            print "inserting severity ", value, " ", i
            c.execute(
                """INSERT INTO enum (type, name, value) VALUES (%s, %s, %s)""",
                (
                    "severity",
                    value.encode('utf-8'),
                    i,
                ))
        self.db().commit()

    def setPriorityList(self, s):
        """Remove all priorities, set them to `s`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("""DELETE FROM enum WHERE type='priority'""")
        for value, i in s:
            print "inserting priority ", value, " ", i
            c.execute(
                """INSERT INTO enum (type, name, value) VALUES (%s, %s, %s)""",
                (
                    "priority",
                    value.encode('utf-8'),
                    i,
                ))
        self.db().commit()

    def setComponentList(self, l, key):
        """Remove all components, set them to `l`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("""DELETE FROM component""")
        for comp in l:
            print "inserting component '", comp[key], "', owner", comp['owner']
            c.execute(
                """INSERT INTO component (name, owner) VALUES (%s, %s)""", (
                    comp[key].encode('utf-8'),
                    comp['owner'].encode('utf-8'),
                ))
        self.db().commit()

    def setVersionList(self, v, key):
        """Remove all versions, set them to `v`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("""DELETE FROM version""")
        for vers in v:
            print "inserting version ", vers[key]
            c.execute("""INSERT INTO version (name) VALUES (%s)""",
                      (vers[key].encode('utf-8'), ))
        self.db().commit()

    def setMilestoneList(self, m, key):
        """Remove all milestones, set them to `m`"""
        self.assertNoTickets()

        c = self.db().cursor()
        c.execute("""DELETE FROM milestone""")
        for ms in m:
            print "inserting milestone ", ms[key]
            c.execute(
                """INSERT INTO milestone (name, due, completed) VALUES (%s, %s, %s)""",
                (ms[key].encode('utf-8'), self.convertTime(
                    ms['date_order']), ms['released']))
        self.db().commit()

    def addTicket(self, id, time, changetime, component, severity, priority,
                  owner, reporter, cc, version, milestone, status, resolution,
                  summary, description, keywords):
        c = self.db().cursor()
        if IGNORE_VERSION:
            version = ''

        desc = description
        type = 'defect'
        if component == 'Features' or severity == 'feature':
            type = 'enhancement'
        if PREFORMAT_COMMENTS:
            desc = '{{{\n%s\n}}}' % desc
        print "inserting ticket %s -- \"%s\"" % (id, summary[0:40].replace(
            "\n", " "))
        c.execute(
            """INSERT INTO ticket (type, time, changetime, component,
                                         severity, priority, owner, reporter, cc,
                                         version, milestone, status, resolution,
                                         summary, description, keywords)
                                 VALUES (%s, %s, %s, %s,
                                         %s, %s, %s, %s, %s,
                                         %s, %s, %s, %s,
                                         %s, %s, %s)""",
            (type, self.convertTime(time), self.convertTime(changetime),
             component.encode('utf-8'), severity.encode('utf-8'),
             priority.encode('utf-8'), owner, reporter, cc, version,
             milestone.encode('utf-8'), status.lower(), resolution,
             summary.decode('utf-8'), desc, keywords.encode('utf-8')))
        self.db().commit()

        ## TODO: add database-specific methods to get the last inserted ticket's id...
        ## PostgreSQL:
        # c.execute('''SELECT currval("ticket_id_seq")''')
        ## SQLite:
        # c.execute('''SELECT last_insert_rowid()''')
        ## MySQL:
        # c.execute('''SELECT LAST_INSERT_ID()''')
        # Oh, Trac db abstraction layer already has a function for this...
        return self.db().get_last_id(c, 'ticket')

    def convertTime(self, time2):
        time2 = datetime.fromtimestamp(time2)
        return long(str(int(time.mktime(time2.timetuple()))) + '000000')

    def addTicketComment(self, ticket, time, author, value):
        #return
        print " * adding comment \"%s...\"" % value[0:40]
        comment = value

        if PREFORMAT_COMMENTS:
            comment = '{{{\n%s\n}}}' % comment

        c = self.db().cursor()
        c.execute(
            """INSERT  INTO ticket_change (ticket, time, author, field, oldvalue, newvalue)
                                 VALUES        (%s, %s, %s, %s, %s, %s)""",
            (ticket, self.convertTime(time), author, 'comment', '', comment))
        self.db().commit()

    def addTicketChange(self, ticket, time, author, field, oldvalue, newvalue):
        if (field[0:4] == 'doba'):
            return

        if field == 'milestone':
            field = 'product_version'

        print " * adding ticket change \"%s\": \"%s\" -> \"%s\" (%s)" % (
            field, oldvalue[0:20], newvalue[0:20], time)
        c = self.db().cursor()

        #workaround 'unique' ticket_change warnings POTENTIALLY BAD IDEA ALERT
        sql = "SELECT * FROM ticket_change WHERE field='%s' AND ticket=%s AND time=%s" % (
            field, ticket, self.convertTime(time))
        c.execute(sql)
        fixtime = c.fetchall()
        if fixtime:
            time = time + 1
        c.execute(
            """INSERT  INTO ticket_change (ticket, time, author, field, oldvalue, newvalue)
                                 VALUES        (%s, %s, %s, %s, %s, %s)""",
            (ticket, self.convertTime(time), author, field,
             oldvalue.encode('utf-8'), newvalue.encode('utf-8')))
        self.db().commit()

        #workaround 'unique' ticket warnings POTENTIALLY BAD IDEA ALERT
        sql = "SELECT * FROM ticket WHERE %s='%s' AND id=%s AND time=%s" % (
            field, newvalue, ticket, self.convertTime(time))
        c.execute(sql)
        fixtime = c.fetchall()
        if fixtime:
            time = time + 1

# Now actually change the ticket because the ticket wont update itself!
        sql = "UPDATE ticket SET %s='%s' WHERE id=%s" % (field, newvalue,
                                                         ticket)
        c.execute(sql)
        self.db().commit()

    # unused in 1.2
    def addAttachment(self, id, attachment, description, author):
        print 'inserting attachment for ticket %s -- %s' % (id, description)
        attachment.filename = attachment.filename.encode('utf-8')
        self.env.create_attachment(self.db(), 'ticket', str(id), attachment,
                                   description.encode('utf-8'), author,
                                   'unknown')

    def getLoginName(self, cursor, userid):
        if userid not in self.loginNameCache and userid is not None and userid != '':
            cursor.execute(
                "SELECT username,email,realname,last_visit FROM mantis_user_table WHERE id = %i"
                % int(userid))
            result = cursor.fetchall()

            if result:
                loginName = result[0]['username']
                print 'Adding user %s to sessions table' % loginName
                c = self.db().cursor()

                # check if user is already in the sessions table
                c.execute("SELECT sid FROM session WHERE sid = '%s'" %
                          result[0]['username'].encode('utf-8'))
                r = c.fetchall()

                # if there was no user sid in the database already
                if not r:
                    sessionSql = """INSERT INTO session 
                            (sid, authenticated, last_visit) 
                        VALUES (%s, %s, %d)""", (
                        result[0]['username'].encode('utf-8'), '1',
                        self.convertTime(result[0]['last_visit']))
                    # pre-populate the session table and the realname/email table with user data
                    try:
                        c.execute(sessionSql)
                    except:
                        print 'failed executing sql: '
                        print sessionSql
                        print 'could not insert %s into sessions table: sql error ' % (
                            loginName)
                    self.db().commit()

                    # insert the user's real name into session attribute table
                    try:
                        c.execute(
                            """INSERT INTO session_attribute 
                            (sid, authenticated, name, value)
                        VALUES
                            (%s, %s, %s, %s)""",
                            (result[0]['username'].encode('utf-8'), '1',
                             'name', result[0]['realname'].encode('utf-8')))
                    except:
                        print 'failed executing session-attribute sql'
                    self.db().commit()

                    # insert the user's email into session attribute table
                    try:
                        c.execute(
                            """INSERT INTO session_attribute 
                            (sid, authenticated, name, value)
                        VALUES
                            (%s, %s, %s, %s)""",
                            (result[0]['username'].encode('utf-8'), '1',
                             'email', result[0]['email'].encode('utf-8')))
                    except:
                        print 'failed executing session-attribute sql2'
                    self.db().commit()
            else:
                print 'warning: unknown mantis userid %d, recording as anonymous' % userid
                loginName = ''

            self.loginNameCache[userid] = loginName
        elif userid is None or userid == '':
            self.loginNameCache[userid] = ''
        return self.loginNameCache[userid]

    def get_attachments_dir(self, bugid=0):
        if bugid > 0:
            return 'importfiles/%i/' % bugid
        else:
            return 'importfiles/'

    def _mkdir(newdir):
        """works the way a good mkdir should :)
            - already exists, silently complete
            - regular file in the way, raise an exception
            - parent directory(ies) does not exist, make them as well
        """
        if os.path.isdir(newdir):
            pass
        elif os.path.isfile(newdir):
            raise OSError("a file with the same name as the desired " \
                          "dir, '%s', already exists." % newdir)
        else:
            head, tail = os.path.split(newdir)
            if head and not os.path.isdir(head):
                _mkdir(head)
            #print "_mkdir %s" % repr(newdir)
            if tail:
                os.mkdir(newdir)
示例#45
0
 def get_tracenv_userdata(self, req, path, userlist=''):
     """Retrieve account data from the environment at the specified path
  @param path path to the environment
  @param userlist comma separated list of users to restrict the result to (e.g. the users from the password file), each user enclosed in single quotes (for SQL)
  @return array (empty array if the environment uses a different password file than the master env calling us)
  """
     self.env.log.debug('Get user data from %s' % (path, ))
     data = {}
     env = Environment(path)
     # if this environment uses a different password file, we return an empty dataset
     if self.env.config.get('account-manager',
                            'password_file') != env.config.get(
                                'account-manager', 'password_file'):
         self.env.log.info(
             'Password files do not match, skipping environment %s' %
             (path, ))
         return data
     perm = PermissionSystem(env)
     if not 'TRAC_ADMIN' in perm.get_user_permissions(req.perm.username):
         raise PermissionError
     db = env.get_db_cnx()
     cursor = db.cursor()
     sync_fields = self.env.config.getlist('user_sync', 'sync_fields')
     attr = "'" + "','".join(
         sync_fields
     ) + "','email_verification_sent_to','email_verification_token'"
     self.env.log.debug('* Checking attributes: %s' % (attr, ))
     if userlist:
         cursor.execute(
             "SELECT sid,name,value FROM session_attribute WHERE sid IN (%s) AND name IN (%s)"
             % (
                 userlist,
                 attr,
             ))
     else:
         cursor.execute(
             "SELECT sid,name,value FROM session_attribute WHERE name IN (%s)"
             % (attr, ))
     for row in cursor:
         if not row[0] in data: data[row[0]] = {}
         data[row[0]][row[1]] = row[2]
     for sid in data.iterkeys():
         no_data = True
         for att in sync_fields:
             if att in data[sid]:
                 no_data = False
                 break
         if no_data:
             self.env.log.debug('No data for %s in %s' % (
                 sid,
                 path,
             ))
             data[sid] = Null
             continue
         data[sid]['path'] = path
         cursor.execute(
             "SELECT authenticated FROM session_attribute WHERE sid='%s'" %
             (sid, ))
         for row in cursor:
             data[sid]['authenticated'] = row[0]
         cursor.execute(
             "SELECT datetime(last_visit,'unixepoch') AS last_visit FROM session WHERE sid='%s'"
             % (sid, ))
         for row in cursor:
             data[sid]['last_visit'] = row[0]
     return data
示例#46
0
class TracDatabase(object):
    def __init__(self, path):
        self.env = Environment(path)
        self._db = self.env.get_db_cnx()
        self._db.autocommit = False
        self.loginNameCache = {}
        self.fieldNameCache = {}
    
    def db(self):
        return self._db
    
    def hasTickets(self):
        c = self.db().cursor()
        c.execute("SELECT count(*) FROM Ticket")
        return int(c.fetchall()[0][0]) > 0

    def assertNoTickets(self):
        if self.hasTickets():
            raise Exception("Will not modify database with existing tickets!")
    
    def setSeverityList(self, s):
        """Remove all severities, set them to `s`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("DELETE FROM enum WHERE type='severity'")
        for value, i in s:
            print "  inserting severity '%s' - '%s'" % (value, i)
            c.execute("""INSERT INTO enum (type, name, value)
                                   VALUES (%s, %s, %s)""",
                      ("severity", value.encode('utf-8'), i))
        self.db().commit()
    
    def setPriorityList(self, s):
        """Remove all priorities, set them to `s`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("DELETE FROM enum WHERE type='priority'")
        for value, i in s:
            print "  inserting priority '%s' - '%s'" % (value, i)
            c.execute("""INSERT INTO enum (type, name, value)
                                   VALUES (%s, %s, %s)""",
                      ("priority", value.encode('utf-8'), i))
        self.db().commit()

    
    def setComponentList(self, l, key):
        """Remove all components, set them to `l`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("DELETE FROM component")
        for comp in l:
            print "  inserting component '%s', owner '%s'" % \
                            (comp[key], comp['owner'])
            c.execute("INSERT INTO component (name, owner) VALUES (%s, %s)",
                      (comp[key].encode('utf-8'),
                       comp['owner'].encode('utf-8')))
        self.db().commit()
    
    def setVersionList(self, v, key):
        """Remove all versions, set them to `v`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("DELETE FROM version")
        for vers in v:
            print "  inserting version '%s'" % (vers[key])
            c.execute("INSERT INTO version (name) VALUES (%s)",
                      (vers[key].encode('utf-8'),))
        self.db().commit()
        
    def setMilestoneList(self, m, key):
        """Remove all milestones, set them to `m`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("DELETE FROM milestone")
        for ms in m:
            milestone = ms[key]
            print "  inserting milestone '%s'" % (milestone)
            c.execute("INSERT INTO milestone (name) VALUES (%s)",
                      (milestone.encode('utf-8'),))
        self.db().commit()
    
    def addTicket(self, id, time, changetime, component, severity, priority,
                  owner, reporter, cc, version, milestone, status, resolution,
                  summary, description, keywords):
        c = self.db().cursor()
        
        desc = description.encode('utf-8')
        type = "defect"
        
        if severity.lower() == "enhancement":
                severity = "minor"
                type = "enhancement"
        
        if PREFORMAT_COMMENTS:
          desc = '{{{\n%s\n}}}' % desc

        if REPLACE_BUG_NO:
            if BUG_NO_RE.search(desc):
                desc = re.sub(BUG_NO_RE, BUG_NO_REPL, desc)

        if PRIORITIES_MAP.has_key(priority):
            priority = PRIORITIES_MAP[priority]

        print "  inserting ticket %s -- %s" % (id, summary)

        c.execute("""INSERT INTO ticket (id, type, time, changetime, component,
                                         severity, priority, owner, reporter,
                                         cc, version, milestone, status,
                                         resolution, summary, description,
                                         keywords)
                                 VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s,
                                         %s, %s, %s, %s, %s, %s, %s, %s)""",
                  (id, type.encode('utf-8'), time.strftime('%s'),
                   changetime.strftime('%s'), component.encode('utf-8'),
                   severity.encode('utf-8'), priority.encode('utf-8'), owner,
                   reporter, cc, version, milestone.encode('utf-8'),
                   status.lower(), resolution, summary.encode('utf-8'), desc,
                   keywords))
        
        self.db().commit()
        return self.db().get_last_id(c, 'ticket')
    
    def addTicketComment(self, ticket, time, author, value):
        comment = value.encode('utf-8')
        
        if PREFORMAT_COMMENTS:
          comment = '{{{\n%s\n}}}' % comment

        if REPLACE_BUG_NO:
            if BUG_NO_RE.search(comment):
                comment = re.sub(BUG_NO_RE, BUG_NO_REPL, comment)

        c = self.db().cursor()
        c.execute("""INSERT INTO ticket_change (ticket, time, author, field,
                                                oldvalue, newvalue)
                                        VALUES (%s, %s, %s, %s, %s, %s)""",
                  (ticket, time.strftime('%s'), author, 'comment', '', comment))
        self.db().commit()

    def addTicketChange(self, ticket, time, author, field, oldvalue, newvalue):
        c = self.db().cursor()

        if field == "owner":
            if LOGIN_MAP.has_key(oldvalue):
                oldvalue = LOGIN_MAP[oldvalue]
            if LOGIN_MAP.has_key(newvalue):
                newvalue = LOGIN_MAP[newvalue]

        if field == "priority":
            if PRIORITIES_MAP.has_key(oldvalue.lower()):
                oldvalue = PRIORITIES_MAP[oldvalue.lower()]
            if PRIORITIES_MAP.has_key(newvalue.lower()):
                newvalue = PRIORITIES_MAP[newvalue.lower()]

        # Doesn't make sense if we go from highest -> highest, for example.
        if oldvalue == newvalue:
            return
        
        c.execute("""INSERT INTO ticket_change (ticket, time, author, field,
                                                oldvalue, newvalue)
                                        VALUES (%s, %s, %s, %s, %s, %s)""",
                  (ticket, time.strftime('%s'), author, field,
                   oldvalue.encode('utf-8'), newvalue.encode('utf-8')))
        self.db().commit()
        
    def addAttachment(self, author, a):
        description = a['description'].encode('utf-8')
        id = a['bug_id']
        filename = a['filename'].encode('utf-8')
        filedata = StringIO.StringIO(a['thedata'].tostring())
        filesize = len(filedata.getvalue())
        time = a['creation_ts']
        print "    ->inserting attachment '%s' for ticket %s -- %s" % \
                (filename, id, description)

        attachment = Attachment(self.env, 'ticket', id)
        attachment.author = author
        attachment.description = description
        attachment.insert(filename, filedata, filesize, time.strftime('%s'))
        del attachment
        
    def getLoginName(self, cursor, userid):
        if userid not in self.loginNameCache:
            cursor.execute("SELECT * FROM profiles WHERE userid = %s", (userid))
            loginName = cursor.fetchall()

            if loginName:
                loginName = loginName[0]['login_name']
            else:
                print """WARNING: unknown bugzilla userid %d, recording as
                         anonymous""" % (userid)
                loginName = "anonymous"

            loginName = LOGIN_MAP.get(loginName, loginName)

            self.loginNameCache[userid] = loginName

        return self.loginNameCache[userid]

    def getFieldName(self, cursor, fieldid):
        if fieldid not in self.fieldNameCache:
            cursor.execute("SELECT * FROM fielddefs WHERE fieldid = %s",
                           (fieldid))
            fieldName = cursor.fetchall()

            if fieldName:
                fieldName = fieldName[0]['name'].lower()
            else:
                print "WARNING: unknown bugzilla fieldid %d, \
                                recording as unknown" % (userid)
                fieldName = "unknown"

            self.fieldNameCache[fieldid] = fieldName

        return self.fieldNameCache[fieldid]
class Client(object):
    def __init__(self, env_path):
        self.env_path = env_path
        self.env = Environment(env_path)
        self.db_cnx = self.env.get_db_cnx()
        self._registered_users_logins = []
        self._timetracking_plugins = self._get_timetracking_plugins()

    def _get_timetracking_plugins(self):
        plugins = {}
        if tracLib.SUPPORT_TIME_TRACKING == 'auto':
            for plugin in tracLib.timetracking.plugins:
                plugin_name = plugin.get_name()
                for com_name, com_enabled in self.env._component_rules.items():
                    if com_name.startswith(plugin_name) and com_enabled and plugin_name not in plugins:
                        plugins[plugin_name] = plugin(self.env)
        else:
            for plugin in tracLib.timetracking.plugins:
                plugin_name = plugin.get_name()
                if plugin_name == tracLib.SUPPORT_TIME_TRACKING:
                    plugins[plugin_name] = plugin(self.env)
                    break;
        for plugin_name in plugins.keys():
            print "Plugin '%s' will be used to get workitems." % plugin_name
        return plugins.values()

    def get_project_description(self):
        return self.env.project_description

    def get_users(self):
        result = self.env.get_known_users()
        trac_users = list([])
        for user in result:
            user_login = user[0].lower()
            if user_login in self._registered_users_logins:
                continue
            u = TracUser(user_login)
            u.email = user[2]
            trac_users.append(u)
            self._registered_users_logins.append(user_login)
        # if we accept only authorised users, we don't have any more users to return
        # all of them were returned by "get_known_users" method
        if not tracLib.ACCEPT_NON_AUTHORISED_USERS:
            return trac_users
        # here we must to get component owners, issue reporters, owners and attachment authors
        # that are not registered users
        user_fields = [("owner", "component"), ("reporter", "ticket"), ("owner", "ticket"), ("author", "attachment")]
        first = True
        request = ""
        for column_name, table_name in user_fields :
            if first:
                first = False
            else:
                request += "UNION "
            request += "SELECT DISTINCT lower(%s) FROM %s " % (column_name, table_name)
        cursor = self.db_cnx.cursor()
        cursor.execute(request)
        for row in cursor:
            if row[0] not in self._registered_users_logins:
                trac_user = self._get_non_authorised_user(row[0])
                if trac_user is not None :
                    trac_users.append(trac_user)
                    self._registered_users_logins.append(trac_user.name)
        return trac_users

    def _get_non_authorised_user(self, user_name):
        if user_name is None :
            return None
        # non authorized users in trac are stored like this "name <email_address>"
        start = user_name.find("<")
        end = user_name.rfind(">")
        # we don't accept users who didn't leave the email
        if (start > -1) and (end > start + 1):
            if user_name.find("@", start, end) > 0:
                user = TracUser(user_name[start + 1 : end].replace(" ", "_"))
                user.email = user_name[start + 1 : end].replace(" ", "_")
                return user
        return None

    def _get_user_login(self, user_name):
        if user_name is None:
            return None
        if user_name in self._registered_users_logins:
            return user_name
        if not tracLib.ACCEPT_NON_AUTHORISED_USERS:
            return None
        user = self._get_non_authorised_user(user_name)
        if (user is None) or (user.name not in self._registered_users_logins) :
            return None
        return user.name

    def get_severities(self):
        return self._get_data_from_enum("severity")

    def get_issue_types(self):
        return self._get_data_from_enum("ticket_type")

    def get_issue_priorities(self):
        return self._get_data_from_enum("priority")

    def get_issue_resolutions(self):
        return [TracResolution(name) for name in self._get_data_from_enum("resolution")]

    def get_components(self):
        cursor = self.db_cnx.cursor()
        cursor.execute("SELECT name, owner, description FROM component")
        trac_components = list([])
        for row in cursor:
            component = TracComponent(row[0])
            component.owner = self._get_user_login(component.owner)
            if row[2] is not None:
                component.description = row[2]
            trac_components.append(component)
        return trac_components

    def get_versions(self):
        cursor = self.db_cnx.cursor()
        cursor.execute("SELECT name, time, description FROM version")
        trac_versions = list([])
        for row in cursor:
            version = TracVersion(row[0])
            if row[1]:
                version.time = to_unix_time(row[1])
            if row[2] is not None:
                version.description = row[2]
            trac_versions.append(version)
        return trac_versions

    def get_issues(self):
        cursor = self.db_cnx.cursor()
        cursor.execute("SELECT id, type, time, changetime, component, severity, priority, owner, reporter,"
                       "cc, version, status, resolution, summary, description, keywords FROM ticket")
        trac_issues = list([])
        for row in cursor:
            issue = TracIssue(row[0])
            issue.time = to_unix_time(row[2])
            issue.changetime = to_unix_time(row[3])
            issue.reporter = self._get_user_login(row[8])
            if row[9] is not None:
                cc = row[9].split(",")
                for c in cc:
                    if len(c) > 0:
                        cc_name = self._get_user_login(c.strip())
                        if cc_name is not None:
                            issue.cc.add(cc_name)
            issue.summary = row[13]
            issue.description = row[14]
            issue.custom_fields["Type"] = row[1]
            issue.custom_fields["Component"] = row[4]
            issue.custom_fields["Severity"] = row[5]
            issue.custom_fields["Priority"] = row[6]
            issue.custom_fields["Owner"] = self._get_user_login(row[7])
            issue.custom_fields["Version"] = row[10]
            issue.custom_fields["Status"] = row[11]
            issue.custom_fields["Resolution"] = row[12]
            if row[15] is not None:
                keywords = row[15].rsplit(",")
                for kw in keywords:
                    if len(kw) > 0:
                        issue.keywords.add(kw.strip())
            #getting custom fields from ticket_custom table
            custom_field_cursor = self.db_cnx.cursor()
            custom_field_cursor.execute("SELECT name, value FROM ticket_custom WHERE ticket=%s", (str(row[0]),))
            for cf in custom_field_cursor:
                issue.custom_fields[cf[0].capitalize()] = cf[1]
            # getting attachments from attachment table
            attachment_cursor = self.db_cnx.cursor()
            attachment_cursor.execute("SELECT filename, size, time, description, author FROM attachment WHERE "
                                      "type = %s AND id = %s", ("ticket", str(issue.id)))
            #path = self.env_path + "/attachments/ticket/" + str(issue.id) + "/"
            for elem in attachment_cursor:
                #at = TracAttachment(path + elem[0])
                at = TracAttachment(Attachment._get_path(self.env.path, 'ticket', str(issue.id), elem[0]))
                at.name = elem[0]
                at.size = elem[1]
                at.time = to_unix_time(elem[2])
                at.description = elem[3]
                at.author_name = elem[4]
                issue.attachment.add(at)
            trac_issues.append(issue)
            #getting comments
            change_cursor = self.db_cnx.cursor()
            change_cursor.execute("SELECT time, author, newvalue, oldvalue FROM ticket_change WHERE ticket = %s AND field = %s ORDER BY time DESC", (str(row[0]), "comment",))
            for elem in change_cursor:
                if (elem[2] is None) or (not len(elem[2].lstrip())):
                    continue
                comment = TracComment(to_unix_time(elem[0]))
                comment.author = str(elem[1])
                comment.content = unicode(elem[2])
                comment.id = elem[3]
                issue.comments.add(comment)
            #getting workitems
            for ttp in self._timetracking_plugins:
                issue.workitems.update(set(ttp[row[0]]))
        return trac_issues


    def get_custom_fields_declared(self):
        ini_file_path = self.env_path + "/conf/trac.ini"
        parser = ConfigParser()
        parser.read(ini_file_path)
        if not("ticket-custom" in parser.sections()):
              return set([])
        result = parser.items("ticket-custom")
        items = dict([])
        for elem in result:
            items[elem[0]] = elem[1]

        keys = items.keys()
        custom_fields = list([])
        for k in keys:
            if not("." in k):
                field = TracCustomFieldDeclaration(k.capitalize())
                field.type = items[k]
                options_key = k + ".options"
                if options_key in items:
                    opts_str = items[options_key]
                    opts = opts_str.rsplit("|")
                    for o in opts:
                        field.options.append(o)
                value_key = k + ".value"
                if value_key in items:
                    field.value = items[value_key]
                label_key = k + ".label"
                if label_key in items:
                    field.label = items[label_key]
                custom_fields.append(field)

        return custom_fields

    def _get_data_from_enum(self, type_name):
        cursor = self.db_cnx.cursor()
        cursor.execute("SELECT name, value FROM enum WHERE type=%s", (type_name,))
        return [row[0] for row in cursor]
示例#48
0
def delete_watchlist_tables(envpath,
                            tables=('watchlist', 'watchlist_settings',
                                    'system'),
                            user=None):
    """Deletes all watchlist DB entries => Uninstaller"""
    from trac.env import Environment
    try:
        env = Environment(envpath)
    except:
        print "Given path '%s' seems not to be a Trac environment." % envpath
        sys.exit(3)

    db = env.get_db_cnx()

    if user is not None:
        cursor = db.cursor()
        if 'watchlist' in tables:
            try:
                cursor.execute("DELETE FROM watchlist WHERE wluser=%s",
                               (user, ))
                print "Deleted user entries from 'watchlist' table."
            except Exception as e:
                db.rollback()
                print "Could not delete user entry from 'watchlist' table: "\
                    + unicode(e)
        cursor = db.cursor()
        if 'watchlist_settings' in tables:
            try:
                cursor.execute(
                    "DELETE FROM watchlist_settings WHERE wluser=%s", (user, ))
                print "Deleted user entries from 'watchlist_settings' table."
            except Exception as e:
                db.rollback()
                print "Could not delete user entry from 'watchlist_settings' table: "\
                    + unicode(e)

        db.commit()
        print "Finished."
        return

    if 'watchlist' in tables:
        cursor = db.cursor()
        try:
            cursor.execute("DROP TABLE watchlist")
            print "Deleted 'watchlist' table."
        except:
            db.rollback()
            print "No 'watchlist' table for deletion found."

    if 'watchlist_settings' in tables:
        cursor = db.cursor()
        try:
            cursor.execute("DROP TABLE watchlist_settings")
            print "Deleted 'watchlist_settings' table."
        except:
            db.rollback()
            print "No 'watchlist_settings' table for deletion found."

    if 'system' in tables:
        cursor = db.cursor()
        try:
            cursor.execute("DELETE FROM system WHERE name='watchlist_version'")
            print "Deleted watchlist version entry from system table."
        except Exception as e:
            db.rollback()
            print "Could not delete 'watchlist_version' from 'system' table: "\
                  + unicode(e)

    db.commit()
    print "Finished."
示例#49
0
    raise Exception(
        "%(mwiki_user)s does not have edit permissions on %(mwiki_host)s" %
        args)
if 'createpage' not in mwsite.rights:
    raise Exception(
        "%(mwiki_user)s does not have page creation permissions on %(mwiki_host)s"
        % args)

if args.sqlite_db is not None:
    import sqlite3
    sqliteconn = sqlite3.connect(args.sqlite_db)
    traccur = sqliteconn.cursor()
elif args.trac_path is not None:
    from trac.env import Environment
    tracenv = Environment(args.trac_path)
    tracdb = tracenv.get_db_cnx()
    traccur = tracdb.cursor()

if args.prefix != "":
    args.prefix = "%s - " % args.prefix

traccur.execute(
    "SELECT `name`, `author`, `text`, `comment` FROM `wiki` ORDER BY `version` ASC"
)
for page in traccur:
    #Format the page from Trac to MW format
    formatter = WikiFormatter(page[2])

    newpage = {}
    newpage['name'] = "%s%s" % (args.prefix, page[0])
    newpage['author'] = page[1]
示例#50
0
class Trac(object):
	def __init__(self, path):
		'''Basic object that supports the wiki and all that jazz'''
		self._env = Environment(os.path.abspath(path))
		purl = self._env.project_url
		if purl.endswith('/'):
			purl = purl[:-1]
		if purl:
			self.name = purl.split('/')[-1]
		else:
			self.name = self._env.project_name

	def listWikiPages(self):
		'''Return a list of all wiki pages that were not written by the 'trac' user'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		wikiPagesQuery = "select distinct name from wiki where author != 'trac'"
		res = cursor.execute(wikiPagesQuery)
		pages = res.fetchall()
		names = [x[0] for x in pages]
		return names

	def listTickets(self):
		'''Return a list of all ticket numbers'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		ticketsQuery = 'select distinct id from ticket'
		res = cursor.execute(ticketsQuery)
		ticketsRes = res.fetchall()
		tickets = [x[0] for x in ticketsRes]
		return tickets
		
	def maxTicket(self):
		'''Return the largest ticket number'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		maxTicketQuery = 'select max(id) from ticket'
		res = cursor.execute(maxTicketQuery)
		(maxTicket, ) = res.fetchone()
		return maxTicket
		
	def listVersions(self):
		'''List all the versions'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		versionsQuery = "select name from version"
		res = cursor.execute(versionsQuery)
		versions = [x[0] for x in res.fetchall()]
		return versions

	def listComponents(self):
		'''List all the ticket components'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		componentsQuery = "select name from component"
		res = cursor.execute(componentsQuery)
		components = [x[0] for x in res.fetchall()]
		return components

	def listEnums(self):
		'''List all the enums'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		enumsQuery = "select name, type from enum"
		res = cursor.execute(enumsQuery)
		return res.fetchall()

	def listMilestones(self):
		'''List all the milestones'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		milestonesQuery = "select name from milestone"
		res = cursor.execute(milestonesQuery)
		milestones = [x[0] for x in res.fetchall()]
		return milestones

	def getAllInfo(self):
		all = {}
		all['wikiNames'] = self.listWikiPages()
		all['maxTicket'] = self.maxTicket()
		all['versions'] = self.listVersions()
		all['components'] = self.listComponents()
		all['enums'] = self.listEnums()
		all['milestones'] = self.listMilestones()
		return all
	
	def getWikiPageAll(self, page):
		'''Get all the versions of a wiki page as a list of dicts and a list of attachments'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		pageCountRes = cursor.execute('select count(*) as count from wiki where name = %s', (page,))
		pageCount = pageCountRes.fetchone()[0]
		assert pageCount >= 1, 'Page %s not found in %s' % (page, self.name)

		attachments = []
		pageAttachmentQuery = "select type, id, filename, size, time, description, author, ipnr from attachment where type = 'wiki' and id = %s"
		pageAttachmentRes = cursor.execute(pageAttachmentQuery, (page,))
		for attachment in pageAttachmentRes:
			thisAttachment = dict(zip([d[0] for d in pageAttachmentRes.description], attachment))
			thisAttachment['fileobj'] = Attachment(self._env, 'wiki', page, thisAttachment['filename']).open()
			attachments.append(thisAttachment)

		baseQuery = 'select name, version, time, author, ipnr, text, comment, readonly from wiki where name = %s'
		res = cursor.execute(baseQuery, (page,))
		wikiData = []
		for row in res:
			wikiData.append(dict(zip([d[0] for d in res.description], row)))
		return wikiData, attachments

	def getWikiPageCurrent(self, page):
		'''Get the current version of a wiki page as a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		pageCountRes = cursor.execute('select count(*) as count from wiki where name = %s', (page,))
		pageCount = pageCountRes.fetchone()[0]
		assert pageCount >= 1, 'Page %s not found in %s' % (page, self.name)
		pageQuery = 'select name, version, time, author, ipnr, text, comment, readonly from wiki where name = %s and version = (select max(version) from wiki where name = %s)'
		pageRes = cursor.execute(pageQuery, (page,page))
		wikiPage = dict(zip([d[0] for d in pageRes.description], pageRes.fetchone()))

		wikiPage['attachment'] = []
		pageAttachmentQuery = "select type, id, filename, size, time, description, author, ipnr from attachment where type = 'wiki' and id = %s"
		pageAttachmentRes = cursor.execute(pageAttachmentQuery, (page,))
		for attachment in pageAttachmentRes:
			thisAttachment = dict(zip([d[0] for d in pageAttachmentRes.description], attachment))
			thisAttachment['fileobj'] = Attachment(self._env, 'wiki', page, thisAttachment['filename']).open()
			wikiPage['attachment'].append(thisAttachment)
		return wikiPage

	def addWikiPage(self, page, attachments):
		'''Add a wiki page as a list of dictionaries'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		pageCountRes = cursor.execute('select count(*) as count from wiki where name = %s', (page[0]['name'],))
		pageCount = pageCountRes.fetchone()[0]
		assert pageCount == 0, 'Page %s found in %s' % (page[0]['name'], self.name)

		insertWikiQuery = 'insert into wiki (name, version, time, author, ipnr, text, comment, readonly) values (%s, %s, %s, %s, %s, %s, %s, %s)'
		for pV in page:
			insertValues = (pV['name'], pV['version'], pV['time'], pV['author'], pV['ipnr'], pV['text'], pV['comment'], pV['readonly'])
			insertRes = cursor.execute(insertWikiQuery, insertValues)
		for a in attachments:
			pageAttach = Attachment(self._env, 'wiki', pV['name'])
			pageAttach.description = a['description']
			pageAttach.author = a['author']
			pageAttach.ipnr = a['ipnr']
			pageAttach.insert(a['filename'], a['fileobj'], a['size'], t=a['time'])
		db.commit()
		

	def getTicket(self, id):
		'''Get a ticket id as a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		idCountRes = cursor.execute('select count(*) as count from ticket where id = %s', (id,))
		idCount = idCountRes.fetchone()[0]
		assert idCount >= 1, 'Page %s not found in %s' % (id, self.id)

		mainTicketQuery = 'select id, type, time, changetime, component, severity, priority, owner, \
			reporter, cc, version, milestone, status, resolution, summary, description, keywords from ticket where id = %s'
		mainTicketRes = cursor.execute(mainTicketQuery, (id, ))
		ticket = dict(zip([d[0] for d in mainTicketRes.description], mainTicketRes.fetchone()))

		ticket['ticket_change'] = []
		ticketChangeQuery = 'select time, author, field, oldvalue, newvalue from ticket_change where ticket = %s'
		ticketChangeRes = cursor.execute(ticketChangeQuery, (id, ))
		for ticket_change in ticketChangeRes:
			ticket['ticket_change'].append(dict(zip([d[0] for d in ticketChangeRes.description], ticket_change)))

		ticket['attachment'] = []
		ticketAttachmentQuery = 'select type, id, filename, size, time, description, author, ipnr from attachment where type = \'ticket\' and id = %s'
		ticketAttachmentRes = cursor.execute(ticketAttachmentQuery, (id, ))
		for attachment in ticketAttachmentRes:
			thisAttachment = dict(zip([d[0] for d in ticketAttachmentRes.description], attachment))
			thisAttachment['fileobj'] = Attachment(self._env, 'ticket', id, thisAttachment['filename']).open()
			ticket['attachment'].append(thisAttachment)
		return ticket
		
	def addTicket(self, ticket, source):
		'''Add a ticket from a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		idCountRes = cursor.execute('select count(*) as count from ticket where id = %s', (ticket['id'],))
		idCount = idCountRes.fetchone()[0]
		assert idCount == 0, 'Ticket %s found in %s' % (ticket['id'], self.name)

		insertMainTicketQuery = 'insert into ticket (id, type, time, changetime, component, severity, priority, owner, \
			reporter, cc, version, milestone, status, resolution, summary, description, keywords) \
			values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'
		insertMainTicketValues = (ticket['id'], ticket['type'], ticket['time'], ticket['changetime'], ticket['component'], \
			ticket['severity'], ticket['priority'], ticket['owner'], ticket['reporter'], ticket['cc'], ticket['version'], \
			ticket['milestone'], ticket['status'], ticket['resolution'], ticket['summary'], ticket['description'], ticket['keywords'])
		insertMainTicketRes = cursor.execute(insertMainTicketQuery, insertMainTicketValues)

		#so we know where the ticket came from
		insertTicketSourceQuery = 'insert into ticket_custom (ticket, name, value) values (%s, %s, %s)'
		insertTicketSourceValues = (ticket['id'], 'project', source)
		insertTicketSourceRes = cursor.execute(insertTicketSourceQuery, insertTicketSourceValues)

		insertTicketChangeQuery = 'insert into ticket_change (ticket, time, author, field, oldvalue, newvalue) values (%s, %s, %s, %s, %s, %s)'
		for ticket_change in ticket['ticket_change']:
			insertTicketChangeValues = (ticket['id'], ticket_change['time'], ticket_change['author'], ticket_change['field'], ticket_change['oldvalue'], ticket_change['newvalue'])
			insertTicketChangeRes = cursor.execute(insertTicketChangeQuery, insertTicketChangeValues)

		for a in ticket['attachment']:
			ticketAttach = Attachment(self._env, 'ticket', ticket['id'])
			ticketAttach.description = a['description']
			ticketAttach.author = a['author']
			ticketAttach.ipnr = a['ipnr']
			ticketAttach.insert(a['filename'], a['fileobj'], a['size'], t=a['time'])
		db.commit()
		
	def getComponent(self, comp):
		'''Get a component as a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		compCountRes = cursor.execute('select count(*) as count from component where name = %s', (comp,))
		compCount = compCountRes.fetchone()[0]
		assert compCount >= 1, 'Component %s not found in %s' % (comp, self.name)
		baseQuery = 'select name, owner, description from component where name = %s'
		res = cursor.execute(baseQuery, (comp,))
		return(dict(zip([d[0] for d in res.description], res.fetchone())))

	def addComponent(self, comp):
		'''Add a component from a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		assert comp['name'] != '', 'No name given' 
		compCountRes = cursor.execute('select count(*) as count from component where name = %s', (comp['name'],))
		compCount = compCountRes.fetchone()[0]
		if compCount > 0:
			'Component %s found in %s. Skipping the re-insertion.' % (comp['name'], self.name)
		else:
			insertComponentQuery = 'insert into component (name, owner, description) values (%s, %s, %s)'
			insertComponentValues = (comp['name'], comp['owner'], comp['description'])
			res = cursor.execute(insertComponentQuery, insertComponentValues)
			db.commit()

	def getMilestone(self, mile):
		'''Get a milestone as a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		mileCountRes = cursor.execute('select count(*) as count from milestone where name = %s', (mile,))
		mileCount = mileCountRes.fetchone()[0]
		assert mileCount >= 1, 'Milestone %s not found in %s' % (mile, self.name)

		baseQuery = 'select name, due, completed, description from milestone where name = %s'
		res = cursor.execute(baseQuery, (mile,))
		return(dict(zip([d[0] for d in res.description], res.fetchone())))

	def addMilestone(self, mile):
		'''Add a milestone from a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		assert mile['name'] != '', 'No name given' 
		mileCountRes = cursor.execute('select count(*) as count from milestone where name = %s', (mile['name'],))
		mileCount = mileCountRes.fetchone()[0]
		if mileCount > 0:
			'Milestone %s found in %s. Skipping the re-insertion.' % (mile['name'], self.name)
		else:
			insertMilestoneQuery = 'insert into milestone (name, due, completed, description) values (%s, %s, %s, %s)'
			insertMilestoneValues = (mile['name'], mile['due'], mile['completed'], mile['description'])
			res = cursor.execute(insertMilestoneQuery, insertMilestoneValues)
			db.commit()

	def getEnum(self, enum):
		'''Get an enum as a dict. Enum should be a tupe of (name, type)'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		enumCountRes = cursor.execute('select count(*) as count from enum where name = %s and type = %s', enum)
		enumCount = enumCountRes.fetchone()[0]
		assert enumCount >= 1, 'Enum %s not found in %s' % (enum, self.name)

		baseQuery = 'select name, type, value from enum where name = %s and type = %s'
		res = cursor.execute(baseQuery, enum)
		return(dict(zip([d[0] for d in res.description], res.fetchone())))

	def addEnum(self, enum):
		'''Add a enum from a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		assert enum['name'] != '', 'No name given' 
		enumCountRes = cursor.execute('select count(*) as count from enum where name = %s and type = %s', (enum['name'], enum['type']))
		enumCount = enumCountRes.fetchone()[0]
		if enumCount > 0:
			print 'Enum %s found in %s. Skipping the re-insertion.' % (enum['name'], self.name)
		else:
			insertEnumQuery = 'insert into enum (name, type, value) values (%s, %s, %s)'
			insertEnumValues = (enum['name'], enum['type'], enum['value'])
			res = cursor.execute(insertEnumQuery, insertEnumValues)
			db.commit()

	def getVersion(self, version):
		'''Get a version as a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		versionCountRes = cursor.execute('select count(*) as count from version where name = %s', (version,))
		versionCount = versionCountRes.fetchone()[0]
		assert versionCount >= 1, 'Version %s not found in %s' % (version, self.name)

		baseQuery = 'select name, time, description from version where name = %s'
		res = cursor.execute(baseQuery, (version,))
		return(dict(zip([d[0] for d in res.description], res.fetchone())))

	def addVersion(self, version):
		'''Add a version from a dict'''
		db = self._env.get_db_cnx()
		cursor = db.cursor()
		assert version['name'] != '', 'No name given' 
		versionCountRes = cursor.execute('select count(*) as count from version where name = %', (version['name'],))
		versionCount = versionCountRes.fetchone()[0]
		if versionCount > 0:
			print 'Version %s found in %s. Skipping the re-insertion.' % (version['name'], self.name)
		else:
			insertVersionQuery = 'insert into version (name, time, description) values (%s, %s, %s)'
			insertVersionValues = (version['name'], version['time'], version['description'])
			res = cursor.execute(insertVersionQuery, insertVersionValues)
			db.commit()


	def getRepository(self):
		'''Get the repository info, particularly the path and type'''
		repository = {}
		repository['type'] = self._env.config.get('trac', 'repository_type')
		repository['dir'] = self._env.config.get('trac', 'repository_dir')
		return repository

	def addRepository(self, repository):
		'''Add a repository from a dict specifying name, type and dir.
		This adds using the multiple repository functionality.'''
		assert repository.has_key('name') and repository.has_key('type') and repository.has_key('dir'), "Repository info not specified"
		self._env.config.set('repositories', '%s.dir' % repository['name'], repository['dir'])
		if repository['type'] == 'svn':
			repotype = 'direct-svnfs'
		else:
			repotype = repository['type']
		self._env.config.set('repositories', '%s.type' % repository['name'], repotype)
		self._env.config.save()
示例#51
0
class TracDatabase(object):
    def __init__(self, path):
        self.env = Environment(path)
        self._db = self.env.get_db_cnx()
        self._db.autocommit = False
        self.loginNameCache = {}
        self.fieldNameCache = {}
    
    def db(self):
        return self._db
    
    def hasTickets(self):
        c = self.db().cursor()
        c.execute('''SELECT count(*) FROM ticket''')
        return int(c.fetchall()[0][0]) > 0

    def assertNoTickets(self):
        if self.hasTickets():
            raise Exception("Will not modify database with existing tickets!")
    
    def setSeverityList(self, s):
        """Remove all severities, set them to `s`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("""DELETE FROM enum WHERE type='severity'""")
        for value, i in s:
            print "inserting severity ", value, " ", i
            c.execute("""INSERT INTO enum (type, name, value) VALUES (%s, %s, %s)""",
                      ("severity", value.encode('utf-8'), i,))
        self.db().commit()
    
    def setPriorityList(self, s):
        """Remove all priorities, set them to `s`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("""DELETE FROM enum WHERE type='priority'""")
        for value, i in s:
            print "inserting priority ", value, " ", i
            c.execute("""INSERT INTO enum (type, name, value) VALUES (%s, %s, %s)""",
                      ("priority", value.encode('utf-8'), i,))
        self.db().commit()
    
    def setComponentList(self, l, key):
        """Remove all components, set them to `l`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("""DELETE FROM component""")
        for comp in l:
            print "inserting component '",comp[key],"', owner",  comp['owner']
            c.execute("""INSERT INTO component (name, owner) VALUES (%s, %s)""",
                      (comp[key].encode('utf-8'), comp['owner'].encode('utf-8'),))
        self.db().commit()
    
    def setVersionList(self, v, key):
        """Remove all versions, set them to `v`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("""DELETE FROM version""")
        for vers in v:
            print "inserting version ", vers[key]
            c.execute("""INSERT INTO version (name) VALUES (%s)""",
                      (vers[key].encode('utf-8'),))
        self.db().commit()
        
    def setMilestoneList(self, m, key):
        """Remove all milestones, set them to `m`"""
        self.assertNoTickets()
        
        c = self.db().cursor()
        c.execute("""DELETE FROM milestone""")
        for ms in m:
            print "inserting milestone ", ms[key]
            c.execute("""INSERT INTO milestone (name, due, completed) VALUES (%s, %s, %s)""",
                      (ms[key].encode('utf-8'), self.convertTime(ms['date_order']), ms['released']))
        self.db().commit()
    
    def addTicket(self, id, time, changetime, component,
                  severity, priority, owner, reporter, cc,
                  version, milestone, status, resolution,
                  summary, description, keywords):
        c = self.db().cursor()
        if IGNORE_VERSION:
          version=''
        
        desc = description
	type = 'defect'
 	if component == 'Features' or severity == 'feature':
	  type = 'enhancement'
        if PREFORMAT_COMMENTS:
          desc = '{{{\n%s\n}}}' % desc
	print "inserting ticket %s -- \"%s\"" % (id, summary[0:40].replace("\n", " "))
        c.execute("""INSERT OR REPLACE INTO ticket (id, type, time, changetime, component,
                                         severity, priority, owner, reporter, cc,
                                         version, milestone, status, resolution,
                                         summary, description, keywords)
                                 VALUES (%s, %s, %s, %s, %s,
                                         %s, %s, %s, %s, %s,
                                         %s, %s, %s, %s,
                                         %s, %s, %s)""",
                  (id, type, self.convertTime(time), self.convertTime(changetime), component.encode('utf-8'),
                  severity.encode('utf-8'), priority.encode('utf-8'), owner, reporter, cc,
                  version, milestone.encode('utf-8'), status.lower(), resolution,
                  summary.decode('utf-8'), desc, keywords.encode('utf-8')))
        self.db().commit()

        ## TODO: add database-specific methods to get the last inserted ticket's id...
        ## PostgreSQL:
        # c.execute('''SELECT currval("ticket_id_seq")''')
        ## SQLite:
        # c.execute('''SELECT last_insert_rowid()''')
        ## MySQL:
        # c.execute('''SELECT LAST_INSERT_ID()''')
        # Oh, Trac db abstraction layer already has a function for this...
        return self.db().get_last_id(c,'ticket')

    def convertTime(self,time2):
	time2 = datetime.fromtimestamp(time2)
	return long(str(int(time.mktime(time2.timetuple()))) + '000000')
    
    def addTicketComment(self, ticket, time, author, value):
	#return
        print " * adding comment \"%s...\"" % value[0:40]
        comment = value

        if PREFORMAT_COMMENTS:
          comment = '{{{\n%s\n}}}' % comment

        c = self.db().cursor()
        c.execute("""INSERT OR IGNORE INTO ticket_change (ticket, time, author, field, oldvalue, newvalue)
                                 VALUES        (%s, %s, %s, %s, %s, %s)""",
                  (ticket, self.convertTime(time), author, 'comment', '', comment))
        self.db().commit()

    def addTicketChange(self, ticket, time, author, field, oldvalue, newvalue):
        if (field[0:4]=='doba'): 
          return

	if field == 'milestone':
	  field = 'product_version'

        print " * adding ticket change \"%s\": \"%s\" -> \"%s\" (%s)" % (field, oldvalue[0:20], newvalue[0:20], time)
        c = self.db().cursor()
	
	#workaround 'unique' ticket_change warnings POTENTIALLY BAD IDEA ALERT
	sql = "SELECT * FROM ticket_change WHERE field='%s' AND ticket=%s AND time=%s" % (field, ticket, self.convertTime(time))
	c.execute(sql)
	fixtime = c.fetchall()
	if fixtime:
	  time = time + 1
        c.execute("""INSERT OR IGNORE INTO ticket_change (ticket, time, author, field, oldvalue, newvalue)
                                 VALUES        (%s, %s, %s, %s, %s, %s)""",
                  (ticket, self.convertTime(time), author, field, oldvalue.encode('utf-8'), newvalue.encode('utf-8')))
        self.db().commit()
       
	#workaround 'unique' ticket warnings POTENTIALLY BAD IDEA ALERT
        sql = "SELECT * FROM ticket WHERE %s='%s' AND id=%s AND time=%s" % (field, newvalue, ticket, self.convertTime(time))
        c.execute(sql)
        fixtime = c.fetchall()
        if fixtime:
          time = time + 1
 
	# Now actually change the ticket because the ticket wont update itself!
	sql = "UPDATE ticket SET %s='%s' WHERE id=%s" % (field, newvalue, ticket)
        c.execute(sql)
        self.db().commit()        
        
    # unused in 1.2
    def addAttachment(self, id, attachment, description, author):
        print 'inserting attachment for ticket %s -- %s' % (id, description)
        attachment.filename = attachment.filename.encode('utf-8')
        self.env.create_attachment(self.db(), 'ticket', str(id), attachment, description.encode('utf-8'),
            author, 'unknown')
        
    def getLoginName(self, cursor, userid):
        if userid not in self.loginNameCache and userid is not None and userid != '':
	    cursor.execute("SELECT username,email,realname,last_visit FROM mantis_user_table WHERE id = %i" % int(userid))
            result = cursor.fetchall()

            if result:
                loginName = result[0]['username']
                print 'Adding user %s to sessions table' % loginName
                c = self.db().cursor()

                # check if user is already in the sessions table
                c.execute("SELECT sid FROM session WHERE sid = '%s'" % result[0]['username'].encode('utf-8'))
                r = c.fetchall()
                
                # if there was no user sid in the database already
                if not r:
                    sessionSql = """INSERT INTO session 
                            (sid, authenticated, last_visit) 
                        VALUES (%s, %s, %s)""", (result[0]['username'].encode('utf-8'), '1', self.convertTime(result[0]['last_visit']))
                    # pre-populate the session table and the realname/email table with user data
                    try:
                        c.execute(sessionSql)
                    except:
                        print 'failed executing sql: '
                        print sessionSql
                        print 'could not insert %s into sessions table: sql error ' % (loginName)
                    self.db().commit()
                
                    # insert the user's real name into session attribute table
                    try:
   		        c.execute(
                        """INSERT INTO session_attribute 
                            (sid, authenticated, name, value)
                        VALUES
                            (%s, %s, %s, %s)""", (result[0]['username'].encode('utf-8'), '1', 'name', result[0]['realname'].encode('utf-8')))
		    except:
			print 'failed executing session-attribute sql'
                    self.db().commit()

                    # insert the user's email into session attribute table
		    try:
                        c.execute(
                        """INSERT INTO session_attribute 
                            (sid, authenticated, name, value)
                        VALUES
                            (%s, %s, %s, %s)""", (result[0]['username'].encode('utf-8'), '1', 'email', result[0]['email'].encode('utf-8')))
		    except:
			print 'failed executing session-attribute sql2'
                    self.db().commit()
            else:
                print 'warning: unknown mantis userid %d, recording as anonymous' % userid
                loginName = ''

            self.loginNameCache[userid] = loginName
	elif userid is None or userid == '':
	    self.loginNameCache[userid] = ''
        return self.loginNameCache[userid]

    def get_attachments_dir(self,bugid=0):
        if bugid > 0:
            return 'importfiles/%i/' % bugid        
        else:
            return 'importfiles/'

    def _mkdir(newdir):
        """works the way a good mkdir should :)
            - already exists, silently complete
            - regular file in the way, raise an exception
            - parent directory(ies) does not exist, make them as well
        """
        if os.path.isdir(newdir):
            pass
        elif os.path.isfile(newdir):
            raise OSError("a file with the same name as the desired " \
                          "dir, '%s', already exists." % newdir)
        else:
            head, tail = os.path.split(newdir)
            if head and not os.path.isdir(head):
                _mkdir(head)
            #print "_mkdir %s" % repr(newdir)
            if tail:
                os.mkdir(newdir)