def process_action(self, msg, author, githash=None): self.env.log.debug('process_action') # Find all the #123 strings in the commit message. ticket_re = re.compile('#[0-9]+') ticket_numbers = ticket_re.findall(msg) # Turn the ticket numbers into ints. ticket_numbers = set( [int(ticket_number[1:]) for ticket_number in ticket_numbers]) # For each ticket date = datetime_now(utc) for ticket_number in ticket_numbers: self.env.log.debug( 'Found ticket number: {n}'.format(n=str(ticket_number))) if (githash is not None and self._githash_storecheck(ticket_number, githash)): continue try: db = self.env.get_db_cnx() ticket = Ticket(self.env, int(ticket_number), db) ticket.save_changes(author, msg, date) db.commit() self._notify(ticket, date) self.env.log.debug('Comment added') except ResourceNotFound, e: self.log.error( 'Ticket not found: {n}'.format(n=str(ticket_number))) continue
def _save_ticket_changes(self, req, env, log, selectedTickets, tickets, values, comment, modify_changetime, send_notifications): for id in selectedTickets: if id in tickets: t = Ticket(env, int(id)) new_changetime = datetime.now(utc) log_msg = "" if not modify_changetime: original_changetime = to_timestamp(t.time_changed) _values = values.copy() for field in [f for f in values.keys() \ if f in self._fields_as_list]: _values[field] = self._merge_keywords(t.values[field], values[field], log) t.populate(_values) t.save_changes(req.authname, comment, when=new_changetime) if send_notifications: tn = TicketNotifyEmail(env) tn.notify(t, newticket=0, modtime=new_changetime) if not modify_changetime: self._reset_changetime(env, original_changetime, t) log_msg = "(changetime not modified)" log.debug('BatchModifyPlugin: saved changes to #%s %s' % (id, log_msg))
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 _implementation(db): for id in selectedTickets: if id in tickets: t = Ticket(env, int(id)) new_changetime = datetime.now(utc) log_msg = "" if not modify_changetime: original_changetime = to_utimestamp(t.time_changed) _values = new_values.copy() for field in [f for f in new_values.keys() \ if f in self._fields_as_list]: _values[field] = self._merge_keywords( t.values[field], new_values[field], log) t.populate(_values) t.save_changes(req.authname, comment, when=new_changetime) if send_notifications: tn = TicketNotifyEmail(env) tn.notify(t, newticket=0, modtime=new_changetime) if not modify_changetime: self._reset_changetime(env, original_changetime, t) log_msg = "(changetime not modified)" log.debug('BatchModifyPlugin: saved changes to #%s %s' % (id, log_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 _update_ticket(self, changeset, biff_names, biff_cc): ticket_updator = self.env.compmgr.components.get(CommitTicketUpdater) if not ticket_updator: self.env.log.error('CommitTicketUpdater is not available, ' 'enable it to parse changeset message') return date = datetime.now(utc) tickets = ticket_updator._parse_message(changeset.message) perm = PermissionCache(self.env, changeset.author) for tkt_id, cmds in tickets.iteritems(): try: has_permission = False with self.env.db_transaction: ticket = Ticket(self.env, tkt_id) ticket_perm = perm(ticket.resource) for cmd in cmds: if cmd(ticket, changeset, ticket_perm) is not False: has_permission = True if has_permission: cc_list = ', ' + ', '.join(biff_cc) ticket['cc'] += cc_list fb_field = FileBiffTicketCustomField(ticket) fb_field.add(biff_names) if fb_field.is_updated: ticket.save_changes(changeset.author, '', date) except Exception as e: self.env.log.error('Unexpected error while processing ticket ' '#%s: %s', tkt_id, exception_to_unicode(e))
def _handle_ripe_save(self, req): """ hander for save """ # TODO: workflow # get ticket id ticket_id = req.args.get("ticket_id") value = req.args.get("value", "").strip() field = req.args.get("field") old_value = req.args.get("old_value") # ticket ticket = Ticket(self.env, ticket_id) current_value = ticket.values.get(field) # validation if current_value != old_value and (old_value or current_value): self.log.info("Field value should be %s, got %s" % (repr(current_value), repr(old_value))) raise TracError("field value inconsistant.") # set params params = {} params[field] = value ticket.populate(params) # save ticket comment = "Updated from report" author = get_reporter_id(req, 'author') ticket.save_changes(author, comment) return value
def handle_commit(commit, env): from trac.ticket.notification import TicketNotifyEmail from trac.ticket import Ticket 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' # trac 1.0: `db` parameter is no longer needed and will be removed in 1.1.1 # trac 1.0: `cnum` parameter is deprecated ticket.save_changes(eml, msg, now) 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, 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 ticket_created(self, ticket): """Called when a ticket is created.""" hours = convertfloat(ticket['hours']) # makes the hours a ticket change like all the other hours records if hours > 0: self.watch_hours(ticket) # clears the hours t = Ticket(self.env, ticket.id) t['hours'] = str(hours) t.save_changes(ticket['reporter'])
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 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, 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 move(self, ticket_id, author, env, delete=False): """ move a ticket to another environment env: environment to move to """ tables = {"attachment": "id", "ticket_change": "ticket"} # open the environment if it is a string if isinstance(env, basestring): base_path, _project = os.path.split(self.env.path) env = open_environment(os.path.join(base_path, env), use_cache=True) # get the old ticket old_ticket = Ticket(self.env, ticket_id) # make a new ticket from the old ticket values new_ticket = Ticket(env) new_ticket.values = old_ticket.values.copy() new_ticket.insert(when=old_ticket.time_created) # copy the changelog and attachment DBs for table, _id in tables.items(): for row in get_all_dict(self.env, "SELECT * FROM %s WHERE %s=%%s" % (table, _id), str(ticket_id)): row[_id] = new_ticket.id insert_row_from_dict(env, table, row) # copy the attachments src_attachment_dir = os.path.join(self.env.path, "attachments", "ticket", str(ticket_id)) if os.path.exists(src_attachment_dir): dest_attachment_dir = os.path.join(env.path, "attachments", "ticket") if not os.path.exists(dest_attachment_dir): os.makedirs(dest_attachment_dir) dest_attachment_dir = os.path.join(dest_attachment_dir, str(new_ticket.id)) shutil.copytree(src_attachment_dir, dest_attachment_dir) # note the previous location on the new ticket new_ticket.save_changes(author, "moved from %s" % self.env.abs_href("ticket", ticket_id)) # location of new ticket new_location = env.abs_href.ticket(new_ticket.id) if delete: old_ticket.delete() else: # close old ticket and point to new one old_ticket["status"] = u"closed" old_ticket["resolution"] = u"moved" old_ticket.save_changes(author, u"moved to %s" % new_location) if env.config["trac"].get("base_url"): return new_location else: return None
def _implementation(db): """Apply each change to the ticket and save it.""" for change in changes.strip(',').split(','): change_items = change.split(':') self.log.debug('WhiteboardModule: change_items=%s', change_items) t = Ticket(self.env, int(change_items[0])) values = {} values[field] = change_items[1] t.populate(values) t.save_changes(req.authname)
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_tickets(self, tickets, authname, comment, date): """Update the tickets with the given comment.""" for tkt_id, cmds in tickets.iteritems(): try: self.log.debug("Updating ticket #%d", tkt_id) save = False with self.env.db_transaction: ticket = Ticket(self.env, tkt_id) ticket.save_changes(authname, comment, date) self._notify(ticket, date) except Exception, e: self.log.error("Unexpected error while processing ticket " "#%s: %s", tkt_id, exception_to_unicode(e))
def _update_tickets(self, tickets, changeset, comment, date): """Update the tickets with the given comment.""" perm = PermissionCache(self.env, changeset.author) for tkt_id, cmds in tickets.iteritems(): try: self.log.debug("Updating ticket #%d", tkt_id) with self.env.db_transaction as db: ticket = Ticket(self.env, tkt_id, db) for cmd in cmds: cmd(ticket, changeset, perm(ticket.resource)) ticket.save_changes(changeset.author, comment, date, db) self._notify(ticket, date) except Exception, e: self.log.error("Unexpected error while processing ticket " "#%s: %s", tkt_id, exception_to_unicode(e))
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_request(self, req): """ Handle the POST and add or remove the current user from Cc of the given ticket. """ cclist = [] # extract the ticket number from the request try: ticket_id = int(req.args.get('ticket')) except ValueError: raise TracError(_("Could not parse ticket ID for Cc Me!")) if not req.perm.has_permission('TICKET_APPEND'): add_warning( req, _("You do not have permission to Cc yourself to ticket #%d"), ticket_id) return self._redirect(req, ticket_id) # pylint: disable=no-member ticket = Ticket(self.env, ticket_id) if len(ticket['cc']) > 0: cclist = re.split(r'[;,\s]+', ticket['cc']) user = req.authname if user is None: add_warning( req, _("Unauthenticated users cannot Cc themselves to tickets")) return self._redirect(req, ticket_id) if user in cclist: add_notice(req, _("You will no longer receive notifications for #%d"), ticket_id) cclist.remove(user) else: add_notice(req, _("You will now receive notifications for ticket #%d"), ticket_id) cclist.append(user) ticket['cc'] = ', '.join(cclist) ticket.save_changes(author=user) return self._redirect(req, ticket_id)
def notify_new_tickets(self, req, id, tickets, addMessage): try: tag = "[[Estimate(%s)]]" % id tickets = intlist(tickets) for t in tickets: ticket = Ticket (self.env, t) if ticket['description'].find (tag) == -1: self.log.debug('Updating Ticket Description : %s'%t) ticket['description'] = ticket['description']+'\n----\n'+tag ticket.save_changes(req.authname, 'added estimate') return True except Exception, e: self.log.error("Error saving new ticket changes: %s" % e) addMessage("Error: %s" % e) return None
def _update_field(self, authname, comment, ticket_ids, fb_methodcaller): date = datetime.now(utc) for tkt_id in chain.from_iterable(ticket_ids): try: with self.env.db_transaction: ticket = Ticket(self.env, tkt_id) fb_field = FileBiffTicketCustomField(ticket) fb_methodcaller(fb_field) if fb_field.is_updated: ticket.save_changes(authname, comment, date) except Exception as e: self.env.log.error( 'Failed to update ticket file biff field value: ' 'tkt id: %s, authname: %s, exception: %s', tkt_id, authname, exception_to_unicode(e))
def _batch_modify(self, req): tickets = req.session["query_tickets"].split(" ") comment = req.args.get("comment", "") values = {} for field in TicketSystem(self.env).get_ticket_fields(): name = field["name"] if name not in ("summary", "reporter", "description", "type", "status", "resolution", "owner"): if req.args.has_key("bm_" + name): values[name] = req.args.get(name) for id in tickets: t = Ticket(self.env, id) t.populate(values) t.save_changes(req.authname, comment)
def process_request(self, req, db=None): req.perm.assert_permission('TRAC_ADMIN') if not db: self.db = self.env.get_db_cnx() ticket_id = req.args.get('ticket_id') req.hdf['ticket_id'] = ticket_id req.hdf['message'] = '' repos = self.env.get_repository(req.authname) authzperm = SubversionAuthorizer(self.env, req.authname) diff_options = get_diff_options(req) if req.args.has_key('update'): req.redirect(self.env.href.svnpublish(ticket_id)) ticket = Ticket(self.env, ticket_id) chgset = [] if (ticket['ticketaction'] == "ClonePublish"): from publishrevert.setchangeset import SetChangesetModule setchangeset = SetChangesetModule(self.env) setchangesets = setchangeset.get_setchangesets(ticket_id) # get the list of changesets for the ticket_id # then loop through and get the actual changesets like the following line for rev in setchangesets: authzperm.assert_permission_for_changeset(rev) changeset = repos.get_changeset(rev) # now loop through the files in changeset to get all the paths # and for each path, find the current test/prod revision number and save that info chgset.append(changeset) format = req.args.get('format') self._render_html(req, ticket, repos, chgset, diff_options) req.hdf['setchangesets'] = setchangesets ticket['ticketaction'] = 'CloneTest' ticket.save_changes(req.authname, 'published to clone', 0, db) req.hdf['message'] += 'Successfully Published All Files' req.hdf['ticket'] = ticket.values else: req.hdf['error'] = 'Error: not in correct state to publish' return 'setchangeset.cs', None
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_request(self, req, db=None): req.perm.assert_permission('TRAC_ADMIN') if not db: self.db = self.env.get_db_cnx() ticket_id = req.args.get('ticket_id') req.hdf['ticket_id'] = ticket_id req.hdf['message'] = '' repos = self.env.get_repository(req.authname) authzperm = SubversionAuthorizer(self.env, req.authname) diff_options = get_diff_options(req) if req.args.has_key('update'): req.redirect(self.env.href.svnpublish(ticket_id)) ticket = Ticket(self.env, ticket_id) chgset = [] if(ticket['ticketaction'] == "ClonePublish"): from publishrevert.setchangeset import SetChangesetModule setchangeset = SetChangesetModule(self.env) setchangesets = setchangeset.get_setchangesets(ticket_id) # get the list of changesets for the ticket_id # then loop through and get the actual changesets like the following line for rev in setchangesets: authzperm.assert_permission_for_changeset(rev) changeset = repos.get_changeset(rev) # now loop through the files in changeset to get all the paths # and for each path, find the current test/prod revision number and save that info chgset.append(changeset) format = req.args.get('format') self._render_html(req, ticket, repos, chgset, diff_options) req.hdf['setchangesets'] = setchangesets ticket['ticketaction'] = 'CloneTest' ticket.save_changes(req.authname, 'published to clone', 0, db) req.hdf['message'] += 'Successfully Published All Files' req.hdf['ticket'] = ticket.values else: req.hdf['error'] = 'Error: not in correct state to publish' return 'setchangeset.cs', None
def process_request(self, req, env, log): tickets = req.session['query_tickets'].split(' ') comment = req.args.get('batchmod_value_comment', '') modify_changetime = bool( req.args.get('batchmod_modify_changetime', False)) values = self._get_new_ticket_values(req, env) self._check_for_resolution(values) self._remove_resolution_if_not_closed(values) selectedTickets = req.args.get('selectedTickets') log.debug('BatchModifyPlugin: selected tickets: %s', selectedTickets) selectedTickets = isinstance( selectedTickets, list) and selectedTickets or selectedTickets.split(',') if not selectedTickets: raise TracError, 'No tickets selected' for id in selectedTickets: if id in tickets: t = Ticket(env, int(id)) log_msg = "" if not modify_changetime: original_changetime = to_timestamp(t.time_changed) _values = values.copy() for field in [ f for f in values.keys() if f in self._fields_as_list ]: _values[field] = self._merge_keywords( t.values[field], values[field], log) t.populate(_values) t.save_changes(req.authname, comment) if not modify_changetime: log_msg = "(changetime not modified)" db = env.get_db_cnx() db.cursor().execute( "UPDATE ticket set changetime=%s where id=%s" % (original_changetime, t.id)) db.commit() log.debug('BatchModifyPlugin: saved changes to #%s %s' % (id, log_msg))
def _batch_modify(self, req): tickets = req.session['query_tickets'].split(' ') comment = req.args.get('comment', '') values = {} for field in TicketSystem(self.env).get_ticket_fields(): name = field['name'] if name not in ('summary', 'reporter', \ 'description', 'type', 'status', 'resolution', 'owner'): if req.args.has_key('bm_' + name): values[name] = req.args.get(name) for id in tickets: t = Ticket(self.env, id) t.populate(values) t.save_changes(req.authname, comment)
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 _process_request(self, req): field = req.args.get("whiteboard_group_by") changes = req.args.get("whiteboard_changes") self.log.debug("WhiteboardModule: field=%s", field) self.log.debug("WhiteboardModule: changes=%s", changes) db = self.env.get_db_cnx() for change in changes.strip(",").split(","): change_items = change.split(":") self.log.debug("WhiteboardModule: change_items=%s", change_items) t = Ticket(self.env, int(change_items[0])) values = {} values[field] = change_items[1] t.populate(values) t.save_changes(req.authname, "") db.commit()
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 _save_ticket_changes(self, req, selected_tickets, new_values, comment, action): """Save all of the changes to tickets.""" when = datetime_now(utc) list_fields = self._get_list_fields() with self.env.db_transaction as db: for id in selected_tickets: t = Ticket(self.env, int(id)) _values = new_values.copy() for field in list_fields: if field in new_values: old = t.values[field] if field in t.values else '' new = new_values[field] mode = req.args.get('batchmod_value_' + field + '_mode') new2 = req.args.get( 'batchmod_value_' + field + '_secondary', '') _values[field] = self._change_list( old, new, new2, mode) controllers = list(self._get_action_controllers( req, t, action)) for controller in controllers: _values.update( controller.get_ticket_changes(req, t, action)) t.populate(_values) t.save_changes(req.authname, comment, when=when) for controller in controllers: controller.apply_action_side_effects(req, t, action) tn = BatchTicketNotifyEmail(self.env) try: tn.notify(selected_tickets, new_values, comment, action, req.authname, when) except Exception, e: self.log.error( "Failure sending notification on ticket batch" "change: %s", exception_to_unicode(e)) add_warning( req, tag_( "The changes have been saved, but an " "error occurred while sending " "notifications: %(message)s", message=to_unicode(e)))
def _process_request(self, req): field = req.args.get('whiteboard_group_by') changes = req.args.get('whiteboard_changes') self.log.debug('WhiteboardModule: field=%s', field) self.log.debug('WhiteboardModule: changes=%s', changes) db = self.env.get_db_cnx() for change in changes.strip(',').split(','): change_items = change.split(':') self.log.debug('WhiteboardModule: change_items=%s', change_items) t = Ticket(self.env, int(change_items[0])) values = {} values[field] = change_items[1] t.populate(values) t.save_changes(req.authname, '') db.commit()
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 _update_tickets(self, tickets, changeset, comment, date): """Update the tickets with the given comment.""" authname = self._authname(changeset) perm = PermissionCache(self.env, authname) for tkt_id, cmds in tickets.iteritems(): try: self.log.debug("Updating ticket #%d", tkt_id) save = False with self.env.db_transaction: ticket = Ticket(self.env, tkt_id) ticket_perm = perm(ticket.resource) for cmd in cmds: if cmd(ticket, changeset, ticket_perm) is not False: save = True if save: ticket.save_changes(authname, comment, date) if save: self._notify(ticket, date, changeset.author, comment) except Exception as e: self.log.error("Unexpected error while processing ticket " "#%s: %s", tkt_id, exception_to_unicode(e))
def process_request(self, req): if not req.args.has_key('ticket_id') or not req.args.has_key('author') or not req.args.has_key('spent') or not req.args.has_key('message'): raise Exception("Request variables 'ticket_id', 'author', 'spent' and 'message' must be set.") ticket = Ticket(self.env, int(req.args.get('ticket_id'))) # Check that timingandestimation plugin is installed... if not ticket.values.has_key('hours'): raise Exception("Ticket doesn't have 'hours' - check timingandestimation plugin is installed.", 500) ticket['hours'] = str(req.args.get('spent')) ticket.save_changes(req.args.get('author'), req.args.get('message'), datetime.now(utc)) content = 'OK' req.send_response(200) req.send_header('Content-Type', 'text/plain') req.send_header('Content-Length', len(content)) req.end_headers() req.write(content)
def _save_ticket_changes(self, req, selected_tickets, new_values, comment, action): """Save all of the changes to tickets.""" when = datetime.now(utc) list_fields = self._get_list_fields() with self.env.db_transaction as db: for id in selected_tickets: t = Ticket(self.env, int(id)) _values = new_values.copy() for field in list_fields: if field in new_values: old = t[field] if field in t else '' new = new_values[field] mode = req.args.get('batchmod_value_' + field + '_mode') new2 = req.args.get('batchmod_value_' + field + '_secondary', '') _values[field] = self._change_list(old, new, new2, mode) controllers = list(self._get_action_controllers(req, t, action)) for controller in controllers: _values.update(controller.get_ticket_changes(req, t, action)) t.populate(_values) t.save_changes(req.authname, comment, when=when) for controller in controllers: controller.apply_action_side_effects(req, t, action) event = BatchTicketChangeEvent(selected_tickets, when, req.authname, comment, new_values, action) try: NotificationSystem(self.env).notify(event) except Exception as e: self.log.error("Failure sending notification on ticket batch" "change: %s", exception_to_unicode(e)) add_warning(req, tag_("The changes have been saved, but an " "error occurred while sending " "notifications: %(message)s", message=to_unicode(e)))
def ticket_changed(self, ticket, comment, author, old_values): pattern = re.compile(self.TICKET_REGEX, re.DOTALL | re.VERBOSE) if not isinstance(comment, basestring): return tickets_referenced = pattern.findall(comment) # convert from strings to ints and discard duplicates tickets_referenced = set(int(t) for t in tickets_referenced) # remove possible self-reference tickets_referenced.discard(ticket.id) # put trackbacks on the tickets that we found if not self.is_tracback(comment): # prevent infinite recursion for ticket_to_tracback in tickets_referenced: try: t = Ticket(self.env, ticket_to_tracback) except ResourceNotFound: # referenced ticket does not exist continue tracback = self.create_tracbacks(ticket, t, comment) # cnum is stored in the ticket_change table as an string # identifying the comment number, and if applicable, # the replyto comment number. If comment 8 is a reply to # comment 4, the string will be '4.8'. The index is used # by the TicketChangePlugin to identify the comment being # edited, so we make sure to add it here. change_log = [ i for i in t.get_changelog() if i[2] == "comment" ] if change_log != []: lastchange = change_log[-1] cnum_lastchange = lastchange[3].rsplit('.', 1) cnum_lastcomment = int(cnum_lastchange[-1]) cnum_thischange = str(cnum_lastcomment + 1) else: cnum_thischange = "1" t.save_changes(author, tracback, cnum=cnum_thischange)
def test_ticket(self): self.env.config.set('ticket-custom', 'foo', 'text') ticket = Ticket(self.env) ticket.populate({ 'reporter': 'santa', 'summary': 'Summary line', 'description': 'Lorem ipsum dolor sit amet', 'foo': 'This is a custom field', 'keywords': 'alpha bravo charlie', 'cc': '[email protected], [email protected]', }) ticket.insert() so = self._get_so() self.assertEquals('%s:ticket:1' % self.basename, so.doc_id) self.assertEquals('ticket', so.realm) self.assertEquals('1', so.id) self.assertTrue('#1' in so.title) self.assertTrue('Summary line' in so.title) self.assertEquals('santa', so.author) self.assertEquals(ticket['time'], so.created) self.assertEquals(ticket['changetime'], so.changed) self.assertTrue('*****@*****.**' in so.involved) self.assertTrue('*****@*****.**' in so.involved) self.assertTrue('bravo' in so.tags) self.assertTrue('Lorem ipsum' in so.oneline) self.assertTrue('Lorem ipsum' in so.body) original_time = ticket['time'] ticket['description'] = 'No latin filler here' ticket.save_changes('Jack Sprat', 'Could eat no fat') so = self._get_so() self.assertEquals('%s:ticket:1' % self.basename, so.doc_id) self.assertEquals('ticket', so.realm) self.assertEquals('1', so.id) self.assertEquals(original_time, so.created) self.assertEquals(ticket['changetime'], so.changed) self.assertFalse('Lorem ipsum' in so.body) self.assertTrue('No latin filler here' in so.body) self.assertTrue('Could eat no fat' in so.comments)
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') ticket.save_changes(attachment.author, comment) #trigger notification since we've changed the ticket tn = TicketNotifyEmail(self.env) tn.notify(ticket, newticket=False, modtime=attachment.date)
def ticket_changed(self, ticket, comment, author, old_values): pattern = re.compile(self.TICKET_REGEX, re.DOTALL|re.VERBOSE) if not isinstance(comment, basestring): return tickets_referenced = pattern.findall(comment) # convert from strings to ints and discard duplicates tickets_referenced = set(int(t) for t in tickets_referenced) # remove possible self-reference tickets_referenced.discard(ticket.id) # put trackbacks on the tickets that we found if not self.is_tracback(comment): # prevent infinite recursion for ticket_to_tracback in tickets_referenced: try: t = Ticket(self.env, ticket_to_tracback) except ResourceNotFound: # referenced ticket does not exist continue tracback = self.create_tracbacks(ticket, t, comment) # cnum is stored in the ticket_change table as an string # identifying the comment number, and if applicable, # the replyto comment number. If comment 8 is a reply to # comment 4, the string will be '4.8'. The index is used # by the TicketChangePlugin to identify the comment being # edited, so we make sure to add it here. change_log = [i for i in t.get_changelog() if i[2] == "comment"] if change_log != []: lastchange = change_log[-1] cnum_lastchange = lastchange[3].rsplit('.', 1) cnum_lastcomment = int(cnum_lastchange[-1]) cnum_thischange = str(cnum_lastcomment + 1) else: cnum_thischange = "1" t.save_changes(author, tracback, cnum=cnum_thischange)
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)
def _update_tickets(self, tickets, changeset, comment, date): """Update the tickets with the given comment.""" authname = self._get_username_for_changeset_author(changeset.author) if not authname: authname = self._authname(changeset) perm = PermissionCache(self.env, authname) ret = {} for tkt_id, cmds in tickets.iteritems(): self.log.debug("Updating ticket #%d", tkt_id) save = False with self.env.db_transaction: try: ticket = Ticket(self.env, tkt_id) except ResourceNotFound: self.log.warning("Ticket %i does not exist", tkt_id) ticket = None if ticket is not None: ticket_perm = perm(ticket.resource) if self.check_perms and not 'TICKET_MODIFY' in ticket_perm: #sys.stderr.write("%s doesn't have TICKET_MODIFY permission for #%d\n" % (authname, ticket.id)) self.log.info("%s doesn't have TICKET_MODIFY permission for #%d", authname, ticket.id) else: if self._is_author_allowed(changeset.author): for cmd in cmds: if cmd(ticket, changeset, ticket_perm): save = True else: #sys.stderr.write("%s is not allowed to modify to #%d\n" % (changeset.author, ticket.id)) self.log.info("%s is not allowed to modify to #%d", changeset.author, ticket.id) if save: ticket.save_changes(authname, comment, date) if save: self._notify(ticket, date) ret[tkt_id] = (cmds, ticket) return ret
def process_request(self, req, env, log): tickets = req.session["query_tickets"].split(" ") comment = req.args.get("batchmod_value_comment", "") modify_changetime = bool(req.args.get("batchmod_modify_changetime", False)) values = self._get_new_ticket_values(req, env) self._check_for_resolution(values) self._remove_resolution_if_not_closed(values) selectedTickets = req.args.get("selectedTickets") log.debug("BatchModifyPlugin: selected tickets: %s", selectedTickets) selectedTickets = isinstance(selectedTickets, list) and selectedTickets or selectedTickets.split(",") if not selectedTickets: raise TracError, "No tickets selected" for id in selectedTickets: if id in tickets: t = Ticket(env, int(id)) log_msg = "" if not modify_changetime: original_changetime = to_timestamp(t.time_changed) _values = values.copy() for field in [f for f in values.keys() if f in self._fields_as_list]: _values[field] = self._merge_keywords(t.values[field], values[field], log) t.populate(_values) t.save_changes(req.authname, comment) if not modify_changetime: log_msg = "(changetime not modified)" db = env.get_db_cnx() db.cursor().execute("UPDATE ticket set changetime=%s where id=%s" % (original_changetime, t.id)) db.commit() log.debug("BatchModifyPlugin: saved changes to #%s %s" % (id, log_msg))
def test_ticket(self): self.env.config.set('ticket-custom', 'foo', 'text') ticket = Ticket(self.env) ticket.populate({'reporter': 'santa', 'summary': 'Summary line', 'description': 'Lorem ipsum dolor sit amet', 'foo': 'This is a custom field', 'keywords': 'alpha bravo charlie', 'cc': '[email protected], [email protected]', }) ticket.insert() so = self._get_so() self.assertEquals('%s:ticket:1' % self.basename, so.doc_id) self.assertEquals('ticket', so.realm) self.assertEquals('1', so.id) self.assertTrue('#1' in so.title) self.assertTrue('Summary line' in so.title) self.assertEquals('santa', so.author) self.assertEquals(ticket['time'], so.created) self.assertEquals(ticket['changetime'], so.changed) self.assertTrue('*****@*****.**' in so.involved) self.assertTrue('*****@*****.**' in so.involved) self.assertTrue('bravo' in so.tags) self.assertTrue('Lorem ipsum' in so.oneline) self.assertTrue('Lorem ipsum' in so.body) original_time = ticket['time'] ticket['description'] = 'No latin filler here' ticket.save_changes('Jack Sprat', 'Could eat no fat') so = self._get_so() self.assertEquals('%s:ticket:1' % self.basename, so.doc_id) self.assertEquals('ticket', so.realm) self.assertEquals('1', so.id) self.assertEquals(original_time, so.created) self.assertEquals(ticket['changetime'], so.changed) self.assertFalse('Lorem ipsum' in so.body) self.assertTrue('No latin filler here' in so.body) self.assertTrue('Could eat no fat' in so.comments)
def process_commit(self, commit): '''Process a new git commit.''' self.env.log.debug('process_commit: {commit}'.format(commit=commit)) # Get the git commit message. msg = '''{author} [{url} {id}] {{{{{{ {message} }}}}}} '''.format(author=commit['author']['name'], url=commit['url'], id=commit['id'], message=commit['message']) # Find all the #123 strings in the commit message. ticket_re = re.compile('#[0-9]*') ticket_numbers = ticket_re.findall(msg) # Turn the ticket numbers into ints. ticket_numbers = set( [int(ticket_number[1:]) for ticket_number in ticket_numbers]) for ticket_number in ticket_numbers: self.env.log.debug( 'Found ticket number: {n}'.format(n=str(ticket_number))) try: db = self.env.get_db_cnx() ticket = Ticket(self.env, int(ticket_number), db) ticket.save_changes('GitHubServiceHook', msg) db.commit() self.env.log.debug('Comment added') except ResourceNotFound, e: self.env.log.debug( 'Ticket not found: {n}'.format(n=str(ticket_number))) continue