Ticket #1072: datamoverplugin.patch
| File datamoverplugin.patch, 25.9 kB (added by Eridius <kevin@sb.org>, 2 years ago) |
|---|
-
datamover/util.py
old new 1 from trac.core import TracError 1 2 from trac.env import Environment 2 3 from trac.web.main import _open_environment 3 4 from trac.wiki.model import WikiPage 5 from trac.ticket.model import Component as TicketComponent, Milestone 4 6 5 __all__ = ['copy_ticket', 'copy_wiki_page' ]7 __all__ = ['copy_ticket', 'copy_wiki_page', 'copy_component', 'copy_enum'] 6 8 7 9 8 10 def make_query(data, table): … … 93 95 94 96 if handle_commit: 95 97 dest_db.commit() 98 99 def copy_component(source_env, dest_env, name, dest_db=None): 100 # In case a string gets passed in 101 if not isinstance(source_env, Environment): 102 source_env = _open_environment(source_env) 103 if not isinstance(dest_env, Environment): 104 dest_env = _open_environment(dest_env) 105 106 # Log message 107 source_env.log.info('DatamoverPlugin: Moving component %s to the environment at %s', name, dest_env.path) 108 dest_env.log.info('DatamoverPlugin: Moving component %s from the environment at %s', name, source_env.path) 109 110 # Open databases 111 source_db = source_env.get_db_cnx() 112 source_cursor = source_db.cursor() 113 handle_commit = True 114 if not dest_db: 115 dest_db, handle_commit = dest_env.get_db_cnx(), False 116 dest_cursor = dest_db.cursor() 117 118 # Remove the component from the destination 119 try: 120 dest_comp = TicketComponent(dest_env, name, db=dest_db) 121 if dest_comp.exists: 122 dest_comp.delete(db=dest_db) 123 except TracError: 124 pass 125 126 # Copy each entry in the component table 127 source_cursor.execute('SELECT * FROM component WHERE name=%s',(name,)) 128 for row in source_cursor: 129 comp_data = dict(zip([d[0] for d in source_cursor.description], row)) 130 q = make_query(comp_data, 'component') 131 dest_cursor.execute(*q) 132 133 if handle_commit: 134 dest_db.commit() 135 136 def copy_enum(source_env, dest_env, etype, name, dest_db=None): 137 # In case a string gets passed in 138 if not isinstance(source_env, Environment): 139 source_env = _open_environment(source_env) 140 if not isinstance(dest_env, Environment): 141 dest_env = _open_environment(dest_env) 142 143 # Log message 144 source_env.log.info('DatamoverPlugin: Moving enum (%s,%s) to the environment at %s', etype, name, dest_env.path) 145 dest_env.log.info('DatamoverPlugin: Moving enum (%s,%s) from the environment at %s', etype, name, source_env.path) 146 147 # Open databases 148 source_db = source_env.get_db_cnx() 149 source_cursor = source_db.cursor() 150 handle_commit = True 151 if not dest_db: 152 dest_db, handle_commit = dest_env.get_db_cnx(), False 153 dest_cursor = dest_db.cursor() 154 155 # Remove the enum from the destination 156 dest_cursor.execute('DELETE FROM enum WHERE type=%s AND name=%s', (etype, name)) 157 158 # Copy each entry in the component table 159 source_cursor.execute('SELECT * FROM enum WHERE type=%s AND name=%s',(etype,name)) 160 for row in source_cursor: 161 comp_data = dict(zip([d[0] for d in source_cursor.description], row)) 162 q = make_query(comp_data, 'enum') 163 dest_cursor.execute(*q) 164 165 if handle_commit: 166 dest_db.commit() 167 168 def copy_milestone(source_env, dest_env, name, dest_db=None): 169 # In case a string gets passed in 170 if not isinstance(source_env, Environment): 171 source_env = _open_environment(source_env) 172 if not isinstance(dest_env, Environment): 173 dest_env = _open_environment(dest_env) 174 175 # Log message 176 source_env.log.info('DatamoverPlugin: Moving milestone %s to the environment at %s', name, dest_env.path) 177 dest_env.log.info('DatamoverPlugin: Moving milestone %s from the environment at %s', name, source_env.path) 178 179 # Open databases 180 source_db = source_env.get_db_cnx() 181 source_cursor = source_db.cursor() 182 handle_commit = True 183 if not dest_db: 184 dest_db, handle_commit = dest_env.get_db_cnx(), False 185 dest_cursor = dest_db.cursor() 186 187 # Remove the milestone from the destination 188 try: 189 dest_milestone = Milestone(dest_env, name, db=dest_db) 190 if dest_milestone.exists: 191 dest_milestone.delete(db=dest_db) 192 except TracError: 193 pass 194 195 # Copy each entry in the milestone table 196 source_cursor.execute('SELECT * FROM milestone WHERE name=%s',(name,)) 197 for row in source_cursor: 198 comp_data = dict(zip([d[0] for d in source_cursor.description], row)) 199 q = make_query(comp_data, 'milestone') 200 dest_cursor.execute(*q) 201 202 if handle_commit: 203 dest_db.commit() -
datamover/milestone.py
old new 1 from trac.core import * 2 from trac.web.main import _open_environment 3 from trac.ticket.model import Milestone 4 5 from webadmin.web_ui import IAdminPageProvider 6 7 from api import DatamoverSystem 8 from util import copy_milestone 9 10 class DatamoverMilestoneModule(Component): 11 """The milestone moving component of the datamover plugin.""" 12 13 implements(IAdminPageProvider) 14 15 # IAdminPageProvider methods 16 def get_admin_pages(self, req): 17 if req.perm.has_permission('TRAC_ADMIN'): 18 yield ('mover', 'Data Mover', 'milestone', 'Milestones') 19 20 def process_admin_request(self, req, cat, page, path_info): 21 envs = DatamoverSystem(self.env).all_environments() 22 milestones = [m.name for m in Milestone.select(self.env)] 23 24 if req.method == 'POST': 25 source_type = req.args.get('source') 26 if not source_type or source_type not in ('milestone', 'all'): 27 raise TracError, "Source type not specified or invalid" 28 source = req.args.get(source_type) 29 dest = req.args.get('destination') 30 action = None 31 if 'copy' in req.args.keys(): 32 action = 'copy' 33 elif 'move' in req.args.keys(): 34 action = 'move' 35 else: 36 raise TracError, 'Action not specified or invalid' 37 38 action_verb = {'copy':'Copied', 'move':'Moved'}[action] 39 40 comp_filter = None 41 if source_type == 'milestone': 42 in_milestones = req.args.getlist('milestone') 43 milestone_filter = lambda c: c in in_milestones 44 elif source_type == 'all': 45 milestone_filter = lambda c: True 46 47 try: 48 sel_milestones = [m for m in milestones if milestone_filter(m)] 49 dest_db = _open_environment(dest).get_db_cnx() 50 for milestone in sel_milestones: 51 copy_milestone(self.env, dest, milestone, dest_db) 52 dest_db.commit() 53 54 if action == 'move': 55 for milestone in sel_milestones: 56 Milestone(self.env, milestone).delete() 57 58 req.hdf['datamover.message'] = '%s milestones %s'%(action_verb, ', '.join(sel_milestones)) 59 except TracError, e: 60 req.hdf['datamover.message'] = "An error has occured: \n"+str(e) 61 self.log.warn(req.hdf['datamover.message'], exc_info=True) 62 63 64 req.hdf['datamover.envs'] = envs 65 req.hdf['datamover.milestones'] = milestones 66 return 'datamover_milestone.cs', None -
datamover/component.py
old new 1 from trac.core import * 2 from trac.web.main import _open_environment 3 from trac.ticket.model import Component as TicketComponent 4 5 from webadmin.web_ui import IAdminPageProvider 6 7 from api import DatamoverSystem 8 from util import copy_component 9 10 class DatamoverComponentModule(Component): 11 """The ticket component moving component of the datamover plugin.""" 12 13 implements(IAdminPageProvider) 14 15 # IAdminPageProvider methods 16 def get_admin_pages(self, req): 17 if req.perm.has_permission('TRAC_ADMIN'): 18 yield ('mover', 'Data Mover', 'component', 'Components') 19 20 def process_admin_request(self, req, cat, page, path_info): 21 envs = DatamoverSystem(self.env).all_environments() 22 components = [c.name for c in TicketComponent.select(self.env)] 23 24 if req.method == 'POST': 25 source_type = req.args.get('source') 26 if not source_type or source_type not in ('component', 'all'): 27 raise TracError, "Source type not specified or invalid" 28 source = req.args.get(source_type) 29 dest = req.args.get('destination') 30 action = None 31 if 'copy' in req.args.keys(): 32 action = 'copy' 33 elif 'move' in req.args.keys(): 34 action = 'move' 35 else: 36 raise TracError, 'Action not specified or invalid' 37 38 action_verb = {'copy':'Copied', 'move':'Moved'}[action] 39 40 comp_filter = None 41 if source_type == 'component': 42 in_components = req.args.getlist('component') 43 comp_filter = lambda c: c in in_components 44 elif source_type == 'all': 45 comp_filter = lambda c: True 46 47 try: 48 sel_components = [c for c in components if comp_filter(c)] 49 dest_db = _open_environment(dest).get_db_cnx() 50 for comp in sel_components: 51 copy_component(self.env, dest, comp, dest_db) 52 dest_db.commit() 53 54 if action == 'move': 55 for comp in sel_components: 56 TicketComponent(self.env, comp).delete() 57 58 req.hdf['datamover.message'] = '%s components %s'%(action_verb, ', '.join(sel_components)) 59 except TracError, e: 60 req.hdf['datamover.message'] = "An error has occured: \n"+str(e) 61 self.log.warn(req.hdf['datamover.message'], exc_info=True) 62 63 64 req.hdf['datamover.envs'] = envs 65 req.hdf['datamover.components'] = components 66 return 'datamover_component.cs', None -
datamover/ticket.py
old new 16 16 # IAdminPageProvider methods 17 17 def get_admin_pages(self, req): 18 18 if req.perm.has_permission('TICKET_ADMIN'): 19 yield ('mover', 'Data Mover', 'ticket', 'Ticket ')19 yield ('mover', 'Data Mover', 'ticket', 'Tickets') 20 20 21 21 def process_admin_request(self, req, cat, page, path_info): 22 22 components = [c.name for c in TicketComponent.select(self.env)] -
datamover/wiki.py
old new 27 27 28 28 if req.method == 'POST': 29 29 source_type = req.args.get('source') 30 if not source_type or source_type not in ('prefix', 'glob', 'regex' ):30 if not source_type or source_type not in ('prefix', 'glob', 'regex', 'all'): 31 31 raise TracError, "Source type not specified or invalid" 32 32 source = req.args.get(source_type) 33 33 dest = req.args.get('destination') … … 48 48 page_filter = lambda p: fnmatch.fnmatch(p, source) 49 49 elif source_type == 'regex': 50 50 page_filter = lambda p: re.search(re.compile(source, re.U), p) 51 elif source_type == 'all': 52 page_filter = lambda p: True 51 53 52 54 53 55 try: -
datamover/enum.py
old new 1 from trac.core import * 2 from trac.web.main import _open_environment 3 4 from webadmin.web_ui import IAdminPageProvider 5 6 from api import DatamoverSystem 7 from util import copy_enum 8 9 class DatamoverEnumModule(Component): 10 """The ticket enum moving component of the datamover plugin.""" 11 12 implements(IAdminPageProvider) 13 14 # IAdminPageProvider methods 15 def get_admin_pages(self, req): 16 if req.perm.has_permission('TRAC_ADMIN'): 17 yield ('mover', 'Data Mover', 'enum', 'Enums') 18 19 def process_admin_request(self, req, cat, page, path_info): 20 envs = DatamoverSystem(self.env).all_environments() 21 enums = [] 22 source_db = self.env.get_db_cnx() 23 source_cursor = source_db.cursor() 24 source_cursor.execute('SELECT type,name FROM enum') 25 for row in source_cursor: 26 enums.append(row) 27 hashedEnums = {} 28 for enum in enums: 29 enum_type = enum[0] 30 enum_name = enum[1] 31 if not hashedEnums.has_key(enum_type): 32 hashedEnums[enum_type] = [] 33 hashedEnums[enum_type].append(enum_name) 34 35 if req.method == 'POST': 36 source_type = req.args.get('source') 37 if not source_type or source_type not in ('type', 'enum', 'all'): 38 raise TracError, "Source type not specified or invalid" 39 source = req.args.get(source_type) 40 dest = req.args.get('destination') 41 action = None 42 if 'copy' in req.args.keys(): 43 action = 'copy' 44 elif 'move' in req.args.keys(): 45 action = 'move' 46 else: 47 raise TracError, 'Action not specified or invalid' 48 49 action_verb = {'copy':'Copied', 'move':'Moved'}[action] 50 51 enum_filter = None 52 if source_type == 'type': 53 sel_type = req.args.get('enumtype') 54 enum_filter = lambda e: e[0] == sel_type 55 elif source_type == 'enum': 56 sel_enums = [(k,v) for k,v in req.args.items() if k.startswith('enum[')] 57 enum_filter = lambda e: ('enum[%s]' % e[0], e[1]) in sel_enums 58 elif source_type == 'all': 59 enum_filter = lambda c: True 60 61 try: 62 filtered_enums = [e for e in enums if enum_filter(e)] 63 dest_db = _open_environment(dest).get_db_cnx() 64 for enum in filtered_enums: 65 copy_enum(self.env, dest, enum[0], enum[1], dest_db) 66 dest_db.commit() 67 68 if action == 'move': 69 for enum in filtered_enums: 70 source_cursor.execute('DELETE FROM enum WHERE type=%s AND name=%s', (enum[0],enum[1])) 71 72 req.hdf['datamover.message'] = '%s enums %s'%(action_verb, ', '.join(['%s:%s'%e for e in filtered_enums])) 73 except TracError, e: 74 req.hdf['datamover.message'] = "An error has occured: \n"+str(e) 75 self.log.warn(req.hdf['datamover.message'], exc_info=True) 76 77 78 req.hdf['datamover.envs'] = envs 79 for k in hashedEnums: 80 req.hdf['datamover.enums.' + k] = hashedEnums[k] 81 req.hdf['datamover.enumtypes'] = hashedEnums.keys() 82 return 'datamover_enum.cs', None -
datamover/templates/datamover_milestone.cs
old new 1 <h2>Move Milestones</h2> 2 3 <?cs if:datamover.message ?> 4 <div id="datamover_message" style="font-weight: bold"> 5 <?cs var:datamover.message ?> 6 </div> 7 <?cs /if ?> 8 9 <form class="mod" method="post" action=""> 10 11 <fieldset> 12 <legend>Source</legend> 13 <div class="field"> 14 <label><input type="radio" name="source" value="milestone" id="source_milestone_radio" checked="checked" /> 15 Milestone 16 </label> 17 <label><input type="radio" name="source" value="all" id="source_all_radio" /> 18 All 19 </label> 20 </div> 21 <div class="field" id="source_milestone_div"> 22 <label>Milestone: 23 <?cs each:milestone = datamover.milestones ?> 24 <br/> 25 <input type="checkbox" name="milestone" value="<?cs var:milestone ?>"><?cs var:milestone ?></input> 26 <?cs /each ?> 27 </label> 28 </div> 29 <div class="field" id="source_all_div" style="display: none"> 30 31 </div> 32 </fieldset> 33 34 <fieldset> 35 <legend>Destination</legend> 36 <div class="field"> 37 <label>Environment: 38 <select name="destination"> 39 <?cs each:env = datamover.envs ?> 40 <option value="<?cs name:env ?>"><?cs var:env.name ?></option> 41 <?cs /each ?> 42 </select> 43 </label> 44 </div> 45 </fieldset> 46 47 <div class="buttons"> 48 <input type="submit" name="copy" value="Copy" /> 49 <input type="submit" name="move" value="Move" /> 50 </div> 51 52 </form> 53 54 55 <script type="text/javascript"> 56 <!-- 57 var current_div = 'source_milestone_div'; 58 59 function show_div(d) { 60 document.getElementById(current_div).style.display = 'none'; 61 document.getElementById(d).style.display = 'block'; 62 current_div = d; 63 } 64 65 function do_addEvent(d) { 66 addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 67 } 68 69 do_addEvent('source_milestone'); 70 do_addEvent('source_all'); 71 //--> 72 </script> 73 -
datamover/templates/datamover_component.cs
old new 1 <h2>Move Components</h2> 2 3 <?cs if:datamover.message ?> 4 <div id="datamover_message" style="font-weight: bold"> 5 <?cs var:datamover.message ?> 6 </div> 7 <?cs /if ?> 8 9 <form class="mod" method="post" action=""> 10 11 <fieldset> 12 <legend>Source</legend> 13 <div class="field"> 14 <label><input type="radio" name="source" value="component" id="source_component_radio" checked="checked" /> 15 Component 16 </label> 17 <label><input type="radio" name="source" value="all" id="source_all_radio" /> 18 All 19 </label> 20 </div> 21 <div class="field" id="source_component_div"> 22 <label>Component: 23 <?cs each:comp = datamover.components ?> 24 <br/> 25 <input type="checkbox" name="component" value="<?cs var:comp ?>"><?cs var:comp ?></input> 26 <?cs /each ?> 27 </label> 28 </div> 29 <div class="field" id="source_all_div" style="display: none"> 30 31 </div> 32 </fieldset> 33 34 <fieldset> 35 <legend>Destination</legend> 36 <div class="field"> 37 <label>Environment: 38 <select name="destination"> 39 <?cs each:env = datamover.envs ?> 40 <option value="<?cs name:env ?>"><?cs var:env.name ?></option> 41 <?cs /each ?> 42 </select> 43 </label> 44 </div> 45 </fieldset> 46 47 <div class="buttons"> 48 <input type="submit" name="copy" value="Copy" /> 49 <input type="submit" name="move" value="Move" /> 50 </div> 51 52 </form> 53 54 55 <script type="text/javascript"> 56 <!-- 57 var current_div = 'source_component_div'; 58 59 function show_div(d) { 60 document.getElementById(current_div).style.display = 'none'; 61 document.getElementById(d).style.display = 'block'; 62 current_div = d; 63 } 64 65 function do_addEvent(d) { 66 addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 67 } 68 69 do_addEvent('source_component'); 70 do_addEvent('source_all'); 71 //--> 72 </script> 73 -
datamover/templates/datamover_ticket.cs
old new 22 22 </label> 23 23 <label><input type="radio" name="source" value="query" id="source_query_radio" /> 24 24 Query 25 </label> 25 </label> 26 26 </div> 27 27 <div class="field" id="source_component_div"> 28 28 <label>Component: … … 80 80 } 81 81 82 82 function do_addEvent(d) { 83 addEvent(document.getElementById(d+'_radio'), 'c hange', function() { show_div(d+'_div'); });83 addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 84 84 } 85 85 86 86 do_addEvent('source_component'); -
datamover/templates/datamover_wiki.cs
old new 20 20 <label><input type="radio" name="source" value="regex" id="source_regex_radio" /> 21 21 Regex 22 22 </label> 23 <label><input type="radio" name="source" value="all" id="source_all_radio" /> 24 All 25 </label> 23 26 </div> 24 27 <div class="field" id="source_prefix_div"> 25 28 <label>Prefix: … … 36 39 <input type="text" name="regex" /> 37 40 </label> 38 41 </div> 42 <div class="field" id="source_all_div" style="display: none"> 43 44 </div> 39 45 </fieldset> 40 46 41 47 <fieldset> … … 70 76 } 71 77 72 78 function do_addEvent(d) { 73 addEvent(document.getElementById(d+'_radio'), 'c hange', function() { show_div(d+'_div'); });79 addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 74 80 } 75 81 76 82 do_addEvent('source_prefix'); 77 83 do_addEvent('source_glob'); 78 84 do_addEvent('source_regex'); 85 do_addEvent('source_all'); 79 86 //--> 80 87 </script> 81 88 -
datamover/templates/datamover_enum.cs
old new 1 <h2>Move Enums</h2> 2 3 <?cs if:datamover.message ?> 4 <div id="datamover_message" style="font-weight: bold"> 5 <?cs var:datamover.message ?> 6 </div> 7 <?cs /if ?> 8 9 <form class="mod" method="post" action=""> 10 11 <fieldset> 12 <legend>Source</legend> 13 <div class="field"> 14 <label><input type="radio" name="source" value="type" id="source_type_radio" checked="checked" /> 15 Enum Type 16 </label> 17 <label><input type="radio" name="source" value="enum" id="source_enum_radio" /> 18 Selected Enums 19 </label> 20 <label><input type="radio" name="source" value="all" id="source_all_radio" /> 21 All 22 </label> 23 </div> 24 <div class="field" id="source_type_div"> 25 <label>Enum Type: 26 <select name="enumtype"> 27 <?cs each:enum = datamover.enums ?> 28 <option value="<?cs name:enum ?>"><?cs name:enum ?></option> 29 <?cs /each ?> 30 </select> 31 </label> 32 </div> 33 <div class="field" id="source_enum_div" style="display: none"> 34 <label>Enums: 35 <br/> 36 <table> 37 <?cs each:enum = datamover.enums ?> 38 <tr><td valign="top" align="right"><b><?cs name:enum ?>: </b></td> 39 <td> 40 <?cs each:name = enum ?> 41 <input type="checkbox" name="enum[<?cs name:enum ?>]" value="<?cs var:name ?>"><?cs var:name ?></input><br/> 42 <?cs /each ?> 43 </td></tr> 44 <?cs /each ?> 45 </table> 46 </label> 47 </div> 48 <div class="field" id="source_all_div" style="display: none"> 49 50 </div> 51 </fieldset> 52 53 <fieldset> 54 <legend>Destination</legend> 55 <div class="field"> 56 <label>Environment: 57 <select name="destination"> 58 <?cs each:env = datamover.envs ?> 59 <option value="<?cs name:env ?>"><?cs var:env.name ?></option> 60 <?cs /each ?> 61 </select> 62 </label> 63 </div> 64 </fieldset> 65 66 <div class="buttons"> 67 <input type="submit" name="copy" value="Copy" /> 68 <input type="submit" name="move" value="Move" /> 69 </div> 70 71 </form> 72 73 74 <script type="text/javascript"> 75 <!-- 76 var current_div = 'source_type_div'; 77 78 function show_div(d) { 79 document.getElementById(current_div).style.display = 'none'; 80 document.getElementById(d).style.display = 'block'; 81 current_div = d; 82 } 83 84 function do_addEvent(d) { 85 addEvent(document.getElementById(d+'_radio'), 'click', function() { show_div(d+'_div'); }); 86 } 87 88 do_addEvent('source_type'); 89 do_addEvent('source_enum'); 90 do_addEvent('source_all'); 91 //--> 92 </script> 93 -
setup.py
old new 5 5 6 6 setup( 7 7 name = 'TracDatamoverPlugin', 8 version = '1.1. 1',8 version = '1.1.2', 9 9 packages = ['datamover'], 10 10 package_data={ 'datamover' : [ 'templates/*.cs' ] }, 11 11 author = "Noah Kantrowitz", … … 22 22 'datamover.web_ui = datamover.web_ui', 23 23 'datamover.ticket = datamover.ticket', 24 24 'datamover.wiki = datamover.wiki', 25 'datamover.component = datamover.component', 26 'datamover.enum = datamover.enum', 27 'datamover.milestone = datamover.milestone', 25 28 ], 26 29 }, 27 30
