~abentley/bzrtools/bzrtools.dev

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/python

import patches
import os
import sys
import string
from bzrlib.commands import Command

def parse_args(args):
    if len(args) == 2 and args[1] == '--bzr-usage':
        print '\n'
        return True
    elif len(args) == 2 and args[1] == '--bzr-help':
        print 'Shelve a patch, you can get it back later with unshelve.'
        return True
    elif len(args) == 1:
        pass
    else:
        raise Exception("Don't understand args %s" % args)

    return False

def unshelve():
    root = run_bzr('root')[0].strip()
    shelf = os.path.join(root, '.bzr-shelf')

    if not os.path.exists(shelf):
        raise Exception("No shelf found in '%s'" % shelf)

    patch = open(shelf, 'r').read()

    print >>sys.stderr, "Reapplying shelved patches"
    pipe = os.popen('patch -d %s -s -p0' % root, 'w')
    pipe.write(patch)
    pipe.flush()

    if pipe.close() is not None:
        raise Exception("Failed running patch!")

    os.remove(shelf)
    print 'Diff status is now:'
    os.system('bzr diff | diffstat')

    return True

def shelve():
    diff_lines = run_bzr('diff')
    patch_list = patches.parse_patches(diff_lines.__iter__())
    to_shelve = prompt_user(patch_list)

    if len(to_shelve) == 0:
        print >>sys.stderr, 'Nothing to shelve'
        return True

    root = run_bzr('root')[0].strip()
    shelf = os.path.join(root, '.bzr-shelf')
    print >>sys.stderr, "Saving shelved patches to", shelf
    shelf = open(shelf, 'a')

    for patch in to_shelve:
        shelf.write(str(patch))

    shelf.flush()
    os.fsync(shelf.fileno())
    shelf.close()

    print >>sys.stderr, "Reverting shelved patches"
    pipe = os.popen('patch -d %s -sR -p0' % root, 'w')
    for patch in to_shelve:
       pipe.write(str(patch))
    pipe.flush()

    if pipe.close() is not None:
        raise Exception("Failed running patch!")

    print 'Diff status is now:'
    os.system('bzr diff | diffstat')

    return True

def run_bzr(args):
    if type(args) is str:
        args = [ args ]
    pipe = os.popen('bzr %s' % string.join(args, ' '), 'r')
    lines = pipe.readlines()
    if pipe.close() is not None:
        raise Exception("Failed running bzr")
    return lines

def prompt_user(patch_list):
    total = 0
    for patch in patch_list:
        total += len(patch.hunks)

    out = sys.stdout
    inp = sys.stdin

    to_shelve = []
    i = 1
    for patch in patch_list:
        if patch.oldname != patch.newname:
            name = "%s -> %s" % (patch.oldname, patch.newname)
        else:
            name = patch.oldname

        hunks = patch.hunks[:]
        for hunk in hunks:
            print name
            print hunk
            while True:
                out.write('Shelve this change? (%d of %d) [yn] ' % (i, total))
                line = inp.readline().strip().lower()
                if line == 'y' or line == 'yes':
                    break
                elif line == 'n' or line == 'no':
                    patch.hunks.remove(hunk)
                    break

            i += 1

        if len(patch.hunks) > 0:
            to_shelve.append(patch)

    return to_shelve

class cmd_shelve(Command):
    """Temporarily remove some changes from the current tree.
    Use 'unshelve' to restore these changes.
    """

    def run(self):
        return shelve()

class cmd_unshelve(Command):
    """Restore previously-shelved changes to the current tree.
    See also 'shelve'.
    """
    def run(self):
        return unshelve()