3
from patches import parse_patches
9
from bzrlib.commands import Command
10
from bzrlib.branch import Branch
11
from bzrlib import DEFAULT_IGNORE
13
DEFAULT_IGNORE.append('./.bzr-shelf*')
16
name = os.path.basename(args.pop(0))
18
if name not in ['shelve', 'unshelve']:
19
raise Exception("Unknown command name '%s'" % name)
22
if args[0] == '--bzr-usage':
25
elif args[0] == '--bzr-help':
26
print 'Shelve a patch, you can get it back later with unshelve.'
29
raise Exception("Don't understand args %s" % args)
37
return run_bzr('root')[0].strip()
39
def shelf_suffix(index):
52
stem = os.path.join(tree_root(), '.bzr-shelf')
53
for end in name_sequence():
55
if not os.path.exists(name):
59
stem = os.path.join(tree_root(), '.bzr-shelf')
60
shelves = glob.glob(stem)
61
shelves.extend(glob.glob(stem + '-*'))
62
def shelf_index(name):
65
return int(name[len(stem)+1:])
66
shelvenums = [shelf_index(f) for f in shelves]
69
if len(shelvenums) == 0:
71
return stem + shelf_suffix(shelvenums[-1])
73
def get_shelf_message(shelf):
75
if not shelf.startswith(prefix):
77
return shelf[len(prefix):shelf.index('\n')]
83
raise Exception("No shelf found in '%s'" % tree_root())
85
patch = open(shelf, 'r').read()
87
print >>sys.stderr, "Reapplying shelved patches",
88
message = get_shelf_message(patch)
89
if message is not None:
90
print >>sys.stderr, ' "%s"' % message
92
print >>sys.stderr, ""
93
pipe = os.popen('patch -d %s -s -p0' % tree_root(), 'w')
97
if pipe.close() is not None:
98
raise Exception("Failed running patch!")
101
print 'Diff status is now:'
102
os.system('bzr diff | diffstat')
106
class QuitException(Exception):
109
def shelve(message = None, revision = None, file_list = None):
111
if revision is not None:
112
cmd.extend(['--revision', str(revision[0])])
113
if file_list is not None:
114
cmd.extend(file_list)
115
patches = parse_patches(run_bzr(cmd))
117
patches = HunkSelector(patches).select()
118
except QuitException:
121
if len(patches) == 0:
122
print >>sys.stderr, 'Nothing to shelve'
126
print >>sys.stderr, "Saving shelved patches to", shelf
127
shelf = open(shelf, 'a')
128
if message is not None:
129
assert '\n' not in message
130
shelf.write("# shelf: %s\n" % message)
131
for patch in patches:
132
shelf.write(str(patch))
135
os.fsync(shelf.fileno())
138
print >>sys.stderr, "Reverting shelved patches"
139
pipe = os.popen('patch -d %s -sR -p0' % tree_root(), 'w')
140
for patch in patches:
141
pipe.write(str(patch))
144
if pipe.close() is not None:
145
raise Exception("Failed running patch!")
147
print 'Diff status is now:'
148
os.system('bzr diff | diffstat')
153
if type(args) is str:
155
pipe = os.popen('bzr %s' % string.join(args, ' '), 'r')
156
lines = pipe.readlines()
157
if pipe.close() is not None:
158
raise Exception("Failed running bzr")
161
class cmd_shelve(Command):
162
"""Temporarily remove some changes from the current tree.
163
Use 'unshelve' to restore these changes.
165
If filenames are specified, only changes to those files will be unshelved.
166
If a revision is specified, all changes since that revision will may be
169
takes_args = ['file*']
170
takes_options = ['message', 'revision']
171
def run(self, file_list=None, message=None, revision=None):
173
if revision is not None and revision:
174
if file_list is not None and len(file_list) > 0:
175
branchdir = file_list[0]
178
b = Branch.open_containing(branchdir)
179
revision_list = ["revid:" + revision[0].in_history(b).rev_id]
181
return shelve(message=message, file_list=file_list,
182
revision=revision_list)
184
class cmd_unshelve(Command):
185
"""Restore previously-shelved changes to the current tree.
193
def __init__(self, char, action, help, default=False):
196
self.default = default
200
Option('n', 'shelve', 'shelve this change for the moment.',
202
Option('y', 'keep', 'keep this change in your tree.'),
203
Option('d', 'done', 'done, skip to the end.'),
204
Option('i', 'invert', 'invert the current selection of all hunks.'),
205
Option('s', 'status', 'show status of hunks.'),
206
Option('q', 'quit', 'quit')
210
Option('y', 'continue', 'proceed to shelve selected changes.',
212
Option('r', 'restart', 'restart the hunk selection loop.'),
213
Option('s', 'status', 'show status of hunks.'),
214
Option('i', 'invert', 'invert the current selection of all hunks.'),
215
Option('q', 'quit', 'quit')
218
def __init__(self, patches):
219
self.patches = patches
221
for patch in patches:
222
for hunk in patch.hunks:
223
# everything's shelved by default
225
self.total_hunks += 1
227
def __get_option(self, char):
228
for opt in self.standard_options:
231
raise Exception('Option "%s" not found!' % char)
233
def __select_loop(self):
235
for patch in self.patches:
238
while i < len(patch.hunks):
239
hunk = patch.hunks[i]
241
print patch.get_header(), hunk
245
prompt = 'Keep this change? (%d of %d)' \
246
% (j, self.total_hunks)
249
self.__get_option('n').default = True
250
self.__get_option('y').default = False
252
self.__get_option('n').default = False
253
self.__get_option('y').default = True
255
action = self.__ask_user(prompt, self.standard_options)
258
hunk.selected = False
259
elif action == 'shelve':
261
elif action == 'done':
263
elif action == 'invert':
264
self.__invert_selection()
267
elif action == 'status':
270
elif action == 'quit':
277
if self.total_hunks == 0:
282
if not self.__select_loop():
287
prompt = "Shelve these changes, or restart?"
288
action = self.__ask_user(prompt, self.end_options)
290
if action == 'continue':
293
elif action == 'quit':
295
elif action == 'status':
297
elif action == 'invert':
298
self.__invert_selection()
299
elif action == 'restart':
303
for patch in self.patches:
305
for hunk in patch.hunks:
311
for patch in self.patches:
318
def __invert_selection(self):
319
for patch in self.patches:
320
for hunk in patch.hunks:
321
if hunk.__dict__.has_key('selected'):
322
hunk.selected = not hunk.selected
326
def __show_status(self):
328
for patch in self.patches:
329
print ' %s' % patch.oldname
332
for hunk in patch.hunks:
338
print ' %d hunks to be shelved' % shelve
339
print ' %d hunks to be kept' % keep
343
fd = sys.stdin.fileno()
344
settings = termios.tcgetattr(fd)
347
ch = sys.stdin.read(1)
349
termios.tcsetattr(fd, termios.TCSADRAIN, settings)
352
def __ask_user(self, prompt, options):
354
sys.stdout.write(prompt)
355
sys.stdout.write(' [')
359
sys.stdout.write(opt.char)
360
sys.stdout.write('?] (%s): ' % default.char)
362
response = self.__getchar()
364
# default, which we see as newline, is 'n'
365
if response in ['\n', '\r', '\r\n']:
366
response = default.char
368
print response # because echo is off
371
if opt.char == response:
375
print ' %s - %s' % (opt.char, opt.help)