Esempio n. 1
0
def func(parser, options, args):
    """Rebase the current stack
    """
    if len(args) != 1:
        parser.error('incorrect number of arguments')

    repository = directory.repository
    stack = repository.get_stack()
    iw = repository.default_iw

    if stack.protected:
        raise CmdException('This branch is protected. Rebase is not permitted')

    target = git_commit(args[0], repository)

    applied = stack.patchorder.applied

    retval = prepare_rebase(stack, 'rebase')
    if retval:
        return retval

    rebase(stack, iw, target)
    if not options.nopush:
        return post_rebase(stack,
                           applied,
                           'rebase',
                           check_merged=options.merged)
def func(parser, options, args):
    """Rebase the current stack"""

    if options.interactive:
        # destination is optional for '--interactive'
        if len(args) not in (0, 1):
            parser.error('incorrect number of arguments')
    else:
        if len(args) != 1:
            parser.error('incorrect number of arguments')

    repository = directory.repository
    stack = repository.get_stack()
    iw = repository.default_iw

    if stack.protected:
        raise CmdException('This branch is protected. Rebase is not permitted')

    if len(args) > 0:
        target = git_commit(args[0], repository)
    else:
        target = stack.base

    if options.autostash and not iw.worktree_clean():
        repository.run(['git', 'stash', 'push']).run()
        stashed_worktree = True
    else:
        stashed_worktree = False

    applied = stack.patchorder.applied
    retval = prepare_rebase(stack, 'rebase')
    if retval:
        return retval
    rebase(stack, iw, target)

    if options.interactive:
        retval = __do_rebase_interactive(repository,
                                         applied,
                                         check_merged=options.merged)
    elif not options.nopush:
        retval = post_rebase(stack,
                             applied,
                             'rebase',
                             check_merged=options.merged)
    else:
        retval = None

    if stashed_worktree:
        try:
            repository.run(['git', 'stash', 'pop']).run()
        except RunException:
            raise StashPopConflictException()

    return retval
Esempio n. 3
0
def func(parser, options, args):
    """Rebase the current stack
    """
    if len(args) != 1:
        parser.error('incorrect number of arguments')

    if crt_series.get_protected():
        raise CmdException('This branch is protected. Rebase is not permitted')

    check_local_changes()
    check_conflicts()
    check_head_top_equal(crt_series)

    # ensure an exception is raised before popping on non-existent target
    if git_id(crt_series, args[0]) is None:
        raise GitException('Unknown revision: %s' % args[0])

    applied = prepare_rebase(crt_series)
    rebase(crt_series, args[0])
    post_rebase(crt_series, applied, options.nopush, options.merged)

    print_crt_patch(crt_series)
Esempio n. 4
0
def func(parser, options, args):
    """Rebase the current stack
    """
    if len(args) != 1:
        parser.error('incorrect number of arguments')

    if crt_series.get_protected():
        raise CmdException('This branch is protected. Rebase is not permitted')

    check_local_changes()
    check_conflicts()
    check_head_top_equal(crt_series)

    # ensure an exception is raised before popping on non-existent target
    if git_id(crt_series, args[0]) is None:
        raise GitException('Unknown revision: %s' % args[0])
        
    applied = prepare_rebase(crt_series)
    rebase(crt_series, args[0])
    post_rebase(crt_series, applied, options.nopush, options.merged)

    print_crt_patch(crt_series)
Esempio n. 5
0
def func(parser, options, args):
    """Rebase the current stack"""

    if options.interactive:
        # destination is optional for '--interactive'
        if len(args) not in (0, 1):
            parser.error('incorrect number of arguments')
    else:
        if len(args) != 1:
            parser.error('incorrect number of arguments')

    repository = directory.repository
    stack = repository.get_stack()
    iw = repository.default_iw

    if stack.protected:
        raise CmdException('This branch is protected. Rebase is not permitted')

    if len(args) > 0:
        target = git_commit(args[0], repository)
    else:
        target = stack.base

    applied = stack.patchorder.applied
    retval = prepare_rebase(stack, 'rebase')
    if retval:
        return retval
    rebase(stack, iw, target)

    if options.interactive:
        return __do_rebase_interactive(repository,
                                       applied,
                                       check_merged=options.merged)
    elif not options.nopush:
        return post_rebase(stack,
                           applied,
                           'rebase',
                           check_merged=options.merged)
Esempio n. 6
0
def func(parser, options, args):
    """Pull the changes from a remote repository"""
    repository = directory.repository
    iw = repository.default_iw
    stack = repository.get_stack()
    policy = config.get('branch.%s.stgit.pull-policy' %
                        stack.name) or config.get('stgit.pull-policy')

    if policy not in ['pull', 'fetch-rebase', 'rebase']:
        raise GitConfigException('Unsupported pull-policy "%s"' % policy)

    remote_name = None
    if policy == 'rebase':
        # parent is local
        if len(args) == 1:
            parser.error(
                'specifying a repository is meaningless for policy="%s"' %
                (policy, ))
        elif len(args) > 0:
            parser.error('incorrect number of arguments')
    else:
        # parent is remote
        if len(args) > 1:
            parser.error('incorrect number of arguments')

        if len(args) >= 1:
            remote_name = args[0]
        else:
            remote_name = stack.parent_remote

    if policy in ['pull', 'fetch-rebase'] and remote_name is None:
        parser.error(
            'There is no tracking information for the current branch.\n'
            'Please specify the remote repository to pull from.')

    if stack.protected:
        raise CmdException('This branch is protected. Pulls are not permitted')

    applied = stack.patchorder.applied

    retval = prepare_rebase(stack, 'pull')
    if retval:
        return retval

    # pull the remote changes
    if policy == 'pull':
        out.info('Pulling from "%s"' % remote_name)
        pull(repository, remote_name)
    elif policy == 'fetch-rebase':
        out.info('Fetching from "%s"' % remote_name)
        fetch(repository, remote_name)
        try:
            target = repository.rev_parse('FETCH_HEAD')
        except RepositoryException:
            out.error('Could not find the remote head to rebase onto - '
                      'fix branch.%s.merge in .git/config' % stack.name)
            out.error('Pushing any patches back...')
            post_rebase(stack, applied, 'pull', check_merged=False)
            raise

        rebase(stack, iw, target)
    elif policy == 'rebase':
        value = config.get('branch.%s.stgit.parentbranch' % stack.name)
        if value:
            parent_commit = git_commit(value, repository)
        else:
            try:
                parent_commit = repository.rev_parse('heads/origin')
            except RepositoryException:
                raise CmdException('Cannot find a parent branch for "%s"' %
                                   stack.name)
            else:
                out.warn(
                    'No parent branch declared for stack "%s", defaulting to'
                    '"heads/origin".' % stack.name,
                    'Consider setting "branch.%s.stgit.parentbranch" with '
                    '"git config".' % stack.name,
                )
        rebase(stack, iw, parent_commit)

    if not options.nopush:
        post_rebase(stack, applied, 'pull', check_merged=options.merged)

    # maybe tidy up
    if config.getbool('stgit.keepoptimized'):
        repository.repack()
Esempio n. 7
0
def func(parser, options, args):
    """Pull the changes from a remote repository
    """
    policy = config.get('branch.%s.stgit.pull-policy' % crt_series.get_name()) or \
             config.get('stgit.pull-policy')

    if policy == 'rebase':
        # parent is local
        if len(args) == 1:
            parser.error(
                'specifying a repository is meaningless for policy="%s"' %
                policy)
        if len(args) > 0:
            parser.error('incorrect number of arguments')

    else:
        # parent is remote
        if len(args) > 1:
            parser.error('incorrect number of arguments')

        if len(args) >= 1:
            repository = args[0]
        else:
            repository = crt_series.get_parent_remote()

    if crt_series.get_protected():
        raise CmdException('This branch is protected. Pulls are not permitted')

    check_local_changes()
    check_conflicts()
    check_head_top_equal(crt_series)

    if policy not in ['pull', 'fetch-rebase', 'rebase']:
        raise GitConfigException('Unsupported pull-policy "%s"' % policy)

    applied = prepare_rebase(crt_series)

    # pull the remote changes
    if policy == 'pull':
        out.info('Pulling from "%s"' % repository)
        git.pull(repository)
    elif policy == 'fetch-rebase':
        out.info('Fetching from "%s"' % repository)
        git.fetch(repository)
        try:
            target = git.fetch_head()
        except git.GitException:
            out.error(
                'Could not find the remote head to rebase onto - fix branch.%s.merge in .git/config'
                % crt_series.get_name())
            out.error('Pushing any patches back...')
            post_rebase(crt_series, applied, False, False)
            raise

        rebase(crt_series, target)
    elif policy == 'rebase':
        rebase(crt_series, crt_series.get_parent_branch())

    post_rebase(crt_series, applied, options.nopush, options.merged)

    # maybe tidy up
    if config.getbool('stgit.keepoptimized'):
        git.repack()

    print_crt_patch(crt_series)
Esempio n. 8
0
File: pull.py Progetto: snits/stgit
def func(parser, options, args):
    """Pull the changes from a remote repository
    """
    policy = config.get('branch.%s.stgit.pull-policy' % crt_series.get_name()) or \
             config.get('stgit.pull-policy')

    if policy == 'rebase':
        # parent is local
        if len(args) == 1:
            parser.error('specifying a repository is meaningless for policy="%s"' % policy)
        if len(args) > 0:
            parser.error('incorrect number of arguments')

    else:
        # parent is remote
        if len(args) > 1:
            parser.error('incorrect number of arguments')

        if len(args) >= 1:
            repository = args[0]
        else:
            repository = crt_series.get_parent_remote()

    if crt_series.get_protected():
        raise CmdException('This branch is protected. Pulls are not permitted')

    check_local_changes()
    check_conflicts()
    check_head_top_equal(crt_series)

    if policy not in ['pull', 'fetch-rebase', 'rebase']:
        raise GitConfigException('Unsupported pull-policy "%s"' % policy)

    applied = prepare_rebase(crt_series)

    # pull the remote changes
    if policy == 'pull':
        out.info('Pulling from "%s"' % repository)
        git.pull(repository)
    elif policy == 'fetch-rebase':
        out.info('Fetching from "%s"' % repository)
        git.fetch(repository)
        try:
            target = git.fetch_head()
        except git.GitException:
            out.error('Could not find the remote head to rebase onto - fix branch.%s.merge in .git/config' % crt_series.get_name())
            out.error('Pushing any patches back...')
            post_rebase(crt_series, applied, False, False)
            raise

        rebase(crt_series, target)
    elif policy == 'rebase':
        rebase(crt_series, crt_series.get_parent_branch())

    post_rebase(crt_series, applied, options.nopush, options.merged)

    # maybe tidy up
    if config.get('stgit.keepoptimized') == 'yes':
        git.repack()

    print_crt_patch(crt_series)
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
Esempio n. 10
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
    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