3
from patches import parse_patches
9
from bzrlib.commands import Command
12
name = os.path.basename(args.pop(0))
14
if name not in ['shelve', 'unshelve']:
15
raise Exception("Unknown command name '%s'" % name)
18
if args[0] == '--bzr-usage':
21
elif args[0] == '--bzr-help':
22
print 'Shelve a patch, you can get it back later with unshelve.'
25
raise Exception("Don't understand args %s" % args)
33
return run_bzr('root')[0].strip()
35
def shelf_suffix(index):
48
stem = os.path.join(tree_root(), '.bzr-shelf')
49
for end in name_sequence():
51
if not os.path.exists(name):
55
stem = os.path.join(tree_root(), '.bzr-shelf')
56
shelves = glob.glob(stem)
57
shelves.extend(glob.glob(stem + '-*'))
58
def shelf_index(name):
61
return int(name[len(stem)+1:])
62
shelvenums = [shelf_index(f) for f in shelves]
65
if len(shelvenums) == 0:
67
return stem + shelf_suffix(shelvenums[-1])
69
def get_shelf_message(shelf):
71
if not shelf.startswith(prefix):
73
return shelf[len(prefix):shelf.index('\n')]
79
raise Exception("No shelf found in '%s'" % tree_root())
81
patch = open(shelf, 'r').read()
83
print >>sys.stderr, "Reapplying shelved patches",
84
message = get_shelf_message(patch)
85
if message is not None:
86
print >>sys.stderr, ' "%s"' % message
88
print >>sys.stderr, ""
89
pipe = os.popen('patch -d %s -s -p0' % tree_root(), 'w')
93
if pipe.close() is not None:
94
raise Exception("Failed running patch!")
97
print 'Diff status is now:'
98
os.system('bzr diff | diffstat')
102
class QuitException(Exception):
105
def shelve(message = None):
106
patches = parse_patches(run_bzr('diff'))
108
patches = HunkSelector(patches).select()
109
except QuitException:
112
if len(patches) == 0:
113
print >>sys.stderr, 'Nothing to shelve'
117
print >>sys.stderr, "Saving shelved patches to", shelf
118
shelf = open(shelf, 'a')
119
if message is not None:
120
assert '\n' not in message
121
shelf.write("# shelf: %s\n" % message)
122
for patch in patches:
123
shelf.write(str(patch))
126
os.fsync(shelf.fileno())
129
print >>sys.stderr, "Reverting shelved patches"
130
pipe = os.popen('patch -d %s -sR -p0' % tree_root(), 'w')
131
for patch in patches:
132
pipe.write(str(patch))
135
if pipe.close() is not None:
136
raise Exception("Failed running patch!")
138
print 'Diff status is now:'
139
os.system('bzr diff | diffstat')
144
if type(args) is str:
146
pipe = os.popen('bzr %s' % string.join(args, ' '), 'r')
147
lines = pipe.readlines()
148
if pipe.close() is not None:
149
raise Exception("Failed running bzr")
152
class cmd_shelve(Command):
153
"""Temporarily remove some changes from the current tree.
154
Use 'unshelve' to restore these changes.
156
takes_options = ['message']
157
def run(self, message=None):
158
return shelve(message)
160
class cmd_unshelve(Command):
161
"""Restore previously-shelved changes to the current tree.
169
def __init__(self, char, action, help, default=False):
172
self.default = default
176
Option('n', 'shelve', 'shelve this change for the moment.',
178
Option('y', 'keep', 'keep this change in your tree.'),
179
Option('d', 'done', 'done, skip to the end.'),
180
Option('i', 'invert', 'invert the current selection of all hunks.'),
181
Option('s', 'status', 'show status of hunks.'),
182
Option('q', 'quit', 'quit')
186
Option('y', 'continue', 'proceed to shelve selected changes.',
188
Option('r', 'restart', 'restart the hunk selection loop.'),
189
Option('s', 'status', 'show status of hunks.'),
190
Option('i', 'invert', 'invert the current selection of all hunks.'),
191
Option('q', 'quit', 'quit')
194
def __init__(self, patches):
195
self.patches = patches
197
for patch in patches:
198
for hunk in patch.hunks:
199
# everything's shelved by default
201
self.total_hunks += 1
203
def __get_option(self, char):
204
for opt in self.standard_options:
207
raise Exception('Option "%s" not found!' % char)
209
def __select_loop(self):
211
for patch in self.patches:
214
while i < len(patch.hunks):
215
hunk = patch.hunks[i]
217
print patch.get_header(), hunk
221
prompt = 'Keep this change? (%d of %d)' \
222
% (j, self.total_hunks)
225
self.__get_option('n').default = True
226
self.__get_option('y').default = False
228
self.__get_option('n').default = False
229
self.__get_option('y').default = True
231
action = self.__ask_user(prompt, self.standard_options)
234
hunk.selected = False
235
elif action == 'shelve':
237
elif action == 'done':
239
elif action == 'invert':
240
self.__invert_selection()
243
elif action == 'status':
246
elif action == 'quit':
253
if self.total_hunks == 0:
258
if not self.__select_loop():
263
prompt = "Shelve these changes, or restart?"
264
action = self.__ask_user(prompt, self.end_options)
266
if action == 'continue':
269
elif action == 'quit':
271
elif action == 'status':
273
elif action == 'invert':
274
self.__invert_selection()
275
elif action == 'restart':
279
for patch in self.patches:
281
for hunk in patch.hunks:
287
for patch in self.patches:
294
def __invert_selection(self):
295
for patch in self.patches:
296
for hunk in patch.hunks:
297
if hunk.__dict__.has_key('selected'):
298
hunk.selected = not hunk.selected
302
def __show_status(self):
304
for patch in self.patches:
305
print ' %s' % patch.oldname
308
for hunk in patch.hunks:
314
print ' %d hunks to be shelved' % shelve
315
print ' %d hunks to be kept' % keep
319
fd = sys.stdin.fileno()
320
settings = termios.tcgetattr(fd)
323
ch = sys.stdin.read(1)
325
termios.tcsetattr(fd, termios.TCSADRAIN, settings)
328
def __ask_user(self, prompt, options):
330
sys.stdout.write(prompt)
331
sys.stdout.write(' [')
335
sys.stdout.write(opt.char)
336
sys.stdout.write('?] (%s): ' % default.char)
338
response = self.__getchar()
340
# default, which we see as newline, is 'n'
341
if response in ['\n', '\r', '\r\n']:
342
response = default.char
344
print response # because echo is off
347
if opt.char == response:
351
print ' %s - %s' % (opt.char, opt.help)