Show More
@@ -40,6 +40,8 b' command = cmdutil.command(cmdtable)' | |||||
40 | # leave the attribute unspecified. |
|
40 | # leave the attribute unspecified. | |
41 | testedwith = 'internal' |
|
41 | testedwith = 'internal' | |
42 |
|
42 | |||
|
43 | backupdir = 'shelve-backup' | |||
|
44 | ||||
43 | class shelvedfile(object): |
|
45 | class shelvedfile(object): | |
44 | """Helper for the file storing a single shelve |
|
46 | """Helper for the file storing a single shelve | |
45 |
|
47 | |||
@@ -49,7 +51,7 b' class shelvedfile(object):' | |||||
49 | self.repo = repo |
|
51 | self.repo = repo | |
50 | self.name = name |
|
52 | self.name = name | |
51 | self.vfs = scmutil.vfs(repo.join('shelved')) |
|
53 | self.vfs = scmutil.vfs(repo.join('shelved')) | |
52 |
self.backupvfs = scmutil.vfs(repo.join( |
|
54 | self.backupvfs = scmutil.vfs(repo.join(backupdir)) | |
53 | self.ui = self.repo.ui |
|
55 | self.ui = self.repo.ui | |
54 | if filetype: |
|
56 | if filetype: | |
55 | self.fname = name + '.' + filetype |
|
57 | self.fname = name + '.' + filetype | |
@@ -156,6 +158,20 b' class shelvedstate(object):' | |||||
156 | def clear(cls, repo): |
|
158 | def clear(cls, repo): | |
157 | util.unlinkpath(repo.join(cls._filename), ignoremissing=True) |
|
159 | util.unlinkpath(repo.join(cls._filename), ignoremissing=True) | |
158 |
|
160 | |||
|
161 | def cleanupoldbackups(repo): | |||
|
162 | vfs = scmutil.vfs(repo.join(backupdir)) | |||
|
163 | maxbackups = repo.ui.configint('shelve', 'maxbackups', 10) | |||
|
164 | hgfiles = [f for f in vfs.listdir() if f.endswith('.hg')] | |||
|
165 | hgfiles = sorted([(vfs.stat(f).st_mtime, f) for f in hgfiles]) | |||
|
166 | for mtime, f in hgfiles[:len(hgfiles) - maxbackups]: | |||
|
167 | base = f[:-3] | |||
|
168 | for ext in 'hg patch'.split(): | |||
|
169 | try: | |||
|
170 | vfs.unlink(base + '.' + ext) | |||
|
171 | except OSError as err: | |||
|
172 | if err.errno != errno.ENOENT: | |||
|
173 | raise | |||
|
174 | ||||
159 | def createcmd(ui, repo, pats, opts): |
|
175 | def createcmd(ui, repo, pats, opts): | |
160 | """subcommand that creates a new shelve""" |
|
176 | """subcommand that creates a new shelve""" | |
161 |
|
177 | |||
@@ -298,6 +314,7 b' def cleanupcmd(ui, repo):' | |||||
298 | suffix = name.rsplit('.', 1)[-1] |
|
314 | suffix = name.rsplit('.', 1)[-1] | |
299 | if suffix in ('hg', 'patch'): |
|
315 | if suffix in ('hg', 'patch'): | |
300 | shelvedfile(repo, name).movetobackup() |
|
316 | shelvedfile(repo, name).movetobackup() | |
|
317 | cleanupoldbackups(repo) | |||
301 | finally: |
|
318 | finally: | |
302 | lockmod.release(wlock) |
|
319 | lockmod.release(wlock) | |
303 |
|
320 | |||
@@ -310,6 +327,7 b' def deletecmd(ui, repo, pats):' | |||||
310 | for name in pats: |
|
327 | for name in pats: | |
311 | for suffix in 'hg patch'.split(): |
|
328 | for suffix in 'hg patch'.split(): | |
312 | shelvedfile(repo, name, suffix).movetobackup() |
|
329 | shelvedfile(repo, name, suffix).movetobackup() | |
|
330 | cleanupoldbackups(repo) | |||
313 | except OSError as err: |
|
331 | except OSError as err: | |
314 | if err.errno != errno.ENOENT: |
|
332 | if err.errno != errno.ENOENT: | |
315 | raise |
|
333 | raise | |
@@ -459,6 +477,7 b' def unshelvecleanup(ui, repo, name, opts' | |||||
459 | if not opts['keep']: |
|
477 | if not opts['keep']: | |
460 | for filetype in 'hg patch'.split(): |
|
478 | for filetype in 'hg patch'.split(): | |
461 | shelvedfile(repo, name, filetype).movetobackup() |
|
479 | shelvedfile(repo, name, filetype).movetobackup() | |
|
480 | cleanupoldbackups(repo) | |||
462 |
|
481 | |||
463 | def unshelvecontinue(ui, repo, state, opts): |
|
482 | def unshelvecontinue(ui, repo, state, opts): | |
464 | """subcommand to continue an in-progress unshelve""" |
|
483 | """subcommand to continue an in-progress unshelve""" | |
@@ -534,6 +553,11 b' def unshelve(ui, repo, *shelved, **opts)' | |||||
534 | (Alternatively, you can use ``--abort`` to abandon an unshelve |
|
553 | (Alternatively, you can use ``--abort`` to abandon an unshelve | |
535 | that causes a conflict. This reverts the unshelved changes, and |
|
554 | that causes a conflict. This reverts the unshelved changes, and | |
536 | leaves the bundle in place.) |
|
555 | leaves the bundle in place.) | |
|
556 | ||||
|
557 | After a successful unshelve, the shelved changes are stored in a | |||
|
558 | backup directory. Only the N most recent backups are kept. N | |||
|
559 | defaults to 10 but can be overridden using the shelve.maxbackups | |||
|
560 | configuration option. | |||
537 | """ |
|
561 | """ | |
538 | abortf = opts['abort'] |
|
562 | abortf = opts['abort'] | |
539 | continuef = opts['continue'] |
|
563 | continuef = opts['continue'] |
@@ -5,6 +5,8 b'' | |||||
5 | > [defaults] |
|
5 | > [defaults] | |
6 | > diff = --nodates --git |
|
6 | > diff = --nodates --git | |
7 | > qnew = --date '0 0' |
|
7 | > qnew = --date '0 0' | |
|
8 | > [shelve] | |||
|
9 | > maxbackups = 2 | |||
8 | > EOF |
|
10 | > EOF | |
9 |
|
11 | |||
10 | $ hg init repo |
|
12 | $ hg init repo | |
@@ -248,6 +250,14 b' and now "a/a" should reappear' | |||||
248 | c |
|
250 | c | |
249 | R b/b |
|
251 | R b/b | |
250 |
|
252 | |||
|
253 | ensure old shelve backups are being deleted automatically | |||
|
254 | ||||
|
255 | $ ls .hg/shelve-backup/ | |||
|
256 | default-01.hg | |||
|
257 | default-01.patch | |||
|
258 | wibble.hg | |||
|
259 | wibble.patch | |||
|
260 | ||||
251 | cause unshelving to result in a merge with 'a' conflicting |
|
261 | cause unshelving to result in a merge with 'a' conflicting | |
252 |
|
262 | |||
253 | $ hg shelve -q |
|
263 | $ hg shelve -q |
General Comments 0
You need to be logged in to leave comments.
Login now