7
7
from errors import CommandError, PatchFailed
8
8
from hunk_selector import ShelveHunkSelector, UnshelveHunkSelector
9
9
from patchsource import PatchSource, FilePatchSource
10
from bzrlib.osutils import rename
12
11
class Shelf(object):
13
12
MESSAGE_PREFIX = "# Shelved patch: "
58
57
def delete(self, patch):
59
58
path = self.__path_from_user(patch)
60
rename(path, '%s~' % path)
62
def display(self, patch=None):
64
path = self.last_patch()
66
path = self.__path_from_user(patch)
61
def display(self, patch):
62
path = self.__path_from_user(patch)
67
63
sys.stdout.write(open(path).read())
82
78
def __path_from_user(self, patch_id):
84
80
patch_index = int(patch_id)
85
except (TypeError, ValueError):
86
82
raise CommandError("Invalid patch name '%s'" % patch_id)
88
84
path = self.__path(patch_index)
135
131
return patch[len(self.MESSAGE_PREFIX):patch.index('\n')]
137
def unshelve(self, patch_source, patch_name=None, all=False, force=False):
133
def unshelve(self, patch_source, all_hunks=False, force=False):
138
134
self._check_upgrade()
136
patch_name = self.last_patch()
140
138
if patch_name is None:
141
patch_path = self.last_patch()
143
patch_path = self.__path_from_user(patch_name)
145
if patch_path is None:
146
139
raise CommandError("No patch found on shelf %s" % self.name)
148
patches = FilePatchSource(patch_path).readpatches()
150
to_unshelve = patches
141
hunks = FilePatchSource(patch_name).readhunks()
153
to_unshelve, to_remain = UnshelveHunkSelector(patches).select()
146
to_unshelve, to_remain = UnshelveHunkSelector(hunks).select()
155
148
if len(to_unshelve) == 0:
156
149
raise CommandError('Nothing to unshelve')
158
message = self.get_patch_message(patch_path)
151
message = self.get_patch_message(patch_name)
159
152
if message is None:
160
153
message = "No message saved with patch."
161
154
self.log('Unshelving from %s/%s: "%s"\n' % \
162
(self.name, os.path.basename(patch_path), message))
155
(self.name, os.path.basename(patch_name), message))
165
158
self._run_patch(to_unshelve, dry_run=True)
166
159
self._run_patch(to_unshelve)
167
160
except PatchFailed:
169
self._run_patch(to_unshelve, strip=1, dry_run=True)
170
self._run_patch(to_unshelve, strip=1)
162
self._run_patch(to_unshelve, strip=0, dry_run=True)
163
self._run_patch(to_unshelve, strip=0)
171
164
except PatchFailed:
173
166
self.log('Warning: Unshelving failed, forcing as ' \
181
174
"longer applies cleanly to the working tree!")
183
176
# Backup the shelved patch
184
rename(patch_path, '%s~' % patch_path)
177
os.rename(patch_name, '%s~' % patch_name)
186
179
if len(to_remain) > 0:
187
f = open(patch_path, 'w')
188
for patch in to_remain:
180
f = open(patch_name, 'w')
181
for hunk in to_remain:
192
def shelve(self, patch_source, all=False, message=None):
185
def shelve(self, patch_source, all_hunks=False, message=None):
193
186
self._check_upgrade()
195
patches = patch_source.readpatches()
188
hunks = patch_source.readhunks()
200
to_shelve = ShelveHunkSelector(patches).select()[0]
193
to_shelve = ShelveHunkSelector(hunks).select()[0]
202
195
if len(to_shelve) == 0:
203
196
raise CommandError('Nothing to shelve')
206
199
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
207
200
message = "Changes shelved on %s" % timestamp
209
patch_path = self.next_patch()
202
patch_name = self.next_patch()
210
203
self.log('Shelving to %s/%s: "%s"\n' % \
211
(self.name, os.path.basename(patch_path), message))
204
(self.name, os.path.basename(patch_name), message))
213
f = open(patch_path, 'a')
206
patch = open(patch_name, 'a')
215
208
assert '\n' not in message
216
f.write("%s%s\n" % (self.MESSAGE_PREFIX, message))
218
for patch in to_shelve:
209
patch.write("%s%s\n" % (self.MESSAGE_PREFIX, message))
211
for hunk in to_shelve:
212
patch.write(str(hunk))
215
os.fsync(patch.fileno())
226
219
self._run_patch(to_shelve, reverse=True, dry_run=True)
227
220
self._run_patch(to_shelve, reverse=True)
228
221
except PatchFailed:
230
self._run_patch(to_shelve, reverse=True, strip=1, dry_run=True)
231
self._run_patch(to_shelve, reverse=True, strip=1)
223
self._run_patch(to_shelve, reverse=True, strip=0, dry_run=True)
224
self._run_patch(to_shelve, reverse=True, strip=0)
232
225
except PatchFailed:
233
226
raise CommandError("Failed removing shelved changes from the"
236
def _run_patch(self, patches, strip=0, reverse=False, dry_run=False):
229
def _run_patch(self, patches, strip=1, reverse=False, dry_run=False):
237
230
args = ['patch', '-d', self.base, '-s', '-p%d' % strip, '-f']
239
if sys.platform == "win32":
240
args.append('--binary')
243
232
args.append('-R')
316
305
self.log('Copied %s to %s/%s\n' % (os.path.basename(patch),
317
306
self.name, os.path.basename(new_path)))
318
rename(patch, patch + '~')
307
os.rename(patch, patch + '~')