Exemple #1
0
 def edit_fun(cd):
     cd, failed_diff = edit.auto_edit_patch(
         stack.repository, cd, msg = options.message, contains_diff = False,
         author = options.author, committer = lambda p: p,
         sign_str = options.sign_str)
     assert not failed_diff
     if options.edit:
         cd, failed_diff = edit.interactive_edit_patch(
             stack.repository, cd, edit_diff = False,
             diff_flags = [], replacement_diff = None)
         assert not failed_diff
     return cd
Exemple #2
0
 def edit_fun(cd):
     orig_msg = cd.message
     cd, failed_diff = edit.auto_edit_patch(
         stack.repository, cd, msg = options.message, contains_diff = False,
         author = options.author, committer = lambda p: p,
         sign_str = options.sign_str)
     assert not failed_diff
     if options.edit:
         cd, failed_diff = edit.interactive_edit_patch(
             stack.repository, cd, edit_diff = False,
             diff_flags = [], replacement_diff = None)
         assert not failed_diff
     if not options.no_verify and (options.edit or cd.message != orig_msg):
         cd = common.run_commit_msg_hook(stack.repository, cd, options.edit)
     return cd
Exemple #3
0
 def edit_fun(cd):
     orig_msg = cd.message
     cd = auto_edit_patch(
         stack.repository,
         cd,
         msg=(None if options.message is None else options.message.encode(
             config.get('i18n.commitencoding'))),
         author=options.author,
         sign_str=options.sign_str,
     )
     if options.edit:
         cd, failed_diff = interactive_edit_patch(stack.repository,
                                                  cd,
                                                  edit_diff=False,
                                                  diff_flags=[])
         assert not failed_diff
     if not options.no_verify and (options.edit or cd.message != orig_msg):
         cd = run_commit_msg_hook(stack.repository, cd, options.edit)
     # Refresh the committer information
     return cd.set_committer(None)
Exemple #4
0
 def edit_fun(cd):
     orig_msg = cd.message
     new_msg = None
     if message is not None:
         new_msg = message.encode(config.get('i18n.commitencoding'))
     cd = auto_edit_patch(
         stack.repository,
         cd,
         msg=new_msg,
         author=author,
         sign_str=sign_str,
     )
     if invoke_editor:
         cd, failed_diff = interactive_edit_patch(stack.repository, cd,
                                                  edit_diff, diff_flags)
         assert not failed_diff
     if not no_verify and (invoke_editor or cd.message != orig_msg):
         cd = run_commit_msg_hook(stack.repository, cd, invoke_editor)
     # Refresh the committer information
     return cd.set_committer(None)
Exemple #5
0
def func(parser, options, args):
    """Edit the given patch or the current one.
    """
    stack = directory.repository.current_stack

    if len(args) == 0:
        if not stack.patchorder.applied:
            raise CmdException(
                'Cannot edit top patch, because no patches are applied')
        patchname = stack.patchorder.applied[-1]
    elif len(args) == 1:
        [patchname] = args
        if not stack.patches.exists(patchname):
            raise CmdException('%s: no such patch' % patchname)
    else:
        parser.error('Cannot edit more than one patch')

    cd = orig_cd = stack.patches.get(patchname).commit.data

    if options.set_tree:
        cd = cd.set_tree(
            stack.repository.rev_parse(options.set_tree,
                                       discard_stderr=True,
                                       object_type='tree'))

    cd = edit.auto_edit_patch(
        stack.repository,
        cd,
        msg=(None if options.message is None else options.message.encode(
            config.get('i18n.commitencoding'))),
        author=options.author,
        sign_str=options.sign_str,
    )

    if options.save_template:
        options.save_template(
            edit.patch_desc(
                stack.repository,
                cd,
                options.diff,
                options.diff_flags,
                replacement_diff=None,
            ))
        return utils.STGIT_SUCCESS

    use_editor = cd == orig_cd or options.edit or options.diff
    if use_editor:
        cd, failed_diff = edit.interactive_edit_patch(stack.repository, cd,
                                                      options.diff,
                                                      options.diff_flags)
    else:
        failed_diff = None

    def failed(reason='Edited patch did not apply.'):
        fn = '.stgit-failed.patch'
        with io.open(fn, 'wb') as f:
            f.write(
                edit.patch_desc(
                    stack.repository,
                    cd,
                    options.diff,
                    options.diff_flags,
                    replacement_diff=failed_diff,
                ))
        out.error(reason, 'The patch has been saved to "%s".' % fn)
        return utils.STGIT_COMMAND_ERROR

    # If we couldn't apply the patch, fail without even trying to
    # effect any of the changes.
    if failed_diff:
        return failed()

    if not options.no_verify and (use_editor or cd.message != orig_cd.message):
        try:
            cd = run_commit_msg_hook(stack.repository, cd, use_editor)
        except Exception:
            if options.diff:
                failed('The commit-msg hook failed.')
            raise

    # Refresh the committer information
    cd = cd.set_committer(None)

    # The patch applied, so now we have to rewrite the StGit patch
    # (and any patches on top of it).
    iw = stack.repository.default_iw
    trans = transaction.StackTransaction(stack, 'edit', allow_conflicts=True)
    if patchname in trans.applied:
        popped = trans.applied[trans.applied.index(patchname) + 1:]
        popped_extra = trans.pop_patches(lambda pn: pn in popped)
        assert not popped_extra
    else:
        popped = []
    trans.patches[patchname] = stack.repository.commit(cd)
    try:
        for pn in popped:
            if options.set_tree:
                trans.push_tree(pn)
            else:
                trans.push_patch(pn, iw, allow_interactive=True)
    except transaction.TransactionHalted:
        pass
    try:
        # Either a complete success, or a conflict during push. But in
        # either case, we've successfully effected the edits the user
        # asked us for.
        return trans.run(iw)
    except transaction.TransactionException:
        # Transaction aborted -- we couldn't check out files due to
        # dirty index/worktree. The edits were not carried out.
        return failed()
def func(parser, options, args):
    """Edit the given patch or the current one."""
    stack = directory.repository.current_stack

    if len(args) == 0:
        if not stack.patchorder.applied:
            raise CmdException(
                'Cannot edit top patch because no patches are applied')
        patchname = stack.patchorder.applied[-1]
    elif len(args) == 1:
        [patchname] = args
        if patchname not in stack.patches:
            raise CmdException('%s: no such patch' % patchname)
    else:
        parser.error('Cannot edit more than one patch')

    cd = orig_cd = stack.patches[patchname].data

    if options.set_tree:
        cd = cd.set_tree(
            stack.repository.rev_parse(options.set_tree,
                                       discard_stderr=True,
                                       object_type='tree'))

    cd = edit.auto_edit_patch(
        stack.repository,
        cd,
        msg=(None if options.message is None else options.message.encode(
            config.get('i18n.commitencoding'))),
        author=options.author,
        trailers=options.trailers,
    )

    if options.save_template:
        options.save_template(
            edit.get_patch_description(stack.repository, cd, patchname,
                                       options.diff, options.diff_flags))
        return utils.STGIT_SUCCESS

    use_editor = cd == orig_cd or options.edit or options.diff
    if use_editor:
        cd, new_patchname, failed_diff = edit.interactive_edit_patch(
            stack.repository, cd, patchname, options.diff, options.diff_flags)
        # If we couldn't apply the patch, fail without even trying to
        # affect any of the changes.
        if failed_diff is not None:
            return utils.STGIT_COMMAND_ERROR
    else:
        new_patchname = None

    if not options.no_verify and (use_editor or cd.message != orig_cd.message):
        try:
            cd = run_commit_msg_hook(stack.repository, cd, use_editor)
        except Exception:
            if options.diff:
                patch_desc = edit.get_patch_description(
                    stack.repository, cd, patchname, options.diff,
                    options.diff_flags)
                edit.note_patch_application_failure(
                    patch_desc, 'The commit-msg hook failed.')
            raise

    retval, _ = edit.perform_edit(
        stack,
        cd,
        patchname,
        new_patchname,
        options.diff,
        options.diff_flags,
        options.set_tree,
    )
    return retval
Exemple #7
0
def func(parser, options, args):
    """Edit the given patch or the current one.
    """
    stack = directory.repository.current_stack

    if len(args) == 0:
        if not stack.patchorder.applied:
            raise common.CmdException(
                'Cannot edit top patch, because no patches are applied')
        patchname = stack.patchorder.applied[-1]
    elif len(args) == 1:
        [patchname] = args
        if not stack.patches.exists(patchname):
            raise common.CmdException('%s: no such patch' % patchname)
    else:
        parser.error('Cannot edit more than one patch')

    cd = orig_cd = stack.patches.get(patchname).commit.data

    if options.set_tree:
        cd = cd.set_tree(stack.repository.rev_parse(
                options.set_tree, discard_stderr = True, object_type = 'tree'))

    cd, failed_diff = edit.auto_edit_patch(
        stack.repository, cd, msg = options.message, contains_diff = True,
        author = options.author, committer = lambda p: p,
        sign_str = options.sign_str)

    if options.save_template:
        options.save_template(
            edit.patch_desc(stack.repository, cd,
                            options.diff, options.diff_flags, failed_diff))
        return utils.STGIT_SUCCESS

    use_editor = cd == orig_cd or options.edit
    if use_editor:
        cd, failed_diff = edit.interactive_edit_patch(
            stack.repository, cd, options.diff, options.diff_flags, failed_diff)

    def failed(reason='Edited patch did not apply.'):
        fn = '.stgit-failed.patch'
        with open(fn, 'w') as f:
            f.write(edit.patch_desc(stack.repository, cd,
                                    options.diff, options.diff_flags,
                                    failed_diff))
        out.error(reason,
                  'The patch has been saved to "%s".' % fn)
        return utils.STGIT_COMMAND_ERROR

    # If we couldn't apply the patch, fail without even trying to
    # effect any of the changes.
    if failed_diff:
        return failed()

    if not options.no_verify and (use_editor or cd.message != orig_cd.message):
        try:
            cd = common.run_commit_msg_hook(stack.repository, cd, use_editor)
        except Exception:
            if options.diff:
                failed('The commit-msg hook failed.')
            raise

    # The patch applied, so now we have to rewrite the StGit patch
    # (and any patches on top of it).
    iw = stack.repository.default_iw
    trans = transaction.StackTransaction(stack, 'edit', allow_conflicts = True)
    if patchname in trans.applied:
        popped = trans.applied[trans.applied.index(patchname)+1:]
        assert not trans.pop_patches(lambda pn: pn in popped)
    else:
        popped = []
    trans.patches[patchname] = stack.repository.commit(cd)
    try:
        for pn in popped:
            if options.set_tree:
                trans.push_tree(pn)
            else:
                trans.push_patch(pn, iw, allow_interactive = True)
    except transaction.TransactionHalted:
        pass
    try:
        # Either a complete success, or a conflict during push. But in
        # either case, we've successfully effected the edits the user
        # asked us for.
        return trans.run(iw)
    except transaction.TransactionException:
        # Transaction aborted -- we couldn't check out files due to
        # dirty index/worktree. The edits were not carried out.
        return failed()
def __do_rebase_interactive(repository, previously_applied_patches,
                            check_merged):
    """Opens an interactive editor, generates instruction list, and executes instructions."""
    stack = repository.get_stack()

    if len(stack.patchorder.all) == 0:
        return utils.STGIT_SUCCESS

    name_len = max((len(s) for s in stack.patchorder.all))
    line = 'keep {{:<{name_len}}} # {{}}'.format(name_len=name_len)

    # create a list of all patches to send to the editor
    raw_editor_instructions = []
    for pn in previously_applied_patches:
        patch = (pn, __get_description(stack, pn))
        raw_editor_instructions.append(line.format(*patch))
    raw_editor_instructions.append(INTERACTIVE_APPLY_LINE)
    for pn in stack.patchorder.all:
        if pn in previously_applied_patches:
            continue
        patch = (pn, __get_description(stack, pn))
        raw_editor_instructions.append(line.format(*patch))
    raw_editor_instructions.append(INTERACTIVE_HELP_INSTRUCTIONS)

    # open an editor to let the user generate the 'todo' instructions
    todo = edit_string(
        '\n'.join(raw_editor_instructions),
        '.stgit-rebase-interactive.txt',
    )

    # parse the instructions we've been given
    seen_apply_line = False
    instructions = []
    for line in todo.splitlines():
        line = line.strip()

        # record when we find the APPLY_LINE so we know which patches to apply
        if INTERACTIVE_APPLY_LINE in line:
            if INTERACTIVE_APPLY_LINE == line:
                seen_apply_line = True
            else:
                raise CmdException("Bad APPLY_LINE: '%s'" % line)

        # ignore comment lines
        if not line or line.startswith('#'):
            continue

        # parse a single instruction
        match = re.match(r'(\S+) (\S+).*', line)
        if not match:
            raise CmdException("Bad todo line: '%s'" % line)
        instruction_str, patch_name = match.groups()
        if patch_name not in stack.patchorder.all:
            raise CmdException("Bad patch name '%s'" % patch_name)
        if instruction_str in ('k', 'keep'):
            instruction_type = Action.KEEP
        elif instruction_str in ('e', 'edit'):
            instruction_type = Action.EDIT
        elif instruction_str in ('s', 'squash'):
            instruction_type = Action.SQUASH
        elif instruction_str in ('f', 'fix', 'fixup'):
            instruction_type = Action.FIXUP
        elif instruction_str in ('h', 'hide'):
            instruction_type = Action.HIDE
        elif instruction_str in ('d', 'delete'):
            instruction_type = Action.DELETE
        else:
            raise CmdException("Unknown instruction '%s'" % instruction_str)

        # save the instruction to execute later
        instructions.append(
            Instruction(patch_name, instruction_type, not seen_apply_line))

    index = 0
    while index < len(instructions):
        patch_name = instructions[index].patch_name
        if instructions[index].action == Action.HIDE:
            hide_patches(stack, stack.repository.default_iw, {patch_name})
            instructions.pop(index)
            index = max(0, index - 1)  # re-run this index another time
            continue
        if instructions[index].action == Action.DELETE:
            delete_patches(stack, stack.repository.default_iw, {patch_name})
            instructions.pop(index)
            index = max(0, index - 1)  # re-run this index another time
            continue
        if instructions[index].action == Action.FIXUP and index > 0:
            base_patch = instructions[index - 1].patch_name
            __fixup_patches(stack, [base_patch, patch_name])
            instructions.pop(index)  # remove 'fixed' (ie deleted) patch
            index -= 1  # re-run this index another time
            continue
        if instructions[index].action == Action.EDIT:
            cd = stack.patches[patch_name].data
            cd, new_patch_name, failed_diff = edit.interactive_edit_patch(
                stack.repository,
                cd,
                patch_name,
                edit_diff=True,
                diff_flags="")
            if failed_diff is not None:
                return utils.STGIT_COMMAND_ERROR
            _, new_patch_name = edit.perform_edit(
                stack,
                cd,
                patch_name,
                new_patch_name,
                edit_diff=True,
                diff_flags="",
            )
            if new_patch_name and patch_name != new_patch_name:
                instructions[index] = Instruction(
                    new_patch_name,
                    instructions[index].action,
                    instructions[index].apply,
                )
                patch_name = new_patch_name

        instructions = __perform_squashes(instructions, index, stack)
        index += 1

    post_rebase(
        stack,
        [
            instruction.patch_name
            for instruction in instructions if instruction.apply
        ],
        'rebase',
        check_merged,
    )

    return utils.STGIT_SUCCESS