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, revision = None, file_list = None):
107
if revision is not None:
108
cmd.extend(['--revision', str(revision[0])])
109
if file_list is not None:
110
cmd.extend(file_list)
111
patches = parse_patches(run_bzr(cmd))
113
patches = HunkSelector(patches).select()
114
except QuitException:
117
if len(patches) == 0:
118
print >>sys.stderr, 'Nothing to shelve'
122
print >>sys.stderr, "Saving shelved patches to", shelf
123
shelf = open(shelf, 'a')
124
if message is not None:
125
assert '\n' not in message
126
shelf.write("# shelf: %s\n" % message)
127
for patch in patches:
128
shelf.write(str(patch))
131
os.fsync(shelf.fileno())
134
print >>sys.stderr, "Reverting shelved patches"
135
pipe = os.popen('patch -d %s -sR -p0' % tree_root(), 'w')
136
for patch in patches:
137
pipe.write(str(patch))
140
if pipe.close() is not None:
141
raise Exception("Failed running patch!")
143
print 'Diff status is now:'
144
os.system('bzr diff | diffstat')
149
if type(args) is str:
151
pipe = os.popen('bzr %s' % string.join(args, ' '), 'r')
152
lines = pipe.readlines()
153
if pipe.close() is not None:
154
raise Exception("Failed running bzr")
157
class cmd_shelve(Command):
158
"""Temporarily remove some changes from the current tree.
159
Use 'unshelve' to restore these changes.
161
If filenames are specified, only changes to those files will be unshelved.
162
If a revision is specified, all changes since that revision will may be
165
takes_args = ['file*']
166
takes_options = ['message', 'revision']
167
def run(self, file_list=None, message=None, revision=None):
168
return shelve(message=message, file_list=file_list, revision=revision)
170
class cmd_unshelve(Command):
171
"""Restore previously-shelved changes to the current tree.
179
def __init__(self, char, action, help, default=False):
182
self.default = default
186
Option('n', 'shelve', 'shelve this change for the moment.',
188
Option('y', 'keep', 'keep this change in your tree.'),
189
Option('d', 'done', 'done, skip to the end.'),
190
Option('i', 'invert', 'invert the current selection of all hunks.'),
191
Option('s', 'status', 'show status of hunks.'),
192
Option('q', 'quit', 'quit')
196
Option('y', 'continue', 'proceed to shelve selected changes.',
198
Option('r', 'restart', 'restart the hunk selection loop.'),
199
Option('s', 'status', 'show status of hunks.'),
200
Option('i', 'invert', 'invert the current selection of all hunks.'),
201
Option('q', 'quit', 'quit')
204
def __init__(self, patches):
205
self.patches = patches
207
for patch in patches:
208
for hunk in patch.hunks:
209
# everything's shelved by default
211
self.total_hunks += 1
213
def __get_option(self, char):
214
for opt in self.standard_options:
217
raise Exception('Option "%s" not found!' % char)
219
def __select_loop(self):
221
for patch in self.patches:
224
while i < len(patch.hunks):
225
hunk = patch.hunks[i]
227
print patch.get_header(), hunk
231
prompt = 'Keep this change? (%d of %d)' \
232
% (j, self.total_hunks)
235
self.__get_option('n').default = True
236
self.__get_option('y').default = False
238
self.__get_option('n').default = False
239
self.__get_option('y').default = True
241
action = self.__ask_user(prompt, self.standard_options)
244
hunk.selected = False
245
elif action == 'shelve':
247
elif action == 'done':
249
elif action == 'invert':
250
self.__invert_selection()
253
elif action == 'status':
256
elif action == 'quit':
263
if self.total_hunks == 0:
268
if not self.__select_loop():
273
prompt = "Shelve these changes, or restart?"
274
action = self.__ask_user(prompt, self.end_options)
276
if action == 'continue':
279
elif action == 'quit':
281
elif action == 'status':
283
elif action == 'invert':
284
self.__invert_selection()
285
elif action == 'restart':
289
for patch in self.patches:
291
for hunk in patch.hunks:
297
for patch in self.patches:
304
def __invert_selection(self):
305
for patch in self.patches:
306
for hunk in patch.hunks:
307
if hunk.__dict__.has_key('selected'):
308
hunk.selected = not hunk.selected
312
def __show_status(self):
314
for patch in self.patches:
315
print ' %s' % patch.oldname
318
for hunk in patch.hunks:
324
print ' %d hunks to be shelved' % shelve
325
print ' %d hunks to be kept' % keep
329
fd = sys.stdin.fileno()
330
settings = termios.tcgetattr(fd)
333
ch = sys.stdin.read(1)
335
termios.tcsetattr(fd, termios.TCSADRAIN, settings)
338
def __ask_user(self, prompt, options):
340
sys.stdout.write(prompt)
341
sys.stdout.write(' [')
345
sys.stdout.write(opt.char)
346
sys.stdout.write('?] (%s): ' % default.char)
348
response = self.__getchar()
350
# default, which we see as newline, is 'n'
351
if response in ['\n', '\r', '\r\n']:
352
response = default.char
354
print response # because echo is off
357
if opt.char == response:
361
print ' %s - %s' % (opt.char, opt.help)