def main(self, folder, message): commit_result = run_command_method_with_kwargs("commit", folder=folder, message=message) push_result = run_command_method_with_kwargs("push", folder=folder) return commit_result, push_result
def test_push_basic(self): status_result = { 'ready': { 'files': [], 'fields': { 'somefield': ('one', 'two', 'two', ), 'otherfield': ('one', 'three', 'three', ) }, 'links': {}, } } with patch.object(self.ticketfolder, 'status') as status: status.return_value = status_result with patch.object(self.ticketfolder.issue, 'update') as update: with patch('jirafs.commands.pull.Command.pull') as pull: pull.return_value = True, True run_command_method_with_kwargs( 'push', folder=self.ticketfolder, ) self.assertEqual(1, len(update.call_args_list)) self.assertEqual( update.call_args, call( **{ field_name: value[1] for field_name, value in status_result['ready']['fields'].items() } ) )
def main(self, folder, message): commit_result = run_command_method_with_kwargs( 'commit', folder=folder, message=message ) push_result = run_command_method_with_kwargs( 'push', folder=folder ) return commit_result, push_result
def test_push_no_changes(self): with patch.object(self.ticketfolder.issue, 'update') as update: with patch('jirafs.commands.pull.Command.pull') as pull: pull.return_value = True, True run_command_method_with_kwargs( 'push', folder=self.ticketfolder, ) self.assertEqual(0, len(update.call_args_list))
def setUp(self): try: import jirafs_list_table # noqa except ImportError: raise SkipTest("Push command macropatch tests require the " "jira-list-table package to be installed.") super(TestPushCommandWithMacropatch, self).setUp() run_command_method_with_kwargs('plugins', folder=self.ticketfolder, args=Mock(enable='list_table', ))
def clone_from_issue(self, match, ticket_url, path, jira): if not path: path = match.group(1) path = os.path.realpath(path) os.mkdir(path) folder = TicketFolder.initialize_ticket_folder(ticket_url, path, jira) utils.run_command_method_with_kwargs('pull', folder=folder) return folder
def test_push_no_changes(self): with patch.object(self.ticketfolder.issue, "update") as update: with patch("jirafs.commands.pull.Command.main") as pull: pull.return_value = True, True run_command_method_with_kwargs( "push", folder=self.ticketfolder, ) self.assertEqual(0, len(update.call_args_list))
def test_push_rejected_if_updated(self): src_path = self.get_asset_path("test_fetch/fetched.jira") dst_path = self.ticketfolder.get_shadow_path("fields.jira") shutil.copyfile( src_path, dst_path, ) self.ticketfolder.run_git_command("add", "-A", shadow=True) self.ticketfolder.run_git_command("commit", "-m", "Changed", shadow=True) self.ticketfolder.run_git_command("push", "origin", "jira", shadow=True) with self.assertRaises(exceptions.LocalCopyOutOfDate): run_command_method_with_kwargs("push", folder=self.ticketfolder)
def test_push_change_patched_content(self): # First, let's write out a patch description_one = u""" {list-table} * - ** Location ** Company * @coddingtonbear ** Portland, OR ** Urban Airship {list-table} """ description_path = self.ticketfolder.get_path('description.jira') with io.open(description_path, 'w', encoding='utf-8') as out: out.write(description_one) run_command_method_with_kwargs( 'commit', folder=self.ticketfolder, message='No me importa', ) with patch.object(self.ticketfolder.issue, 'update'): with patch('jirafs.commands.pull.Command.pull') as pull: pull.return_value = True, True run_command_method_with_kwargs( 'push', folder=self.ticketfolder, ) description_two = u""" {list-table:horizontal} * - ** Location ** Company * @coddingtonbear ** Portland, OR ** Urban Airship * @ralphbean ** New York, NY ** RedHat {list-table} """ with io.open(description_path, 'w', encoding='utf-8') as out: out.write(description_two) run_command_method_with_kwargs( 'commit', folder=self.ticketfolder, message='No me importa', ) with patch.object(self.ticketfolder.issue, 'update'): with patch('jirafs.commands.pull.Command.pull') as pull: pull.return_value = True, True run_command_method_with_kwargs( 'push', folder=self.ticketfolder, )
def setUp(self): try: import jirafs_list_table # noqa except ImportError: raise SkipTest( "Push command macropatch tests require the " "jira-list-table package to be installed." ) super(TestPushCommandWithMacropatch, self).setUp() run_command_method_with_kwargs( 'plugins', folder=self.ticketfolder, args=Mock( enable='list_table', ) )
def handle(self, args, jira, path, parser, **kwargs): server = args.server if not server: server = utils.get_default_jira_server() issue_data = {} for field in self.FIELDS: if getattr(args, field['name']) is not None: self.set_field_value( issue_data, field, getattr(args, field['name']) ) elif args.quiet: self.set_field_value(issue_data, field, field.get('default')) else: self.set_field_value( issue_data, field, self.prompt_for_input(field) ) jira_client = jira(server) issue = jira_client.create_issue(issue_data) return run_command_method_with_kwargs( 'clone', path=None, url=issue.permalink(), jira=jira, )
def test_fetch(self): self.ticketfolder._issue = ( self.rehydrate_issue('test_fetch/fetched.json') ) with patch.object(self.ticketfolder, 'clear_cache') as clear_cache: run_command_method_with_kwargs( 'fetch', folder=self.ticketfolder, ) self.assertTrue(clear_cache.called) expected_result = self.get_asset_contents('test_fetch/fetched.jira') with open(self.ticketfolder.get_shadow_path('fields.jira')) as _in: actual_result = _in.read() self.assertEqual(actual_result, expected_result)
def main(self, args, jira, path, parser, **kwargs): server = args.server if not server: server = utils.get_default_jira_server() issue_data = {} for field in self.FIELDS: if getattr(args, field["name"]) is not None: self.set_field_value(issue_data, field, getattr(args, field["name"])) elif args.quiet: self.set_field_value(issue_data, field, field.get("default")) else: self.set_field_value(issue_data, field, self.prompt_for_input(field)) jira_client = jira(server) issue = jira_client.create_issue(issue_data) return run_command_method_with_kwargs( "clone", path=None, url=issue.permalink(), jira=jira, )
def test_push(self): changed_field = u"description" changed_value = u"Something Else" status = self.get_empty_status() status["ready"]["fields"][changed_field] = ( u"Something", changed_value, changed_value, ) with patch("jirafs.commands.pull.Command.main") as pull: with patch.object(self.ticketfolder, "status") as status_method: status_method.return_value = status with patch.object(self.ticketfolder.issue, "update") as out: run_command_method_with_kwargs("push", folder=self.ticketfolder) self.assertTrue(pull.called) out.assert_called_with(**{"description": changed_value})
def test_push(self): changed_field = 'description' changed_value = 'Something Else' status = self.get_empty_status() status['ready']['fields'][changed_field] = ( 'Something', changed_value, ) with patch('jirafs.commands.pull.Command.pull') as pull: with patch.object(self.ticketfolder, 'status') as status_method: status_method.return_value = status with patch.object(self.ticketfolder.issue, 'update') as out: run_command_method_with_kwargs('push', folder=self.ticketfolder) self.assertTrue(pull.called) out.assert_called_with(**{'description': changed_value})
def test_fetch(self): self.ticketfolder._issue = self.rehydrate_issue("test_fetch/fetched.json") with patch.object(self.ticketfolder, "clear_cache") as clear_cache: run_command_method_with_kwargs( "fetch", folder=self.ticketfolder, ) self.assertTrue(clear_cache.called) expected_result = JiraFieldManager( self.get_asset_contents("test_fetch/fetched.jira") ) with io.open( self.ticketfolder.get_shadow_path("fields.jira"), encoding="utf-8" ) as _in: actual_result = JiraFieldManager(_in.read()) self.assertEqual(actual_result, expected_result)
def test_push_rejected_if_updated(self): src_path = self.get_asset_path('test_fetch/fetched.jira') dst_path = self.ticketfolder.get_shadow_path('fields.jira') shutil.copyfile( src_path, dst_path, ) self.ticketfolder.run_git_command('add', '-A', shadow=True) self.ticketfolder.run_git_command('commit', '-m', 'Changed', shadow=True) self.ticketfolder.run_git_command('push', 'origin', 'jira', shadow=True) with self.assertRaises(exceptions.LocalCopyOutOfDate): run_command_method_with_kwargs('push', folder=self.ticketfolder)
def test_push_rejected_if_updated(self): src_path = self.get_asset_path('test_fetch/fetched.jira') dst_path = self.ticketfolder.get_shadow_path('fields.jira') shutil.copyfile( src_path, dst_path, ) self.ticketfolder.run_git_command('add', '-A', shadow=True) self.ticketfolder.run_git_command( 'commit', '-m', 'Changed', shadow=True ) self.ticketfolder.run_git_command( 'push', 'origin', 'jira', shadow=True ) with self.assertRaises(exceptions.LocalCopyOutOfDate): run_command_method_with_kwargs( 'push', folder=self.ticketfolder )
def test_push_basic(self): status_result = { "ready": { "files": [], "fields": { "somefield": ( "one", "two", "two", ), "otherfield": ( "one", "three", "three", ), }, "links": {}, "deleted": [], } } with patch.object(self.ticketfolder, "status") as status: status.return_value = status_result with patch.object(self.ticketfolder.issue, "update") as update: with patch("jirafs.commands.pull.Command.main") as pull: pull.return_value = True, True run_command_method_with_kwargs( "push", folder=self.ticketfolder, ) self.assertEqual(1, len(update.call_args_list)) self.assertEqual( update.call_args, call( **{ field_name: value[1] for field_name, value in status_result["ready"] ["fields"].items() }), )
def clone_from_issue(self, match, ticket_url, path, jira): if not path: path = match.group(1) path = os.path.realpath(path) os.mkdir(path) try: folder = TicketFolder.initialize_ticket_folder( ticket_url, path, jira) utils.run_command_method_with_kwargs("pull", folder=folder) except BaseException: shutil.rmtree(path) raise folder.log("Issue %s cloned successfully to %s", ( folder.issue_url, folder.path, )) return folder
def test_push(self): changed_field = 'description' changed_value = 'Something Else' status = self.get_empty_status() status['ready']['fields'][changed_field] = ( 'Something', changed_value, ) with patch('jirafs.commands.pull.Command.pull') as pull: with patch.object(self.ticketfolder, 'status') as status_method: status_method.return_value = status with patch.object(self.ticketfolder.issue, 'update') as out: run_command_method_with_kwargs( 'push', folder=self.ticketfolder ) self.assertTrue(pull.called) out.assert_called_with( **{ 'description': changed_value } )
def test_push_basic(self): status_result = { 'ready': { 'files': [], 'fields': { 'somefield': ( 'one', 'two', 'two', ), 'otherfield': ( 'one', 'three', 'three', ) }, 'links': {}, } } with patch.object(self.ticketfolder, 'status') as status: status.return_value = status_result with patch.object(self.ticketfolder.issue, 'update') as update: with patch('jirafs.commands.pull.Command.main') as pull: pull.return_value = True, True run_command_method_with_kwargs( 'push', folder=self.ticketfolder, ) self.assertEqual(1, len(update.call_args_list)) self.assertEqual( update.call_args, call( **{ field_name: value[1] for field_name, value in status_result['ready'] ['fields'].items() }))
def clone_from_issue(self, match, ticket_url, path, jira): if not path: path = match.group(1) path = os.path.realpath(path) os.mkdir(path) try: folder = TicketFolder.initialize_ticket_folder(ticket_url, path, jira) utils.run_command_method_with_kwargs('pull', folder=folder) except Exception: shutil.rmtree(path) raise folder.log( "Issue %s cloned successfully to %s", ( folder.issue_url, folder.path, ) ) return folder
def setUp(self): self.arbitrary_ticket_number = "ALPHA-123" self.root_folder = tempfile.mkdtemp() self.mock_jira = mock.MagicMock() self.mock_jira.issue.return_value = self.rehydrate_issue("basic.issue.json") self.mock_get_jira = lambda _, config=None: self.mock_jira with patch( "jirafs.ticketfolder.TicketFolder.get_remotely_changed" ) as get_remotely_changed: get_remotely_changed.return_value = [] self.ticketfolder = run_command_method_with_kwargs( "clone", url="http://arbitrary.com/browse/ALPHA-123", jira=self.mock_get_jira, path=os.path.join(self.root_folder, self.arbitrary_ticket_number,), )
def main(self, folder, state_id): folder.jira.transition_issue(folder.issue, state_id) starting_status = folder.get_fields()["status"] pull_result = run_command_method_with_kwargs("pull", folder=folder) if starting_status == folder.get_fields()["status"]: # I'd love it if we could instead just check the response code # from the transitions API, but that API returns a 204 whether # or not the issue itself can be successfully transitioned. raise JiraInteractionFailed( "Jira was not able to successfully transition this issue " "into the requested state. This type of failure usually " "occurs when one's Jira configuration requires that certain " "fields be specified before transitioning into a " "given state. Unfortunately, no details regarding what " "fields may be required are provided via Jira's API.") return pull_result[1]
def main(self, folder, state_id): folder.jira.transition_issue(folder.issue, state_id) starting_status = folder.get_fields()['status'] pull_result = run_command_method_with_kwargs('pull', folder=folder) if starting_status == folder.get_fields()['status']: # I'd love it if we could instead just check the response code # from the transitions API, but that API returns a 204 whether # or not the issue itself can be successfully transitioned. raise JiraInteractionFailed( "JIRA was not able to successfully transition this issue " "into the requested state. This type of failure usually " "occurs when one's JIRA configuration requires that certain " "fields be specified before transitioning into a " "given state. Unfortunately, no details regarding what " "fields may be required are provided via JIRA's API." ) return pull_result[1]
def setUp(self): super(BaseCommandTestCase, self).setUp() self.arbitrary_ticket_number = 'ALPHA-123' self.root_folder = tempfile.mkdtemp() self.mock_jira = mock.MagicMock() self.mock_jira.issue.return_value = self.rehydrate_issue( 'basic.issue.json') self.mock_get_jira = lambda _, config=None: self.mock_jira with patch('jirafs.ticketfolder.TicketFolder.get_remotely_changed' ) as get_remotely_changed: get_remotely_changed.return_value = [] self.ticketfolder = run_command_method_with_kwargs( 'clone', url='http://arbitrary.com/browse/ALPHA-123', jira=self.mock_get_jira, path=os.path.join( self.root_folder, self.arbitrary_ticket_number, ))
def main( self, folder, field_name, field_value, isjson, negate, raw, quiet, execute, execute_here ): actual_value = run_command_method_with_kwargs( 'field', method='get_field_value_by_dotpath', folder=folder, field_name=field_name, raw=raw, ) if isjson: field_value = json.loads(field_value) success = actual_value == field_value comparison_result = u" != " if success: comparison_result = u" == " message = u"{left} {comparison} {right}".format( left=actual_value, comparison=comparison_result, right=field_value, ) if negate: success = not success if execute and success: execute = execute.replace('{}', folder.path) subprocess.call( execute, shell=True, cwd=os.getcwd() if execute_here else folder.path ) return ( message if not quiet else None, 0 if success else 1, )
def setUp(self): self.arbitrary_ticket_number = 'ALPHA-123' self.root_folder = tempfile.mkdtemp() self.mock_jira = mock.MagicMock() self.mock_jira.issue.return_value = self.rehydrate_issue( 'basic.issue.json' ) self.mock_get_jira = lambda _, config=None: self.mock_jira with patch( 'jirafs.ticketfolder.TicketFolder.get_remotely_changed' ) as get_remotely_changed: get_remotely_changed.return_value = [] self.ticketfolder = run_command_method_with_kwargs( 'clone', url='http://arbitrary.com/browse/ALPHA-123', jira=self.mock_get_jira, path=os.path.join( self.root_folder, self.arbitrary_ticket_number, ) )
def main(self, folder, field_name, field_value, isjson, negate, raw, quiet, execute, execute_here): actual_value = run_command_method_with_kwargs( 'field', method='get_field_value_by_dotpath', folder=folder, field_name=field_name, raw=raw, ) if isjson: field_value = json.loads(field_value) success = actual_value == field_value comparison_result = u" != " if success: comparison_result = u" == " message = u"{left} {comparison} {right}".format( left=actual_value, comparison=comparison_result, right=field_value, ) if negate: success = not success if execute and success: execute = execute.replace('{}', folder.path) subprocess.call(execute, shell=True, cwd=os.getcwd() if execute_here else folder.path) return ( message if not quiet else None, 0 if success else 1, )
def main(self, folder, **kwargs): self.validate_issue(folder) with utils.stash_local_changes(folder): status = folder.status() if not folder.is_up_to_date(): raise exceptions.LocalCopyOutOfDate( "Your local copy is out-of-date. You must use " "the 'merge' command to update your local copy " "before pushing changes.") file_meta = folder.get_remote_file_metadata(shadow=False) deleted = set() for filename in status["ready"]["deleted"]: folder.log( 'Deleting file "%s"', (filename, ), ) for attachment in folder.issue.fields.attachment: if attachment.filename == filename and attachment.id not in deleted: folder.jira.delete_attachment(attachment.id) deleted.add(id) for filename in status["ready"]["files"]: upload = io.BytesIO( folder.get_local_file_at_revision(filename, "HEAD", binary=True)) folder.log( 'Uploading file "%s"', (filename, ), ) # Delete the existing issue if there is one for attachment in folder.issue.fields.attachment: if attachment.filename == filename: attachment.delete() upload.seek(0) attachment = folder.jira.add_attachment( folder.ticket_number, upload, filename=filename, ) file_meta[filename] = attachment.created folder.set_remote_file_metadata(file_meta, shadow=False) comment = folder.get_new_comment(clear=True, ready=True) if comment: folder.log(u'Adding comment "{comment}"'.format( comment=self.truncate_field_value(comment))) folder.jira.add_comment(folder.ticket_number, comment) collected_updates = {} for field, diff_values in status["ready"]["fields"].items(): collected_updates[field] = diff_values[1] if collected_updates: folder.log('Updating fields "%s"', (collected_updates, )) folder.issue.update(**collected_updates) links = status["ready"]["links"] statuses = self.get_valid_issue_link_types(folder) for target, data in links.get("issue", {}).items(): orig = data[0] new = data[1] other = folder.jira.issue(target) if orig is None: # New links status_data = statuses[new["status"]] args = [ status_data[1].name, ] if status_data[0] == "inward": args.extend([other, folder.issue]) elif status_data[0] == "outward": args.extend([folder.issue, other]) folder.jira.create_issue_link(*args) elif new is None: # Deleted links for existing_link in folder.issue.fields.issuelinks: if (hasattr(existing_link, "inwardIssue") and existing_link.inwardIssue.key == target): existing_link.delete() if (hasattr(existing_link, "outwardIssue") and existing_link.outwardIssue.key == target): existing_link.delete() else: # Changed links for existing_link in folder.issue.fields.issuelinks: if (hasattr(existing_link, "inwardIssue") and existing_link.inwardIssue.key == target): existing_link.type = statuses[new["status"]][1] existing_link.update() if (hasattr(existing_link, "outwardIssue") and existing_link.outwardIssue.key == target): existing_link.type = statuses[new["status"]][1] existing_link.update() links = status["ready"]["links"] remote_links = folder.jira.remote_links(folder.issue) # Workaround for bug in python-jira: folder.jira._applicationlinks = [] for target, data in links.get("remote", {}).items(): orig = data[0] new = data[1] if orig is None: # New links link_object = { "url": target, "title": new["description"], } folder.jira.add_remote_link(folder.issue, link_object) elif new is None: # Deleted links for existing_link in remote_links: if existing_link.object.url == target: existing_link.delete() else: # Changed links for existing_link in remote_links: if existing_link.object.url == target: existing_link.update({ "url": target, "title": new["description"] }) # Commit local copy folder.run_git_command("reset", "--soft", failure_ok=True) folder.run_git_command( "add", folder.get_path(".jirafs/remote_files.json"), failure_ok=True) folder.run_git_command("add", folder.get_path( constants.TICKET_NEW_COMMENT), failure_ok=True) folder.run_git_command("commit", "-m", "Pushed local changes", failure_ok=True) # Commit changes to remote copy, too, so we record remote # file metadata. folder.run_git_command("fetch", shadow=True) folder.run_git_command("merge", "origin/master", shadow=True) folder.run_git_command("add", "-A", shadow=True) folder.run_git_command("commit", "-m", "Pulled remote changes", failure_ok=True, shadow=True) folder.run_git_command("push", "origin", "jira", shadow=True) pull_result = run_command_method_with_kwargs("pull", folder=folder) return pull_result[1]
def run_command(self, name, **kwargs): return run_command_method_with_kwargs(name, **kwargs)
def main(self, folder, **kwargs): fetch_result = run_command_method_with_kwargs('fetch', folder=folder) merge_result = run_command_method_with_kwargs('merge', folder=folder) return fetch_result, merge_result
def push(self, folder): self.validate_issue(folder) with utils.stash_local_changes(folder): status = folder.status() if not folder.is_up_to_date(): raise exceptions.LocalCopyOutOfDate() file_meta = folder.get_remote_file_metadata(shadow=False) for filename in status['ready']['files']: upload = six.BytesIO( folder.get_local_file_at_revision( filename, 'HEAD', binary=True ) ) filename, upload = folder.execute_plugin_method_series( 'alter_file_upload', args=((filename, upload, ), ), single_response=True, ) folder.log( 'Uploading file "%s"', (filename, ), ) # Delete the existing issue if there is one for attachment in folder.issue.fields.attachment: if attachment.filename == filename: attachment.delete() upload.seek(0) attachment = folder.jira.add_attachment( folder.ticket_number, upload, filename=filename, ) file_meta[filename] = attachment.created folder.set_remote_file_metadata(file_meta, shadow=False) comment = folder.get_new_comment(clear=True, ready=True) if comment: folder.log( 'Adding comment "%s..."' % comment[0:30].replace('%', '%%') ) folder.jira.add_comment(folder.ticket_number, comment) collected_updates = {} for field, diff_values in status['ready']['fields'].items(): collected_updates[field] = diff_values[1] if collected_updates: folder.log( 'Updating fields "%s"', (collected_updates, ) ) folder.issue.update(**collected_updates) links = status['ready']['links'] statuses = self.get_valid_issue_link_types(folder) for target, data in links.get('issue', {}).items(): orig = data[0] new = data[1] other = folder.jira.issue(target) if orig is None: # New links status_data = statuses[new['status']] args = [ status_data[1].name, ] if status_data[0] == 'inward': args.extend([ other, folder.issue ]) elif status_data[0] == 'outward': args.extend([ folder.issue, other, ]) folder.jira.create_issue_link(*args) elif new is None: # Deleted links for existing_link in folder.issue.fields.issuelinks: if ( hasattr(existing_link, 'inwardIssue') and existing_link.inwardIssue.key == target ): existing_link.delete() if ( hasattr(existing_link, 'outwardIssue') and existing_link.outwardIssue.key == target ): existing_link.delete() else: # Changed links for existing_link in folder.issue.fields.issuelinks: if ( hasattr(existing_link, 'inwardIssue') and existing_link.inwardIssue.key == target ): existing_link.type = statuses[new['status']][1] existing_link.update() if ( hasattr(existing_link, 'outwardIssue') and existing_link.outwardIssue.key == target ): existing_link.type = statuses[new['status']][1] existing_link.update() links = status['ready']['links'] remote_links = folder.jira.remote_links(folder.issue) # Workaround for bug in python-jira: folder.jira._applicationlinks = [] for target, data in links.get('remote', {}).items(): orig = data[0] new = data[1] if orig is None: # New links link_object = { 'url': target, 'title': new['description'], } folder.jira.add_remote_link(folder.issue, link_object) elif new is None: # Deleted links for existing_link in remote_links: if existing_link.object.url == target: existing_link.delete() else: # Changed links for existing_link in remote_links: if existing_link.object.url == target: existing_link.update({ 'url': target, 'title': new['description'] }) # Commit local copy folder.run_git_command('reset', '--soft', failure_ok=True) folder.run_git_command( 'add', '.jirafs/remote_files.json', failure_ok=True ) folder.run_git_command( 'add', constants.TICKET_NEW_COMMENT, failure_ok=True ) folder.run_git_command( 'commit', '-m', 'Pushed local changes', failure_ok=True ) # Commit changes to remote copy, too, so we record remote # file metadata. folder.run_git_command('fetch', shadow=True) folder.run_git_command('merge', 'origin/master', shadow=True) folder.run_git_command('add', '-A', shadow=True) folder.run_git_command( 'commit', '-m', 'Pulled remote changes', failure_ok=True, shadow=True ) folder.run_git_command('push', 'origin', 'jira', shadow=True) pull_result = run_command_method_with_kwargs('pull', folder=folder) return pull_result[1]
def main(self, folder, **kwargs): self.validate_issue(folder) with utils.stash_local_changes(folder): status = folder.status() if not folder.is_up_to_date(): raise exceptions.LocalCopyOutOfDate() file_meta = folder.get_remote_file_metadata(shadow=False) for filename in status['ready']['files']: upload = six.BytesIO( folder.get_local_file_at_revision( filename, 'HEAD', binary=True ) ) filename, upload = folder.execute_plugin_method_series( 'alter_file_upload', args=((filename, upload, ), ), single_response=True, ) folder.log( 'Uploading file "%s"', (filename, ), ) # Delete the existing issue if there is one for attachment in folder.issue.fields.attachment: if attachment.filename == filename: attachment.delete() upload.seek(0) attachment = folder.jira.add_attachment( folder.ticket_number, upload, filename=filename, ) file_meta[filename] = attachment.created folder.set_remote_file_metadata(file_meta, shadow=False) comment = folder.get_new_comment(clear=True, ready=True) if comment: folder.log( u'Adding comment "{comment}"'.format( comment=self.truncate_field_value(comment) ) ) folder.jira.add_comment(folder.ticket_number, comment) collected_updates = {} for field, diff_values in status['ready']['fields'].items(): collected_updates[field] = diff_values[1] if collected_updates: folder.log( 'Updating fields "%s"', (collected_updates, ) ) folder.issue.update(**collected_updates) links = status['ready']['links'] statuses = self.get_valid_issue_link_types(folder) for target, data in links.get('issue', {}).items(): orig = data[0] new = data[1] other = folder.jira.issue(target) if orig is None: # New links status_data = statuses[new['status']] args = [ status_data[1].name, ] if status_data[0] == 'inward': args.extend([ other, folder.issue ]) elif status_data[0] == 'outward': args.extend([ folder.issue, other, ]) folder.jira.create_issue_link(*args) elif new is None: # Deleted links for existing_link in folder.issue.fields.issuelinks: if ( hasattr(existing_link, 'inwardIssue') and existing_link.inwardIssue.key == target ): existing_link.delete() if ( hasattr(existing_link, 'outwardIssue') and existing_link.outwardIssue.key == target ): existing_link.delete() else: # Changed links for existing_link in folder.issue.fields.issuelinks: if ( hasattr(existing_link, 'inwardIssue') and existing_link.inwardIssue.key == target ): existing_link.type = statuses[new['status']][1] existing_link.update() if ( hasattr(existing_link, 'outwardIssue') and existing_link.outwardIssue.key == target ): existing_link.type = statuses[new['status']][1] existing_link.update() links = status['ready']['links'] remote_links = folder.jira.remote_links(folder.issue) # Workaround for bug in python-jira: folder.jira._applicationlinks = [] for target, data in links.get('remote', {}).items(): orig = data[0] new = data[1] if orig is None: # New links link_object = { 'url': target, 'title': new['description'], } folder.jira.add_remote_link(folder.issue, link_object) elif new is None: # Deleted links for existing_link in remote_links: if existing_link.object.url == target: existing_link.delete() else: # Changed links for existing_link in remote_links: if existing_link.object.url == target: existing_link.update({ 'url': target, 'title': new['description'] }) # Commit local copy folder.run_git_command('reset', '--soft', failure_ok=True) folder.run_git_command( 'add', folder.get_path('.jirafs/remote_files.json'), failure_ok=True ) folder.run_git_command( 'add', folder.get_path(constants.TICKET_NEW_COMMENT), failure_ok=True ) folder.run_git_command( 'commit', '-m', 'Pushed local changes', failure_ok=True ) # Apply macros and record the changes so we can reverse # them a little later. macro_patch_filename = folder.get_path( '.jirafs/macros_applied.patch' ) folder.run_git_command( 'apply', macro_patch_filename, failure_ok=True ) fields = folder.get_fields() for field, value in collected_updates.items(): fields[field] = value fields.write() field_data_files = fields.get_field_data_files() result = folder.run_git_command('diff', *field_data_files) if result.strip(): with io.open(macro_patch_filename, 'w', encoding='utf-8') as o: o.write(result) o.write(u'\n\n') folder.run_git_command( 'add', macro_patch_filename, failure_ok=True ) folder.run_git_command( 'commit', '-m', 'Updating macro patch', failure_ok=True ) # Re-set the applied changes we just made above folder.run_git_command( 'checkout', '--', '.' ) else: with io.open(macro_patch_filename, 'w', encoding='utf-8') as o: o.write(u'\n\n') # Commit changes to remote copy, too, so we record remote # file metadata. folder.run_git_command('fetch', shadow=True) folder.run_git_command('merge', 'origin/master', shadow=True) folder.run_git_command('add', '-A', shadow=True) folder.run_git_command( 'commit', '-m', 'Pulled remote changes', failure_ok=True, shadow=True ) folder.run_git_command('push', 'origin', 'jira', shadow=True) pull_result = run_command_method_with_kwargs('pull', folder=folder) return pull_result[1]
def push(self, folder): with utils.stash_local_changes(folder): status = folder.status() if not folder.is_up_to_date(): raise exceptions.LocalCopyOutOfDate() file_meta = folder.get_remote_file_metadata(shadow=False) for filename in status['ready']['files']: upload = six.BytesIO( folder.get_local_file_at_revision( filename, 'HEAD', binary=True ) ) filename, upload = folder.execute_plugin_method_series( 'alter_file_upload', args=((filename, upload, ), ), single_response=True, ) folder.log( 'Uploading file "%s"', (filename, ), ) # Delete the existing issue if there is one for attachment in folder.issue.fields.attachment: if attachment.filename == filename: attachment.delete() upload.seek(0) attachment = folder.jira.add_attachment( folder.ticket_number, upload, filename=filename, ) file_meta[filename] = attachment.created folder.set_remote_file_metadata(file_meta, shadow=False) comment = folder.get_new_comment(clear=True, ready=True) if comment: folder.log( 'Adding comment "%s..."' % comment[0:30].replace('%', '%%') ) folder.jira.add_comment(folder.ticket_number, comment) collected_updates = {} for field, diff_values in status['ready']['fields'].items(): collected_updates[field] = diff_values[1] if collected_updates: folder.log( 'Updating fields "%s"', (collected_updates, ) ) folder.issue.update(**collected_updates) # Commit local copy folder.run_git_command('reset', '--soft', failure_ok=True) folder.run_git_command( 'add', '.jirafs/remote_files.json', failure_ok=True ) folder.run_git_command( 'add', constants.TICKET_NEW_COMMENT, failure_ok=True ) folder.run_git_command( 'commit', '-m', 'Pushed local changes', failure_ok=True ) # Commit changes to remote copy, too, so we record remote # file metadata. folder.run_git_command('fetch', shadow=True) folder.run_git_command('merge', 'origin/master', shadow=True) folder.run_git_command('add', '-A', shadow=True) folder.run_git_command( 'commit', '-m', 'Pulled remote changes', failure_ok=True, shadow=True ) folder.run_git_command('push', 'origin', 'jira', shadow=True) pull_result = run_command_method_with_kwargs('pull', folder=folder) return pull_result[1]
def main(self, folder, **kwargs): self.validate_issue(folder) with utils.stash_local_changes(folder): status = folder.status() if not folder.is_up_to_date(): raise exceptions.LocalCopyOutOfDate( "Your local copy is out-of-date. You must use " "the 'merge' command to update your local copy " "before pushing changes." ) file_meta = folder.get_remote_file_metadata(shadow=False) for filename in status['ready']['files']: upload = six.BytesIO( folder.get_local_file_at_revision( filename, 'HEAD', binary=True ) ) filename, upload = folder.execute_plugin_method_series( 'alter_file_upload', args=((filename, upload, ), ), single_response=True, ) folder.log( 'Uploading file "%s"', (filename, ), ) # Delete the existing issue if there is one for attachment in folder.issue.fields.attachment: if attachment.filename == filename: attachment.delete() upload.seek(0) attachment = folder.jira.add_attachment( folder.ticket_number, upload, filename=filename, ) file_meta[filename] = attachment.created folder.set_remote_file_metadata(file_meta, shadow=False) comment = folder.get_new_comment(clear=True, ready=True) if comment: folder.log( u'Adding comment "{comment}"'.format( comment=self.truncate_field_value(comment) ) ) folder.jira.add_comment(folder.ticket_number, comment) collected_updates = {} for field, diff_values in status['ready']['fields'].items(): collected_updates[field] = diff_values[1] if collected_updates: folder.log( 'Updating fields "%s"', (collected_updates, ) ) folder.issue.update(**collected_updates) links = status['ready']['links'] statuses = self.get_valid_issue_link_types(folder) for target, data in links.get('issue', {}).items(): orig = data[0] new = data[1] other = folder.jira.issue(target) if orig is None: # New links status_data = statuses[new['status']] args = [ status_data[1].name, ] if status_data[0] == 'inward': args.extend([ other, folder.issue ]) elif status_data[0] == 'outward': args.extend([ folder.issue, other, ]) folder.jira.create_issue_link(*args) elif new is None: # Deleted links for existing_link in folder.issue.fields.issuelinks: if ( hasattr(existing_link, 'inwardIssue') and existing_link.inwardIssue.key == target ): existing_link.delete() if ( hasattr(existing_link, 'outwardIssue') and existing_link.outwardIssue.key == target ): existing_link.delete() else: # Changed links for existing_link in folder.issue.fields.issuelinks: if ( hasattr(existing_link, 'inwardIssue') and existing_link.inwardIssue.key == target ): existing_link.type = statuses[new['status']][1] existing_link.update() if ( hasattr(existing_link, 'outwardIssue') and existing_link.outwardIssue.key == target ): existing_link.type = statuses[new['status']][1] existing_link.update() links = status['ready']['links'] remote_links = folder.jira.remote_links(folder.issue) # Workaround for bug in python-jira: folder.jira._applicationlinks = [] for target, data in links.get('remote', {}).items(): orig = data[0] new = data[1] if orig is None: # New links link_object = { 'url': target, 'title': new['description'], } folder.jira.add_remote_link(folder.issue, link_object) elif new is None: # Deleted links for existing_link in remote_links: if existing_link.object.url == target: existing_link.delete() else: # Changed links for existing_link in remote_links: if existing_link.object.url == target: existing_link.update({ 'url': target, 'title': new['description'] }) # Commit local copy folder.run_git_command('reset', '--soft', failure_ok=True) folder.run_git_command( 'add', folder.get_path('.jirafs/remote_files.json'), failure_ok=True ) folder.run_git_command( 'add', folder.get_path(constants.TICKET_NEW_COMMENT), failure_ok=True ) folder.run_git_command( 'commit', '-m', 'Pushed local changes', failure_ok=True ) # Apply macros and record the changes so we can reverse # them a little later. macro_patch_filename = folder.get_path( '.jirafs/macros_applied.patch' ) folder.run_git_command( 'apply', macro_patch_filename, failure_ok=True ) fields = folder.get_fields() for field, value in collected_updates.items(): fields[field] = value fields.write() field_data_files = fields.get_field_data_files() result = folder.run_git_command('diff', *field_data_files) if result.strip(): with io.open(macro_patch_filename, 'w', encoding='utf-8') as o: o.write(result) o.write(u'\n\n') folder.run_git_command( 'add', macro_patch_filename, failure_ok=True ) folder.run_git_command( 'commit', '-m', 'Updating macro patch', failure_ok=True ) # Re-set the applied changes we just made above folder.run_git_command( 'checkout', '--', '.' ) else: with io.open(macro_patch_filename, 'w', encoding='utf-8') as o: o.write(u'\n\n') # Commit changes to remote copy, too, so we record remote # file metadata. folder.run_git_command('fetch', shadow=True) folder.run_git_command('merge', 'origin/master', shadow=True) folder.run_git_command('add', '-A', shadow=True) folder.run_git_command( 'commit', '-m', 'Pulled remote changes', failure_ok=True, shadow=True ) folder.run_git_command('push', 'origin', 'jira', shadow=True) pull_result = run_command_method_with_kwargs('pull', folder=folder) return pull_result[1]