Beispiel #1
0
    def save_ticket(self, tckt, msg):
        # determine sequence number...
        cnum = 0
        tm = TicketModule(self.env)
        for change in tm.grouped_changelog_entries(tckt, None):
            if change['permanent']:
                cnum += 1
        nowdt = self.now
        nowdt = to_datetime(nowdt)
        tckt.save_changes(self.authname, msg, nowdt, cnum=str(cnum + 1))
        ## Often the time overlaps and causes a db error,
        ## especially when the trac integration post-commit hook is used.
        ## NOTE TO SELF. I DON'T THINK THIS IS NECESSARY RIGHT NOW...
        #count = 0
        #while count < 10:
        #    try:
        #        tckt.save_changes(self.authname, msg, self.now, cnum=cnum+1)
        #        count = 42
        #    except Exception, e:
        #        self.now += 1
        #        count += 1

        tn = TicketNotifyEmail(self.env)
        tn.notify(tckt, newticket=0, modtime=nowdt)
        # We fudge time as it has to be unique
        self.now += 1
Beispiel #2
0
    def attachment_added(self, attachment):
        # Check whether we're dealing with a ticket resource
        resource = attachment.resource
        while resource:
            if resource.realm == 'ticket':
                break
            resource = resource.parent

        if (resource and resource.realm == 'ticket' and resource.id is not None):
            with self.env.db_transaction as db:
                ticket = Ticket(attachment.env, resource.id, db)
                if (attachment.author == ticket['reporter'] and ticket['status'] == 'pending'):
                    self.env.log.info('Removing Pending status for ticket %s due to attachment' % (ticket.id))

                    comment = 'Attachment (%s) added by ticket reporter.' % (attachment.filename)
                    ticket['status'] = self.config.get('ticket', 'pending_removal_status')

                    # determine sequence number...
                    cnum = 0
                    tm = TicketModule(self.env)
                    for change in tm.grouped_changelog_entries(ticket, db):
                        c_cnum = change.get('cnum', None)
                        if c_cnum and int(c_cnum) > cnum:
                            cnum = int(c_cnum)

                    #We can't just use attachment.date as it screws up event sequencing
                    now = datetime.now(utc)

                    ticket.save_changes(attachment.author, comment, now, db, str(cnum + 1))

                    #trigger notification since we've changed the ticket
                    tn = TicketNotifyEmail(self.env)
                    tn.notify(ticket, newticket=False, modtime=now)
Beispiel #3
0
 def _create_html_body(self, chrome, req, ticket, cnum, link):
     tktmod = TicketModule(self.env)
     attmod = AttachmentModule(self.env)
     data = tktmod._prepare_data(req, ticket)
     tktmod._insert_ticket_data(req, ticket, data, req.authname, {})
     data['ticket']['link'] = link
     changes = data.get('changes')
     if cnum is None:
         changes = []
     else:
         changes = [
             change for change in (changes or [])
             if change.get('cnum') == cnum
         ]
     data['changes'] = changes
     context = Context.from_request(req, ticket.resource, absurls=True)
     data.update({
         'can_append': False,
         'show_editor': False,
         'start_time': ticket['changetime'],
         'context': context,
         'alist': attmod.attachment_data(context),
         'styles': self._get_styles(chrome),
         'link': tag.a(link, href=link),
         'tag_': tag_,
     })
     rendered = chrome.render_template(req,
                                       'htmlnotification_ticket.html',
                                       data,
                                       fragment=True)
     return unicode(rendered)
Beispiel #4
0
 def save_ticket(self, tckt, db, msg):
     # determine sequence number... 
     cnum = 0
     tm = TicketModule(self.env)
     for change in tm.grouped_changelog_entries(tckt, db):
         if change['permanent']:
             cnum += 1
     tckt.save_changes(self.authname, msg, self.now, db, cnum+1)
     ## Often the time overlaps and causes a db error,
     ## especially when the trac integration post-commit hook is used.
     ## NOTE TO SELF. I DON'T THINK THIS IS NECESSARY RIGHT NOW...
     #count = 0
     #while count < 10:
     #    try:
     #        tckt.save_changes(self.authname, msg, self.now, db, cnum+1)
     #        count = 42
     #    except Exception, e:
     #        self.now += 1
     #        count += 1
     db.commit()
     
     tn = TicketNotifyEmail(self.env)
     tn.notify(tckt, newticket=0, modtime=self.now)
     # We fudge time as it has to be unique
     self.now += 1
Beispiel #5
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.env.config.set(
         'trac', 'permission_policies',
         'DefaultTicketPolicy, DefaultPermissionPolicy, '
         'LegacyAttachmentPolicy')
     self.ticket_module = TicketModule(self.env)
Beispiel #6
0
def post_to_ticket(msg, author, tkt_id, env):
    """Post the message to the ticket and send a notify email."""
    from trac.ticket.notification import TicketNotifyEmail
    from trac.ticket import Ticket
    from trac.ticket.web_ui import TicketModule
    from trac.util.datefmt import utc

    now = datetime.now(utc)

    try:
        db = env.get_db_cnx()
        # Get the related trac ticket object
        ticket = Ticket(env, tkt_id, db)

        # determine sequence number...
        cnum = 0
        tm = TicketModule(env)
        for change in tm.grouped_changelog_entries(ticket, db):
            if change['permanent']:
                cnum += 1

        ticket.save_changes(author, msg, now, db, cnum + 1)
        db.commit()

        tn = TicketNotifyEmail(env)
        tn.notify(ticket, newticket=0, modtime=now)
    except Exception, e:
        msg = 'Unexpected error processing ticket ID %s: %s' % (tkt_id, e)
        print >>sys.stderr, msg
Beispiel #7
0
    def apply_preset(self, req, tickets, preset=None):
        if preset is None:
            return tickets
            
        presets = preset and [kw.split('=', 1) for kw in preset.split('&')] or []
        fields = dict([(field, value) for field, value in presets])

        warn = []
        modified_tickets = []
        if tickets and presets:
            db = self.env.get_db_cnx()
            ticket_module = TicketModule(self.env)
            action = fields.get('action')

            for ticket_id in tickets:
                if 'TICKET_CHGPROP' in req.perm('ticket', ticket_id):
                    ticket  = Ticket(self.env, ticket_id, db)
                    ticket.populate(fields)
                    if action:
                        field_changes, problems = ticket_module.get_ticket_changes(req, ticket, action)
                        if problems:
                            for problem in problems:
                                warn.append(problem)
                        ticket_module._apply_ticket_changes(ticket, field_changes) # Apply changes made by the workflow

                    ticket.save_changes(req.authname, None, db=db)
                    modified_tickets.append(ticket_id)
                else:
                    warn.append(_("You have no permission to modify ticket '%(ticket)s'", ticket=ticket_id))
            db.commit()
        return { 'tickets' : modified_tickets, 'warnings': warn}
Beispiel #8
0
    def process_request(self, req):
        """Creating a new pull request ticket needs some pre- and post-
        processing:

         * Check if the given repository is a fork of another known
           repository.
         * Initialize some ticket fields.

        Then forward the processing to `TicketModule`

         * Add the repository as is must be looked up via the used path
           and is not yet known to the ticket.
        """
        req.perm.require('TICKET_CREATE')

        rm = RepositoryManager(self.env)
        reponame, repo, path = rm.get_repository_by_path(req.args.get('path'))
        convert_managed_repository(self.env, repo)
        if not repo.is_fork:
            raise TracError(_("Repository is not a fork."))

        req.args['type'] = 'pull request'
        req.args['pr_srcrev'] = req.args.get('pr_srcrev',
                                             repo.get_youngest_rev())

        tm = TicketModule(self.env)
        template, data, content_type = tm.process_request(req)

        data.update({'pr_srcrepo': repo})

        return template, data, content_type
Beispiel #9
0
    def process(self, commit, status, branch):
        self.closestatus = status

        milestones = [
            m.name for m in Milestone.select(self.env) if m.name != 'unknown'
        ]
        if branch.startswith('fixes/'):
            branch = branch[6:]
            milestones = [m for m in milestones if m.startswith(branch)]
        self.milestone = sorted(milestones)[-1]

        msg = commit['message']
        self.env.log.debug("Processing Commit: %s", msg)
        msg = "%s \n Branch:    %s \n Changeset: %s" % (msg, branch,
                                                        commit['id'])
        #        author = commit['author']['name']
        author = 'Github'
        timestamp = datetime.now(utc)

        cmd_groups = command_re.findall(msg)
        self.env.log.debug("Function Handlers: %s" % cmd_groups)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self.__class__._supported_cmds.get(cmd.lower(), '')
            self.env.log.debug("Function Handler: %s" % funcname)
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    if (branch == "master") or branch.startswith("fixes/"):
                        tickets.setdefault(tkt_id,
                                           []).append(getattr(self, funcname))
#                    disable this stuff for now, it causes duplicates on merges
#                    proper implementation of this will require tracking commit hashes
#                    else:
#                        tickets.setdefault(tkt_id, []).append(self._cmdRefs)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()

                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1

                ticket.save_changes(author, msg, timestamp, db, cnum + 1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=timestamp)
            except Exception, e:
                import traceback
                traceback.print_exc(file=sys.stderr)
Beispiel #10
0
    def __init__(self,
                 project=options.project,
                 author=AUTHOR,
                 maxage=options.maxage,
                 url=options.url):

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

        if url is None:
            url = self.env.config.get('trac', 'base_url')

        self.env.href = Href(url)
        self.env.abs_href = Href(url)

        self.msg = MESSAGE % (maxage)
        self.now = int(time.time())

        maxtime = int(time.time()) - (60 * 60 * 24 * maxage)

        cursor.execute("SELECT id FROM ticket t, ticket_custom c " \
                       "WHERE t.status <> %s " \
                "AND t.changetime < %s " \
                       "AND t.id = c.ticket " \
                       "AND c.name = %s " \
                       "AND c.value = %s ", ('closed', maxtime, 'pending', '1'))

        rows = cursor.fetchall()

        for row in rows:
            id = row[0]
            try:
                ticket = Ticket(self.env, id, db)

                ticket['status'] = 'closed'
                ticket['pending'] = '0'

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1

                ticket.save_changes(author, self.msg, self.now, db, cnum + 1)
                db.commit()

                print 'Closing Ticket %s (%s)\n' % (id, ticket['summary'])

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=self.now)
            except Exception, e:
                import traceback
                traceback.print_exc(file=sys.stderr)
                print>>sys.stderr, 'Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (id, e)
Beispiel #11
0
    def __init__(self,
                 project=options.project,
                 author=options.user,
                 rev=options.rev,
                 url=options.url):
        self.env = open_environment(project)
        repos = self.env.get_repository()
        repos.sync()

        # Instead of bothering with the encoding, we'll use unicode data
        # as provided by the Trac versioncontrol API (#1310).
        try:
            chgset = repos.get_changeset(rev)
        except NoSuchChangeset:
            return  # out of scope changesets are not cached
        self.author = chgset.author
        self.rev = rev
        self.msg = "(In [%s]) %s" % (rev, chgset.message)
        self.now = datetime.now(utc)

        cmd_groups = command_re.findall(self.msg)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = CommitHook._supported_cmds.get(cmd.lower(), '')
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()

                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1

                ticket.save_changes(self.author, self.msg, self.now, db,
                                    cnum + 1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=self.now)
            except Exception, e:
                # import traceback
                # traceback.print_exc(file=sys.stderr)
                print>>sys.stderr, 'Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (tkt_id, e)
Beispiel #12
0
    def process_request(self, req):
        id = req.args.getint('id')
        req.perm('ticket', id).require('TICKET_ADMIN')
        ticket = Ticket(self.env, id)
        action = req.args['action']
        cnum = req.args.get('cnum')
        if req.method == 'POST':
            if 'cancel' in req.args:
                href = req.href.ticket(id)
                if action == 'delete-comment':
                    href += '#comment:%s' % cnum
                req.redirect(href)

            if action == 'delete':
                ticket.delete()
                add_notice(
                    req,
                    _("Ticket #%(num)s and all associated data "
                      "removed.",
                      num=ticket.id))
                req.redirect(req.href())

            elif action == 'delete-comment':
                cdate = from_utimestamp(long(req.args.get('cdate')))
                ticket.delete_change(cdate=cdate)
                add_notice(
                    req,
                    _(
                        "The ticket comment %(num)s on ticket "
                        "#%(id)s has been deleted.",
                        num=cnum,
                        id=ticket.id))
                req.redirect(req.href.ticket(id))

        tm = TicketModule(self.env)
        data = tm._prepare_data(req, ticket)
        tm._insert_ticket_data(req, ticket, data,
                               get_reporter_id(req, 'author'), {})
        data.update(action=action, cdate=None)

        if action == 'delete-comment':
            data['cdate'] = req.args.get('cdate')
            cdate = from_utimestamp(long(data['cdate']))
            for change in data['changes']:
                if change.get('date') == cdate:
                    data['change'] = change
                    data['cnum'] = change.get('cnum')
                    break
            else:
                raise TracError(_("Comment %(num)s not found", num=cnum))
        elif action == 'delete':
            attachments = Attachment.select(self.env, ticket.realm, ticket.id)
            data.update(attachments=list(attachments))

        add_stylesheet(req, 'common/css/ticket.css')
        return 'ticket_delete.html', data
Beispiel #13
0
    def process(self, commit, status, branch):
        self.closestatus = status

        milestones = [m.name for m in Milestone.select(self.env) if m.name != "unknown"]
        if branch.startswith("fixes/"):
            branch = branch[6:]
            milestones = [m for m in milestones if m.startswith(branch)]
        self.milestone = sorted(milestones)[-1]

        msg = commit["message"]
        self.env.log.debug("Processing Commit: %s", msg)
        msg = "%s \n Branch:    %s \n Changeset: %s" % (msg, branch, commit["id"])
        #        author = commit['author']['name']
        author = "Github"
        timestamp = datetime.now(utc)

        cmd_groups = command_re.findall(msg)
        self.env.log.debug("Function Handlers: %s" % cmd_groups)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self.__class__._supported_cmds.get(cmd.lower(), "")
            self.env.log.debug("Function Handler: %s" % funcname)
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    if (branch == "master") or branch.startswith("fixes/"):
                        tickets.setdefault(tkt_id, []).append(getattr(self, funcname))
        #                    disable this stuff for now, it causes duplicates on merges
        #                    proper implementation of this will require tracking commit hashes
        #                    else:
        #                        tickets.setdefault(tkt_id, []).append(self._cmdRefs)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()

                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change["permanent"]:
                        cnum += 1

                ticket.save_changes(author, msg, timestamp, db, cnum + 1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=timestamp)
            except Exception, e:
                import traceback

                traceback.print_exc(file=sys.stderr)
Beispiel #14
0
    def __init__(self, project=options.project, author=AUTHOR,
                     maxage=options.maxage, url=options.url):

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

        if url is None:
        	url = self.env.config.get('trac', 'base_url')

        self.env.href = Href(url)
        self.env.abs_href = Href(url)

        self.msg = MESSAGE % (maxage)
        self.now = int(time.time())

        maxtime = int(time.time()) - (60 * 60 * 24 * maxage)

        cursor.execute("SELECT id FROM ticket t, ticket_custom c " \
                       "WHERE t.status <> %s " \
        	       "AND t.changetime < %s " \
                       "AND t.id = c.ticket " \
                       "AND c.name = %s " \
                       "AND c.value = %s ", ('closed', maxtime, 'pending', '1'))
    
        rows = cursor.fetchall()

        for row in rows:
            id = row[0]
            try:
                ticket = Ticket(self.env, id, db);

                ticket['status'] = 'closed'
                ticket['pending'] = '0';

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                	if change['permanent']:
                		cnum += 1

        
                ticket.save_changes(author, self.msg, self.now, db, cnum + 1)
                db.commit()

                print 'Closing Ticket %s (%s)\n' % (id, ticket['summary'])

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=self.now)
            except Exception, e:
                import traceback
                traceback.print_exc(file=sys.stderr)
                print>>sys.stderr, 'Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (id, e)
Beispiel #15
0
    def process(self, commit, status, enable_revmap, reponame):
        self.closestatus = status

        msg = commit['message']
        self.env.log.debug("Processing Commit: %s", msg)
        note = "Changeset: [/changeset/%s %s]" % (commit['id'], commit['id'])
        url = "URL: %s" % commit['url']
        msg = "%s \n * %s \n * %s" % (msg, note, url)
        author = commit['author']['name']
        timestamp = datetime.now(utc)
        if int(enable_revmap):
            self.env.log.debug("adding commit %s to revmap", commit['id'])
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            cursor.execute(
                "INSERT INTO svn_revmap (svn_rev, git_hash, commit_msg) VALUES (0, %s, %s);",
                (commit['id'], commit['message']))
            db.commit()

        cmd_groups = command_re.findall(msg)
        self.env.log.debug("Function Handlers: %s" % cmd_groups)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self.__class__._supported_cmds.get(cmd.lower(), '')
            self.env.log.debug("Function Handler: %s" % funcname)
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()

                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1

                ticket.save_changes(author, msg, timestamp, db, cnum + 1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=timestamp)
            except Exception, e:
                import traceback
                traceback.print_exc(file=sys.stderr)
Beispiel #16
0
    def process(self, commit, status, enable_revmap,reponame):
        self.closestatus = status
        
        msg = commit['message']
        self.env.log.debug("Processing Commit: %s", msg)
        note = "Changeset: [/changeset/%s %s]" % (commit['id'], commit['id'])
        url = "URL: %s" % commit['url']
        msg = "%s \n * %s \n * %s" % (msg, note, url)
        author = commit['author']['name']
        timestamp = datetime.now(utc)
        if int(enable_revmap):
            self.env.log.debug("adding commit %s to revmap", commit['id'])
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            cursor.execute("INSERT INTO svn_revmap (svn_rev, git_hash, commit_msg) VALUES (0, %s, %s);",
                    (commit['id'], commit['message']))
            db.commit()
        
        cmd_groups = command_re.findall(msg)
        self.env.log.debug("Function Handlers: %s" % cmd_groups)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self.__class__._supported_cmds.get(cmd.lower(), '')
            self.env.log.debug("Function Handler: %s" % funcname)
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()
                
                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number... 
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1
                
                ticket.save_changes(author, msg, timestamp, db, cnum+1)
                db.commit()
                
                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=timestamp)
            except Exception, e:
                import traceback
                traceback.print_exc(file=sys.stderr)
    def __init__(self, project=options.project, author=options.user,
                 rev=options.rev, url=options.url):
        self.env = open_environment(project)
        repos = self.env.get_repository()
        repos.sync()
        
        # Instead of bothering with the encoding, we'll use unicode data
        # as provided by the Trac versioncontrol API (#1310).
        try:
            chgset = repos.get_changeset(rev)
        except NoSuchChangeset:
            return # out of scope changesets are not cached
        self.author = chgset.author
        self.rev = rev
        self.msg = "(In [%s]) %s" % (rev, chgset.message)
        self.now = datetime.now(utc)

        cmd_groups = command_re.findall(self.msg)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = CommitHook._supported_cmds.get(cmd.lower(), '')
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()
                
                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number... 
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1
                
                ticket.save_changes(self.author, self.msg, self.now, db, cnum+1)
                db.commit()
                
                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=self.now)
            except Exception, e:
                # import traceback
                # traceback.print_exc(file=sys.stderr)
                print>>sys.stderr, 'Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (tkt_id, e)
 def _update_ticket(ticket):
     # Determine sequence number.
     cnum = 0
     tm = TicketModule(self.env)
     db = self.env.get_db_cnx()
     for change in tm.grouped_changelog_entries(ticket, db):
         # FIXME - should this say "and change['cnum'] > cnum?
         if change['permanent']:
             cnum = change['cnum']
     # FIXME - Put something in the message?
     # FIXME - the ticket_changed method gets an author, should
     # this say "value propagation on behalf of <author>"?
     ticket.save_changes('value propagation', '', when, db, cnum+1)
    def _update_controls(self, req, action_controls, actions, tkt):
        """Given list of actions, update action_controls w/all requiring input.

        control[2] represents HTML inputs required before an action can be
        completed. If it exists, we make a note of the action operation."""
        tm = TicketModule(self.env)
        for (act, act_ops) in actions.itervalues():
            for act_op in act_ops:
                if act_op not in action_controls:
                    control = list(tm.get_action_control(req, act, tkt))
                    control[2] = str(control[2])
                    if control[2]:
                        action_controls[act_op] = control
Beispiel #20
0
    def __init__(self, project=options.project, author=AUTHOR,
                     maxage=options.maxage):

        try:
            self.env = open_environment(project)
            db = self.env.get_db_cnx()
            cursor = db.cursor()

            msg = MESSAGE % (maxage)

            now = datetime.now(utc)
            maxtime = to_utimestamp(now - timedelta(days=maxage))

            cursor.execute("SELECT id FROM ticket " \
                           "WHERE status = %s " \
                           "AND changetime < %s ", ('pending', maxtime))
    
            rows = cursor.fetchall()

            for row in rows:
                id = row[0]
                try:
                    ticket = Ticket(self.env, id, db);

                    ticket['status'] = 'closed'

                    # determine sequence number...
                    cnum = 0
                    tm = TicketModule(self.env)
                    for change in tm.grouped_changelog_entries(ticket, db):
                        c_cnum = change.get('cnum', None)
                        if c_cnum and int(c_cnum) > cnum:
                            cnum = int(c_cnum)

                    ticket.save_changes(author, msg, now, db, str(cnum + 1))
                    db.commit()

                    print 'Closing Ticket %s (%s)' % (id, ticket['summary'])

                    tn = TicketNotifyEmail(self.env)
                    tn.notify(ticket, newticket=0, modtime=now)
                except Exception, e:
                    import traceback
                    traceback.print_exc(file=sys.stderr)
                    print>>sys.stderr, 'Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (id, e)
        except Exception, e:
               import traceback
               traceback.print_exc(file=sys.stderr)
               print>>sys.stderr, 'Unexpected error while retrieving tickets '
Beispiel #21
0
    def process_request(self, req):
        id = int(req.args.get('id'))
        req.perm('ticket', id).require('TICKET_ADMIN')
        ticket = Ticket(self.env, id)
        action = req.args['action']
        cnum = req.args.get('cnum')
        if req.method == 'POST':
            if 'cancel' in req.args:
                href = req.href.ticket(id)
                if action == 'delete-comment':
                    href += '#comment:%s' % cnum
                req.redirect(href)

            if action == 'delete':
                ticket.delete()
                add_notice(req, _('The ticket #%(id)s has been deleted.',
                                  id=ticket.id))
                req.redirect(req.href())

            elif action == 'delete-comment':
                cdate = from_utimestamp(long(req.args.get('cdate')))
                ticket.delete_change(cdate=cdate)
                add_notice(req, _('The ticket comment %(num)s on ticket '
                                  '#%(id)s has been deleted.',
                                  num=cnum, id=ticket.id))
                req.redirect(req.href.ticket(id))

        tm = TicketModule(self.env)
        data = tm._prepare_data(req, ticket)
        tm._insert_ticket_data(req, ticket, data,
                               get_reporter_id(req, 'author'), {})
        data.update(action=action, cdate=None)

        if action == 'delete-comment':
            data['cdate'] = req.args.get('cdate')
            cdate = from_utimestamp(long(data['cdate']))
            for change in data['changes']:
                if change.get('date') == cdate:
                    data['change'] = change
                    data['cnum'] = change.get('cnum')
                    break
            else:
                raise TracError(_('Comment %(num)s not found', num=cnum))
        elif action == 'delete':
            attachments = Attachment.select(self.env, ticket.realm, ticket.id)
            data.update(attachments=list(attachments))

        add_stylesheet(req, 'common/css/ticket.css')
        return 'ticket_delete.html', data, None
Beispiel #22
0
    def process_request(self, req):
        id = int(req.args.get('id'))
        req.perm('ticket', id).require('TICKET_ADMIN')
        ticket = Ticket(self.env, id)
        action = req.args['action']
        if req.method == 'POST':
            if 'cancel' in req.args:
                href = req.href.ticket(id)
                if action == 'delete-comment':
                    href += '#comment:%s' % req.args.get('cnum')
                req.redirect(href)

            if action == 'delete':
                ticket.delete()
                add_notice(
                    req, _('The ticket #%(id)s has been deleted.',
                           id=ticket.id))
                req.redirect(req.href())

            elif action == 'delete-comment':
                cnum = int(req.args.get('cnum'))
                ticket.delete_change(cnum)
                add_notice(
                    req,
                    _(
                        'The ticket comment %(num)s on ticket '
                        '#%(id)s has been deleted.',
                        num=cnum,
                        id=ticket.id))
                req.redirect(req.href.ticket(id))

        tm = TicketModule(self.env)
        data = tm._prepare_data(req, ticket)
        tm._insert_ticket_data(req, ticket, data,
                               get_reporter_id(req, 'author'), {})
        data.update(action=action, del_cnum=None)

        if action == 'delete-comment':
            cnum = int(req.args.get('cnum'))
            data['del_cnum'] = cnum
            for change in data['changes']:
                if change.get('cnum') == cnum:
                    data['change'] = change
                    break
            else:
                raise TracError(_('Comment %(num)s not found', num=cnum))

        add_stylesheet(req, 'common/css/ticket.css')
        return 'ticket_delete.html', data, None
Beispiel #23
0
    def _render_editor(self, req, db, milestone):
        data = {
            'milestone': milestone,
            'ticket': milestone.ticket,
            'datefields': self.date_fields,
            'date_hint': get_date_format_hint(),
            'datetime_hint': get_datetime_format_hint(),
            'milestone_groups': [],
            'jump_to': req.args.get('jump_to') or referer_module(req)
        }

        if milestone.exists:
            req.perm(milestone.resource).require('MILESTONE_VIEW')
            milestones = [
                m for m in StructuredMilestone.select(self.env, db=db)
                if m.name != milestone.name
                and 'MILESTONE_VIEW' in req.perm(m.resource)
            ]
            data['milestone_groups'] = group_milestones(
                milestones, 'TICKET_ADMIN' in req.perm)
        else:
            req.perm(milestone.resource).require('MILESTONE_CREATE')

        TicketModule(self.env)._insert_ticket_data(
            req, milestone.ticket, data, get_reporter_id(req, 'author'), {})
        self._add_tickets_report_data(milestone, req, data)
        context = Context.from_request(req, milestone.resource)

        data['attachments'] = AttachmentModule(
            self.env).attachment_data(context)

        return 'itteco_milestone_edit.html', data, None
Beispiel #24
0
 def decorate_message(self, event, message, charset):
     if event.realm != 'ticket':
         return
     if event.category == 'batchmodify':
         notify = BatchTicketNotifyEmail(self.env)
         tickets = event.target
         tickets_descr = ', '.join(['#%s' % t for t in tickets])
         subject = notify.format_subj(tickets_descr)
     else:
         notify = TicketNotifyEmail(self.env)
         ticket = event.target
         notify.ticket = ticket
         summary = ticket['summary']
         from trac.ticket.web_ui import TicketModule
         for change in TicketModule(self.env) \
                       .grouped_changelog_entries(ticket, when=event.time):
             if 'summary' in change['fields']:
                 values = change['fields']['summary']
                 summary = "%s (was: %s)" % (values['new'], values['old'])
         subject = notify.format_subj(summary, event.category == 'created')
         msgid = self._get_message_id(event, newticket=True)
         url = self.env.abs_href.ticket(ticket.id)
         if event.category == 'created':
             set_header(message, 'Message-ID', msgid, charset)
         else:
             set_header(message, 'Message-ID', self._get_message_id(event),
                        charset)
             set_header(message, 'In-Reply-To', msgid, charset)
             set_header(message, 'References', msgid, charset)
             cnum = ticket.get_comment_number(event.time)
             if cnum is not None:
                 url += '#comment:%d' % cnum
         set_header(message, 'X-Trac-Ticket-ID', ticket.id, charset)
         set_header(message, 'X-Trac-Ticket-URL', url, charset)
     set_header(message, 'Subject', subject, charset)
 def setUp(self):
     self.env = EnvironmentStub(default_data=True)
     config = self.env.config
     config.set('ticket-workflow', 'change_owner', 'new -> new')
     config.set('ticket-workflow', 'change_owner.operations', 'set_owner')
     self.ctlr = TicketSystem(self.env).action_controllers[0]
     self.ticket_module = TicketModule(self.env)
Beispiel #26
0
 def pre_process_request(self, req, handler):
     if handler is not TicketModule(self.env):
         return handler
     action = req.args.get('action')
     if action in ('delete', 'delete-comment'):
         return self
     else:
         return handler
Beispiel #27
0
    def process(self, commit, status, payload):
        self.closestatus = status
        
        self.env.log.debug("Processing Commit: %s", commit['id'])
        comment = (commit['message']
            + "\n\n"
            + self.comment_template.format(commit=commit,**payload))
        self.env.log.debug("Prepared Comment: %s", comment)
        author = commit['author']['name']
        timestamp = datetime.now(utc)
        
        cmd_groups = command_re.findall(comment)
        self.env.log.debug("Function Handlers: %s" % cmd_groups)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self.__class__._supported_cmds.get(cmd.lower(), '')
            self.env.log.debug("Function Handler: %s" % funcname)
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()
                
                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number... 
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1
                
                ticket.save_changes(author, comment, timestamp, db, cnum+1)
                db.commit()
                
                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=timestamp)
            except Exception, e:
                import traceback
                traceback.print_exc(file=sys.stderr)
Beispiel #28
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.env.config.set(
         'trac', 'templates_dir',
         os.path.join(os.path.dirname(self.env.path), 'templates'))
     self.ticket_module = TicketModule(self.env)
     self.mimeview = Mimeview(self.env)
     self.req = MockRequest(self.env, authname='anonymous')
Beispiel #29
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.ticket_module = TicketModule(self.env)
     self.mimeview = Mimeview(self.env)
     self.req = Mock(hdf=HDFWrapper(['./templates']),
                     base_path='/trac.cgi',
                     path_info='',
                     href=Href('/trac.cgi'))
Beispiel #30
0
    def process(self, commit, status):
        self.closestatus = status

        msg = commit['message']
        self.env.log.debug("Processing Commit: %s", msg)
        note = "Changeset: %s" % commit['id']
        msg = "%s[[BR]]\n%s" % (msg, note)
        author = commit['author']['name']
        timestamp = datetime.now(utc)

        cmd_groups = command_re.findall(msg)
        self.env.log.debug("Function Handlers: %s" % cmd_groups)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self.__class__._supported_cmds.get(cmd.lower(), '')
            self.env.log.debug("Function Handler: %s" % funcname)
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()

                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1

                ticket.save_changes(author, msg, timestamp, db, cnum + 1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=timestamp)
            except Exception, e:
                import traceback
                traceback.print_exc(file=sys.stderr)
def handle_commit(commit, env, repo):
    from trac.ticket.notification import TicketNotifyEmail
    from trac.ticket import Ticket
    from trac.ticket.web_ui import TicketModule
    from trac.util.text import to_unicode
    from trac.util.datefmt import utc

    commit_log = call_git("rev-list", ["-n", "1", commit, "--pretty=medium"])
    commit_log = process_commit_log(commit_log, repo)
    commit_log = commit_log.rstrip()
    msg = to_unicode(commit_log)
    eml = to_unicode(call_git("rev-list", ["-n", "1", commit, "--pretty=format:%ae"]).splitlines()[1])
    now = datetime.now(utc)

    tickets = {}
    for cmd, tkts in command_re.findall(msg.split("\n\n", 1)[1]):
        action = COMMANDS.get(cmd.lower())
        if action:
            for tkt_id in ticket_re.findall(tkts):
                tickets.setdefault(tkt_id, []).append(action)

    for tkt_id, actions in tickets.iteritems():
        try:
            db = env.get_db_cnx()
            ticket = Ticket(env, int(tkt_id), db)

            if "close" in actions:
                ticket["status"] = "closed"
                ticket["resolution"] = "fixed"

            # determine sequence number...
            cnum = 0
            tm = TicketModule(env)
            for change in tm.grouped_changelog_entries(ticket, db):
                if change["permanent"]:
                    cnum += 1

            ticket.save_changes(eml, msg, now, db, cnum + 1)
            db.commit()

            tn = TicketNotifyEmail(env)
            tn.notify(ticket, newticket=0, modtime=now)
        except Exception, e:
            print >>sys.stderr, "Unexpected error while processing ticket ID %s: %s" % (tkt_id, e)
Beispiel #32
0
    def on_change(self, env, chgset):
        self.env = env
        self.author = chgset.author
        self.rev = chgset.rev
        self.msg = "(In [%s]) %s" % (self.rev, chgset.message)
        self.now = chgset.date

        cmd_groups = command_re.findall(self.msg)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self._supported_cmds.get(cmd.lower(), '')
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()

                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1

                ticket.save_changes(self.author, self.msg, self.now, db,
                                    cnum + 1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=self.now)
            except Exception, e:
                # import traceback
                # traceback.print_exc(file=sys.stderr)
                print>>sys.stderr, 'Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (tkt_id, e)
Beispiel #33
0
 def test_get_moved_attributes(self):
     """The attributes `max_comment_size`, `max_description_size` and
     `max_summary_size` have been moved to TicketSystem but are
     accessible on TicketModule for backward compatibility.
     """
     ts = TicketSystem(self.env)
     tm = TicketModule(self.env)
     self.assertEqual(ts.max_comment_size, tm.max_comment_size)
     self.assertEqual(ts.max_description_size, tm.max_description_size)
     self.assertEqual(ts.max_summary_size, tm.max_summary_size)
Beispiel #34
0
def _preserve_newlines(env):
    ticket = TicketModule(env)
    # Trac 0.11.2 later
    if hasattr(ticket, 'must_preserve_newlines'):
        return ticket.must_preserve_newlines

    preserve_newlines = ticket.preserve_newlines
    if preserve_newlines == 'default':
        preserve_newlines = env.get_version(initial=True) >= 21  # 0.11
    return preserve_newlines in _TRUE_VALUES
Beispiel #35
0
    def on_change(self, env, chgset):
        self.env = env
        self.author = chgset.author
        self.rev = chgset.rev        
        self.msg = "(In [%s]) %s" % (self.rev, chgset.message)        
        self.now = chgset.date

        cmd_groups = command_re.findall(self.msg)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self._supported_cmds.get(cmd.lower(), '')
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()
                
                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number... 
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1
                
                ticket.save_changes(self.author, self.msg, self.now, db, cnum+1)
                db.commit()
                
                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=self.now)
            except Exception, e:
                # import traceback
                # traceback.print_exc(file=sys.stderr)
                print>>sys.stderr, 'Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (tkt_id, e)
        def _implementation(db):
            tkt = Ticket(self.env, ticket_id)
            ts = TicketSystem(self.env)
            tm = TicketModule(self.env)
            if action not in ts.get_available_actions(req, tkt):
                raise ValueError(["This ticket cannot be moved to this status,\
                      perhaps the ticket has been updated by someone else."])

            field_changes, problems = \
                tm.get_ticket_changes(req, tkt, action)

            if problems:
                raise ValueError(problems)

            tm._apply_ticket_changes(tkt, field_changes)
            valid = tm._validate_ticket(req, tkt, force_collision_check=True)
            if not valid:
                raise ValueError(req.chrome['warnings'])
            else:
                tkt.save_changes(req.authname, "", when=datetime.now(utc))
Beispiel #37
0
 def _comment_ticket(self, req, tkt_id):
     tkt = Ticket(self.env, tkt_id)
     if not tkt.exists:
         raise ResourceNotFound('Ticket %s does not exist.' % tkt_id,
                                'Invalid Ticket Id')
         req.perm.require('TICKET_MODIFY', Resource('ticket', tkt.resource))
     changes = TicketModule(self.env).rendered_changelog_entries(req, tkt)
     return 'itteco_ticket_comment.html', {
         'ticket': tkt,
         'changes': changes
     }, 'text/html'
def handle_commit(commit, env):
    from trac.ticket.notification import TicketNotifyEmail
    from trac.ticket import Ticket
    from trac.ticket.web_ui import TicketModule
    from trac.util.text import to_unicode
    from trac.util.datefmt import utc

    msg = to_unicode(call_git('rev-list', ['-n', '1', commit, '--pretty=medium']).rstrip())
    eml = to_unicode(call_git('rev-list', ['-n', '1', commit, '--pretty=format:%ae']).splitlines()[1])
    now = datetime.now(utc)

    tickets = {}
    for cmd, tkts in command_re.findall(msg.split('\n\n', 1)[1]):
        action = COMMANDS.get(cmd.lower())
        if action:
            for tkt_id in ticket_re.findall(tkts):
                tickets.setdefault(tkt_id, []).append(action)

    for tkt_id, actions in tickets.iteritems():
        try:
            db = env.get_db_cnx()
            ticket = Ticket(env, int(tkt_id), db)

            if 'close' in actions:
                ticket['status'] = 'closed'
                ticket['resolution'] = 'fixed'

            # determine sequence number...
            cnum = 0
            tm = TicketModule(env)
            for change in tm.grouped_changelog_entries(ticket, db):
                if change['permanent']:
                    cnum += 1

            ticket.save_changes(eml, msg, now, db, cnum + 1)
            db.commit()

            tn = TicketNotifyEmail(env)
            tn.notify(ticket, newticket=0, modtime=now)
        except Exception, e:
            print >>sys.stderr, 'Unexpected error while processing ticket ID %s: %s' % (tkt_id, e)
Beispiel #39
0
 def setUp(self):
     self.env = EnvironmentStub()
     self.env.config.set('trac', 'templates_dir',
                         os.path.join(os.path.dirname(self.env.path),
                                      'templates'))
     self.ticket_module = TicketModule(self.env)
     self.mimeview = Mimeview(self.env)
     self.req = Mock(base_path='/trac.cgi', path_info='',
                     href=Href('/trac.cgi'), chrome={'logo': {}},
                     abs_href=Href('http://example.org/trac.cgi'),
                     environ={}, perm=[], authname='-', args={}, tz=None,
                     locale='', session=None, form_token=None)
Beispiel #40
0
    def _comment_milestone(self, req, mil_id):
        milestone = StructuredMilestone(self.env, mil_id)
        if not milestone.exists:
            raise ResourceNotFound('Milestone %s does not exist.' % mil_id,
                                   'Invalid Milestone Name')

        req.perm.require('MILESTONE_MODIFY', milestone.resource)
        changes = TicketModule(self.env).rendered_changelog_entries(
            req, milestone.ticket)
        return 'itteco_milestone_comment.html', {
            'milestone': milestone,
            'changes': changes
        }, 'text/html'
    def validate_ticket(self, req, ticket):
        """Validate any user fields by checking to see if the specified user
        belongs to any of the fields' allowed groups"""
        for field in self._user_fields():
            flc = TicketModule(self.env).field_layout_controller
            fl_config = flc.get_layout_for_field_on_type(ticket['type'],field)
            manual_entry = self.config.get("ticket-custom", field + ".manual")

            if not manual_entry and fl_config:
                username = (ticket[field] or u'').strip()
                valid_groups = self._get_valid_groups(field)
                valid = False

                if not username and not fl_config.get("mandatory"):
                    continue

                try:
                    spsystem = SimplifiedPermissionsSystem(self.env)
                    for provider in spsystem.user_lookup_providers:
                        info = provider.fetch_user_data(username)
                        if info and "groups" in info:
                            if any(g in info["groups"] for g in valid_groups):
                                valid = True
                                break

                    if valid:
                        continue
                    else:
                        yield field, ("User '%s', selected for field '%s' does"
                                      " not appear to be a member of any of"
                                      " the valid groups '%s'" % (username,
                                        field, ", ".join(valid_groups)))

                except Exception:
                    self.log.warn('UserFieldModule: Got an exception, '
                                  'assuming it is a validation failure.\n%s',
                                  format_exc())
                    yield field, ("Field %s does not appear to contain a valid"
                                  " user" % (field))
Beispiel #42
0
    def process(self, commit):
        msg = commit['message']
        author = commit['author']['name']
        timestamp = datetime.now(utc)
        
        cmd_groups = command_re.findall(msg)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self.__class__._supported_cmds.get(cmd.lower(), '')
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    tickets.setdefault(tkt_id, []).append(func)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()
                
                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number... 
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1
                
                ticket.save_changes(author, msg, timestamp, db, cnum+1)
                db.commit()
                
                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=timestamp)
            except Exception, e:
                import traceback
                traceback.print_exc(file=sys.stderr)
Beispiel #43
0
 def _get_search_filters(self, req):
     filters = []
     if TicketModule(self.env).get_search_filters(req) is not None:
         filters.extend([{
             'name': ticket.name,
             'label': ticket.name,
             'active': True
         } for ticket in Type.select(self.env)])
     wikifilters = WikiModule(self.env).get_search_filters(req)
     if wikifilters:
         filters.extend([{
             'name': f[0],
             'label': f[1],
             'active': True
         } for f in wikifilters])
     return filters
        def _implementation(db):
            tkt = Ticket(self.env, ticket_id)
            tm = TicketModule(self.env)
            req.args[field] = new_value
            tm._populate(req, tkt, plain_fields=True)

            changes, problems = tm.get_ticket_changes(req, tkt, "btn_save")

            if problems:
                raise ValueError(problems)

            tm._apply_ticket_changes(tkt, changes)
            valid = tm._validate_ticket(req, tkt, force_collision_check=True)
            if not valid:
                raise ValueError(req.chrome['warnings'])
            else:
                tkt.save_changes(req.authname, "", when=datetime.now(utc))
Beispiel #45
0
    def get_navigation_items(self, req):
        # Don't allow this to be exposed
        if 'DO_PRIVATETICKETS_FILTER' in req.args.keys():
            del req.args['DO_PRIVATETICKETS_FILTER']

        # Various ways to allow access
        if not req.perm.has_permission('TICKET_VIEW') and \
           (req.perm.has_permission('TICKET_VIEW_REPORTER') or \
           req.perm.has_permission('TICKET_VIEW_OWNER') or \
           req.perm.has_permission('TICKET_VIEW_CC') or \
           req.perm.has_permission('TICKET_VIEW_REPORTER_GROUP') or \
           req.perm.has_permission('TICKET_VIEW_OWNER_GROUP') or \
           req.perm.has_permission('TICKET_VIEW_CC_GROUP')):
            if TicketModule(self.env).match_request(req):
                if PrivateTicketsSystem(self.env).check_ticket_access(
                        req, req.args['id']):
                    self._grant_view(req)
            elif AttachmentModule(self.env).match_request(req):
                if req.args['type'] == 'ticket' and PrivateTicketsSystem(
                        self.env).check_ticket_access(
                            req, req.args['path'].split('/')[0]):
                    self._grant_view(req)
            elif QueryModule(self.env).match_request(req):
                req.args['DO_PRIVATETICKETS_FILTER'] = 'query'
                self._grant_view(req)  # Further filtering in query.py
            elif SearchModule(self.env).match_request(req):
                if 'ticket' in req.args.keys():
                    req.args['pticket'] = req.args['ticket']
                    del req.args['ticket']
            elif ReportModule(self.env).match_request(req):
                self._grant_view(req)  # So they can see the query page link
                if req.args.get('id'):
                    req.args['DO_PRIVATETICKETS_FILTER'] = 'report'

            # NOTE: Send this back here because the button would be hidden otherwise. <NPK t:1129>
            if not self.env.is_component_enabled(
                    ReportModule) or not req.perm.has_permission(
                        'REPORT_VIEW'):
                return [('mainnav', 'tickets',
                         html.A('View Tickets', href=req.href.query()))]

        return []
        def do_save(db):
            tm = TicketModule(self.env)
            req.args["milestone"] = milestone

            if ts:
                req.args["ts"] = ts
                
            tm._populate(req, ticket, plain_fields=True)

            changes, problems = tm.get_ticket_changes(req, ticket, "btn_save")

            if problems:
                raise ValueError(problems)

            tm._apply_ticket_changes(ticket, changes)
            valid = tm._validate_ticket(req, ticket, force_collision_check=True)
            if not valid:
                raise ValueError(req.chrome['warnings'])
            else:
                ticket.save_changes(req.authname, "", when=datetime.now(utc))
Beispiel #47
0
    def _create_sheet_history(self, req, context, data, book):
        sheet = book.add_sheet(dgettext("messages", "Change History"))
        writer = WorksheetWriter(sheet, req)

        groups = data['groups']
        headers = [header for header in data['headers']
                   if header['name'] not in ('id', 'time', 'changetime')]
        headers[0:0] = [
            {'name': 'id', 'label': dgettext("messages", "Ticket")},
            {'name': 'time', 'label': dgettext("messages", "Time")},
            {'name': 'author', 'label': dgettext("messages", "Author")},
            {'name': 'comment', 'label': dgettext("messages", "Comment")},
        ]

        writer.write_row(
            (header['label'], 'thead', None, None)
            for idx, header in enumerate(headers))

        mod = TicketModule(self.env)
        for result in chain(*[results for groupname, results in groups]):
            id = result['id']
            ticket = Ticket(self.env, id)
            ticket_context = context('ticket', id)
            values = ticket.values.copy()
            changes = []

            for change in mod.rendered_changelog_entries(req, ticket):
                if change['permanent']:
                    changes.append(change)
            for change in reversed(changes):
                change['values'] = values
                values = values.copy()
                for name, field in change['fields'].iteritems():
                    if name in values:
                        values[name] = field['old']
            changes[0:0] = [{'date': ticket.time_created, 'fields': {},
                             'values': values, 'cnum': None,
                             'comment': '', 'author': ticket['reporter']}]

            for change in changes:
                cells = []
                for idx, header in enumerate(headers):
                    name = header['name']
                    if name == 'id':
                        value = id
                    elif name == 'time':
                        value = change.get('date', '')
                    elif name == 'comment':
                        value = change.get('comment', '')
                    elif name == 'author':
                        value = change.get('author', '')
                    else:
                        value = change['values'].get(name, '')
                    value, style, width, line = \
                            self._get_cell_data(name, value, req,
                                                ticket_context, writer)
                    if name in change['fields']:
                        style = '%s:change' % style
                    cells.append((value, style, width, line))
                writer.write_row(cells)

        writer.set_col_widths()
Beispiel #48
0
    def _do_save(self, req, db, milestone):
        if milestone.exists:
            req.perm(milestone.resource).require('MILESTONE_MODIFY')
        else:
            req.perm(milestone.resource).require('MILESTONE_CREATE')
        
        ticket_module = TicketModule(self.env)
        ticket_module._populate(req, milestone.ticket, False)
        if not milestone.exists:
            reporter_id = get_reporter_id(req, 'author')
            milestone.ticket.values['reporter'] = reporter_id

        action = req.args.get('action', 'leave')

        field_changes, problems = ticket_module.get_ticket_changes(req, milestone.ticket,
                                    action)
        if problems:
            for problem in problems:
                add_warning(req, problem)
                add_warning(req,
                            tag(tag.p('Please review your configuration, '
                                      'probably starting with'),
                                tag.pre('[trac]\nworkflow = ...\n'),
                                tag.p('in your ', tag.tt('trac.ini'), '.'))
                            )

        ticket_module._apply_ticket_changes(milestone.ticket, field_changes)

        old_name = milestone.name
        new_name = milestone.ticket['summary']
        
        milestone.name = new_name
        milestone.description = milestone.ticket['description']

        due = req.args.get('duedate', '')
        milestone.due = due and parse_date(due, tzinfo=req.tz) or None
        milestone.ticket['duedate']=milestone.due and str(to_timestamp(milestone.due)) or None

        completed = req.args.get('completedate', '')
        retarget_to = req.args.get('target')

        # Instead of raising one single error, check all the constraints and
        # let the user fix them by going back to edit mode showing the warnings
        warnings = []
        def warn(msg):
            add_warning(req, msg)
            warnings.append(msg)

        # -- check the name
        if new_name:
            if new_name != old_name:
                # check that the milestone doesn't already exists
                # FIXME: the whole .exists business needs to be clarified
                #        (#4130) and should behave like a WikiPage does in
                #        this respect.
                try:
                    other_milestone = StructuredMilestone(self.env, new_name, db)
                    warn(_('Milestone "%(name)s" already exists, please '
                           'choose another name', name=new_name))
                except ResourceNotFound:
                    pass
        else:
            warn(_('You must provide a name for the milestone.'))

        # -- check completed date
        if action in MilestoneSystem(self.env).starting_action:
            milestone.ticket['started'] = str(to_timestamp(datetime.now(utc)))
        if action in MilestoneSystem(self.env).completing_action:
            milestone.completed = datetime.now(utc)
            
        if warnings:
            return self._render_editor(req, db, milestone)
        
        # -- actually save changes
        if milestone.exists:
            cnum = req.args.get('cnum')
            replyto = req.args.get('replyto')
            internal_cnum = cnum
            if cnum and replyto: # record parent.child relationship
                internal_cnum = '%s.%s' % (replyto, cnum)

            now = datetime.now(utc)
            milestone.save_changes(get_reporter_id(req, 'author'),
                                         req.args.get('comment'), when=now,
                                         cnum=internal_cnum)
            # eventually retarget opened tickets associated with the milestone
            if 'retarget' in req.args and completed:
                cursor = db.cursor()
                cursor.execute("UPDATE ticket SET milestone=%s WHERE "
                               "milestone=%s and status != 'closed'",
                                (retarget_to, old_name))
                self.env.log.info('Tickets associated with milestone %s '
                                  'retargeted to %s' % (old_name, retarget_to))
        else:
            milestone.insert()
        db.commit()

        add_notice(req, _('Your changes have been saved.'))
        jump_to = req.args.get('jump_to', 'roadmap')
        if jump_to=='roadmap':
            req.redirect(req.href.roadmap())
        elif jump_to =='whiteboard':
            req.redirect(req.href.whiteboard('team_tasks')+'#'+milestone.name)
        else:
            req.redirect(req.href.milestone(milestone.name))
 def setUp(self):
     self.env = EnvironmentStub(default_data=True,
                                enable=['trac.*', 'advancedworkflow.*'])
     self.tktmod = TicketModule(self.env)
class AdvancedTicketWorkflowTestCase(unittest.TestCase):

    def setUp(self):
        self.env = EnvironmentStub(default_data=True,
                                   enable=['trac.*', 'advancedworkflow.*'])
        self.tktmod = TicketModule(self.env)

    def tearDown(self):
        self.env.reset_db()

    def _config_set(self, section, entries):
        for option, value in entries:
            self.env.config.set(section, option, value)

    def _insert_ticket(self, when=None, **values):
        values.setdefault('status', 'new')
        values.setdefault('type', 'defect')
        ticket = Ticket(self.env)
        ticket.populate(values)
        return ticket.insert(when=when)

    def _insert_component(self, name, owner):
        component = model.Component(self.env)
        component.name = name
        component.owner = owner
        component.insert()

    def _post_req(self, action, ticket):
        form_token = 'x' * 40
        args = {'action': action, 'submit': '1', '__FORM_TOKEN': form_token,
                'view_time': str(to_utimestamp(ticket['changetime']))}
        args.update(('field_' + f['name'], ticket[f['name']])
                    for f in ticket.fields)
        return MockRequest(self.env, method='POST', form_token=form_token,
                           path_info='/ticket/%d' % ticket.id, args=args)

    def test_set_owner_to_reporter(self):
        self.env.config.set('ticket', 'workflow',
            'ConfigurableTicketWorkflow,TicketWorkflowOpOwnerReporter')
        self._config_set('ticket-workflow', [
            ('needinfo', '* -> needinfo'),
            ('needinfo.name', 'Need info'),
            ('needinfo.operations', 'set_owner_to_reporter'),
        ])
        tktid = self._insert_ticket(summary='set owner to reporter',
                                    reporter='john', owner='joe')
        ticket = Ticket(self.env, tktid)
        req = self._post_req('needinfo', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('john', ticket['owner'])
        self.assertEqual('needinfo', ticket['status'])

    def test_set_owner_to_component_owner(self):
        self.env.config.set('ticket', 'workflow',
            'ConfigurableTicketWorkflow,TicketWorkflowOpOwnerComponent')
        self._config_set('ticket-workflow', [
            ('to-c-owner', '* -> assigned'),
            ('to-c-owner.operations', 'set_owner_to_component_owner'),
        ])
        self._insert_component('component3', 'foo')
        tktid = self._insert_ticket(summary='set owner to component owner',
                                    reporter='anonymous', owner='joe',
                                    component='component3')
        ticket = Ticket(self.env, tktid)
        req = self._post_req('to-c-owner', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('foo', ticket['owner'])
        self.assertEqual('assigned', ticket['status'])

    def test_set_owner_to_component_owner_with_missing_component(self):
        self.env.config.set('ticket', 'workflow',
            'ConfigurableTicketWorkflow,TicketWorkflowOpOwnerComponent')
        self._config_set('ticket-workflow', [
            ('to-c-owner', '* -> assigned'),
            ('to-c-owner.operations', 'set_owner_to_component_owner'),
        ])
        tktid = self._insert_ticket(summary='set owner to component owner',
                                    reporter='anonymous', owner='joe',
                                    component='component3')
        ticket = Ticket(self.env, tktid)
        req = self._post_req('to-c-owner', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('', ticket['owner'])
        self.assertEqual('assigned', ticket['status'])

    def test_set_owner_to_field(self):
        self.env.config.set('ticket', 'workflow',
            'ConfigurableTicketWorkflow,TicketWorkflowOpOwnerField')
        self._config_set('ticket-workflow', [
            ('to-owner', '* -> assigned'),
            ('to-owner.operations', 'set_owner_to_field'),
            ('to-owner.set_owner_to_field', 'keywords'),
        ])
        tktid = self._insert_ticket(summary='set owner to field',
                                    reporter='anonymous', owner='joe',
                                    keywords='john')
        ticket = Ticket(self.env, tktid)
        req = self._post_req('to-owner', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('john', ticket['owner'])
        self.assertEqual('assigned', ticket['status'])

    def test_set_owner_to_previous(self):
        self.env.config.set('ticket', 'workflow',
            'ConfigurableTicketWorkflow,TicketWorkflowOpOwnerPrevious')
        self._config_set('ticket-workflow', [
            ('to-prev', '* -> assigned'),
            ('to-prev.operations', 'set_owner_to_previous'),
        ])
        tktid = self._insert_ticket(when=datetime(2017, 3, 9, tzinfo=utc),
                                    summary='set owner to previous',
                                    reporter='anonymous', owner='joe')

        ticket = Ticket(self.env, tktid)
        req = self._post_req('to-prev', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('joe', ticket['owner'])
        self.assertEqual('assigned', ticket['status'])

        ticket = Ticket(self.env, tktid)
        ticket['owner'] = 'alice'
        ticket.save_changes(when=datetime(2017, 3, 9, 1, tzinfo=utc))
        ticket['owner'] = 'john'
        ticket.save_changes(when=datetime(2017, 3, 9, 2, tzinfo=utc))

        ticket = Ticket(self.env, tktid)
        req = self._post_req('to-prev', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('alice', ticket['owner'])
        self.assertEqual('assigned', ticket['status'])

        ticket = Ticket(self.env, tktid)
        req = self._post_req('to-prev', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('john', ticket['owner'])
        self.assertEqual('assigned', ticket['status'])

    def test_set_status_to_previous(self):
        self.env.config.set('ticket', 'workflow',
            'ConfigurableTicketWorkflow,TicketWorkflowOpStatusPrevious')
        self._config_set('ticket-workflow', [
            ('revert-status', '* -> *'),
            ('revert-status.operations', 'set_status_to_previous'),
        ])
        tktid = self._insert_ticket(when=datetime(2017, 3, 9, tzinfo=utc),
                                    summary='set status to previous',
                                    reporter='anonymous', owner='joe')

        ticket = Ticket(self.env, tktid)
        req = self._post_req('revert-status', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('new', ticket['status'])

        ticket = Ticket(self.env, tktid)
        ticket['status'] = 'assigned'
        ticket.save_changes(when=datetime(2017, 3, 9, 1, tzinfo=utc))
        ticket['status'] = 'closed'
        ticket.save_changes(when=datetime(2017, 3, 9, 2, tzinfo=utc))

        ticket = Ticket(self.env, tktid)
        req = self._post_req('revert-status', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('assigned', ticket['status'])

    def test_reset_milestone(self):
        self.env.config.set('ticket', 'workflow',
            'ConfigurableTicketWorkflow,TicketWorkflowOpResetMilestone')
        self._config_set('ticket-workflow', [
            ('reset-milestone', '* -> *'),
            ('reset-milestone.operations', 'reset_milestone'),
        ])
        tktid = self._insert_ticket(when=datetime(2017, 3, 9, tzinfo=utc),
                                    summary='reset milestone',
                                    milestone='milestone1',
                                    reporter='anonymous', owner='joe')

        ticket = Ticket(self.env, tktid)
        req = self._post_req('reset-milestone', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('milestone1', ticket['milestone'])

        milestone = Milestone(self.env, ticket['milestone'])
        milestone.completed = datetime(2017, 3, 8, tzinfo=utc)
        milestone.update()
        req = self._post_req('reset-milestone', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('', ticket['milestone'])

        ticket['milestone'] = 'unknown-milestone'
        ticket.save_changes(when=datetime(2017, 3, 8, 1, tzinfo=utc))
        req = self._post_req('reset-milestone', ticket)
        self.assertTrue(self.tktmod.match_request(req))
        self.assertRaises(RequestDone, self.tktmod.process_request, req)
        ticket = Ticket(self.env, tktid)
        self.assertEqual('unknown-milestone', ticket['milestone'])
Beispiel #51
0
 def update(self, req, id, comment, attributes={}, notify=False, author='', when=None):
     """ Update a ticket, returning the new ticket in the same form as
     get(). 'New-style' call requires two additional items in attributes:
     (1) 'action' for workflow support (including any supporting fields
     as retrieved by getActions()),
     (2) '_ts' changetime token for detecting update collisions (as received
     from get() or update() calls).
     ''Calling update without 'action' and '_ts' changetime token is
     deprecated, and will raise errors in a future version.'' """
     t = model.Ticket(self.env, id)
     # custom author?
     if author and not (req.authname == 'anonymous' \
                         or 'TICKET_ADMIN' in req.perm(t.resource)):
         # only allow custom author if anonymous is permitted or user is admin
         self.log.warn("RPC ticket.update: %r not allowed to change author "
                 "to %r for comment on #%d", req.authname, author, id)
         author = ''
     author = author or req.authname
     # custom change timestamp?
     if when and not 'TICKET_ADMIN' in req.perm(t.resource):
         self.log.warn("RPC ticket.update: %r not allowed to update #%d with "
                 "non-current timestamp (%r)", author, id, when)
         when = None
     when = when or to_datetime(None, utc)
     # and action...
     if not 'action' in attributes:
         # FIXME: Old, non-restricted update - remove soon!
         self.log.warning("Rpc ticket.update for ticket %d by user %s " \
                 "has no workflow 'action'." % (id, req.authname))
         req.perm(t.resource).require('TICKET_MODIFY')
         time_changed = attributes.pop('_ts', None)
         if time_changed and \
                 str(time_changed) != str(to_utimestamp(t.time_changed)):
             raise TracError("Ticket has been updated since last get().")
         for k, v in attributes.iteritems():
             t[k] = v
         t.save_changes(author, comment, when=when)
     else:
         ts = TicketSystem(self.env)
         tm = TicketModule(self.env)
         # TODO: Deprecate update without time_changed timestamp
         time_changed = attributes.pop('_ts', to_utimestamp(t.time_changed))
         try:
             time_changed = int(time_changed)
         except ValueError:
             raise TracError("RPC ticket.update: Wrong '_ts' token " \
                             "in attributes (%r)." % time_changed)
         action = attributes.get('action')
         avail_actions = ts.get_available_actions(req, t)
         if not action in avail_actions:
             raise TracError("Rpc: Ticket %d by %s " \
                     "invalid action '%s'" % (id, req.authname, action))
         controllers = list(tm._get_action_controllers(req, t, action))
         all_fields = [field['name'] for field in ts.get_ticket_fields()]
         for k, v in attributes.iteritems():
             if k in all_fields and k != 'status':
                 t[k] = v
         # TicketModule reads req.args - need to move things there...
         req.args.update(attributes)
         req.args['comment'] = comment
         # Collision detection: 0.11+0.12 timestamp
         req.args['ts'] = str(from_utimestamp(time_changed))
         # Collision detection: 0.13/1.0+ timestamp
         req.args['view_time'] = str(time_changed)
         changes, problems = tm.get_ticket_changes(req, t, action)
         for warning in problems:
             add_warning(req, "Rpc ticket.update: %s" % warning)
         valid = problems and False or tm._validate_ticket(req, t)
         if not valid:
             raise TracError(
                 " ".join([warning for warning in req.chrome['warnings']]))
         else:
             tm._apply_ticket_changes(t, changes)
             self.log.debug("Rpc ticket.update save: %s" % repr(t.values))
             t.save_changes(author, comment, when=when)
             # Apply workflow side-effects
             for controller in controllers:
                 controller.apply_action_side_effects(req, t, action)
     if notify:
         try:
             tn = TicketNotifyEmail(self.env)
             tn.notify(t, newticket=False, modtime=when)
         except Exception, e:
             self.log.exception("Failure sending notification on change of "
                                "ticket #%s: %s" % (t.id, e))
env = open_environment(project)
for command, ticketList in commandPattern.findall(message):
	if commands.has_key(command.lower()):
		for ticketId in ticketPattern.findall(ticketList):
			tickets.setdefault(ticketId, []).append(commands[command.lower()])

for ticketId, commands in tickets.iteritems():
	db = env.get_db_cnx()

	ticket = Ticket(env, int(ticketId), db)
	for command in commands:
		command(ticket)

	# determine sequence number...
	cnum = 0
	tm = TicketModule(env)
	for change in tm.grouped_changelog_entries(ticket, db):
		c_cnum = change.get('cnum', None)
		if c_cnum and int(c_cnum) > cnum:
			cnum = int(c_cnum)

	username = authorPattern.findall(author)[0]
	now = datetime.now(utc)
	message = "(On %s [changeset:%s %s]) %s" % (refname, rev, describe_tags, message)
	ticket['branch'] = refname
	ticket.save_changes(username, message, now, db, cnum+1)
	db.commit()

	tn = TicketNotifyEmail(env)
	tn.notify(ticket, newticket=0, modtime=now)
Beispiel #53
0
    def handle_trac(self):
        if ('is_draft' in self.options_dict and
                self.options.is_draft == 'true'):
            return

	if self.trac_over_rpc:
            import xmlrpclib
        else:
            if not (os.path.exists(self.trac_env) and
                    os.path.isdir(self.trac_env)):
                print "trac_env (%s) is not a directory." % self.trac_env
                sys.exit(1)
            # trac specific imports
            from trac.ticket import Ticket
            from trac.env import open_environment
            from trac.ticket.notification import TicketNotifyEmail
            from trac.ticket.web_ui import TicketModule
            from trac.util.datefmt import utc


        # should never be used. but why not...
        if len(self.options.commit) == 0:
            return

        # get actual commit and extract ticket number(s)
        self.commit_msg = call_git('show',['--format=%s%n%b',
                                                '--summary',
                                                self.options.commit])

        # get author for trac comment
        if 'uploader' in self.options_dict and self.options.uploader:
            author = self.options.uploader
        elif 'author' in self.options_dict and self.options.author:
            author = self.options.author
        else:
            author = call_git('rev-list', ['-n',
                                            '1',
                                            self.options.commit,
                                            '--pretty=format:%an <%ae>']
                                    ).splitlines()[1]

        # find ticket numbers referenced in commit message
        ticket_numbers = TICKET_RE.findall(self.commit_msg)

        # create trac comment for every referenced ticket
        if (ticket_numbers):
            for ticket_id in ticket_numbers:

                if self.hook_name.endswith('patchset-created'):
                    msg = self.trac_new_patchset()
                elif self.hook_name.endswith('change-merged'):
                    msg = self.trac_merge_success()
                elif self.hook_name.endswith('comment-added'):
                    if self.comment_always:
                        msg = self.trac_new_review()
                    else:
                        if self.options.verified or self.options.review:
                            if self.options.verified_oldValue == None:
                                continue
                            elif self.options.review_oldValue == None:
                                continue
                        msg = self.trac_new_review()

                if self.debug:
                    print "you should be able to copy and paste the output " \
                          "to trac-comment-preview:"
                    print "---------------------------------------------------"
                    print "%s\n" % msg
                    print "---------------------------------------------------"
                    print "the author of the comment would be: %s"


                if self.trac_over_rpc:
                    try:
                        server = xmlrpclib.ServerProxy(self.trac_env)
                        ticket = {}
                        if self.hook_name.endswith('patchset-created'):
                            if re.search(
                                    "(close|closed|closes|fix|fixed|fixes) #" + \
                                    ticket_id, self.commit_msg, re.IGNORECASE):
                                ticket['status'] = "testing"
                        elif self.hook_name.endswith('change-merged'):
                                ticket['status'] = "closed"
                                ticket['resolution'] = "fixed"
                        server.ticket.update(int(ticket_id), msg, ticket,
                            True, author)

                    except Exception, e:
                        sys.stderr.write('Unexpected error while handling Trac ' \
                                         'ticket ID %s: %s (RPC)' \
                                         % (ticket_id, e))
                        
                else:
                    try:
                        db = self.env.get_db_cnx()
                        ticket = Ticket(self.env, ticket_id, db)
                        now = datetime.now(utc)

                        if self.hook_name.endswith('patchset-created'):
                            if re.search(
                                    "(close|closed|closes|fix|fixed|fixes) #" + \
                                    ticket_id, self.commit_msg, re.IGNORECASE):
                                ticket['status'] = "testing"
                        elif self.hook_name.endswith('change-merged'):
                                ticket['status'] = "closed"
                                ticket['resolution'] = "fixed"

                        cnum = 0
                        tm = TicketModule(self.env)
                        for change in tm.grouped_changelog_entries(ticket, db):
                            if change['permanent']:
                                cnum += 1

                        ticket.save_changes(author, msg, now, db, str(cnum+1))
                        db.commit()

                        tn = TicketNotifyEmail(self.env)
                        tn.notify(ticket, newticket=0, modtime=now)

                    except Exception, e:
                        sys.stderr.write('Unexpected error while handling Trac ' \
                                         'ticket ID %s: %s (MODULE)' \
                                         % (ticket_id, e))
Beispiel #54
0
    def __init__(self, project=options.project, author=options.user,
                 rev=options.rev, url=options.url):
        self.init_env( project )
        
        repos = self.env.get_repository()
        repos.sync()
        # Instead of bothering with the encoding, we'll use unicode data
        # as provided by the Trac versioncontrol API (#1310).
        try:
            chgset = repos.get_changeset(rev)
        except NoSuchChangeset:
            return # out of scope changesets are not cached
        self.author = chgset.author
        self.rev = rev
        self.msg = "(In [%s]) %s" % (rev, chgset.message)
        self.now = int(time.time())

        cmd_groups = command_re.findall(self.msg)
        log ("cmd_groups:%s", cmd_groups)
        tickets = {}
        for cmd, tkts, xxx1, xxx2 in cmd_groups:
            log ("cmd:%s, tkts%s ", cmd, tkts)
            funcname = _supported_cmds.get(cmd.lower(), '')
            if funcname:
                for tkt_id, spent in ticket_re.findall(tkts):
                    func = getattr(self, funcname)
                    lst = tickets.setdefault(tkt_id, [])
                    lst.append([func, spent])
                    

        for tkt_id, vals in tickets.iteritems():
            log ("tkt_id:%s, vals%s ", tkt_id, vals)
            spent_total = 0.0
            try:
                db = self.env.get_db_cnx()
                
                ticket = Ticket(self.env, int(tkt_id), db)
                for (cmd, spent) in vals:
                    cmd(ticket)
                    if spent:
                        spent_total += float(spent)

                # determine sequence number... 
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1
                if spent_total:
                    self._setTimeTrackerFields(ticket, spent_total)
                ticket.save_changes(self.author, self.msg, self.now, db, cnum+1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=self.now)
            except Exception, e:
                # import traceback
                # traceback.print_exc(file=sys.stderr)
                log('Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (tkt_id, e))
                print>>sys.stderr, 'Unexpected error while processing ticket ' \
                                   'ID %s: %s' % (tkt_id, e)
 def __init__(self):
     TicketModule.__init__(self, self.compmgr)