10
name = os.path.basename(args.pop(0))
12
if name not in ['shelve', 'unshelve']:
13
raise Exception("Unknown command name '%s'" % name)
16
if args[0] == '--bzr-usage':
19
elif args[0] == '--bzr-help':
20
print 'Shelve a patch, you can get it back later with unshelve.'
23
raise Exception("Don't understand args %s" % args)
31
root = run_bzr('root')[0].strip()
32
shelf = os.path.join(root, '.bzr-shelf')
34
if not os.path.exists(shelf):
35
raise Exception("No shelf found in '%s'" % shelf)
37
patch = open(shelf, 'r').read()
39
print >>sys.stderr, "Reapplying shelved patches"
40
pipe = os.popen('patch -d %s -s -p0' % root, 'w')
44
if pipe.close() is not None:
45
raise Exception("Failed running patch!")
48
print 'Diff status is now:'
49
os.system('bzr diff | diffstat')
9
from bzrlib.commands import Command
10
from bzrlib.branch import Branch
11
from bzrlib import DEFAULT_IGNORE
12
from hunk_selector import HunkSelector
13
from diffstat import DiffStat
14
from subprocess import Popen, PIPE
16
DEFAULT_IGNORE.append('./.bzr-shelf*')
53
18
class QuitException(Exception):
57
patches = parse_patches(run_bzr('diff'))
59
patches = HunkSelector(patches).select()
64
print >>sys.stderr, 'Nothing to shelve'
67
root = run_bzr('root')[0].strip()
68
shelf = os.path.join(root, '.bzr-shelf')
69
print >>sys.stderr, "Saving shelved patches to", shelf
70
shelf = open(shelf, 'a')
73
shelf.write(str(patch))
76
os.fsync(shelf.fileno())
79
print >>sys.stderr, "Reverting shelved patches"
80
pipe = os.popen('patch -d %s -sR -p0' % root, 'w')
82
pipe.write(str(patch))
85
if pipe.close() is not None:
86
raise Exception("Failed running patch!")
88
print 'Diff status is now:'
89
os.system('bzr diff | diffstat')
96
pipe = os.popen('bzr %s' % string.join(args, ' '), 'r')
97
lines = pipe.readlines()
98
if pipe.close() is not None:
99
raise Exception("Failed running bzr")
105
def __init__(self, char, action, help, default=False):
108
self.default = default
112
Option('n', 'shelve', 'shelve this change for the moment.',
114
Option('y', 'keep', 'keep this change in your tree.'),
115
Option('d', 'done', 'done, skip to the end.'),
116
Option('i', 'invert', 'invert the current selection of all hunks.'),
117
Option('s', 'status', 'show status of hunks.'),
118
Option('q', 'quit', 'quit')
122
Option('y', 'continue', 'proceed to shelve selected changes.',
124
Option('r', 'restart', 'restart the hunk selection loop.'),
125
Option('s', 'status', 'show status of hunks.'),
126
Option('i', 'invert', 'invert the current selection of all hunks.'),
127
Option('q', 'quit', 'quit')
130
def __init__(self, patches):
131
self.patches = patches
133
for patch in patches:
134
for hunk in patch.hunks:
135
# everything's shelved by default
137
self.total_hunks += 1
139
def __get_option(self, char):
140
for opt in self.standard_options:
143
raise Exception('Option "%s" not found!' % char)
145
def __select_loop(self):
147
for patch in self.patches:
22
def __init__(self, location):
23
self.branch = Branch.open_containing(location)[0]
25
def shelf_suffix(self, index):
150
while i < len(patch.hunks):
151
hunk = patch.hunks[i]
153
print patch.get_header(), hunk
157
prompt = 'Keep this change? (%d of %d)' \
158
% (j, self.total_hunks)
161
self.__get_option('n').default = True
162
self.__get_option('y').default = False
164
self.__get_option('n').default = False
165
self.__get_option('y').default = True
167
action = self.__ask_user(prompt, self.standard_options)
170
hunk.selected = False
171
elif action == 'shelve':
173
elif action == 'done':
175
elif action == 'invert':
176
self.__invert_selection()
179
elif action == 'status':
182
elif action == 'quit':
189
if self.total_hunks == 0:
194
if not self.__select_loop():
199
prompt = "Shelve these changes, or restart?"
200
action = self.__ask_user(prompt, self.end_options)
202
if action == 'continue':
205
elif action == 'quit':
207
elif action == 'status':
209
elif action == 'invert':
210
self.__invert_selection()
211
elif action == 'restart':
215
for patch in self.patches:
217
for hunk in patch.hunks:
223
for patch in self.patches:
230
def __invert_selection(self):
231
for patch in self.patches:
232
for hunk in patch.hunks:
233
if hunk.__dict__.has_key('selected'):
234
hunk.selected = not hunk.selected
238
def __show_status(self):
240
for patch in self.patches:
241
print ' %s' % patch.oldname
244
for hunk in patch.hunks:
250
print ' %d hunks to be shelved' % shelve
251
print ' %d hunks to be kept' % keep
255
fd = sys.stdin.fileno()
256
settings = termios.tcgetattr(fd)
259
ch = sys.stdin.read(1)
261
termios.tcsetattr(fd, termios.TCSADRAIN, settings)
264
def __ask_user(self, prompt, options):
266
sys.stdout.write(prompt)
267
sys.stdout.write(' [')
271
sys.stdout.write(opt.char)
272
sys.stdout.write('?] (%s): ' % default.char)
274
response = self.__getchar()
276
# default, which we see as newline, is 'n'
277
if response in ['\n', '\r', '\r\n']:
278
response = default.char
280
print response # because echo is off
283
if opt.char == response:
287
print ' %s - %s' % (opt.char, opt.help)
35
yield self.shelf_suffix(i)
38
stem = os.path.join(self.branch.base, '.bzr-shelf')
39
for end in name_sequence():
41
if not os.path.exists(name):
45
stem = os.path.join(self.branch.base, '.bzr-shelf')
46
shelves = glob.glob(stem)
47
shelves.extend(glob.glob(stem + '-*'))
48
def shelf_index(name):
51
return int(name[len(stem)+1:])
52
shelvenums = [shelf_index(f) for f in shelves]
55
if len(shelvenums) == 0:
57
return stem + self.shelf_suffix(shelvenums[-1])
59
def get_shelf_message(self, shelf):
61
if not shelf.startswith(prefix):
63
return shelf[len(prefix):shelf.index('\n')]
66
shelf = self.last_shelf()
69
raise Exception("No shelf found in '%s'" % self.branch.base)
71
patch = open(shelf, 'r').read()
73
print >>sys.stderr, "Reapplying shelved patches",
74
message = self.get_shelf_message(patch)
75
if message is not None:
76
print >>sys.stderr, ' "%s"' % message
78
print >>sys.stderr, ""
79
run_patch(self.branch.base, (patch,))
82
diff_stat = DiffStat(self.get_patches(None, None))
83
print 'Diff status is now:\n', diff_stat
87
def get_patches(self, revision, file_list):
88
from StringIO import StringIO
89
from bzrlib.diff import show_diff
91
show_diff(self.branch, revision, specific_files=file_list, output=out)
93
return out.readlines()
95
def shelve(self, all_hunks=False, message=None, revision=None,
97
patches = parse_patches(self.get_patches(revision, file_list))
101
patches = HunkSelector(patches).select()
102
except QuitException:
105
if len(patches) == 0:
106
print >>sys.stderr, 'Nothing to shelve'
109
shelf = self.next_shelf()
110
print >>sys.stderr, "Saving shelved patches to", shelf
111
shelf = open(shelf, 'a')
112
if message is not None:
113
assert '\n' not in message
114
shelf.write("# shelf: %s\n" % message)
115
for patch in patches:
116
shelf.write(str(patch))
119
os.fsync(shelf.fileno())
122
print >>sys.stderr, "Reverting shelved patches"
123
run_patch(self.branch.base, patches, reverse=True)
125
diff_stat = DiffStat(self.get_patches(None, None))
126
print 'Diff status is now:\n', diff_stat
130
def run_patch(branch_base, patches, reverse=False):
131
args = ['patch', '-d', branch_base, '-s', '-p0', '-f']
134
process = Popen(args, stdin=PIPE)
135
for patch in patches:
136
process.stdin.write(str(patch))
137
process.stdin.close()
138
result = process.wait()
139
if result not in (0, 1):
140
raise Exception("Error applying patches")