Options for including attachments when moving tickets Template changes Option to copy_ticket method to include_attachments Make handle_commit an option to copy_attachment Use suboption scripts for source options on tickets template Include script on tickets template Version bump Index: datamover/templates/datamover_ticket.cs =================================================================== --- datamover/templates/datamover_ticket.cs (revision 4963) +++ datamover/templates/datamover_ticket.cs (revision 4992) @@ -46,6 +46,11 @@ +
+ +
@@ -65,26 +70,16 @@   Index: datamover/util.py =================================================================== --- datamover/util.py (revision 4963) +++ datamover/util.py (revision 4992) @@ -15,18 +15,18 @@ '(' + ', '.join(data.keys()) + ') ' + \ 'VALUES (' + ', '.join(['%s']*len(data)) + ')' return (sql, data.values()) +def copy_ticket(source_env, dest_env, source_id, dest_db=None, include_attachments=False, action='copy'): + """Copy a ticket from {{{source_env}}} #{{{source_id}}} to {{{dest_env}}}.""" -def copy_ticket(source_env, dest_env, source_id, dest_db=None): - """Copy a ticket from {{{source_env}}} #{{{source_id}}} to {{{dest_env}}}.""" # In case a string gets passed in if not isinstance(source_env, Environment): source_env = open_environment(source_env) if not isinstance(dest_env, Environment): dest_env = open_environment(dest_env) # Open databases source_db = source_env.get_db_cnx() source_cursor = source_db.cursor() @@ -58,7 +56,18 @@ ticket_custom_data['ticket'] = dest_id q = make_query(ticket_custom_data, 'ticket_custom') dest_cursor.execute(*q) + # Copy the attachments + if include_attachments: + source_cursor.execute("SELECT id,filename FROM attachment where type='ticket' and id=%s" % (source_id,)) + for row in source_cursor: + t_att_data = dict(zip([d[0] for d in source_cursor.description], row)) + copy_attachment(source_env, dest_env, 'ticket', source_id, t_att_data['filename'], dest_db, dest_id, False) + # TODO: move all the if-move-then-delete-object clauses into util? + if action == 'move': + att = Attachment(source_env, 'ticket', t_att_data['id'], t_att_data['filename']) + att.delete() + if handle_commit: dest_db.commit() @@ -199,11 +208,11 @@ milestone_data = dict(zip([d[0] for d in source_cursor.description], row)) q = make_query(milestone_data, 'milestone') dest_cursor.execute(*q) if handle_commit: dest_db.commit() -def copy_attachment(source_env, dest_env, parent_realm, parent_id, filename, dest_db=None, dest_parent_id=None): +def copy_attachment(source_env, dest_env, parent_realm, parent_id, filename, dest_db=None, dest_parent_id=None, handle_commit = True): # In case a string gets passed in if not isinstance(source_env, Environment): source_env = open_environment(source_env) @@ -217,15 +226,14 @@ # Log message source_env.log.info('DatamoverPlugin: Moving attachment (%s,%s,%s) to the environment at %s', parent_realm, parent_id, filename, dest_env.path) dest_env.log.info('DatamoverPlugin: Moving attachment (%s,%s,%s) from the environment at %s', parent_realm, parent_id, filename, source_env.path) # Open databases source_db = source_env.get_db_cnx() source_cursor = source_db.cursor() - handle_commit = True if not dest_db: dest_db, handle_commit = dest_env.get_db_cnx(), False dest_cursor = dest_db.cursor() # Remove the attachment from the destination try: dest_attachment = Attachment(dest_env, parent_realm, dest_parent_id, filename, db=dest_db) Index: datamover/ticket.py =================================================================== --- datamover/ticket.py (revision 4963) +++ datamover/ticket.py (revision 4992) @@ -4,6 +4,7 @@ from trac.ticket.query import Query from trac.admin.api import IAdminPanelProvider +from trac.web.chrome import add_script from api import DatamoverSystem from util import copy_ticket @@ -12,18 +13,19 @@ """The ticket moving component of the datamover plugin.""" implements(IAdminPanelProvider) # IAdminPanelProvider methods def get_admin_panels(self, req): if req.perm.has_permission('TICKET_ADMIN'): yield ('mover', 'Data Mover', 'ticket', 'Tickets') def process_admin_request(self, req, cat, page, path_info): components = [c.name for c in TicketComponent.select(self.env)] envs = DatamoverSystem(self.env).all_environments() if req.method == 'POST': source_type = req.args.get('source') + include_attachments = req.args.get('include_attachments',False) if not source_type or source_type not in ('component', 'ticket', 'all', 'query'): raise TracError, "Source type not specified or invalid" source = req.args.get(source_type) @@ -63,16 +65,16 @@ self.log.debug('DatamoverTicketModule: Running query %r', query_string) ids = [x['id'] for x in Query.from_string(self.env, query_string).execute(req)] self.log.debug('DatamoverTicketModule: Results: %r', ids) dest_db = open_environment(dest).get_db_cnx() for id in ids: - copy_ticket(self.env, dest, id, dest_db) + copy_ticket(self.env, dest, id, dest_db, include_attachments, action) dest_db.commit() if action == 'move': for id in ids: Ticket(self.env, id).delete() if ids: req.hdf['datamover.message'] = '%s tickets %s'%(action_verb, ', '.join([str(n) for n in ids])) else: @@ -80,8 +82,8 @@ except TracError, e: req.hdf['datamover.message'] = "An error has occured: \n"+str(e) self.log.warn(req.hdf['datamover.message'], exc_info=True) - + add_script(req, "datamover/scripts.js") req.hdf['datamover.components'] = components req.hdf['datamover.envs'] = envs Index: setup.py =================================================================== --- setup.py (revision 4963) +++ setup.py (revision 4992) @@ -5,7 +5,7 @@ setup( name = 'TracDatamoverPlugin', - version = '1.3.7.t', + version = '1.3.7.u', packages = ['datamover'], package_data={ 'datamover' : [ 'templates/*.cs', "htdocs/*.js" ] }, author = "Noah Kantrowitz",