~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to shelf.py

  • Committer: Robert Collins
  • Date: 2006-04-24 01:45:23 UTC
  • mto: (364.1.3 bzrtools)
  • mto: This revision was merged to the branch mainline in revision 366.
  • Revision ID: robertc@robertcollins.net-20060424014523-ef18f22034f17ec2
Backout debugging tweak to fai.py

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
1
3
import os
2
4
import sys
3
5
import subprocess
4
6
from datetime import datetime
5
 
from errors import CommandError, PatchFailed, PatchInvokeError
 
7
from errors import CommandError, PatchFailed
6
8
from hunk_selector import ShelveHunkSelector, UnshelveHunkSelector
7
9
from patchsource import PatchSource, FilePatchSource
8
 
from bzrlib.osutils import rename
9
10
 
10
11
class Shelf(object):
11
12
    MESSAGE_PREFIX = "# Shelved patch: "
55
56
 
56
57
    def delete(self, patch):
57
58
        path = self.__path_from_user(patch)
58
 
        rename(path, '%s~' % path)
 
59
        os.remove(path)
59
60
 
60
 
    def display(self, patch=None):
61
 
        if patch is None:
62
 
            path = self.last_patch()
63
 
        else:
64
 
            path = self.__path_from_user(patch)
 
61
    def display(self, patch):
 
62
        path = self.__path_from_user(patch)
65
63
        sys.stdout.write(open(path).read())
66
64
 
67
65
    def list(self):
80
78
    def __path_from_user(self, patch_id):
81
79
        try:
82
80
            patch_index = int(patch_id)
83
 
        except (TypeError, ValueError):
 
81
        except TypeError:
84
82
            raise CommandError("Invalid patch name '%s'" % patch_id)
85
83
 
86
84
        path = self.__path(patch_index)
132
130
            return None
133
131
        return patch[len(self.MESSAGE_PREFIX):patch.index('\n')]
134
132
 
135
 
    def unshelve(self, patch_source, patch_name=None, all=False, force=False,
136
 
                 no_color=False):
 
133
    def unshelve(self, patch_source, all_hunks=False, force=False):
137
134
        self._check_upgrade()
138
135
 
139
 
        if no_color is False:
140
 
            color = None
141
 
        else:
142
 
            color = False
 
136
        patch_name = self.last_patch()
 
137
 
143
138
        if patch_name is None:
144
 
            patch_path = self.last_patch()
145
 
        else:
146
 
            patch_path = self.__path_from_user(patch_name)
147
 
 
148
 
        if patch_path is None:
149
139
            raise CommandError("No patch found on shelf %s" % self.name)
150
140
 
151
 
        patches = FilePatchSource(patch_path).readpatches()
152
 
        if all:
153
 
            to_unshelve = patches
 
141
        hunks = FilePatchSource(patch_name).readhunks()
 
142
        if all_hunks:
 
143
            to_unshelve = hunks
154
144
            to_remain = []
155
145
        else:
156
 
            hs = UnshelveHunkSelector(patches, color)
157
 
            to_unshelve, to_remain = hs.select()
 
146
            to_unshelve, to_remain = UnshelveHunkSelector(hunks).select()
158
147
 
159
148
        if len(to_unshelve) == 0:
160
149
            raise CommandError('Nothing to unshelve')
161
150
 
162
 
        message = self.get_patch_message(patch_path)
 
151
        message = self.get_patch_message(patch_name)
163
152
        if message is None:
164
153
            message = "No message saved with patch."
165
154
        self.log('Unshelving from %s/%s: "%s"\n' % \
166
 
                (self.name, os.path.basename(patch_path), message))
 
155
                (self.name, os.path.basename(patch_name), message))
167
156
 
168
157
        try:
169
158
            self._run_patch(to_unshelve, dry_run=True)
170
159
            self._run_patch(to_unshelve)
171
160
        except PatchFailed:
172
161
            try:
173
 
                self._run_patch(to_unshelve, strip=1, dry_run=True)
174
 
                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)
175
164
            except PatchFailed:
176
165
                if force:
177
166
                    self.log('Warning: Unshelving failed, forcing as ' \
185
174
                    "longer applies cleanly to the working tree!")
186
175
 
187
176
        # Backup the shelved patch
188
 
        rename(patch_path, '%s~' % patch_path)
 
177
        os.rename(patch_name, '%s~' % patch_name)
189
178
 
190
179
        if len(to_remain) > 0:
191
 
            f = open(patch_path, 'w')
192
 
            for patch in to_remain:
193
 
                f.write(str(patch))
 
180
            f = open(patch_name, 'w')
 
181
            for hunk in to_remain:
 
182
                f.write(str(hunk))
194
183
            f.close()
195
184
 
196
 
    def shelve(self, patch_source, all=False, message=None, no_color=False):
 
185
    def shelve(self, patch_source, all_hunks=False, message=None):
197
186
        self._check_upgrade()
198
 
        if no_color is False:
199
 
            color = None
200
 
        else:
201
 
            color = False
202
 
 
203
 
        patches = patch_source.readpatches()
204
 
 
205
 
        if all:
206
 
            to_shelve = patches
207
 
        else:
208
 
            to_shelve = ShelveHunkSelector(patches, color).select()[0]
 
187
 
 
188
        hunks = patch_source.readhunks()
 
189
 
 
190
        if all_hunks:
 
191
            to_shelve = hunks
 
192
        else:
 
193
            to_shelve = ShelveHunkSelector(hunks).select()[0]
209
194
 
210
195
        if len(to_shelve) == 0:
211
196
            raise CommandError('Nothing to shelve')
214
199
            timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
215
200
            message = "Changes shelved on %s" % timestamp
216
201
 
217
 
        patch_path = self.next_patch()
 
202
        patch_name = self.next_patch()
218
203
        self.log('Shelving to %s/%s: "%s"\n' % \
219
 
                (self.name, os.path.basename(patch_path), message))
 
204
                (self.name, os.path.basename(patch_name), message))
220
205
 
221
 
        f = open(patch_path, 'a')
 
206
        patch = open(patch_name, 'a')
222
207
 
223
208
        assert '\n' not in message
224
 
        f.write("%s%s\n" % (self.MESSAGE_PREFIX, message))
225
 
 
226
 
        for patch in to_shelve:
227
 
            f.write(str(patch))
228
 
 
229
 
        f.flush()
230
 
        os.fsync(f.fileno())
231
 
        f.close()
 
209
        patch.write("%s%s\n" % (self.MESSAGE_PREFIX, message))
 
210
 
 
211
        for hunk in to_shelve:
 
212
            patch.write(str(hunk))
 
213
 
 
214
        patch.flush()
 
215
        os.fsync(patch.fileno())
 
216
        patch.close()
232
217
 
233
218
        try:
234
219
            self._run_patch(to_shelve, reverse=True, dry_run=True)
235
220
            self._run_patch(to_shelve, reverse=True)
236
221
        except PatchFailed:
237
222
            try:
238
 
                self._run_patch(to_shelve, reverse=True, strip=1, dry_run=True)
239
 
                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)
240
225
            except PatchFailed:
241
226
                raise CommandError("Failed removing shelved changes from the"
242
227
                    "working tree!")
243
228
 
244
 
    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):
245
230
        args = ['patch', '-d', self.base, '-s', '-p%d' % strip, '-f']
246
 
 
247
 
        if sys.platform == "win32":
248
 
            args.append('--binary')
249
 
 
250
231
        if reverse:
251
232
            args.append('-R')
252
233
        if dry_run:
255
236
        else:
256
237
            stdout = stderr = None
257
238
 
258
 
        try:
259
 
            process = subprocess.Popen(args, stdin=subprocess.PIPE,
260
 
                                       stdout=stdout, stderr=stderr)
261
 
            for patch in patches:
262
 
                process.stdin.write(str(patch))
263
 
 
264
 
        except IOError, e:
265
 
            raise PatchInvokeError(e, process.stderr.read())
 
239
        process = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=stdout,
 
240
                        stderr=stderr)
 
241
        for patch in patches:
 
242
            process.stdin.write(str(patch))
266
243
 
267
244
        process.communicate()
268
245
 
327
304
            new_file.close()
328
305
            self.log('Copied %s to %s/%s\n' % (os.path.basename(patch),
329
306
                self.name, os.path.basename(new_path)))
330
 
            rename(patch, patch + '~')
 
307
            os.rename(patch, patch + '~')