3
from patches import parse_patches
8
from bzrlib.commands import Command
9
from bzrlib.branch import Branch
10
from bzrlib import DEFAULT_IGNORE
12
DEFAULT_IGNORE.append('./.bzr-shelf*')
15
name = os.path.basename(args.pop(0))
17
if name not in ['shelve', 'unshelve']:
18
raise Exception("Unknown command name '%s'" % name)
21
if args[0] == '--bzr-usage':
24
elif args[0] == '--bzr-help':
25
print 'Shelve a patch, you can get it back later with unshelve.'
28
raise Exception("Don't understand args %s" % args)
36
return run_bzr('root')[0].strip()
38
def shelf_suffix(index):
51
stem = os.path.join(tree_root(), '.bzr-shelf')
52
for end in name_sequence():
54
if not os.path.exists(name):
58
stem = os.path.join(tree_root(), '.bzr-shelf')
59
shelves = glob.glob(stem)
60
shelves.extend(glob.glob(stem + '-*'))
61
def shelf_index(name):
64
return int(name[len(stem)+1:])
65
shelvenums = [shelf_index(f) for f in shelves]
68
if len(shelvenums) == 0:
70
return stem + shelf_suffix(shelvenums[-1])
72
def get_shelf_message(shelf):
74
if not shelf.startswith(prefix):
76
return shelf[len(prefix):shelf.index('\n')]
82
raise Exception("No shelf found in '%s'" % tree_root())
84
patch = open(shelf, 'r').read()
86
print >>sys.stderr, "Reapplying shelved patches",
87
message = get_shelf_message(patch)
88
if message is not None:
89
print >>sys.stderr, ' "%s"' % message
91
print >>sys.stderr, ""
92
pipe = os.popen('patch -d %s -s -p0' % tree_root(), 'w')
96
if pipe.close() is not None:
97
raise Exception("Failed running patch!")
100
print 'Diff status is now:'
101
os.system('bzr diff | diffstat')
105
class QuitException(Exception):
108
def shelve(message = None, revision = None, file_list = None):
110
if revision is not None:
111
cmd.extend(['--revision', str(revision[0])])
112
if file_list is not None:
113
cmd.extend(file_list)
114
patches = parse_patches(run_bzr(cmd))
116
patches = HunkSelector(patches).select()
117
except QuitException:
120
if len(patches) == 0:
121
print >>sys.stderr, 'Nothing to shelve'
125
print >>sys.stderr, "Saving shelved patches to", shelf
126
shelf = open(shelf, 'a')
127
if message is not None:
128
assert '\n' not in message
129
shelf.write("# shelf: %s\n" % message)
130
for patch in patches:
131
shelf.write(str(patch))
134
os.fsync(shelf.fileno())
137
print >>sys.stderr, "Reverting shelved patches"
138
pipe = os.popen('patch -d %s -sR -p0' % tree_root(), 'w')
139
for patch in patches:
140
pipe.write(str(patch))
143
if pipe.close() is not None:
144
raise Exception("Failed running patch!")
146
print 'Diff status is now:'
147
os.system('bzr diff | diffstat')
152
if type(args) is str:
154
pipe = os.popen('bzr %s' % string.join(args, ' '), 'r')
155
lines = pipe.readlines()
156
if pipe.close() is not None:
157
raise Exception("Failed running bzr")
160
class cmd_shelve(Command):
161
"""Temporarily remove some changes from the current tree.
162
Use 'unshelve' to restore these changes.
164
If filenames are specified, only changes to those files will be unshelved.
165
If a revision is specified, all changes since that revision will may be
168
takes_args = ['file*']
169
takes_options = ['message', 'revision']
170
def run(self, file_list=None, message=None, revision=None):
172
if revision is not None and revision:
173
if file_list is not None and len(file_list) > 0:
174
branchdir = file_list[0]
177
b = Branch.open_containing(branchdir)[0]
178
revision_list = ["revid:" + revision[0].in_history(b).rev_id]
180
return shelve(message=message, file_list=file_list,
181
revision=revision_list)
183
class cmd_unshelve(Command):
184
"""Restore previously-shelved changes to the current tree.
192
def __init__(self, char, action, help, default=False):
195
self.default = default
199
Option('n', 'shelve', 'shelve this change for the moment.',
201
Option('y', 'keep', 'keep this change in your tree.'),
202
Option('d', 'done', 'done, skip to the end.'),
203
Option('i', 'invert', 'invert the current selection of all hunks.'),
204
Option('s', 'status', 'show status of hunks.'),
205
Option('q', 'quit', 'quit')
209
Option('y', 'continue', 'proceed to shelve selected changes.',
211
Option('r', 'restart', 'restart the hunk selection loop.'),
212
Option('s', 'status', 'show status of hunks.'),
213
Option('i', 'invert', 'invert the current selection of all hunks.'),
214
Option('q', 'quit', 'quit')
217
def __init__(self, patches):
218
self.patches = patches
220
for patch in patches:
221
for hunk in patch.hunks:
222
# everything's shelved by default
224
self.total_hunks += 1
226
def __get_option(self, char):
227
for opt in self.standard_options:
230
raise Exception('Option "%s" not found!' % char)
232
def __select_loop(self):
234
for patch in self.patches:
237
while i < len(patch.hunks):
238
hunk = patch.hunks[i]
240
print patch.get_header(), hunk
244
prompt = 'Keep this change? (%d of %d)' \
245
% (j, self.total_hunks)
248
self.__get_option('n').default = True
249
self.__get_option('y').default = False
251
self.__get_option('n').default = False
252
self.__get_option('y').default = True
254
action = self.__ask_user(prompt, self.standard_options)
257
hunk.selected = False
258
elif action == 'shelve':
260
elif action == 'done':
262
elif action == 'invert':
263
self.__invert_selection()
266
elif action == 'status':
269
elif action == 'quit':
276
if self.total_hunks == 0:
281
if not self.__select_loop():
286
prompt = "Shelve these changes, or restart?"
287
action = self.__ask_user(prompt, self.end_options)
289
if action == 'continue':
292
elif action == 'quit':
294
elif action == 'status':
296
elif action == 'invert':
297
self.__invert_selection()
298
elif action == 'restart':
302
for patch in self.patches:
304
for hunk in patch.hunks:
310
for patch in self.patches:
317
def __invert_selection(self):
318
for patch in self.patches:
319
for hunk in patch.hunks:
320
if hunk.__dict__.has_key('selected'):
321
hunk.selected = not hunk.selected
325
def __show_status(self):
327
for patch in self.patches:
328
print ' %s' % patch.oldname
331
for hunk in patch.hunks:
337
print ' %d hunks to be shelved' % shelve
338
print ' %d hunks to be kept' % keep
341
if sys.platform != "win32":
345
fd = sys.stdin.fileno()
346
settings = termios.tcgetattr(fd)
349
ch = sys.stdin.read(1)
351
termios.tcsetattr(fd, termios.TCSADRAIN, settings)
356
return msvcrt.getche()
358
def __ask_user(self, prompt, options):
360
sys.stdout.write(prompt)
361
sys.stdout.write(' [')
365
sys.stdout.write(opt.char)
366
sys.stdout.write('?] (%s): ' % default.char)
368
response = self.__getchar()
370
# default, which we see as newline, is 'n'
371
if response in ['\n', '\r', '\r\n']:
372
response = default.char
374
print response # because echo is off
377
if opt.char == response:
381
print ' %s - %s' % (opt.char, opt.help)