3
from patches import parse_patches
9
7
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):
10
if len(args) == 2 and args[1] == '--bzr-usage':
13
elif len(args) == 2 and args[1] == '--bzr-help':
14
print 'Shelve a patch, you can get it back later with unshelve.'
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')]
19
raise Exception("Don't understand args %s" % args)
24
root = run_bzr('root')[0].strip()
25
shelf = os.path.join(root, '.bzr-shelf')
79
raise Exception("No shelf found in '%s'" % tree_root())
27
if not os.path.exists(shelf):
28
raise Exception("No shelf found in '%s'" % shelf)
81
30
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')
32
print >>sys.stderr, "Reapplying shelved patches"
33
pipe = os.popen('patch -d %s -s -p0' % root, 'w')
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:
47
diff_lines = run_bzr('diff')
48
patch_list = patches.parse_patches(diff_lines.__iter__())
49
to_shelve = prompt_user(patch_list)
51
if len(to_shelve) == 0:
118
52
print >>sys.stderr, 'Nothing to shelve'
55
root = run_bzr('root')[0].strip()
56
shelf = os.path.join(root, '.bzr-shelf')
122
57
print >>sys.stderr, "Saving shelved patches to", shelf
123
58
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:
60
for patch in to_shelve:
128
61
shelf.write(str(patch))
154
87
raise Exception("Failed running bzr")
90
def prompt_user(patch_list):
92
for patch in patch_list:
93
total += len(patch.hunks)
100
for patch in patch_list:
101
if patch.oldname != patch.newname:
102
name = "%s -> %s" % (patch.oldname, patch.newname)
106
hunks = patch.hunks[:]
111
out.write('Shelve this change? (%d of %d) [yn] ' % (i, total))
112
line = inp.readline().strip().lower()
113
if line == 'y' or line == 'yes':
115
elif line == 'n' or line == 'no':
116
patch.hunks.remove(hunk)
121
if len(patch.hunks) > 0:
122
to_shelve.append(patch)
157
126
class cmd_shelve(Command):
158
127
"""Temporarily remove some changes from the current tree.
159
128
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
134
class cmd_unshelve(Command):
171
135
"""Restore previously-shelved changes to the current tree.
175
139
return unshelve()
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)