~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to shelf.py

  • Committer: Aaron Bentley
  • Date: 2005-07-27 17:57:32 UTC
  • Revision ID: abentley@panoramicfeedback.com-20050727175732-3637e3a9c1af9c33
Added iter_patched, handled files with no terminating newline

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
# Copyright (C) 2005 Michael Ellerman <michael@ellerman.id.au>
 
4
#
 
5
#    This program is free software; you can redistribute it and/or modify
 
6
#    it under the terms of the GNU General Public License as published by
 
7
#    the Free Software Foundation; either version 2 of the License, or
 
8
#    (at your option) any later version.
 
9
#
 
10
#    This program is distributed in the hope that it will be useful,
 
11
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
#    GNU General Public License for more details.
 
14
#
 
15
#    You should have received a copy of the GNU General Public License
 
16
#    along with this program; if not, write to the Free Software
 
17
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
import patches
 
20
import os
 
21
import sys
 
22
import string
 
23
from bzrlib.commands import Command
 
24
 
 
25
def parse_args(args):
 
26
    if len(args) == 2 and args[1] == '--bzr-usage':
 
27
        print '\n'
 
28
        return True
 
29
    elif len(args) == 2 and args[1] == '--bzr-help':
 
30
        print 'Shelve a patch, you can get it back later with unshelve.'
 
31
        return True
 
32
    elif len(args) == 1:
 
33
        pass
 
34
    else:
 
35
        raise Exception("Don't understand args %s" % args)
 
36
 
 
37
    return False
 
38
 
 
39
def unshelve():
 
40
    root = run_bzr('root')[0].strip()
 
41
    shelf = os.path.join(root, '.bzr-shelf')
 
42
 
 
43
    if not os.path.exists(shelf):
 
44
        raise Exception("No shelf found in '%s'" % shelf)
 
45
 
 
46
    patch = open(shelf, 'r').read()
 
47
 
 
48
    print >>sys.stderr, "Reapplying shelved patches"
 
49
    pipe = os.popen('patch -d %s -s -p0' % root, 'w')
 
50
    pipe.write(patch)
 
51
    pipe.flush()
 
52
 
 
53
    if pipe.close() is not None:
 
54
        raise Exception("Failed running patch!")
 
55
 
 
56
    os.remove(shelf)
 
57
    print 'Diff status is now:'
 
58
    os.system('bzr diff | diffstat')
 
59
 
 
60
    return True
 
61
 
 
62
def shelve():
 
63
    diff_lines = run_bzr('diff')
 
64
    patch_list = patches.parse_patches(diff_lines.__iter__())
 
65
    to_shelve = prompt_user(patch_list)
 
66
 
 
67
    if len(to_shelve) == 0:
 
68
        print >>sys.stderr, 'Nothing to shelve'
 
69
        return True
 
70
 
 
71
    root = run_bzr('root')[0].strip()
 
72
    shelf = os.path.join(root, '.bzr-shelf')
 
73
    print >>sys.stderr, "Saving shelved patches to", shelf
 
74
    shelf = open(shelf, 'a')
 
75
 
 
76
    for patch in to_shelve:
 
77
        shelf.write(str(patch))
 
78
 
 
79
    shelf.flush()
 
80
    os.fsync(shelf.fileno())
 
81
    shelf.close()
 
82
 
 
83
    print >>sys.stderr, "Reverting shelved patches"
 
84
    pipe = os.popen('patch -d %s -sR -p0' % root, 'w')
 
85
    for patch in to_shelve:
 
86
       pipe.write(str(patch))
 
87
    pipe.flush()
 
88
 
 
89
    if pipe.close() is not None:
 
90
        raise Exception("Failed running patch!")
 
91
 
 
92
    print 'Diff status is now:'
 
93
    os.system('bzr diff | diffstat')
 
94
 
 
95
    return True
 
96
 
 
97
def run_bzr(args):
 
98
    if type(args) is str:
 
99
        args = [ args ]
 
100
    pipe = os.popen('bzr %s' % string.join(args, ' '), 'r')
 
101
    lines = pipe.readlines()
 
102
    if pipe.close() is not None:
 
103
        raise Exception("Failed running bzr")
 
104
    return lines
 
105
 
 
106
def prompt_user(patch_list):
 
107
    total = 0
 
108
    for patch in patch_list:
 
109
        total += len(patch.hunks)
 
110
 
 
111
    out = sys.stdout
 
112
    inp = sys.stdin
 
113
 
 
114
    to_shelve = []
 
115
    i = 1
 
116
    for patch in patch_list:
 
117
        if patch.oldname != patch.newname:
 
118
            name = "%s -> %s" % (patch.oldname, patch.newname)
 
119
        else:
 
120
            name = patch.oldname
 
121
 
 
122
        hunks = patch.hunks[:]
 
123
        for hunk in hunks:
 
124
            print name
 
125
            print hunk
 
126
            while True:
 
127
                out.write('Shelve this change? (%d of %d) [yn] ' % (i, total))
 
128
                line = inp.readline().strip().lower()
 
129
                if line == 'y' or line == 'yes':
 
130
                    break
 
131
                elif line == 'n' or line == 'no':
 
132
                    patch.hunks.remove(hunk)
 
133
                    break
 
134
 
 
135
            i += 1
 
136
 
 
137
        if len(patch.hunks) > 0:
 
138
            to_shelve.append(patch)
 
139
 
 
140
    return to_shelve
 
141
 
 
142
class cmd_shelve(Command):
 
143
    """Temporarily remove some changes from the current tree.
 
144
    Use 'unshelve' to restore these changes.
 
145
    """
 
146
 
 
147
    def run(self):
 
148
        return shelve()
 
149
 
 
150
class cmd_unshelve(Command):
 
151
    """Restore previously-shelved changes to the current tree.
 
152
    See also 'shelve'.
 
153
    """
 
154
    def run(self):
 
155
        return unshelve()