~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to shelf.py

  • Committer: Michael Ellerman
  • Date: 2006-06-17 06:41:34 UTC
  • mfrom: (0.5.3 shelf.bialix)
  • mto: (0.3.4 shelf-dev)
  • mto: This revision was merged to the branch mainline in revision 414.
  • Revision ID: michael@ellerman.id.au-20060617064134-1dd813742ee1dea4
Win32 fixes from Alexander, slightly reworked by me.

Show diffs side-by-side

added added

removed removed

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