Exemplo n.º 1
0
    def main(self, folder, **kwargs):
        with utils.stash_local_changes(folder):
            original_merge_base = folder.git_merge_base

            folder.run_git_command("merge", "jira", failure_ok=True)

            final_merge_base = folder.git_merge_base

            new_comments = folder.run_git_command(
                "diff",
                "%s..%s" % (original_merge_base, final_merge_base),
                "--",
                constants.TICKET_COMMENTS,
            ).strip()
            if new_comments:
                folder.log("New comment(s) have been posted.")

            jira_fields = JiraFieldManager.create(folder, revision="jira")
            master_fields = JiraFieldManager.create(
                folder, revision=original_merge_base
            )
            for field, values in (jira_fields - master_fields).items():
                folder.log(
                    u'Field {field} changed: "{fr}" -> "{to}"'.format(
                        field=field,
                        fr=self.truncate_field_value(values[0]),
                        to=self.truncate_field_value(values[1]),
                    )
                )

            jira_links = JiraLinkManager.create(folder, revision="jira")
            master_links = JiraLinkManager.create(folder, revision=original_merge_base)
            for category in ("issue", "remote"):
                values_dict = (jira_links - master_links).get(category, {})
                for field, values in values_dict.items():
                    folder.log(
                        u'Link {field} changed: "{fr}" -> "{to}"'.format(
                            field=field, fr=values[0], to=values[1]
                        )
                    )

            if original_merge_base != final_merge_base:
                folder.log(
                    "Merged 'jira' into 'master'; merge-base is now %s"
                    % (final_merge_base)
                )

            conflicted_files = folder.run_git_command(
                "diff", "--name-only", "--diff-filter=U",
            ).strip()
            if conflicted_files:
                folder.log(
                    "Conflicts between your local changes and Jira were found!",
                    level=logging.WARN,
                )

            return utils.PostStatusResponse(
                original_merge_base == final_merge_base, final_merge_base
            )
Exemplo n.º 2
0
    def test_stash_local_changes(self):
        repo = mock.Mock()
        repo.version = 10

        with utils.stash_local_changes(repo):
            pass

        self.assertEqual(
            repo.run_git_command.call_count,
            4,
        )
Exemplo n.º 3
0
    def test_stash_local_changes_exception(self):
        repo = mock.Mock()
        repo.version = 10

        with self.assertRaises(Exception):
            with utils.stash_local_changes(repo):
                raise Exception()

        self.assertEqual(
            repo.run_git_command.call_count,
            4,
        )
Exemplo n.º 4
0
    def merge(self, folder):
        with utils.stash_local_changes(folder):
            original_merge_base = folder.git_merge_base
            folder.run_git_command('merge', 'jira')
            final_merge_base = folder.git_merge_base

            if original_merge_base != final_merge_base:
                folder.log(
                    "Merged 'jira' into 'master'; merge-base is now %s" % (
                        final_merge_base
                    )
                )
            return utils.PostStatusResponse(
                original_merge_base == final_merge_base,
                final_merge_base
            )
Exemplo n.º 5
0
    def test_stash_local_changes(self):
        repo = mock.Mock()
        repo.version = 10

        with utils.stash_local_changes(repo):
            pass

        self.assertEqual(
            repo.run_git_command.call_count,
            3,
        )
        repo.run_git_command.assert_has_calls([
            mock.call('stash', '--include-untracked', failure_ok=True),
            mock.call('stash', 'apply', failure_ok=True),
            mock.call('stash', 'drop', failure_ok=True),
        ])
Exemplo n.º 6
0
    def merge(self, folder):
        with utils.stash_local_changes(folder):
            original_merge_base = folder.git_merge_base
            folder.run_git_command('merge', 'jira')
            final_merge_base = folder.git_merge_base

            new_comments = folder.run_git_command(
                'diff',
                '%s..%s' % (original_merge_base, final_merge_base),
                '--',
                constants.TICKET_COMMENTS,
            ).strip()
            if new_comments:
                folder.log("New comment(s) have been posted.")

            jira_fields = JiraFieldManager.create(folder, revision='jira')
            master_fields = JiraFieldManager.create(
                folder, revision=original_merge_base)
            for field, values in (jira_fields - master_fields).items():
                folder.log(
                    "Field {field} changed: \"{fr}\" -> \"{to}\"".format(
                        field=field, fr=values[0], to=values[1]))

            jira_links = JiraLinkManager.create(folder, revision='jira')
            master_links = JiraLinkManager.create(folder,
                                                  revision=original_merge_base)
            for category in ('issue', 'remote'):
                values_dict = (jira_links - master_links).get(category, {})
                for field, values in values_dict.items():
                    folder.log(
                        "Link {field} changed: \"{fr}\" -> \"{to}\"".format(
                            field=field, fr=values[0], to=values[1]))

            if original_merge_base != final_merge_base:
                folder.log(
                    "Merged 'jira' into 'master'; merge-base is now %s" %
                    (final_merge_base))
            return utils.PostStatusResponse(
                original_merge_base == final_merge_base, final_merge_base)
Exemplo n.º 7
0
    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]
Exemplo n.º 8
0
    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]
Exemplo n.º 9
0
    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]
Exemplo n.º 10
0
    def main(self, folder, **kwargs):
        with utils.stash_local_changes(folder):
            original_merge_base = folder.git_merge_base
            folder.run_git_command('merge', 'jira')
            final_merge_base = folder.git_merge_base

            new_comments = folder.run_git_command(
                'diff',
                '%s..%s' % (
                    original_merge_base,
                    final_merge_base
                ),
                '--',
                constants.TICKET_COMMENTS,
            ).strip()
            if new_comments:
                folder.log(
                    "New comment(s) have been posted."
                )

            jira_fields = JiraFieldManager.create(
                folder, revision='jira'
            )
            master_fields = JiraFieldManager.create(
                folder, revision=original_merge_base
            )
            for field, values in (jira_fields - master_fields).items():
                folder.log(
                    u"Field {field} changed: \"{fr}\" -> \"{to}\"".format(
                        field=field,
                        fr=self.truncate_field_value(values[0]),
                        to=self.truncate_field_value(values[1])
                    )
                )

            jira_links = JiraLinkManager.create(
                folder, revision='jira'
            )
            master_links = JiraLinkManager.create(
                folder, revision=original_merge_base
            )
            for category in ('issue', 'remote'):
                values_dict = (jira_links - master_links).get(category, {})
                for field, values in values_dict.items():
                    folder.log(
                        u"Link {field} changed: \"{fr}\" -> \"{to}\"".format(
                            field=field,
                            fr=values[0],
                            to=values[1]
                        )
                    )

            if original_merge_base != final_merge_base:
                folder.log(
                    "Merged 'jira' into 'master'; merge-base is now %s" % (
                        final_merge_base
                    )
                )
            return utils.PostStatusResponse(
                original_merge_base == final_merge_base,
                final_merge_base
            )
Exemplo n.º 11
0
    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]
Exemplo n.º 12
0
    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]