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
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)
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
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
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)
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)
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)
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 __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)
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 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 __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 '
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)
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)
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 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 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)
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)
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)
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) log("cmd_groups:%s", cmd_groups) tickets = {} # \todo Explain what xxx1 and xxx2 do; I can't see more params # in command_re. 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) tickets.setdefault(tkt_id, []).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)
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)
def invoke(self, chgset): # regular expressions ticket_prefix = "(?:#|(?:ticket|issue|bug)[: ]?)" if self.intertrac: # TODO: split to separate function? # find intertrac links intertrac = {} aliases = {} for key, value in self.env.config.options("intertrac"): if "." in key: name, type_ = key.rsplit(".", 1) if type_ == "url": intertrac[name] = value else: aliases.setdefault(value, []).append(key) intertrac = dict([(value, [key] + aliases.get(key, [])) for key, value in intertrac.items()]) project = os.path.basename(self.env.path) if "/%s" % project in intertrac: # TODO: checking using base_url for full paths: ticket_prefix = "(?:%s):%s" % ("|".join(intertrac["/%s" % project]), ticket_prefix) else: # hopefully sesible default: ticket_prefix = "%s:%s" % (project, ticket_prefix) ticket_reference = ticket_prefix + "[0-9]+" ticket_command = r"(?P<action>[A-Za-z]*).?" "(?P<ticket>%s(?:(?:[, &]*|[ ]?and[ ]?)%s)*)" % ( ticket_reference, ticket_reference, ) ticket_command = r"%s%s%s" % (re.escape(self.envelope_open), ticket_command, re.escape(self.envelope_close)) command_re = re.compile(ticket_command, re.IGNORECASE) ticket_re = re.compile(ticket_prefix + "([0-9]+)", re.IGNORECASE) # other variables msg = "(In [%s]) %s" % (chgset.rev, chgset.message) now = chgset.date supported_cmds = {} # TODO: this could become an extension point supported_cmds.update(dict([(key, self._cmdClose) for key in self.cmd_close])) supported_cmds.update(dict([(key, self._cmdRefs) for key in self.cmd_refs])) cmd_groups = command_re.findall(msg) tickets = {} for cmd, tkts in cmd_groups: func = supported_cmds.get(cmd.lower(), None) if func: for tkt_id in ticket_re.findall(tkts): 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 comment sequence number cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change["permanent"]: cnum += 1 # validate the ticket # fake a request # XXX cargo-culted environ from # http://trac.edgewall.org/browser/trunk/trac/web/tests/api.py environ = { "wsgi.url_scheme": "http", "wsgi.input": StringIO(""), "SERVER_NAME": "0.0.0.0", "REQUEST_METHOD": "POST", "SERVER_PORT": 80, "SCRIPT_NAME": "/" + self.env.project_name, "REMOTE_USER": chgset.author, "QUERY_STRING": "", } req = Request(environ, None) req.args["comment"] = msg req.authname = chgset.author req.perm = PermissionCache(self.env, req.authname) for manipulator in tm.ticket_manipulators: manipulator.validate_ticket(req, ticket) msg = req.args["comment"] ticket.save_changes(chgset.author, msg, now, db, cnum + 1) db.commit() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=now) except Exception, e: message = "Unexpected error while processing ticket ID %s: %s" % (tkt_id, repr(e)) print >>sys.stderr, message self.env.log.error("TicketChanger: " + message)
def _create_sheet_history(self, req, context, data, book): def write_headers(writer, headers): writer.write_row((header['label'], 'thead', None, None) for idx, header in enumerate(headers)) 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") }, ] sheet_name = dgettext("messages", "Change History") sheet_count = 1 writer = book.create_sheet(sheet_name) write_headers(writer, headers) tkt_ids = [ result['id'] for result in chain(*[results for groupname, results in groups]) ] tickets = BulkFetchTicket.select(self.env, tkt_ids) mod = TicketModule(self.env) for result in chain(*[results for groupname, results in groups]): id = result['id'] ticket = tickets[id] ticket_context = context('ticket', id) if 'TICKET_VIEW' not in req.perm(ticket_context.resource): continue values = ticket.values.copy() changes = [] for change in mod.grouped_changelog_entries(ticket, None): 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'] }] if writer.row_idx + len(changes) >= writer.MAX_ROWS: sheet_count += 1 writer = book.create_sheet('%s (%d)' % (sheet_name, sheet_count)) write_headers(writer, headers) 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', '') value = Chrome(self.env).format_author(req, value) 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()
def invoke(self, chgset): # regular expressions ticket_prefix = '(?:#|(?:ticket|issue|bug)[: ]?)' if self.intertrac: # TODO: split to separate function? # find intertrac links intertrac = {} aliases = {} for key, value in self.env.config.options('intertrac'): if '.' in key: name, type_ = key.rsplit('.', 1) if type_ == 'url': intertrac[name] = value else: aliases.setdefault(value, []).append(key) intertrac = dict([(value, [key] + aliases.get(key, [])) for key, value in intertrac.items()]) project = os.path.basename(self.env.path) if '/%s' % project in intertrac: # TODO: checking using base_url for full paths: ticket_prefix = '(?:%s):%s' % ('|'.join( intertrac['/%s' % project]), ticket_prefix) else: # hopefully sesible default: ticket_prefix = '%s:%s' % (project, ticket_prefix) ticket_reference = ticket_prefix + '[0-9]+' ticket_command = (r'(?P<action>[A-Za-z]*).?' '(?P<ticket>%s(?:(?:[, &]*|[ ]?and[ ]?)%s)*)' % (ticket_reference, ticket_reference)) ticket_command = r'%s%s%s' % (re.escape( self.envelope_open), ticket_command, re.escape( self.envelope_close)) command_re = re.compile(ticket_command, re.IGNORECASE) ticket_re = re.compile(ticket_prefix + '([0-9]+)', re.IGNORECASE) # other variables msg = "(In [%s]) %s" % (chgset.rev, chgset.message) now = chgset.date supported_cmds = {} # TODO: this could become an extension point supported_cmds.update( dict([(key, self._cmdClose) for key in self.cmd_close])) supported_cmds.update( dict([(key, self._cmdRefs) for key in self.cmd_refs])) cmd_groups = command_re.findall(msg) tickets = {} for cmd, tkts in cmd_groups: func = supported_cmds.get(cmd.lower(), None) if func: for tkt_id in ticket_re.findall(tkts): 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 comment sequence number cnum = 0 tm = TicketModule(self.env) for change in tm.grouped_changelog_entries(ticket, db): if change['permanent']: cnum += 1 # validate the ticket # fake a request # XXX cargo-culted environ from # http://trac.edgewall.org/browser/trunk/trac/web/tests/api.py environ = { 'wsgi.url_scheme': 'http', 'wsgi.input': StringIO(''), 'SERVER_NAME': '0.0.0.0', 'REQUEST_METHOD': 'POST', 'SERVER_PORT': 80, 'SCRIPT_NAME': '/' + self.env.project_name, 'REMOTE_USER': chgset.author, 'QUERY_STRING': '' } req = Request(environ, None) req.args['comment'] = msg req.authname = chgset.author req.perm = PermissionCache(self.env, req.authname) for manipulator in tm.ticket_manipulators: manipulator.validate_ticket(req, ticket) msg = req.args['comment'] ticket.save_changes(chgset.author, msg, now, db, cnum + 1) db.commit() tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=0, modtime=now) except Exception, e: message = 'Unexpected error while processing ticket ID %s: %s' % ( tkt_id, repr(e)) print >> sys.stderr, message self.env.log.error('TicketChanger: ' + message)
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))
def get_ticket_changes(self, ticket): """Actually calls :meth:`trac.ticket.web_ui.TicketModule.grouped_changelog_entries` since the alternative is to reimplement that method.""" module = TicketModule(self.env) return list(module.grouped_changelog_entries(ticket, None))
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 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) content = msg.split('\n\n', 1)[1] tickets = {} for cmd, tkts in command_re.findall(content): action = COMMANDS.get(cmd.lower()) #print "action: %s " % action 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) #print "ticket: %s" % ticket if ADD_HOURS: #print "message: %s" % content hours = hours_re.findall(content) if hours: #ADD hours to ticket hours = float(hours[0])/len(tickets) #code from http://trac-hacks.org/browser/timingandestimationplugin/branches/trac0.11/timingandestimationplugin/ticket_daemon.py #print "hours: %s" % hours totalHours = readTicketValue("totalhours", convertfloat,ticket,env) #print "totalhours: %s" % totalHours newtotal = str(totalHours+hours) #print "newtotal: %s" % newtotal cl = ticket.get_changelog() if cl: #print "cl: %s" % cl most_recent_change = cl[-1] change_time = most_recent_change[0] #print "changetime: %s" % change_time author = most_recent_change[1] else: change_time = ticket.time_created author = ticket.values["reporter"] db = env.get_db_cnx() #print "saving changes" save_ticket_change( db, tkt_id, author, change_time, "hours", '0.0', str(hours) ) save_ticket_change( db, tkt_id, author, change_time, "totalhours", str(totalHours), str(newtotal)) save_custom_field_value( db, tkt_id, "hours", '0') save_custom_field_value( db, tkt_id, "totalhours", str(newtotal) ) #print "hour changes saved" 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) #dirty workaround for being able to save only one ticket/second, should be fixed in track 0.12 (1 ticket/microsecond) #see also http://trac.edgewall.org/ticket/9993 time.sleep(1) now = datetime.now(utc) except Exception, e: print 'Unexpected error while processing commit %s, for ticket ID %s: %s %s' % (commit, tkt_id, e.__class__,e)