3
from patches import parse_patches
9
from bzrlib.commands import Command
10
from bzrlib.branch import Branch
13
name = os.path.basename(args.pop(0))
15
if name not in ['shelve', 'unshelve']:
16
raise Exception("Unknown command name '%s'" % name)
19
if args[0] == '--bzr-usage':
22
elif args[0] == '--bzr-help':
23
print 'Shelve a patch, you can get it back later with unshelve.'
26
raise Exception("Don't understand args %s" % args)
34
return run_bzr('root')[0].strip()
36
def shelf_suffix(index):
49
stem = os.path.join(tree_root(), '.bzr-shelf')
50
for end in name_sequence():
52
if not os.path.exists(name):
56
stem = os.path.join(tree_root(), '.bzr-shelf')
57
shelves = glob.glob(stem)
58
shelves.extend(glob.glob(stem + '-*'))
59
def shelf_index(name):
62
return int(name[len(stem)+1:])
63
shelvenums = [shelf_index(f) for f in shelves]
66
if len(shelvenums) == 0:
68
return stem + shelf_suffix(shelvenums[-1])
70
def get_shelf_message(shelf):
72
if not shelf.startswith(prefix):
74
return shelf[len(prefix):shelf.index('\n')]
80
raise Exception("No shelf found in '%s'" % tree_root())
82
patch = open(shelf, 'r').read()
84
print >>sys.stderr, "Reapplying shelved patches",
85
message = get_shelf_message(patch)
86
if message is not None:
87
print >>sys.stderr, ' "%s"' % message
89
print >>sys.stderr, ""
90
pipe = os.popen('patch -d %s -s -p0' % tree_root(), 'w')
94
if pipe.close() is not None:
95
raise Exception("Failed running patch!")
98
print 'Diff status is now:'
99
os.system('bzr diff | diffstat')
103
class QuitException(Exception):
106
def shelve(message = None, revision = None, file_list = None):
108
if revision is not None:
109
cmd.extend(['--revision', str(revision[0])])
110
if file_list is not None:
111
cmd.extend(file_list)
112
patches = parse_patches(run_bzr(cmd))
114
patches = HunkSelector(patches).select()
115
except QuitException:
118
if len(patches) == 0:
119
print >>sys.stderr, 'Nothing to shelve'
123
print >>sys.stderr, "Saving shelved patches to", shelf
124
shelf = open(shelf, 'a')
125
if message is not None:
126
assert '\n' not in message
127
shelf.write("# shelf: %s\n" % message)
128
for patch in patches:
129
shelf.write(str(patch))
132
os.fsync(shelf.fileno())
135
print >>sys.stderr, "Reverting shelved patches"
136
pipe = os.popen('patch -d %s -sR -p0' % tree_root(), 'w')
137
for patch in patches:
138
pipe.write(str(patch))
141
if pipe.close() is not None:
142
raise Exception("Failed running patch!")
144
print 'Diff status is now:'
145
os.system('bzr diff | diffstat')
150
if type(args) is str:
152
pipe = os.popen('bzr %s' % string.join(args, ' '), 'r')
153
lines = pipe.readlines()
154
if pipe.close() is not None:
155
raise Exception("Failed running bzr")
158
class cmd_shelve(Command):
159
"""Temporarily remove some changes from the current tree.
160
Use 'unshelve' to restore these changes.
162
If filenames are specified, only changes to those files will be unshelved.
163
If a revision is specified, all changes since that revision will may be
166
takes_args = ['file*']
167
takes_options = ['message', 'revision']
168
def run(self, file_list=None, message=None, revision=None):
170
if revision is not None and revision:
171
if file_list is not None and len(file_list) > 0:
172
branchdir = file_list[0]
175
b = Branch.open_containing(branchdir)
176
revision_list = ["revid:" + revision[0].in_history(b).rev_id]
178
return shelve(message=message, file_list=file_list,
179
revision=revision_list)
181
class cmd_unshelve(Command):
182
"""Restore previously-shelved changes to the current tree.
190
def __init__(self, char, action, help, default=False):
193
self.default = default
197
Option('n', 'shelve', 'shelve this change for the moment.',
199
Option('y', 'keep', 'keep this change in your tree.'),
200
Option('d', 'done', 'done, skip to the end.'),
201
Option('i', 'invert', 'invert the current selection of all hunks.'),
202
Option('s', 'status', 'show status of hunks.'),
203
Option('q', 'quit', 'quit')
207
Option('y', 'continue', 'proceed to shelve selected changes.',
209
Option('r', 'restart', 'restart the hunk selection loop.'),
210
Option('s', 'status', 'show status of hunks.'),
211
Option('i', 'invert', 'invert the current selection of all hunks.'),
212
Option('q', 'quit', 'quit')
215
def __init__(self, patches):
216
self.patches = patches
218
for patch in patches:
219
for hunk in patch.hunks:
220
# everything's shelved by default
222
self.total_hunks += 1
224
def __get_option(self, char):
225
for opt in self.standard_options:
228
raise Exception('Option "%s" not found!' % char)
230
def __select_loop(self):
232
for patch in self.patches:
235
while i < len(patch.hunks):
236
hunk = patch.hunks[i]
238
print patch.get_header(), hunk
242
prompt = 'Keep this change? (%d of %d)' \
243
% (j, self.total_hunks)
246
self.__get_option('n').default = True
247
self.__get_option('y').default = False
249
self.__get_option('n').default = False
250
self.__get_option('y').default = True
252
action = self.__ask_user(prompt, self.standard_options)
255
hunk.selected = False
256
elif action == 'shelve':
258
elif action == 'done':
260
elif action == 'invert':
261
self.__invert_selection()
264
elif action == 'status':
267
elif action == 'quit':
274
if self.total_hunks == 0:
279
if not self.__select_loop():
284
prompt = "Shelve these changes, or restart?"
285
action = self.__ask_user(prompt, self.end_options)
287
if action == 'continue':
290
elif action == 'quit':
292
elif action == 'status':
294
elif action == 'invert':
295
self.__invert_selection()
296
elif action == 'restart':
300
for patch in self.patches:
302
for hunk in patch.hunks:
308
for patch in self.patches:
315
def __invert_selection(self):
316
for patch in self.patches:
317
for hunk in patch.hunks:
318
if hunk.__dict__.has_key('selected'):
319
hunk.selected = not hunk.selected
323
def __show_status(self):
325
for patch in self.patches:
326
print ' %s' % patch.oldname
329
for hunk in patch.hunks:
335
print ' %d hunks to be shelved' % shelve
336
print ' %d hunks to be kept' % keep
340
fd = sys.stdin.fileno()
341
settings = termios.tcgetattr(fd)
344
ch = sys.stdin.read(1)
346
termios.tcsetattr(fd, termios.TCSADRAIN, settings)
349
def __ask_user(self, prompt, options):
351
sys.stdout.write(prompt)
352
sys.stdout.write(' [')
356
sys.stdout.write(opt.char)
357
sys.stdout.write('?] (%s): ' % default.char)
359
response = self.__getchar()
361
# default, which we see as newline, is 'n'
362
if response in ['\n', '\r', '\r\n']:
363
response = default.char
365
print response # because echo is off
368
if opt.char == response:
372
print ' %s - %s' % (opt.char, opt.help)