예제 #1
0
def update_commit_data(cd, options):
    """Return a new CommitData object updated according to the command line
    options."""
    # Set the commit message from commandline.
    if options.message is not None:
        cd = cd.set_message(options.message)

    # Modify author data.
    cd = cd.set_author(options.author(cd.author))

    # Add Signed-off-by: or similar.
    if options.sign_str is not None:
        sign_str = options.sign_str
    else:
        sign_str = config.get("stgit.autosign")
    if sign_str is not None:
        cd = cd.set_message(
            add_sign_line(cd.message, sign_str, cd.committer.name,
                          cd.committer.email))

    # Let user edit the commit message manually, unless
    # --save-template or --message was specified.
    if not getattr(options, 'save_template', None) and options.message is None:
        tmpl = templates.get_template('patchdescr.tmpl')
        if tmpl:
            cd = cd.set_message(cd.message + tmpl)
        cd = cd.set_message(edit_string(cd.message, '.stgit-new.txt'))

    return cd
예제 #2
0
def _squash_patches(trans, patches, msg, save_template, no_verify=False):
    cd = trans.patches[patches[0]].data
    for pn in patches[1:]:
        c = trans.patches[pn]
        tree = trans.stack.repository.simple_merge(
            base=c.data.parent.data.tree,
            ours=cd.tree,
            theirs=c.data.tree,
        )
        if not tree:
            return None
        cd = cd.set_tree(tree)
    if msg is None:
        msg = _append_comment(
            cd.message_str,
            '\n\n'.join('%s\n\n%s' %
                        (pn.ljust(70, '-'), trans.patches[pn].data.message_str)
                        for pn in patches[1:]))
        if save_template:
            save_template(msg.encode(cd.encoding))
            raise SaveTemplateDone()
        else:
            msg = utils.edit_string(msg, '.stgit-squash.txt')
    msg = _strip_comment(msg).strip()
    cd = cd.set_message(msg)

    if not no_verify:
        cd = run_commit_msg_hook(trans.stack.repository, cd)

    return cd
예제 #3
0
파일: squash.py 프로젝트: miracle2k/stgit
def _squash_patches(trans, patches, msg, save_template):
    cd = trans.patches[patches[0]].data
    cd = git.CommitData(tree = cd.tree, parents = cd.parents)
    for pn in patches[1:]:
        c = trans.patches[pn]
        tree = trans.stack.repository.simple_merge(
            base = c.data.parent.data.tree,
            ours = cd.tree, theirs = c.data.tree)
        if not tree:
            return None
        cd = cd.set_tree(tree)
    if msg == None:
        msg = utils.append_comment(
            trans.patches[patches[0]].data.message,
            '\n\n'.join('%s\n\n%s' % (pn.ljust(70, '-'),
                                      trans.patches[pn].data.message)
                        for pn in patches[1:]))
        if save_template:
            save_template(msg)
            raise SaveTemplateDone()
        else:
            msg = utils.edit_string(msg, '.stgit-squash.txt')
    msg = utils.strip_comment(msg).strip()
    cd = cd.set_message(msg)

    return cd
예제 #4
0
파일: common.py 프로젝트: hasturkun/stgit
def update_commit_data(
    cd, message=None, author=None, sign_str=None, edit=False
):
    """Return a new CommitData object updated according to the command line
    options."""
    # Set the commit message from commandline.
    if message is not None:
        cd = cd.set_message(message)

    # Modify author data.
    if author is not None:
        cd = cd.set_author(author)

    # Add Signed-off-by: or similar.
    if sign_str is None:
        sign_str = config.get("stgit.autosign")
    if sign_str:
        cd = cd.set_message(
            add_sign_line(
                cd.message, sign_str, cd.committer.name, cd.committer.email
            )
        )

    if edit:
        tmpl = templates.get_template('patchdescr.tmpl')
        if tmpl:
            cd = cd.set_message(cd.message + tmpl)
        cd = cd.set_message(edit_string(cd.message, '.stgit-new.txt'))

    return cd
예제 #5
0
파일: common.py 프로젝트: snits/stgit
def update_commit_data(cd, options):
    """Return a new CommitData object updated according to the command line
    options."""
    # Set the commit message from commandline.
    if options.message is not None:
        cd = cd.set_message(options.message)

    # Modify author data.
    cd = cd.set_author(options.author(cd.author))

    # Add Signed-off-by: or similar.
    if options.sign_str is not None:
        sign_str = options.sign_str
    else:
        sign_str = config.get("stgit.autosign")
    if sign_str is not None:
        cd = cd.set_message(
            add_sign_line(cd.message, sign_str,
                          cd.committer.name, cd.committer.email))

    # Let user edit the commit message manually, unless
    # --save-template or --message was specified.
    if not getattr(options, 'save_template', None) and options.message is None:
        cd = cd.set_message(edit_string(cd.message, '.stgit-new.txt'))

    return cd
예제 #6
0
파일: edit.py 프로젝트: samv/stgit
def interactive_edit_patch(repo, cd, edit_diff, diff_flags, replacement_diff):
    """Edit the patch interactively. If C{edit_diff} is true, edit the
    diff as well. If C{replacement_diff} is not C{None}, it contains a
    diff to edit instead of the patch's real diff.

    Return a pair: the new L{CommitData<stgit.lib.git.CommitData>};
    and the diff text if it didn't apply, or C{None} otherwise."""
    return update_patch_description(
        repo, cd, utils.edit_string(
            patch_desc(repo, cd, edit_diff, diff_flags, replacement_diff),
            '.stgit-edit.' + ['txt', 'patch'][bool(edit_diff)]),
        edit_diff)
예제 #7
0
파일: edit.py 프로젝트: snits/stgit
def interactive_edit_patch(repo, cd, edit_diff, diff_flags, replacement_diff):
    """Edit the patch interactively. If C{edit_diff} is true, edit the
    diff as well. If C{replacement_diff} is not C{None}, it contains a
    diff to edit instead of the patch's real diff.

    Return a pair: the new L{CommitData<stgit.lib.git.CommitData>};
    and the diff text if it didn't apply, or C{None} otherwise."""
    return update_patch_description(
        repo, cd, utils.edit_string(
            patch_desc(repo, cd, edit_diff, diff_flags, replacement_diff),
            '.stgit-edit.' + ['txt', 'patch'][bool(edit_diff)]),
        edit_diff)
예제 #8
0
def update_commit_data(repo,
                       cd,
                       message=None,
                       author=None,
                       trailers=None,
                       edit=False,
                       verbose=False):
    """Create updated CommitData according to the command line options."""
    iw = repo.default_iw

    # Set the commit message from commandline.
    if message is not None:
        cd = cd.set_message(message)

    # Modify author data.
    if author is not None:
        cd = cd.set_author(author)

    # Add Signed-off-by: or similar.
    if not trailers:
        autosign = config.get("stgit.autosign")
        if autosign:
            trailers = [(autosign, None)]
    if trailers:
        cd = cd.set_message(
            add_trailers(cd.message_str, trailers, cd.committer.name,
                         cd.committer.email))

    if edit:
        message_str = cd.message_str
        tmpl = templates.get_template('patchdescr.tmpl')
        if tmpl:
            message_str += tmpl

        status = '\n# '.join(_git_status())
        message_str += COMMIT_MESSAGE_INSTRUCTIONS + status
        if verbose:
            # include a diff
            message_str += (COMMIT_MESSAGE_DEMARCATION_LINE +
                            COMMIT_MESSAGE_INSTRUCTIONS_2)
            message_str += iw.diff(
                repo.rev_parse('HEAD').data.tree,
                binary=False,
            ).decode('utf-8')
        new_message = edit_string(message_str, '.stgit-new.txt')
        new_message = new_message.split(COMMIT_MESSAGE_DEMARCATION_LINE)[0]
        new_message = '\n'.join(line for line in new_message.splitlines()
                                if not line.startswith('#'))
        cd = cd.set_message(new_message)

    return cd
예제 #9
0
파일: common.py 프로젝트: wildmichael/stgit
def update_commit_data(cd,
                       message=None,
                       author=None,
                       sign_str=None,
                       edit=False,
                       verbose=False):
    """Create updated CommitData according to the command line options."""
    # Set the commit message from commandline.
    if message is not None:
        cd = cd.set_message(message)

    # Modify author data.
    if author is not None:
        cd = cd.set_author(author)

    # Add Signed-off-by: or similar.
    if sign_str is None:
        sign_str = config.get("stgit.autosign")
    if sign_str:
        cd = cd.set_message(
            add_trailer(cd.message_str, sign_str, cd.committer.name,
                        cd.committer.email))

    if edit:
        message_str = cd.message_str
        tmpl = templates.get_template('patchdescr.tmpl')
        if tmpl:
            message_str += tmpl

        status = '\n# '.join(_git_status())
        message_str += COMMIT_MESSAGE_INSTRUCTIONS + status
        if verbose:
            # include a diff
            message_str += (COMMIT_MESSAGE_DEMARCATION_LINE +
                            COMMIT_MESSAGE_INSTRUCTIONS_2)
            message_str += '\n'.join(_git_diff())
        new_message = edit_string(message_str, '.stgit-new.txt')
        new_message = new_message.split(COMMIT_MESSAGE_DEMARCATION_LINE)[0]
        new_message = '\n'.join(line for line in new_message.splitlines()
                                if not line.startswith('#'))
        cd = cd.set_message(new_message)

    return cd
예제 #10
0
def _squash_patches(trans, patches, name, msg, save_template, no_verify=False):
    cd = trans.patches[patches[0]].data
    for pn in patches[1:]:
        c = trans.patches[pn]
        tree = trans.stack.repository.simple_merge(
            base=c.data.parent.data.tree,
            ours=cd.tree,
            theirs=c.data.tree,
        )
        if not tree:
            return None
        cd = cd.set_tree(tree)
    if msg is None:
        if name:
            msg = "# Squashing %s patches as '%s'.\n" % (len(patches), name)
        else:
            msg = "# Squashing %s patches.\n" % len(patches)
        for num, pn in enumerate(patches, 1):
            msg += "# This is the commit message for patch #%s (%s):" % (
                num,
                pn,
            )
            msg += "\n%s\n\n" % trans.patches[pn].data.message_str.rstrip()
        msg += (
            "# Please enter the commit message for your patch. Lines starting\n"
            "# with '#' will be ignored.")

        if save_template:
            save_template(msg.encode(cd.encoding))
            raise SaveTemplateDone()
        else:
            msg = utils.edit_string(msg, '.stgit-squash.txt')

    msg = '\n'.join(_strip_comments(msg)).strip()
    if not msg:
        raise CmdException('Aborting squash due to empty commit message')

    cd = cd.set_message(msg)

    if not no_verify:
        cd = run_commit_msg_hook(trans.stack.repository, cd)

    return cd
예제 #11
0
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
예제 #12
0
파일: rebase.py 프로젝트: wildmichael/stgit
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
    instructions = []
    for pn in previously_applied_patches:
        patch = (pn, __get_description(stack, pn))
        instructions.append(line.format(*patch))
    instructions.append(INTERACTIVE_APPLY_LINE)
    for pn in stack.patchorder.all:
        if pn in previously_applied_patches:
            continue
        patch = (pn, __get_description(stack, pn))
        instructions.append(line.format(*patch))
    instructions.append(INTERACTIVE_HELP_INSTRUCTIONS)

    # open an editor to let the user generate the 'todo' instructions
    todo = edit_string(
        '\n'.join(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 ('d', 'delete'):
            instruction_type = Action.DELETE
        elif instruction_str in ('s', 'squash'):
            instruction_type = Action.SQUASH
        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))

    # execute all the non-squash instructions first. we use a copy to make sure
    # we don't skip any instructions as we delete from the list
    for instruction in copy.copy(instructions):
        if instruction.apply:
            post_rebase(stack, {instruction.patch_name}, 'rebase',
                        check_merged)
        if instruction.action == Action.DELETE:
            delete_patches(stack, stack.repository.default_iw,
                           {instruction.patch_name})
            instructions.remove(instruction)

    # execute squashes last because patch names may change during squashes. this
    # is a double loop so we can handle multiple chains of multiple squashes
    for index in itertools.count():
        if index >= len(instructions):
            break  # reached the end of the instruction list
        # determine how many of the next N instructions are squashes
        squashes_found = False
        for num_squashes in itertools.count(1):
            if len(instructions) <= index + num_squashes:
                break  # reached the end of the instruction list
            if instructions[index + num_squashes].action == Action.SQUASH:
                squashes_found = True
            else:
                break  # not a squash; chain is over
        # execute squash
        if squashes_found:
            squashes = instructions[index:index + num_squashes]
            squash(
                stack,
                stack.repository.default_iw,
                None,
                None,
                None,
                [p.patch_name for p in squashes],
            )
            # remove the squashed patches from the instruction set
            instructions = (instructions[:index + 1] +
                            instructions[index + num_squashes:])
    return utils.STGIT_SUCCESS