Пример #1
0
 def write_commit(self):
     metadata = self.__metadata_string()
     tree = self.__tree(metadata)
     self.__simplified = self.__repo.commit(
         CommitData(tree=tree,
                    message=self.message,
                    parents=[
                        prev.simplified for prev in [self.prev]
                        if prev is not None
                    ]))
     parents = list(self.__parents())
     while len(parents) >= self.__max_parents:
         g = self.__repo.commit(
             CommitData(
                 tree=tree,
                 parents=parents[-self.__max_parents:],
                 message='Stack log parent grouping',
             ))
         parents[-self.__max_parents:] = [g]
     self.commit = self.__repo.commit(
         CommitData(
             tree=tree,
             message=self.message,
             parents=[self.simplified] + parents,
         ))
Пример #2
0
 def commit_state(self, repo, message):
     """Commit stack state to stack metadata branch."""
     prev_state = self.get_prev_state(repo)
     tree = self._tree(repo, prev_state)
     simplified_parent = repo.commit(
         CommitData(
             tree=tree,
             message=message,
             parents=[] if prev_state is None else [prev_state.simplified_parent],
         )
     )
     parents = list(self._parents(prev_state))
     while len(parents) >= self._max_parents:
         g = repo.commit(
             CommitData(
                 tree=tree,
                 parents=parents[-self._max_parents :],
                 message='Stack log parent grouping',
             )
         )
         parents[-self._max_parents :] = [g]
     self.commit = repo.commit(
         CommitData(
             tree=tree,
             message=message,
             parents=[simplified_parent] + parents,
         )
     )
     return self.commit
Пример #3
0
def _squash_patches(trans, patches, msg, save_template, no_verify=False):
    cd = trans.patches[patches[0]].data
    cd = 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 is 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.encode('utf-8'))
            raise SaveTemplateDone()
        else:
            msg = utils.edit_string(msg, '.stgit-squash.txt')
    msg = utils.strip_comment(msg).strip()
    cd = cd.set_message(msg)

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

    return cd
Пример #4
0
 def commit_state(self):
     """Commit stack state to stack metadata branch."""
     tree = self._tree()
     self._simplified = self._repo.commit(
         CommitData(
             tree=tree,
             message=self.message,
             parents=[
                 prev.simplified for prev in [self.prev] if prev is not None
             ],
         ))
     parents = list(self._parents())
     while len(parents) >= self._max_parents:
         g = self._repo.commit(
             CommitData(
                 tree=tree,
                 parents=parents[-self._max_parents:],
                 message='Stack log parent grouping',
             ))
         parents[-self._max_parents:] = [g]
     self.commit = self._repo.commit(
         CommitData(
             tree=tree,
             message=self.message,
             parents=[self.simplified] + parents,
         ))
     return self.commit
Пример #5
0
def apply_patch(stack, diff, base=None, reject=False, strip=None):
    iw = stack.repository.default_iw
    iw.refresh_index()
    if base:
        orig_head = stack.head
        iw.checkout(orig_head.data.tree, base.data.tree)
        stack.set_head(base, msg='apply patch')

    try:
        iw.apply(diff, quiet=False, reject=reject, strip=strip)
    except MergeException:
        if base:
            iw.checkout_hard(orig_head.data.tree)
        raise

    if base:
        iw.update_index(iw.changed_files(base.data.tree))
        top = stack.repository.commit(
            CommitData(
                tree=stack.repository.default_index.write_tree(),
                message='temporary commit used for applying a patch',
                parents=[base],
            ))
        iw.checkout(top.data.tree, orig_head.data.tree)
        stack.set_head(orig_head, msg='post apply')
        iw.merge(base.data.tree, orig_head.data.tree, top.data.tree)
Пример #6
0
def __series_merge_patch(patchdir, stack, commit, pname):
    """Merge a patch file with the given StGIT patch.
    """
    with io.open(os.path.join(patchdir, pname), 'rb') as f:
        diff = f.read()
    base = commit.data.parent
    orig_head = stack.head
    iw = stack.repository.default_iw
    iw.refresh_index()
    iw.checkout(new_tree=base.data.tree, old_tree=orig_head.data.tree)
    stack.set_head(base, msg='apply patch')
    iw.apply(diff, quiet=False)
    iw.update_index(iw.changed_files(base.data.tree))
    new_tree = iw.index.write_tree()
    stack.repository.commit(
        CommitData(
            tree=new_tree,
            message='temp commit for applying patch',
            parents=[base],
        ))
    iw.checkout(new_tree=orig_head.data.tree, old_tree=new_tree)
    stack.set_head(orig_head, msg='post apply')
    iw.merge(base=base.data.tree, ours=orig_head.data.tree, theirs=new_tree)
    if iw.index.is_clean(orig_head.data.tree):
        return None
    else:
        return new_tree
Пример #7
0
def func(parser, options, args):
    """Create a new patch."""
    stack = directory.repository.current_stack
    if stack.repository.default_index.conflicts():
        raise CmdException(
            'Cannot create a new patch -- resolve conflicts first')

    # Choose a name for the new patch -- or None, which means make one
    # up later when we've gotten hold of the commit message.
    if len(args) == 0:
        name = None
    elif len(args) == 1:
        name = args[0]
        if not stack.patches.is_name_valid(name):
            raise CmdException('Invalid patch name: "%s"' % name)
        elif name in stack.patches:
            raise CmdException('%s: patch already exists' % name)
    else:
        parser.error('incorrect number of arguments')

    if options.verbose:
        verbose = options.verbose
    else:
        verbose = config.getbool('stgit.new.verbose') or False

    cd = CommitData(
        tree=stack.head.data.tree,
        parents=[stack.head],
        message='',
        author=Person.author(),
        committer=Person.committer(),
    )
    cd = update_commit_data(
        stack.repository,
        cd,
        message=options.message,
        author=options.author(cd.author),
        trailers=options.trailers,
        edit=(not options.save_template and options.message is None),
        verbose=verbose,
    )

    if options.save_template:
        options.save_template(cd.message)
        return utils.STGIT_SUCCESS

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

    if name is None:
        name = stack.patches.make_name(cd.message_str)

    # Write the new patch.
    check_head_top_equal(stack)
    trans = StackTransaction(stack)
    trans.patches[name] = stack.repository.commit(cd)
    trans.applied.append(name)
    return trans.execute('new: %s' % name)
Пример #8
0
def __create_commit(repository, tree, parents, options, message=''):
    """Return a new Commit object."""
    cd = CommitData(
        tree=tree,
        parents=parents,
        message=message,
        author=Person.author(),
        committer=Person.committer(),
    )
    cd = common.update_commit_data(cd, options)
    return repository.commit(cd)
Пример #9
0
 def write_patchlog():
     try:
         old_log = [self._stack.repository.refs.get(self._log_ref)]
     except KeyError:
         old_log = []
     cd = CommitData(
         tree=new_commit.data.tree,
         parents=old_log,
         message='%s\t%s' % (msg, new_commit.sha1),
     )
     c = self._stack.repository.commit(cd)
     self._stack.repository.refs.set(self._log_ref, c, msg)
     return c
Пример #10
0
def make_temp_patch(stack, patch_name, tree):
    """Commit tree to temp patch, in a complete transaction."""
    commit = stack.repository.commit(
        CommitData(
            tree=tree,
            parents=[stack.head],
            message='Refresh of %s' % patch_name,
        ))
    temp_name = utils.make_patch_name('refresh-temp', stack.patches.exists)
    trans = StackTransaction(stack, 'refresh (create temporary patch)')
    trans.patches[temp_name] = commit
    trans.applied.append(temp_name)
    return (
        trans.run(stack.repository.default_iw, print_current_patch=False),
        temp_name,
    )
Пример #11
0
def make_temp_patch(stack, patch_name, paths, temp_index):
    """Commit index to temp patch, in a complete transaction. If any path
    limiting is in effect, use a temp index."""
    tree = write_tree(stack, paths, temp_index)
    commit = stack.repository.commit(
        CommitData(
            tree=tree,
            parents=[stack.head],
            message='Refresh of %s' % patch_name,
        ))
    temp_name = utils.make_patch_name('refresh-temp', stack.patches.exists)
    trans = transaction.StackTransaction(stack,
                                         'refresh (create temporary patch)')
    trans.patches[temp_name] = commit
    trans.applied.append(temp_name)
    return (trans.run(stack.repository.default_iw,
                      print_current_patch=False), temp_name)
Пример #12
0
Файл: new.py Проект: gwd/stgit
def func(parser, options, args):
    """Create a new patch."""
    stack = directory.repository.current_stack
    if stack.repository.default_index.conflicts():
        raise CmdException(
            'Cannot create a new patch -- resolve conflicts first')

    # Choose a name for the new patch -- or None, which means make one
    # up later when we've gotten hold of the commit message.
    if len(args) == 0:
        name = None
    elif len(args) == 1:
        name = args[0]
        if stack.patches.exists(name):
            raise CmdException('%s: patch already exists' % name)
        elif not stack.patches.is_name_valid(name):
            raise CmdException('Invalid patch name: "%s"' % name)
    else:
        parser.error('incorrect number of arguments')

    cd = CommitData(
        tree=stack.head.data.tree,
        parents=[stack.head],
        message='',
        author=Person.author(),
        committer=Person.committer(),
    )
    cd = update_commit_data(cd, options)

    if options.save_template:
        options.save_template(cd.message.encode('utf-8'))
        return utils.STGIT_SUCCESS

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

    if name is None:
        name = utils.make_patch_name(cd.message, stack.patches.exists)
        assert stack.patches.is_name_valid(name)

    # Write the new patch.
    stack.repository.default_iw
    trans = StackTransaction(stack, 'new: %s' % name)
    trans.patches[name] = stack.repository.commit(cd)
    trans.applied.append(name)
    return trans.run()
Пример #13
0
def __create_commit(repository, tree, parents, options, message=''):
    """Return a new Commit object."""
    cd = CommitData(
        tree=tree,
        parents=parents,
        message=message,
        author=Person.author(),
        committer=Person.committer(),
    )
    cd = update_commit_data(
        cd,
        message=options.message,
        author=options.author(cd.author),
        sign_str=options.sign_str,
        edit=options.message is None,
    )
    return repository.commit(cd)
Пример #14
0
def __pick_commit(stack, ref_stack, iw, commit, patchname, options):
    """Pick a commit."""
    repository = stack.repository

    if options.name:
        patchname = options.name
    elif patchname and options.revert:
        patchname = 'revert-' + patchname

    if patchname:
        patchname = find_patch_name(patchname, stack.patches.exists)
    else:
        patchname = make_patch_name(commit.data.message_str,
                                    stack.patches.exists)

    if options.parent:
        parent = git_commit(options.parent, repository, ref_stack.name)
    else:
        parent = commit.data.parent

    if not options.revert:
        bottom = parent
        top = commit
    else:
        bottom = commit
        top = parent

    if options.fold:
        out.start('Folding commit %s' % commit.sha1)

        diff = repository.diff_tree(bottom.data.tree,
                                    top.data.tree,
                                    pathlimits=options.file)

        if diff:
            try:
                # try a direct git apply first
                iw.apply(diff, quiet=True)
            except MergeException:
                if options.file:
                    out.done('conflict(s)')
                    out.error('%s does not apply cleanly' % patchname)
                    return STGIT_CONFLICT
                else:
                    try:
                        iw.merge(
                            bottom.data.tree,
                            stack.head.data.tree,
                            top.data.tree,
                        )
                    except MergeConflictException as e:
                        out.done('%s conflicts' % len(e.conflicts))
                        out.error('%s does not apply cleanly' % patchname,
                                  *e.conflicts)
                        return STGIT_CONFLICT
            out.done()
        else:
            out.done('no changes')
        return STGIT_SUCCESS
    elif options.update:
        files = [
            fn1 for _, _, _, _, _, fn1, fn2 in repository.diff_tree_files(
                stack.top.data.parent.data.tree, stack.top.data.tree)
        ]

        diff = repository.diff_tree(bottom.data.tree,
                                    top.data.tree,
                                    pathlimits=files)

        out.start('Updating with commit %s' % commit.sha1)

        try:
            iw.apply(diff, quiet=True)
        except MergeException:
            out.done('conflict(s)')
            out.error('%s does not apply cleanly' % patchname)
            return STGIT_CONFLICT
        else:
            out.done()
            return STGIT_SUCCESS
    else:
        author = commit.data.author
        message = commit.data.message_str

        if options.revert:
            author = Person.author()
            if message:
                lines = message.splitlines()
                subject = lines[0]
                body = '\n'.join(lines[2:])
            else:
                subject = commit.sha1
                body = ''
            message = 'Revert "%s"\n\nThis reverts commit %s.\n\n%s\n' % (
                subject,
                commit.sha1,
                body,
            )
        elif options.expose:
            fmt = config.get('stgit.pick.expose-format')
            message = Run('git', 'show', '--no-patch', '--pretty=' + fmt,
                          commit.sha1).raw_output()
            message = message.rstrip() + '\n'

        out.start('Importing commit %s' % commit.sha1)

        new_commit = repository.commit(
            CommitData(
                tree=top.data.tree,
                parents=[bottom],
                message=message,
                author=author,
            ))

        trans = StackTransaction(
            stack, 'pick %s from %s' % (patchname, ref_stack.name))
        trans.patches[patchname] = new_commit

        trans.unapplied.append(patchname)
        if not options.unapplied:
            try:
                trans.push_patch(patchname, iw, allow_interactive=True)
            except TransactionHalted:
                pass

        retval = trans.run(iw, print_current_patch=False)

        if retval == STGIT_CONFLICT:
            out.done('conflict(s)')
        elif stack.patches.get(patchname).is_empty():
            out.done('empty patch')
        else:
            out.done()

        return retval
Пример #15
0
def __create_patch(filename, message, author_name, author_email,
                   author_date, diff, options):
    """Create a new patch on the stack
    """
    stack = directory.repository.current_stack

    if options.name:
        name = options.name
        if not stack.patches.is_name_valid(name):
            raise CmdException('Invalid patch name: %s' % name)
    elif filename:
        name = os.path.basename(filename)
    else:
        name = ''
    if options.stripname:
        name = __strip_patch_name(name)

    if not name:
        if options.ignore or options.replace:
            def unacceptable_name(name):
                return False
        else:
            unacceptable_name = stack.patches.exists
        name = make_patch_name(message, unacceptable_name)
    else:
        # fix possible invalid characters in the patch name
        name = re.sub(r'[^\w.]+', '-', name).strip('-')

    assert stack.patches.is_name_valid(name)

    if options.ignore and name in stack.patchorder.applied:
        out.info('Ignoring already applied patch "%s"' % name)
        return

    out.start('Importing patch "%s"' % name)

    author = Person(
        author_name,
        author_email,
        Date.maybe(author_date),
    )
    author = options.author(author)

    try:
        if not diff:
            out.warn('No diff found, creating empty patch')
            tree = stack.head.data.tree
        else:
            iw = stack.repository.default_iw
            iw.apply(
                diff, quiet=False, reject=options.reject, strip=options.strip
            )
            tree = iw.index.write_tree()

        cd = CommitData(
            tree=tree,
            parents=[stack.head],
            author=author,
            message=message,
        )
        cd = update_commit_data(
            cd,
            message=None,
            author=None,
            sign_str=options.sign_str,
            edit=options.edit,
        )
        commit = stack.repository.commit(cd)

        trans = StackTransaction(stack, 'import: %s' % name)

        try:
            if options.replace and name in stack.patchorder.unapplied:
                trans.delete_patches(lambda pn: pn == name, quiet=True)

            trans.patches[name] = commit
            trans.applied.append(name)
        except TransactionHalted:
            pass
        trans.run()
    finally:
        out.done()
Пример #16
0
def __create_patch(filename, message, patch_name, author_name, author_email,
                   author_date, diff, options):
    """Create a new patch on the stack"""
    stack = directory.repository.current_stack

    if patch_name:
        name = patch_name
    elif options.name:
        name = options.name
    elif filename:
        name = os.path.basename(filename)
    else:
        name = ''

    if options.stripname:
        # Removing leading numbers and trailing extension
        name = re.sub(
            r'''^
                (?:[0-9]+-)?           # Optional leading patch number
                (.*?)                  # Patch name group (non-greedy)
                (?:\.(?:diff|patch))?  # Optional .diff or .patch extension
                $
            ''',
            r'\g<1>',
            name,
            flags=re.VERBOSE,
        )

    need_unique = not (options.ignore or options.replace)

    if name:
        name = stack.patches.make_name(name, unique=need_unique, lower=False)
    else:
        name = stack.patches.make_name(message, unique=need_unique, lower=True)

    if options.ignore and name in stack.patchorder.applied:
        out.info('Ignoring already applied patch "%s"' % name)
        return

    out.start('Importing patch "%s"' % name)

    author = options.author(
        Person(
            author_name,
            author_email,
            Date.maybe(author_date),
        ))

    try:
        if not diff:
            out.warn('No diff found, creating empty patch')
            tree = stack.head.data.tree
        else:
            iw = stack.repository.default_iw
            iw.apply(
                diff,
                quiet=False,
                reject=options.reject,
                strip=options.strip,
                context_lines=options.context_lines,
            )
            tree = iw.index.write_tree()

        cd = CommitData(
            tree=tree,
            parents=[stack.head],
            author=author,
            message=message,
        )
        cd = update_commit_data(
            stack.repository,
            cd,
            message=None,
            author=None,
            trailers=options.trailers,
            edit=options.edit,
        )
        commit = stack.repository.commit(cd)

        trans = StackTransaction(stack)

        try:
            if options.replace and name in stack.patchorder.unapplied:
                trans.delete_patches(lambda pn: pn == name, quiet=True)

            trans.patches[name] = commit
            trans.applied.append(name)
        except TransactionHalted:
            pass
        trans.execute('import: %s' % name)
    finally:
        out.done()