Hi,

Sorry about that. Here's the py file, and also a test.

I mimicked the test for 'pick', and I'm not quite happy with it: The test
is very sequential (each subtest depends on all previous subtests to
succeed), and upon a failure the output isn't very useful. Are there any
tools in your test framework that I can use to improve the test? Are there
any existing tests I can read and learn from?

By the way, two more implementation notes:
- If one tries to allow moving a patch from a branch to itself, it will
effectively be popped, but also renamed. The rename comes from some strange
aspect of the Patches class: stgit will not realize that a patch is deleted
within the same stgit process, so make_patch_name will find a new name.
- I chose to let any conflicts abort the entire transaction, to avoid some
headache.

By the way: While looking at this, I noticed that delete (from which most
of my implementation is derived) contains some code that doesn't work the
way it seems to be intended:
    def allow_conflicts(trans):
        # Allow conflicts if the topmost patch stays the same.
        if stack.patchorder.applied:
            return (trans.applied
                    and trans.applied[-1] == stack.patchorder.applied[-1])
        else:
            return not trans.applied

Looks like the author wants delete to abort the transaction if there is a
merge conflict below the stack top. However, it does not. If your series is
A B C, and you delete A, yielding a conflict when pushing B, then the
command ends up with B's conflict in the working tree.



On Thu, Apr 3, 2014 at 3:34 PM, Catalin Marinas <[email protected]>wrote:

> Erik,
>
> On 31 March 2014 23:12, Erik Carstensen <[email protected]> wrote:
> > Here is an implementation of stg move.
>
> Is there a way to decompile a .pyc file? It's easier if you sent the
> .py one directly ;).
>
> > Some notes:
> > - I didn't use a transaction for creating patches in the new branch,
> because
> > patch creation cannot fail (and transactions don't span multiple
> branches).
>
> I think that's fine, Karl know more about this.
>
> > - Branches are given with explicit options --from and --to. Specifying
> none
> > would be a strange way of expressing pop, and likely a mistake, so I made
> > that an error.
>
> So we won't have default options. Fine by me.
>
> > - The patch log is not copied to the new branch. I never used patch
> logs, so
> > I don't know about your expectations there.
>
> I don't use them much either. It can be added afterwards if we find a way.
>
> > - Is there a function to pick a name for a patch? I couldn't find one,
> so I
> > rewrote the logic instead (find_unique_name). It would be better to use
> an
> > existing one, or to promote mine to a library if none exists.
>
> There is make_patch_name() in stgit/utils.py. See __create_patch() in
> stgit/commands/imprt.py for an example on how to use this.
>
> Catalin
>

Attachment: t3500-move.sh
Description: Bourne shell script

__copyright__ = """
Copyright (C) 2005, Catalin Marinas <[email protected]>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""

import itertools

from stgit.argparse import opt
from stgit.commands import common
from stgit.lib import transaction
from stgit import argparse
from stgit import utils
from stgit.out import out

help = 'Move patches between branches'
kind = 'patch'
usage = ['DEST_BRANCH <patch1> [<patch2>] [<patch3>..<patch4>]']
description = """
Delete the given patches from the current branch, and add them unapplied to
DEST_BRANCH."""

args = [argparse.patch_range(argparse.applied_patches,
                             argparse.unapplied_patches)]
options = [
    opt('-f', '--from', args=[argparse.stg_branches],
        dest='src', short='Move from branch BRANCH'),
    opt('-t', '--to', args=[argparse.stg_branches],
        dest='dest', short='Move to branch BRANCH')]

directory = common.DirectoryHasRepositoryLib()

def find_unique_name(oldname, blacklist):
    # TODO: is this the right place?
    if oldname in blacklist:
        base, dash, num = oldname.rpartition('-')
        if not dash or not num.isdigit:
            base = oldname
        for i in itertools.count():
            name = '%s-%d' % (base, i)
            if name not in blacklist:
                return name
    else:
        return oldname

def func(parser, options, args):
    """Move patches between branches."""
    if not options.src and not options.dest:
        parser.error('Must specify either --from or --to')

    src = directory.repository.get_stack(options.src)
    dest = directory.repository.get_stack(options.dest)

    if options.src:
        iw = None # can't use index/workdir to manipulate another branch
    else:
        iw = src.repository.default_iw
    if not len(args):
        parser.error('No patch specified')

    patches = common.parse_patches(args, list(src.patchorder.all),
                                   len(src.patchorder.applied))

    trans = transaction.StackTransaction(src, 'move')
    commits = [(n, src.patches.get(n).commit) for n in patches]
    try:
        to_push = trans.delete_patches(lambda pn: pn in patches)
        for pn in to_push:
            trans.push_patch(pn, iw)
    except transaction.TransactionHalted:
        out.info('Conflicts, everything rolled back.')
        return utils.STGIT_CONFLICT
    else:
        result = trans.run(iw)

        # Creating patches directly. Not using a transaction, because
        # this cannot fail
        created = []
        for (name, commit) in commits:
            # This rename criterion will cause the patch to be renamed
            # if it is moved from a branch to itself, because of how
            # Patches works: it is not possible to re-add a patch that
            # previously existed in the same stgit process.
            if dest.patches.exists(name):
                name = utils.make_patch_name(
                    commit.data.message,
                    lambda name: dest.patches.exists(name))
            newpatch = dest.patches.new(name, commit, 'move')
            created.append(name)

        dest.patchorder.unapplied = (tuple(created) + dest.patchorder.unapplied)
        out.info('Created %s on branch %s' % (", ".join(created), dest.name))
        return result
_______________________________________________
stgit-users mailing list
[email protected]
https://mail.gna.org/listinfo/stgit-users

Reply via email to