monotone-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Monotone-devel] Re: mtnpatch (updated)


From: cyril Romain
Subject: [Monotone-devel] Re: mtnpatch (updated)
Date: Sun, 11 Mar 2007 15:59:12 +0100
User-agent: Thunderbird 1.5.0.10 (X11/20070303)

Justin Patrin wrote:
Just thought I'd let everyone know that I just cherrypicked my first
revision with mtnpatch.py. I made some efl/e17 updates to .dev and
edited one file, made a diff, and applied the diff to .oz354x with
mtnpatch.py. It worked like a charm.

For those that missed it, I have checked in mtnpatch.py into
org.openembedded.dev in contrib/. I have also switch to using a regex
instead of split() so that whitespace in filenames should be correctly
taken care of.

The script is used like this:
 mtn diff -r ParentRev -r RevToCherryPick > file.patch
 cd /branch/to/cherrypick/to
 contrib/mtnpatch.py file.patch
Look at the output to make sure it's sane
 contrib/mtnpatch.py file.patch | sh
 mtn ci
Maybe I've just missed the right mtn command reading the documentation, but as I'm submitting some patches/recipes for OE metadata, I'd like to: 1. test that my 'mtn diff' patches successfully apply on a up-to-date metadata tree without any local modifications.
2. apply some patches to another development tree.

And this script is "almost" what I'm looking for :)
"Almost" because it does not takes file/directory drop order into account, i.e. "mtnpatch.py the.patch | sh" can fail.
For example if mtnpatch dumps:
---
mtn drop -e packages/quilt/files/install.patch
mtn drop -e packages/quilt/files
---
And if you run these commands in that order, you get "mtn: misuse: cannot remove packages/quilt/files/, it is not empty"

In attachment, an updated version of mtnpatch.py with the following improvements: 1. output command are sorted, so that 'mtnpatch.py my_patch.patch | sh' should now succeed in all cases, hopefully :)
2. help (-h, --help) option added, and usage message is printed on misuse
3. reverse mode (-R option) can be also set with --reverse
4. the reverse option is used to unapply the patch. The dropped files are reverted (not added), but maybe it is not what you, Justin, wanted to do with -R ?


Best regards,

 cyril

#!/usr/bin/env python

"""
mtnpatch is a patch tool intended to apply 'mtn diff' patch, including the 
additional cset operations (e.g. add, drop and rename) listed in mtn diff 
comments.

mtnpatch does not actually apply the patch. It only dumps the list of commands 
to enter
to actually apply the patch.
To apply the patch, use 'mtnpatch.py file.patch | sh'
"""

import sys, os, string, getopt, re

mtncmd = "mtn"


def usage():
    print "Usage: mtnpatch.py [options] file.patch"
    print "Options:"
    print "  -h  --help         display help message"
    print "  -R  --reverse      apply patch in reverse"
    print "\nTo actually apply the patch, use 'mtnpatch.py file.patch | sh'"

def main(argv = None):
    if argv is None:
        argv = sys.argv
    try:
        opts, list = getopt.getopt(sys.argv[1:], 'h:R', ["--help", "--reverse"])
    except:
        usage()
        sys.exit(2)
    reverse = False
    for o, a in opts:
        if o in ("-h", "--help"):
            usage()
            sys.exit(1)
        if o in ("-R", "--reverse"):
            reverse = True
    if len(list) != 1:
        usage()
        sys.exit(1)
    if os.path.exists(list[0]):
        input = open(list[0], 'r')
        renameFrom = ""
        cmd = ""
        addedFiles = []
        addedDirs = []
        droppedFiles = []
        droppedDirs = []
        renamedFiles = []
        for line in input:
            if len(line) > 0:
                if line[0] == '#':
                    matches = re.search("#\s+(\w+)\s+\"(.*)\"", line)
                    if matches is not None:
                        cmd = matches.group(1)
                        fileName = matches.group(2)
                        isDir = os.path.isdir(fileName)
                        if cmd == "delete":
                            if isDir: droppedDirs.append(fileName)
                            else: droppedFiles.append(fileName)
                        elif cmd == "add" or cmd == "add_file" or cmd == 
"add_dir":
                            if isDir: addedDirs.append(fileName)
                            else: addedFiles.append(fileName)
                        elif cmd == "rename":
                            renameFrom = fileName
                        elif cmd == "to" and renameFrom != "":
                            renamedFiles.append((renameFrom, fileName))
                            renameFrom = ""
                        else:
                            cmd = ""
        if reverse:
            print "patch -R -p0 < %s" % list[0]
            for f in addedFiles: print "%s drop -e %s" % (mtncmd, f)
            for f in addedDirs: print "%s drop -e %s" % (mtncmd, f)
            for fold,fnew in renamedFiles: print "%s rename -e %s %s" % 
(mtncmd, fnew, fold)
            for f in droppedDirs: print "%s revert %s" % (mtncmd, f)
            for f in droppedFiles: print "%s revert %s" % (mtncmd, f)
        else:
            print "patch -p0 < %s" % list[0]
            for f in droppedFiles: print "%s drop -e %s" % (mtncmd, f)
            for f in droppedDirs: print "%s drop -e %s" % (mtncmd, f)
            for fold,fnew in renamedFiles: print "%s rename -e %s %s" % 
(mtncmd, fold, fnew)
            for f in addedDirs: print "%s add %s" % (mtncmd, f)
            for f in addedFiles: print "%s add %s" % (mtncmd, f)

if __name__ == "__main__":
    sys.exit(main())

reply via email to

[Prev in Thread] Current Thread [Next in Thread]