##// END OF EJS Templates
shelve: use absolute_import
timeless -
r28378:96a7368a default
parent child Browse files
Show More
@@ -1,859 +1,880 b''
1 # shelve.py - save/restore working directory state
1 # shelve.py - save/restore working directory state
2 #
2 #
3 # Copyright 2013 Facebook, Inc.
3 # Copyright 2013 Facebook, Inc.
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 """save and restore changes to the working directory
8 """save and restore changes to the working directory
9
9
10 The "hg shelve" command saves changes made to the working directory
10 The "hg shelve" command saves changes made to the working directory
11 and reverts those changes, resetting the working directory to a clean
11 and reverts those changes, resetting the working directory to a clean
12 state.
12 state.
13
13
14 Later on, the "hg unshelve" command restores the changes saved by "hg
14 Later on, the "hg unshelve" command restores the changes saved by "hg
15 shelve". Changes can be restored even after updating to a different
15 shelve". Changes can be restored even after updating to a different
16 parent, in which case Mercurial's merge machinery will resolve any
16 parent, in which case Mercurial's merge machinery will resolve any
17 conflicts if necessary.
17 conflicts if necessary.
18
18
19 You can have more than one shelved change outstanding at a time; each
19 You can have more than one shelved change outstanding at a time; each
20 shelved change has a distinct name. For details, see the help for "hg
20 shelved change has a distinct name. For details, see the help for "hg
21 shelve".
21 shelve".
22 """
22 """
23 from __future__ import absolute_import
23
24
24 import collections
25 import collections
26 import errno
25 import itertools
27 import itertools
28 from mercurial import (
29 bundle2,
30 bundlerepo,
31 changegroup,
32 cmdutil,
33 commands,
34 error,
35 exchange,
36 hg,
37 lock as lockmod,
38 mdiff,
39 merge,
40 node as nodemod,
41 patch,
42 phases,
43 repair,
44 scmutil,
45 templatefilters,
46 util,
47 )
26 from mercurial.i18n import _
48 from mercurial.i18n import _
27 from mercurial.node import nullid, nullrev, bin, hex
49
28 from mercurial import changegroup, cmdutil, scmutil, phases, commands
50 from . import (
29 from mercurial import error, hg, mdiff, merge, patch, repair, util
51 rebase,
30 from mercurial import templatefilters, exchange, bundlerepo, bundle2
52 )
31 from mercurial import lock as lockmod
32 from hgext import rebase
33 import errno
34
53
35 cmdtable = {}
54 cmdtable = {}
36 command = cmdutil.command(cmdtable)
55 command = cmdutil.command(cmdtable)
37 # Note for extension authors: ONLY specify testedwith = 'internal' for
56 # Note for extension authors: ONLY specify testedwith = 'internal' for
38 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
57 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
39 # be specifying the version(s) of Mercurial they are tested with, or
58 # be specifying the version(s) of Mercurial they are tested with, or
40 # leave the attribute unspecified.
59 # leave the attribute unspecified.
41 testedwith = 'internal'
60 testedwith = 'internal'
42
61
43 backupdir = 'shelve-backup'
62 backupdir = 'shelve-backup'
44
63
45 class shelvedfile(object):
64 class shelvedfile(object):
46 """Helper for the file storing a single shelve
65 """Helper for the file storing a single shelve
47
66
48 Handles common functions on shelve files (.hg/.patch) using
67 Handles common functions on shelve files (.hg/.patch) using
49 the vfs layer"""
68 the vfs layer"""
50 def __init__(self, repo, name, filetype=None):
69 def __init__(self, repo, name, filetype=None):
51 self.repo = repo
70 self.repo = repo
52 self.name = name
71 self.name = name
53 self.vfs = scmutil.vfs(repo.join('shelved'))
72 self.vfs = scmutil.vfs(repo.join('shelved'))
54 self.backupvfs = scmutil.vfs(repo.join(backupdir))
73 self.backupvfs = scmutil.vfs(repo.join(backupdir))
55 self.ui = self.repo.ui
74 self.ui = self.repo.ui
56 if filetype:
75 if filetype:
57 self.fname = name + '.' + filetype
76 self.fname = name + '.' + filetype
58 else:
77 else:
59 self.fname = name
78 self.fname = name
60
79
61 def exists(self):
80 def exists(self):
62 return self.vfs.exists(self.fname)
81 return self.vfs.exists(self.fname)
63
82
64 def filename(self):
83 def filename(self):
65 return self.vfs.join(self.fname)
84 return self.vfs.join(self.fname)
66
85
67 def backupfilename(self):
86 def backupfilename(self):
68 def gennames(base):
87 def gennames(base):
69 yield base
88 yield base
70 base, ext = base.rsplit('.', 1)
89 base, ext = base.rsplit('.', 1)
71 for i in itertools.count(1):
90 for i in itertools.count(1):
72 yield '%s-%d.%s' % (base, i, ext)
91 yield '%s-%d.%s' % (base, i, ext)
73
92
74 name = self.backupvfs.join(self.fname)
93 name = self.backupvfs.join(self.fname)
75 for n in gennames(name):
94 for n in gennames(name):
76 if not self.backupvfs.exists(n):
95 if not self.backupvfs.exists(n):
77 return n
96 return n
78
97
79 def movetobackup(self):
98 def movetobackup(self):
80 if not self.backupvfs.isdir():
99 if not self.backupvfs.isdir():
81 self.backupvfs.makedir()
100 self.backupvfs.makedir()
82 util.rename(self.filename(), self.backupfilename())
101 util.rename(self.filename(), self.backupfilename())
83
102
84 def stat(self):
103 def stat(self):
85 return self.vfs.stat(self.fname)
104 return self.vfs.stat(self.fname)
86
105
87 def opener(self, mode='rb'):
106 def opener(self, mode='rb'):
88 try:
107 try:
89 return self.vfs(self.fname, mode)
108 return self.vfs(self.fname, mode)
90 except IOError as err:
109 except IOError as err:
91 if err.errno != errno.ENOENT:
110 if err.errno != errno.ENOENT:
92 raise
111 raise
93 raise error.Abort(_("shelved change '%s' not found") % self.name)
112 raise error.Abort(_("shelved change '%s' not found") % self.name)
94
113
95 def applybundle(self):
114 def applybundle(self):
96 fp = self.opener()
115 fp = self.opener()
97 try:
116 try:
98 gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
117 gen = exchange.readbundle(self.repo.ui, fp, self.fname, self.vfs)
99 if not isinstance(gen, bundle2.unbundle20):
118 if not isinstance(gen, bundle2.unbundle20):
100 gen.apply(self.repo, 'unshelve',
119 gen.apply(self.repo, 'unshelve',
101 'bundle:' + self.vfs.join(self.fname),
120 'bundle:' + self.vfs.join(self.fname),
102 targetphase=phases.secret)
121 targetphase=phases.secret)
103 if isinstance(gen, bundle2.unbundle20):
122 if isinstance(gen, bundle2.unbundle20):
104 bundle2.applybundle(self.repo, gen,
123 bundle2.applybundle(self.repo, gen,
105 self.repo.currenttransaction(),
124 self.repo.currenttransaction(),
106 source='unshelve',
125 source='unshelve',
107 url='bundle:' + self.vfs.join(self.fname))
126 url='bundle:' + self.vfs.join(self.fname))
108 finally:
127 finally:
109 fp.close()
128 fp.close()
110
129
111 def bundlerepo(self):
130 def bundlerepo(self):
112 return bundlerepo.bundlerepository(self.repo.baseui, self.repo.root,
131 return bundlerepo.bundlerepository(self.repo.baseui, self.repo.root,
113 self.vfs.join(self.fname))
132 self.vfs.join(self.fname))
114 def writebundle(self, bases, node):
133 def writebundle(self, bases, node):
115 cgversion = changegroup.safeversion(self.repo)
134 cgversion = changegroup.safeversion(self.repo)
116 if cgversion == '01':
135 if cgversion == '01':
117 btype = 'HG10BZ'
136 btype = 'HG10BZ'
118 compression = None
137 compression = None
119 else:
138 else:
120 btype = 'HG20'
139 btype = 'HG20'
121 compression = 'BZ'
140 compression = 'BZ'
122
141
123 cg = changegroup.changegroupsubset(self.repo, bases, [node], 'shelve',
142 cg = changegroup.changegroupsubset(self.repo, bases, [node], 'shelve',
124 version=cgversion)
143 version=cgversion)
125 changegroup.writebundle(self.ui, cg, self.fname, btype, self.vfs,
144 changegroup.writebundle(self.ui, cg, self.fname, btype, self.vfs,
126 compression=compression)
145 compression=compression)
127
146
128 class shelvedstate(object):
147 class shelvedstate(object):
129 """Handle persistence during unshelving operations.
148 """Handle persistence during unshelving operations.
130
149
131 Handles saving and restoring a shelved state. Ensures that different
150 Handles saving and restoring a shelved state. Ensures that different
132 versions of a shelved state are possible and handles them appropriately.
151 versions of a shelved state are possible and handles them appropriately.
133 """
152 """
134 _version = 1
153 _version = 1
135 _filename = 'shelvedstate'
154 _filename = 'shelvedstate'
136
155
137 @classmethod
156 @classmethod
138 def load(cls, repo):
157 def load(cls, repo):
139 fp = repo.vfs(cls._filename)
158 fp = repo.vfs(cls._filename)
140 try:
159 try:
141 version = int(fp.readline().strip())
160 version = int(fp.readline().strip())
142
161
143 if version != cls._version:
162 if version != cls._version:
144 raise error.Abort(_('this version of shelve is incompatible '
163 raise error.Abort(_('this version of shelve is incompatible '
145 'with the version used in this repo'))
164 'with the version used in this repo'))
146 name = fp.readline().strip()
165 name = fp.readline().strip()
147 wctx = fp.readline().strip()
166 wctx = fp.readline().strip()
148 pendingctx = fp.readline().strip()
167 pendingctx = fp.readline().strip()
149 parents = [bin(h) for h in fp.readline().split()]
168 parents = [nodemod.bin(h) for h in fp.readline().split()]
150 stripnodes = [bin(h) for h in fp.readline().split()]
169 stripnodes = [nodemod.bin(h) for h in fp.readline().split()]
151 finally:
170 finally:
152 fp.close()
171 fp.close()
153
172
154 obj = cls()
173 obj = cls()
155 obj.name = name
174 obj.name = name
156 obj.wctx = repo[bin(wctx)]
175 obj.wctx = repo[nodemod.bin(wctx)]
157 obj.pendingctx = repo[bin(pendingctx)]
176 obj.pendingctx = repo[nodemod.bin(pendingctx)]
158 obj.parents = parents
177 obj.parents = parents
159 obj.stripnodes = stripnodes
178 obj.stripnodes = stripnodes
160
179
161 return obj
180 return obj
162
181
163 @classmethod
182 @classmethod
164 def save(cls, repo, name, originalwctx, pendingctx, stripnodes):
183 def save(cls, repo, name, originalwctx, pendingctx, stripnodes):
165 fp = repo.vfs(cls._filename, 'wb')
184 fp = repo.vfs(cls._filename, 'wb')
166 fp.write('%i\n' % cls._version)
185 fp.write('%i\n' % cls._version)
167 fp.write('%s\n' % name)
186 fp.write('%s\n' % name)
168 fp.write('%s\n' % hex(originalwctx.node()))
187 fp.write('%s\n' % nodemod.hex(originalwctx.node()))
169 fp.write('%s\n' % hex(pendingctx.node()))
188 fp.write('%s\n' % nodemod.hex(pendingctx.node()))
170 fp.write('%s\n' % ' '.join([hex(p) for p in repo.dirstate.parents()]))
189 fp.write('%s\n' %
171 fp.write('%s\n' % ' '.join([hex(n) for n in stripnodes]))
190 ' '.join([nodemod.hex(p) for p in repo.dirstate.parents()]))
191 fp.write('%s\n' %
192 ' '.join([nodemod.hex(n) for n in stripnodes]))
172 fp.close()
193 fp.close()
173
194
174 @classmethod
195 @classmethod
175 def clear(cls, repo):
196 def clear(cls, repo):
176 util.unlinkpath(repo.join(cls._filename), ignoremissing=True)
197 util.unlinkpath(repo.join(cls._filename), ignoremissing=True)
177
198
178 def cleanupoldbackups(repo):
199 def cleanupoldbackups(repo):
179 vfs = scmutil.vfs(repo.join(backupdir))
200 vfs = scmutil.vfs(repo.join(backupdir))
180 maxbackups = repo.ui.configint('shelve', 'maxbackups', 10)
201 maxbackups = repo.ui.configint('shelve', 'maxbackups', 10)
181 hgfiles = [f for f in vfs.listdir() if f.endswith('.hg')]
202 hgfiles = [f for f in vfs.listdir() if f.endswith('.hg')]
182 hgfiles = sorted([(vfs.stat(f).st_mtime, f) for f in hgfiles])
203 hgfiles = sorted([(vfs.stat(f).st_mtime, f) for f in hgfiles])
183 if 0 < maxbackups and maxbackups < len(hgfiles):
204 if 0 < maxbackups and maxbackups < len(hgfiles):
184 bordermtime = hgfiles[-maxbackups][0]
205 bordermtime = hgfiles[-maxbackups][0]
185 else:
206 else:
186 bordermtime = None
207 bordermtime = None
187 for mtime, f in hgfiles[:len(hgfiles) - maxbackups]:
208 for mtime, f in hgfiles[:len(hgfiles) - maxbackups]:
188 if mtime == bordermtime:
209 if mtime == bordermtime:
189 # keep it, because timestamp can't decide exact order of backups
210 # keep it, because timestamp can't decide exact order of backups
190 continue
211 continue
191 base = f[:-3]
212 base = f[:-3]
192 for ext in 'hg patch'.split():
213 for ext in 'hg patch'.split():
193 try:
214 try:
194 vfs.unlink(base + '.' + ext)
215 vfs.unlink(base + '.' + ext)
195 except OSError as err:
216 except OSError as err:
196 if err.errno != errno.ENOENT:
217 if err.errno != errno.ENOENT:
197 raise
218 raise
198
219
199 def _aborttransaction(repo):
220 def _aborttransaction(repo):
200 '''Abort current transaction for shelve/unshelve, but keep dirstate
221 '''Abort current transaction for shelve/unshelve, but keep dirstate
201 '''
222 '''
202 backupname = 'dirstate.shelve'
223 backupname = 'dirstate.shelve'
203 dirstatebackup = None
224 dirstatebackup = None
204 try:
225 try:
205 # create backup of (un)shelved dirstate, because aborting transaction
226 # create backup of (un)shelved dirstate, because aborting transaction
206 # should restore dirstate to one at the beginning of the
227 # should restore dirstate to one at the beginning of the
207 # transaction, which doesn't include the result of (un)shelving
228 # transaction, which doesn't include the result of (un)shelving
208 fp = repo.vfs.open(backupname, "w")
229 fp = repo.vfs.open(backupname, "w")
209 dirstatebackup = backupname
230 dirstatebackup = backupname
210 # clearing _dirty/_dirtypl of dirstate by _writedirstate below
231 # clearing _dirty/_dirtypl of dirstate by _writedirstate below
211 # is unintentional. but it doesn't cause problem in this case,
232 # is unintentional. but it doesn't cause problem in this case,
212 # because no code path refers them until transaction is aborted.
233 # because no code path refers them until transaction is aborted.
213 repo.dirstate._writedirstate(fp) # write in-memory changes forcibly
234 repo.dirstate._writedirstate(fp) # write in-memory changes forcibly
214
235
215 tr = repo.currenttransaction()
236 tr = repo.currenttransaction()
216 tr.abort()
237 tr.abort()
217
238
218 # restore to backuped dirstate
239 # restore to backuped dirstate
219 repo.vfs.rename(dirstatebackup, 'dirstate')
240 repo.vfs.rename(dirstatebackup, 'dirstate')
220 dirstatebackup = None
241 dirstatebackup = None
221 finally:
242 finally:
222 if dirstatebackup:
243 if dirstatebackup:
223 repo.vfs.unlink(dirstatebackup)
244 repo.vfs.unlink(dirstatebackup)
224
245
225 def createcmd(ui, repo, pats, opts):
246 def createcmd(ui, repo, pats, opts):
226 """subcommand that creates a new shelve"""
247 """subcommand that creates a new shelve"""
227 with repo.wlock():
248 with repo.wlock():
228 cmdutil.checkunfinished(repo)
249 cmdutil.checkunfinished(repo)
229 return _docreatecmd(ui, repo, pats, opts)
250 return _docreatecmd(ui, repo, pats, opts)
230
251
231 def _docreatecmd(ui, repo, pats, opts):
252 def _docreatecmd(ui, repo, pats, opts):
232 def mutableancestors(ctx):
253 def mutableancestors(ctx):
233 """return all mutable ancestors for ctx (included)
254 """return all mutable ancestors for ctx (included)
234
255
235 Much faster than the revset ancestors(ctx) & draft()"""
256 Much faster than the revset ancestors(ctx) & draft()"""
236 seen = set([nullrev])
257 seen = set([nodemod.nullrev])
237 visit = collections.deque()
258 visit = collections.deque()
238 visit.append(ctx)
259 visit.append(ctx)
239 while visit:
260 while visit:
240 ctx = visit.popleft()
261 ctx = visit.popleft()
241 yield ctx.node()
262 yield ctx.node()
242 for parent in ctx.parents():
263 for parent in ctx.parents():
243 rev = parent.rev()
264 rev = parent.rev()
244 if rev not in seen:
265 if rev not in seen:
245 seen.add(rev)
266 seen.add(rev)
246 if parent.mutable():
267 if parent.mutable():
247 visit.append(parent)
268 visit.append(parent)
248
269
249 wctx = repo[None]
270 wctx = repo[None]
250 parents = wctx.parents()
271 parents = wctx.parents()
251 if len(parents) > 1:
272 if len(parents) > 1:
252 raise error.Abort(_('cannot shelve while merging'))
273 raise error.Abort(_('cannot shelve while merging'))
253 parent = parents[0]
274 parent = parents[0]
254
275
255 # we never need the user, so we use a generic user for all shelve operations
276 # we never need the user, so we use a generic user for all shelve operations
256 user = 'shelve@localhost'
277 user = 'shelve@localhost'
257 label = repo._activebookmark or parent.branch() or 'default'
278 label = repo._activebookmark or parent.branch() or 'default'
258
279
259 # slashes aren't allowed in filenames, therefore we rename it
280 # slashes aren't allowed in filenames, therefore we rename it
260 label = label.replace('/', '_')
281 label = label.replace('/', '_')
261
282
262 def gennames():
283 def gennames():
263 yield label
284 yield label
264 for i in xrange(1, 100):
285 for i in xrange(1, 100):
265 yield '%s-%02d' % (label, i)
286 yield '%s-%02d' % (label, i)
266
287
267 if parent.node() != nullid:
288 if parent.node() != nodemod.nullid:
268 desc = "changes to: %s" % parent.description().split('\n', 1)[0]
289 desc = "changes to: %s" % parent.description().split('\n', 1)[0]
269 else:
290 else:
270 desc = '(changes in empty repository)'
291 desc = '(changes in empty repository)'
271
292
272 if not opts['message']:
293 if not opts['message']:
273 opts['message'] = desc
294 opts['message'] = desc
274
295
275 name = opts['name']
296 name = opts['name']
276
297
277 lock = tr = None
298 lock = tr = None
278 try:
299 try:
279 lock = repo.lock()
300 lock = repo.lock()
280
301
281 # use an uncommitted transaction to generate the bundle to avoid
302 # use an uncommitted transaction to generate the bundle to avoid
282 # pull races. ensure we don't print the abort message to stderr.
303 # pull races. ensure we don't print the abort message to stderr.
283 tr = repo.transaction('commit', report=lambda x: None)
304 tr = repo.transaction('commit', report=lambda x: None)
284
305
285 if name:
306 if name:
286 if shelvedfile(repo, name, 'hg').exists():
307 if shelvedfile(repo, name, 'hg').exists():
287 raise error.Abort(_("a shelved change named '%s' already exists"
308 raise error.Abort(_("a shelved change named '%s' already exists"
288 ) % name)
309 ) % name)
289 else:
310 else:
290 for n in gennames():
311 for n in gennames():
291 if not shelvedfile(repo, n, 'hg').exists():
312 if not shelvedfile(repo, n, 'hg').exists():
292 name = n
313 name = n
293 break
314 break
294 else:
315 else:
295 raise error.Abort(_("too many shelved changes named '%s'") %
316 raise error.Abort(_("too many shelved changes named '%s'") %
296 label)
317 label)
297
318
298 # ensure we are not creating a subdirectory or a hidden file
319 # ensure we are not creating a subdirectory or a hidden file
299 if '/' in name or '\\' in name:
320 if '/' in name or '\\' in name:
300 raise error.Abort(_('shelved change names may not contain slashes'))
321 raise error.Abort(_('shelved change names may not contain slashes'))
301 if name.startswith('.'):
322 if name.startswith('.'):
302 raise error.Abort(_("shelved change names may not start with '.'"))
323 raise error.Abort(_("shelved change names may not start with '.'"))
303 interactive = opts.get('interactive', False)
324 interactive = opts.get('interactive', False)
304 includeunknown = (opts.get('unknown', False) and
325 includeunknown = (opts.get('unknown', False) and
305 not opts.get('addremove', False))
326 not opts.get('addremove', False))
306
327
307 extra={}
328 extra={}
308 if includeunknown:
329 if includeunknown:
309 s = repo.status(match=scmutil.match(repo[None], pats, opts),
330 s = repo.status(match=scmutil.match(repo[None], pats, opts),
310 unknown=True)
331 unknown=True)
311 if s.unknown:
332 if s.unknown:
312 extra['shelve_unknown'] = '\0'.join(s.unknown)
333 extra['shelve_unknown'] = '\0'.join(s.unknown)
313 repo[None].add(s.unknown)
334 repo[None].add(s.unknown)
314
335
315 def commitfunc(ui, repo, message, match, opts):
336 def commitfunc(ui, repo, message, match, opts):
316 hasmq = util.safehasattr(repo, 'mq')
337 hasmq = util.safehasattr(repo, 'mq')
317 if hasmq:
338 if hasmq:
318 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
339 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
319 backup = repo.ui.backupconfig('phases', 'new-commit')
340 backup = repo.ui.backupconfig('phases', 'new-commit')
320 try:
341 try:
321 repo.ui. setconfig('phases', 'new-commit', phases.secret)
342 repo.ui. setconfig('phases', 'new-commit', phases.secret)
322 editor = cmdutil.getcommiteditor(editform='shelve.shelve',
343 editor = cmdutil.getcommiteditor(editform='shelve.shelve',
323 **opts)
344 **opts)
324 return repo.commit(message, user, opts.get('date'), match,
345 return repo.commit(message, user, opts.get('date'), match,
325 editor=editor, extra=extra)
346 editor=editor, extra=extra)
326 finally:
347 finally:
327 repo.ui.restoreconfig(backup)
348 repo.ui.restoreconfig(backup)
328 if hasmq:
349 if hasmq:
329 repo.mq.checkapplied = saved
350 repo.mq.checkapplied = saved
330
351
331 def interactivecommitfunc(ui, repo, *pats, **opts):
352 def interactivecommitfunc(ui, repo, *pats, **opts):
332 match = scmutil.match(repo['.'], pats, {})
353 match = scmutil.match(repo['.'], pats, {})
333 message = opts['message']
354 message = opts['message']
334 return commitfunc(ui, repo, message, match, opts)
355 return commitfunc(ui, repo, message, match, opts)
335 if not interactive:
356 if not interactive:
336 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
357 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
337 else:
358 else:
338 node = cmdutil.dorecord(ui, repo, interactivecommitfunc, None,
359 node = cmdutil.dorecord(ui, repo, interactivecommitfunc, None,
339 False, cmdutil.recordfilter, *pats, **opts)
360 False, cmdutil.recordfilter, *pats, **opts)
340 if not node:
361 if not node:
341 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
362 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
342 if stat.deleted:
363 if stat.deleted:
343 ui.status(_("nothing changed (%d missing files, see "
364 ui.status(_("nothing changed (%d missing files, see "
344 "'hg status')\n") % len(stat.deleted))
365 "'hg status')\n") % len(stat.deleted))
345 else:
366 else:
346 ui.status(_("nothing changed\n"))
367 ui.status(_("nothing changed\n"))
347 return 1
368 return 1
348
369
349 bases = list(mutableancestors(repo[node]))
370 bases = list(mutableancestors(repo[node]))
350 shelvedfile(repo, name, 'hg').writebundle(bases, node)
371 shelvedfile(repo, name, 'hg').writebundle(bases, node)
351 cmdutil.export(repo, [node],
372 cmdutil.export(repo, [node],
352 fp=shelvedfile(repo, name, 'patch').opener('wb'),
373 fp=shelvedfile(repo, name, 'patch').opener('wb'),
353 opts=mdiff.diffopts(git=True))
374 opts=mdiff.diffopts(git=True))
354
375
355
376
356 if ui.formatted():
377 if ui.formatted():
357 desc = util.ellipsis(desc, ui.termwidth())
378 desc = util.ellipsis(desc, ui.termwidth())
358 ui.status(_('shelved as %s\n') % name)
379 ui.status(_('shelved as %s\n') % name)
359 hg.update(repo, parent.node())
380 hg.update(repo, parent.node())
360
381
361 _aborttransaction(repo)
382 _aborttransaction(repo)
362 finally:
383 finally:
363 lockmod.release(tr, lock)
384 lockmod.release(tr, lock)
364
385
365 def cleanupcmd(ui, repo):
386 def cleanupcmd(ui, repo):
366 """subcommand that deletes all shelves"""
387 """subcommand that deletes all shelves"""
367
388
368 with repo.wlock():
389 with repo.wlock():
369 for (name, _type) in repo.vfs.readdir('shelved'):
390 for (name, _type) in repo.vfs.readdir('shelved'):
370 suffix = name.rsplit('.', 1)[-1]
391 suffix = name.rsplit('.', 1)[-1]
371 if suffix in ('hg', 'patch'):
392 if suffix in ('hg', 'patch'):
372 shelvedfile(repo, name).movetobackup()
393 shelvedfile(repo, name).movetobackup()
373 cleanupoldbackups(repo)
394 cleanupoldbackups(repo)
374
395
375 def deletecmd(ui, repo, pats):
396 def deletecmd(ui, repo, pats):
376 """subcommand that deletes a specific shelve"""
397 """subcommand that deletes a specific shelve"""
377 if not pats:
398 if not pats:
378 raise error.Abort(_('no shelved changes specified!'))
399 raise error.Abort(_('no shelved changes specified!'))
379 with repo.wlock():
400 with repo.wlock():
380 try:
401 try:
381 for name in pats:
402 for name in pats:
382 for suffix in 'hg patch'.split():
403 for suffix in 'hg patch'.split():
383 shelvedfile(repo, name, suffix).movetobackup()
404 shelvedfile(repo, name, suffix).movetobackup()
384 cleanupoldbackups(repo)
405 cleanupoldbackups(repo)
385 except OSError as err:
406 except OSError as err:
386 if err.errno != errno.ENOENT:
407 if err.errno != errno.ENOENT:
387 raise
408 raise
388 raise error.Abort(_("shelved change '%s' not found") % name)
409 raise error.Abort(_("shelved change '%s' not found") % name)
389
410
390 def listshelves(repo):
411 def listshelves(repo):
391 """return all shelves in repo as list of (time, filename)"""
412 """return all shelves in repo as list of (time, filename)"""
392 try:
413 try:
393 names = repo.vfs.readdir('shelved')
414 names = repo.vfs.readdir('shelved')
394 except OSError as err:
415 except OSError as err:
395 if err.errno != errno.ENOENT:
416 if err.errno != errno.ENOENT:
396 raise
417 raise
397 return []
418 return []
398 info = []
419 info = []
399 for (name, _type) in names:
420 for (name, _type) in names:
400 pfx, sfx = name.rsplit('.', 1)
421 pfx, sfx = name.rsplit('.', 1)
401 if not pfx or sfx != 'patch':
422 if not pfx or sfx != 'patch':
402 continue
423 continue
403 st = shelvedfile(repo, name).stat()
424 st = shelvedfile(repo, name).stat()
404 info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
425 info.append((st.st_mtime, shelvedfile(repo, pfx).filename()))
405 return sorted(info, reverse=True)
426 return sorted(info, reverse=True)
406
427
407 def listcmd(ui, repo, pats, opts):
428 def listcmd(ui, repo, pats, opts):
408 """subcommand that displays the list of shelves"""
429 """subcommand that displays the list of shelves"""
409 pats = set(pats)
430 pats = set(pats)
410 width = 80
431 width = 80
411 if not ui.plain():
432 if not ui.plain():
412 width = ui.termwidth()
433 width = ui.termwidth()
413 namelabel = 'shelve.newest'
434 namelabel = 'shelve.newest'
414 for mtime, name in listshelves(repo):
435 for mtime, name in listshelves(repo):
415 sname = util.split(name)[1]
436 sname = util.split(name)[1]
416 if pats and sname not in pats:
437 if pats and sname not in pats:
417 continue
438 continue
418 ui.write(sname, label=namelabel)
439 ui.write(sname, label=namelabel)
419 namelabel = 'shelve.name'
440 namelabel = 'shelve.name'
420 if ui.quiet:
441 if ui.quiet:
421 ui.write('\n')
442 ui.write('\n')
422 continue
443 continue
423 ui.write(' ' * (16 - len(sname)))
444 ui.write(' ' * (16 - len(sname)))
424 used = 16
445 used = 16
425 age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
446 age = '(%s)' % templatefilters.age(util.makedate(mtime), abbrev=True)
426 ui.write(age, label='shelve.age')
447 ui.write(age, label='shelve.age')
427 ui.write(' ' * (12 - len(age)))
448 ui.write(' ' * (12 - len(age)))
428 used += 12
449 used += 12
429 with open(name + '.patch', 'rb') as fp:
450 with open(name + '.patch', 'rb') as fp:
430 while True:
451 while True:
431 line = fp.readline()
452 line = fp.readline()
432 if not line:
453 if not line:
433 break
454 break
434 if not line.startswith('#'):
455 if not line.startswith('#'):
435 desc = line.rstrip()
456 desc = line.rstrip()
436 if ui.formatted():
457 if ui.formatted():
437 desc = util.ellipsis(desc, width - used)
458 desc = util.ellipsis(desc, width - used)
438 ui.write(desc)
459 ui.write(desc)
439 break
460 break
440 ui.write('\n')
461 ui.write('\n')
441 if not (opts['patch'] or opts['stat']):
462 if not (opts['patch'] or opts['stat']):
442 continue
463 continue
443 difflines = fp.readlines()
464 difflines = fp.readlines()
444 if opts['patch']:
465 if opts['patch']:
445 for chunk, label in patch.difflabel(iter, difflines):
466 for chunk, label in patch.difflabel(iter, difflines):
446 ui.write(chunk, label=label)
467 ui.write(chunk, label=label)
447 if opts['stat']:
468 if opts['stat']:
448 for chunk, label in patch.diffstatui(difflines, width=width,
469 for chunk, label in patch.diffstatui(difflines, width=width,
449 git=True):
470 git=True):
450 ui.write(chunk, label=label)
471 ui.write(chunk, label=label)
451
472
452 def singlepatchcmds(ui, repo, pats, opts, subcommand):
473 def singlepatchcmds(ui, repo, pats, opts, subcommand):
453 """subcommand that displays a single shelf"""
474 """subcommand that displays a single shelf"""
454 if len(pats) != 1:
475 if len(pats) != 1:
455 raise error.Abort(_("--%s expects a single shelf") % subcommand)
476 raise error.Abort(_("--%s expects a single shelf") % subcommand)
456 shelfname = pats[0]
477 shelfname = pats[0]
457
478
458 if not shelvedfile(repo, shelfname, 'patch').exists():
479 if not shelvedfile(repo, shelfname, 'patch').exists():
459 raise error.Abort(_("cannot find shelf %s") % shelfname)
480 raise error.Abort(_("cannot find shelf %s") % shelfname)
460
481
461 listcmd(ui, repo, pats, opts)
482 listcmd(ui, repo, pats, opts)
462
483
463 def checkparents(repo, state):
484 def checkparents(repo, state):
464 """check parent while resuming an unshelve"""
485 """check parent while resuming an unshelve"""
465 if state.parents != repo.dirstate.parents():
486 if state.parents != repo.dirstate.parents():
466 raise error.Abort(_('working directory parents do not match unshelve '
487 raise error.Abort(_('working directory parents do not match unshelve '
467 'state'))
488 'state'))
468
489
469 def pathtofiles(repo, files):
490 def pathtofiles(repo, files):
470 cwd = repo.getcwd()
491 cwd = repo.getcwd()
471 return [repo.pathto(f, cwd) for f in files]
492 return [repo.pathto(f, cwd) for f in files]
472
493
473 def unshelveabort(ui, repo, state, opts):
494 def unshelveabort(ui, repo, state, opts):
474 """subcommand that abort an in-progress unshelve"""
495 """subcommand that abort an in-progress unshelve"""
475 with repo.lock():
496 with repo.lock():
476 try:
497 try:
477 checkparents(repo, state)
498 checkparents(repo, state)
478
499
479 util.rename(repo.join('unshelverebasestate'),
500 util.rename(repo.join('unshelverebasestate'),
480 repo.join('rebasestate'))
501 repo.join('rebasestate'))
481 try:
502 try:
482 rebase.rebase(ui, repo, **{
503 rebase.rebase(ui, repo, **{
483 'abort' : True
504 'abort' : True
484 })
505 })
485 except Exception:
506 except Exception:
486 util.rename(repo.join('rebasestate'),
507 util.rename(repo.join('rebasestate'),
487 repo.join('unshelverebasestate'))
508 repo.join('unshelverebasestate'))
488 raise
509 raise
489
510
490 mergefiles(ui, repo, state.wctx, state.pendingctx)
511 mergefiles(ui, repo, state.wctx, state.pendingctx)
491 repair.strip(ui, repo, state.stripnodes, backup=False,
512 repair.strip(ui, repo, state.stripnodes, backup=False,
492 topic='shelve')
513 topic='shelve')
493 finally:
514 finally:
494 shelvedstate.clear(repo)
515 shelvedstate.clear(repo)
495 ui.warn(_("unshelve of '%s' aborted\n") % state.name)
516 ui.warn(_("unshelve of '%s' aborted\n") % state.name)
496
517
497 def mergefiles(ui, repo, wctx, shelvectx):
518 def mergefiles(ui, repo, wctx, shelvectx):
498 """updates to wctx and merges the changes from shelvectx into the
519 """updates to wctx and merges the changes from shelvectx into the
499 dirstate."""
520 dirstate."""
500 oldquiet = ui.quiet
521 oldquiet = ui.quiet
501 try:
522 try:
502 ui.quiet = True
523 ui.quiet = True
503 hg.update(repo, wctx.node())
524 hg.update(repo, wctx.node())
504 files = []
525 files = []
505 files.extend(shelvectx.files())
526 files.extend(shelvectx.files())
506 files.extend(shelvectx.parents()[0].files())
527 files.extend(shelvectx.parents()[0].files())
507
528
508 # revert will overwrite unknown files, so move them out of the way
529 # revert will overwrite unknown files, so move them out of the way
509 for file in repo.status(unknown=True).unknown:
530 for file in repo.status(unknown=True).unknown:
510 if file in files:
531 if file in files:
511 util.rename(file, scmutil.origpath(ui, repo, file))
532 util.rename(file, scmutil.origpath(ui, repo, file))
512 ui.pushbuffer(True)
533 ui.pushbuffer(True)
513 cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(),
534 cmdutil.revert(ui, repo, shelvectx, repo.dirstate.parents(),
514 *pathtofiles(repo, files),
535 *pathtofiles(repo, files),
515 **{'no_backup': True})
536 **{'no_backup': True})
516 ui.popbuffer()
537 ui.popbuffer()
517 finally:
538 finally:
518 ui.quiet = oldquiet
539 ui.quiet = oldquiet
519
540
520 def unshelvecleanup(ui, repo, name, opts):
541 def unshelvecleanup(ui, repo, name, opts):
521 """remove related files after an unshelve"""
542 """remove related files after an unshelve"""
522 if not opts['keep']:
543 if not opts['keep']:
523 for filetype in 'hg patch'.split():
544 for filetype in 'hg patch'.split():
524 shelvedfile(repo, name, filetype).movetobackup()
545 shelvedfile(repo, name, filetype).movetobackup()
525 cleanupoldbackups(repo)
546 cleanupoldbackups(repo)
526
547
527 def unshelvecontinue(ui, repo, state, opts):
548 def unshelvecontinue(ui, repo, state, opts):
528 """subcommand to continue an in-progress unshelve"""
549 """subcommand to continue an in-progress unshelve"""
529 # We're finishing off a merge. First parent is our original
550 # We're finishing off a merge. First parent is our original
530 # parent, second is the temporary "fake" commit we're unshelving.
551 # parent, second is the temporary "fake" commit we're unshelving.
531 with repo.lock():
552 with repo.lock():
532 checkparents(repo, state)
553 checkparents(repo, state)
533 ms = merge.mergestate.read(repo)
554 ms = merge.mergestate.read(repo)
534 if [f for f in ms if ms[f] == 'u']:
555 if [f for f in ms if ms[f] == 'u']:
535 raise error.Abort(
556 raise error.Abort(
536 _("unresolved conflicts, can't continue"),
557 _("unresolved conflicts, can't continue"),
537 hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
558 hint=_("see 'hg resolve', then 'hg unshelve --continue'"))
538
559
539 util.rename(repo.join('unshelverebasestate'),
560 util.rename(repo.join('unshelverebasestate'),
540 repo.join('rebasestate'))
561 repo.join('rebasestate'))
541 try:
562 try:
542 rebase.rebase(ui, repo, **{
563 rebase.rebase(ui, repo, **{
543 'continue' : True
564 'continue' : True
544 })
565 })
545 except Exception:
566 except Exception:
546 util.rename(repo.join('rebasestate'),
567 util.rename(repo.join('rebasestate'),
547 repo.join('unshelverebasestate'))
568 repo.join('unshelverebasestate'))
548 raise
569 raise
549
570
550 shelvectx = repo['tip']
571 shelvectx = repo['tip']
551 if not shelvectx in state.pendingctx.children():
572 if not shelvectx in state.pendingctx.children():
552 # rebase was a no-op, so it produced no child commit
573 # rebase was a no-op, so it produced no child commit
553 shelvectx = state.pendingctx
574 shelvectx = state.pendingctx
554 else:
575 else:
555 # only strip the shelvectx if the rebase produced it
576 # only strip the shelvectx if the rebase produced it
556 state.stripnodes.append(shelvectx.node())
577 state.stripnodes.append(shelvectx.node())
557
578
558 mergefiles(ui, repo, state.wctx, shelvectx)
579 mergefiles(ui, repo, state.wctx, shelvectx)
559
580
560 repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
581 repair.strip(ui, repo, state.stripnodes, backup=False, topic='shelve')
561 shelvedstate.clear(repo)
582 shelvedstate.clear(repo)
562 unshelvecleanup(ui, repo, state.name, opts)
583 unshelvecleanup(ui, repo, state.name, opts)
563 ui.status(_("unshelve of '%s' complete\n") % state.name)
584 ui.status(_("unshelve of '%s' complete\n") % state.name)
564
585
565 @command('unshelve',
586 @command('unshelve',
566 [('a', 'abort', None,
587 [('a', 'abort', None,
567 _('abort an incomplete unshelve operation')),
588 _('abort an incomplete unshelve operation')),
568 ('c', 'continue', None,
589 ('c', 'continue', None,
569 _('continue an incomplete unshelve operation')),
590 _('continue an incomplete unshelve operation')),
570 ('k', 'keep', None,
591 ('k', 'keep', None,
571 _('keep shelve after unshelving')),
592 _('keep shelve after unshelving')),
572 ('t', 'tool', '', _('specify merge tool')),
593 ('t', 'tool', '', _('specify merge tool')),
573 ('', 'date', '',
594 ('', 'date', '',
574 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
595 _('set date for temporary commits (DEPRECATED)'), _('DATE'))],
575 _('hg unshelve [SHELVED]'))
596 _('hg unshelve [SHELVED]'))
576 def unshelve(ui, repo, *shelved, **opts):
597 def unshelve(ui, repo, *shelved, **opts):
577 """restore a shelved change to the working directory
598 """restore a shelved change to the working directory
578
599
579 This command accepts an optional name of a shelved change to
600 This command accepts an optional name of a shelved change to
580 restore. If none is given, the most recent shelved change is used.
601 restore. If none is given, the most recent shelved change is used.
581
602
582 If a shelved change is applied successfully, the bundle that
603 If a shelved change is applied successfully, the bundle that
583 contains the shelved changes is moved to a backup location
604 contains the shelved changes is moved to a backup location
584 (.hg/shelve-backup).
605 (.hg/shelve-backup).
585
606
586 Since you can restore a shelved change on top of an arbitrary
607 Since you can restore a shelved change on top of an arbitrary
587 commit, it is possible that unshelving will result in a conflict
608 commit, it is possible that unshelving will result in a conflict
588 between your changes and the commits you are unshelving onto. If
609 between your changes and the commits you are unshelving onto. If
589 this occurs, you must resolve the conflict, then use
610 this occurs, you must resolve the conflict, then use
590 ``--continue`` to complete the unshelve operation. (The bundle
611 ``--continue`` to complete the unshelve operation. (The bundle
591 will not be moved until you successfully complete the unshelve.)
612 will not be moved until you successfully complete the unshelve.)
592
613
593 (Alternatively, you can use ``--abort`` to abandon an unshelve
614 (Alternatively, you can use ``--abort`` to abandon an unshelve
594 that causes a conflict. This reverts the unshelved changes, and
615 that causes a conflict. This reverts the unshelved changes, and
595 leaves the bundle in place.)
616 leaves the bundle in place.)
596
617
597 After a successful unshelve, the shelved changes are stored in a
618 After a successful unshelve, the shelved changes are stored in a
598 backup directory. Only the N most recent backups are kept. N
619 backup directory. Only the N most recent backups are kept. N
599 defaults to 10 but can be overridden using the ``shelve.maxbackups``
620 defaults to 10 but can be overridden using the ``shelve.maxbackups``
600 configuration option.
621 configuration option.
601
622
602 .. container:: verbose
623 .. container:: verbose
603
624
604 Timestamp in seconds is used to decide order of backups. More
625 Timestamp in seconds is used to decide order of backups. More
605 than ``maxbackups`` backups are kept, if same timestamp
626 than ``maxbackups`` backups are kept, if same timestamp
606 prevents from deciding exact order of them, for safety.
627 prevents from deciding exact order of them, for safety.
607 """
628 """
608 with repo.wlock():
629 with repo.wlock():
609 return _dounshelve(ui, repo, *shelved, **opts)
630 return _dounshelve(ui, repo, *shelved, **opts)
610
631
611 def _dounshelve(ui, repo, *shelved, **opts):
632 def _dounshelve(ui, repo, *shelved, **opts):
612 abortf = opts['abort']
633 abortf = opts['abort']
613 continuef = opts['continue']
634 continuef = opts['continue']
614 if not abortf and not continuef:
635 if not abortf and not continuef:
615 cmdutil.checkunfinished(repo)
636 cmdutil.checkunfinished(repo)
616
637
617 if abortf or continuef:
638 if abortf or continuef:
618 if abortf and continuef:
639 if abortf and continuef:
619 raise error.Abort(_('cannot use both abort and continue'))
640 raise error.Abort(_('cannot use both abort and continue'))
620 if shelved:
641 if shelved:
621 raise error.Abort(_('cannot combine abort/continue with '
642 raise error.Abort(_('cannot combine abort/continue with '
622 'naming a shelved change'))
643 'naming a shelved change'))
623 if abortf and opts.get('tool', False):
644 if abortf and opts.get('tool', False):
624 ui.warn(_('tool option will be ignored\n'))
645 ui.warn(_('tool option will be ignored\n'))
625
646
626 try:
647 try:
627 state = shelvedstate.load(repo)
648 state = shelvedstate.load(repo)
628 except IOError as err:
649 except IOError as err:
629 if err.errno != errno.ENOENT:
650 if err.errno != errno.ENOENT:
630 raise
651 raise
631 cmdutil.wrongtooltocontinue(repo, _('unshelve'))
652 cmdutil.wrongtooltocontinue(repo, _('unshelve'))
632
653
633 if abortf:
654 if abortf:
634 return unshelveabort(ui, repo, state, opts)
655 return unshelveabort(ui, repo, state, opts)
635 elif continuef:
656 elif continuef:
636 return unshelvecontinue(ui, repo, state, opts)
657 return unshelvecontinue(ui, repo, state, opts)
637 elif len(shelved) > 1:
658 elif len(shelved) > 1:
638 raise error.Abort(_('can only unshelve one change at a time'))
659 raise error.Abort(_('can only unshelve one change at a time'))
639 elif not shelved:
660 elif not shelved:
640 shelved = listshelves(repo)
661 shelved = listshelves(repo)
641 if not shelved:
662 if not shelved:
642 raise error.Abort(_('no shelved changes to apply!'))
663 raise error.Abort(_('no shelved changes to apply!'))
643 basename = util.split(shelved[0][1])[1]
664 basename = util.split(shelved[0][1])[1]
644 ui.status(_("unshelving change '%s'\n") % basename)
665 ui.status(_("unshelving change '%s'\n") % basename)
645 else:
666 else:
646 basename = shelved[0]
667 basename = shelved[0]
647
668
648 if not shelvedfile(repo, basename, 'patch').exists():
669 if not shelvedfile(repo, basename, 'patch').exists():
649 raise error.Abort(_("shelved change '%s' not found") % basename)
670 raise error.Abort(_("shelved change '%s' not found") % basename)
650
671
651 oldquiet = ui.quiet
672 oldquiet = ui.quiet
652 lock = tr = None
673 lock = tr = None
653 forcemerge = ui.backupconfig('ui', 'forcemerge')
674 forcemerge = ui.backupconfig('ui', 'forcemerge')
654 try:
675 try:
655 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'unshelve')
676 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'unshelve')
656 lock = repo.lock()
677 lock = repo.lock()
657
678
658 tr = repo.transaction('unshelve', report=lambda x: None)
679 tr = repo.transaction('unshelve', report=lambda x: None)
659 oldtiprev = len(repo)
680 oldtiprev = len(repo)
660
681
661 pctx = repo['.']
682 pctx = repo['.']
662 tmpwctx = pctx
683 tmpwctx = pctx
663 # The goal is to have a commit structure like so:
684 # The goal is to have a commit structure like so:
664 # ...-> pctx -> tmpwctx -> shelvectx
685 # ...-> pctx -> tmpwctx -> shelvectx
665 # where tmpwctx is an optional commit with the user's pending changes
686 # where tmpwctx is an optional commit with the user's pending changes
666 # and shelvectx is the unshelved changes. Then we merge it all down
687 # and shelvectx is the unshelved changes. Then we merge it all down
667 # to the original pctx.
688 # to the original pctx.
668
689
669 # Store pending changes in a commit and remember added in case a shelve
690 # Store pending changes in a commit and remember added in case a shelve
670 # contains unknown files that are part of the pending change
691 # contains unknown files that are part of the pending change
671 s = repo.status()
692 s = repo.status()
672 addedbefore = frozenset(s.added)
693 addedbefore = frozenset(s.added)
673 if s.modified or s.added or s.removed or s.deleted:
694 if s.modified or s.added or s.removed or s.deleted:
674 ui.status(_("temporarily committing pending changes "
695 ui.status(_("temporarily committing pending changes "
675 "(restore with 'hg unshelve --abort')\n"))
696 "(restore with 'hg unshelve --abort')\n"))
676 def commitfunc(ui, repo, message, match, opts):
697 def commitfunc(ui, repo, message, match, opts):
677 hasmq = util.safehasattr(repo, 'mq')
698 hasmq = util.safehasattr(repo, 'mq')
678 if hasmq:
699 if hasmq:
679 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
700 saved, repo.mq.checkapplied = repo.mq.checkapplied, False
680
701
681 backup = repo.ui.backupconfig('phases', 'new-commit')
702 backup = repo.ui.backupconfig('phases', 'new-commit')
682 try:
703 try:
683 repo.ui.setconfig('phases', 'new-commit', phases.secret)
704 repo.ui.setconfig('phases', 'new-commit', phases.secret)
684 return repo.commit(message, 'shelve@localhost',
705 return repo.commit(message, 'shelve@localhost',
685 opts.get('date'), match)
706 opts.get('date'), match)
686 finally:
707 finally:
687 repo.ui.restoreconfig(backup)
708 repo.ui.restoreconfig(backup)
688 if hasmq:
709 if hasmq:
689 repo.mq.checkapplied = saved
710 repo.mq.checkapplied = saved
690
711
691 tempopts = {}
712 tempopts = {}
692 tempopts['message'] = "pending changes temporary commit"
713 tempopts['message'] = "pending changes temporary commit"
693 tempopts['date'] = opts.get('date')
714 tempopts['date'] = opts.get('date')
694 ui.quiet = True
715 ui.quiet = True
695 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
716 node = cmdutil.commit(ui, repo, commitfunc, [], tempopts)
696 tmpwctx = repo[node]
717 tmpwctx = repo[node]
697
718
698 ui.quiet = True
719 ui.quiet = True
699 shelvedfile(repo, basename, 'hg').applybundle()
720 shelvedfile(repo, basename, 'hg').applybundle()
700
721
701 ui.quiet = oldquiet
722 ui.quiet = oldquiet
702
723
703 shelvectx = repo['tip']
724 shelvectx = repo['tip']
704
725
705 # If the shelve is not immediately on top of the commit
726 # If the shelve is not immediately on top of the commit
706 # we'll be merging with, rebase it to be on top.
727 # we'll be merging with, rebase it to be on top.
707 if tmpwctx.node() != shelvectx.parents()[0].node():
728 if tmpwctx.node() != shelvectx.parents()[0].node():
708 ui.status(_('rebasing shelved changes\n'))
729 ui.status(_('rebasing shelved changes\n'))
709 try:
730 try:
710 rebase.rebase(ui, repo, **{
731 rebase.rebase(ui, repo, **{
711 'rev' : [shelvectx.rev()],
732 'rev' : [shelvectx.rev()],
712 'dest' : str(tmpwctx.rev()),
733 'dest' : str(tmpwctx.rev()),
713 'keep' : True,
734 'keep' : True,
714 'tool' : opts.get('tool', ''),
735 'tool' : opts.get('tool', ''),
715 })
736 })
716 except error.InterventionRequired:
737 except error.InterventionRequired:
717 tr.close()
738 tr.close()
718
739
719 stripnodes = [repo.changelog.node(rev)
740 stripnodes = [repo.changelog.node(rev)
720 for rev in xrange(oldtiprev, len(repo))]
741 for rev in xrange(oldtiprev, len(repo))]
721 shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
742 shelvedstate.save(repo, basename, pctx, tmpwctx, stripnodes)
722
743
723 util.rename(repo.join('rebasestate'),
744 util.rename(repo.join('rebasestate'),
724 repo.join('unshelverebasestate'))
745 repo.join('unshelverebasestate'))
725 raise error.InterventionRequired(
746 raise error.InterventionRequired(
726 _("unresolved conflicts (see 'hg resolve', then "
747 _("unresolved conflicts (see 'hg resolve', then "
727 "'hg unshelve --continue')"))
748 "'hg unshelve --continue')"))
728
749
729 # refresh ctx after rebase completes
750 # refresh ctx after rebase completes
730 shelvectx = repo['tip']
751 shelvectx = repo['tip']
731
752
732 if not shelvectx in tmpwctx.children():
753 if not shelvectx in tmpwctx.children():
733 # rebase was a no-op, so it produced no child commit
754 # rebase was a no-op, so it produced no child commit
734 shelvectx = tmpwctx
755 shelvectx = tmpwctx
735
756
736 mergefiles(ui, repo, pctx, shelvectx)
757 mergefiles(ui, repo, pctx, shelvectx)
737
758
738 # Forget any files that were unknown before the shelve, unknown before
759 # Forget any files that were unknown before the shelve, unknown before
739 # unshelve started, but are now added.
760 # unshelve started, but are now added.
740 shelveunknown = shelvectx.extra().get('shelve_unknown')
761 shelveunknown = shelvectx.extra().get('shelve_unknown')
741 if shelveunknown:
762 if shelveunknown:
742 shelveunknown = frozenset(shelveunknown.split('\0'))
763 shelveunknown = frozenset(shelveunknown.split('\0'))
743 addedafter = frozenset(repo.status().added)
764 addedafter = frozenset(repo.status().added)
744 toforget = (addedafter & shelveunknown) - addedbefore
765 toforget = (addedafter & shelveunknown) - addedbefore
745 repo[None].forget(toforget)
766 repo[None].forget(toforget)
746
767
747 shelvedstate.clear(repo)
768 shelvedstate.clear(repo)
748
769
749 # The transaction aborting will strip all the commits for us,
770 # The transaction aborting will strip all the commits for us,
750 # but it doesn't update the inmemory structures, so addchangegroup
771 # but it doesn't update the inmemory structures, so addchangegroup
751 # hooks still fire and try to operate on the missing commits.
772 # hooks still fire and try to operate on the missing commits.
752 # Clean up manually to prevent this.
773 # Clean up manually to prevent this.
753 repo.unfiltered().changelog.strip(oldtiprev, tr)
774 repo.unfiltered().changelog.strip(oldtiprev, tr)
754
775
755 unshelvecleanup(ui, repo, basename, opts)
776 unshelvecleanup(ui, repo, basename, opts)
756
777
757 _aborttransaction(repo)
778 _aborttransaction(repo)
758 finally:
779 finally:
759 ui.quiet = oldquiet
780 ui.quiet = oldquiet
760 if tr:
781 if tr:
761 tr.release()
782 tr.release()
762 lockmod.release(lock)
783 lockmod.release(lock)
763 ui.restoreconfig(forcemerge)
784 ui.restoreconfig(forcemerge)
764
785
765 @command('shelve',
786 @command('shelve',
766 [('A', 'addremove', None,
787 [('A', 'addremove', None,
767 _('mark new/missing files as added/removed before shelving')),
788 _('mark new/missing files as added/removed before shelving')),
768 ('u', 'unknown', None,
789 ('u', 'unknown', None,
769 _('store unknown files in the shelve')),
790 _('store unknown files in the shelve')),
770 ('', 'cleanup', None,
791 ('', 'cleanup', None,
771 _('delete all shelved changes')),
792 _('delete all shelved changes')),
772 ('', 'date', '',
793 ('', 'date', '',
773 _('shelve with the specified commit date'), _('DATE')),
794 _('shelve with the specified commit date'), _('DATE')),
774 ('d', 'delete', None,
795 ('d', 'delete', None,
775 _('delete the named shelved change(s)')),
796 _('delete the named shelved change(s)')),
776 ('e', 'edit', False,
797 ('e', 'edit', False,
777 _('invoke editor on commit messages')),
798 _('invoke editor on commit messages')),
778 ('l', 'list', None,
799 ('l', 'list', None,
779 _('list current shelves')),
800 _('list current shelves')),
780 ('m', 'message', '',
801 ('m', 'message', '',
781 _('use text as shelve message'), _('TEXT')),
802 _('use text as shelve message'), _('TEXT')),
782 ('n', 'name', '',
803 ('n', 'name', '',
783 _('use the given name for the shelved commit'), _('NAME')),
804 _('use the given name for the shelved commit'), _('NAME')),
784 ('p', 'patch', None,
805 ('p', 'patch', None,
785 _('show patch')),
806 _('show patch')),
786 ('i', 'interactive', None,
807 ('i', 'interactive', None,
787 _('interactive mode, only works while creating a shelve')),
808 _('interactive mode, only works while creating a shelve')),
788 ('', 'stat', None,
809 ('', 'stat', None,
789 _('output diffstat-style summary of changes'))] + commands.walkopts,
810 _('output diffstat-style summary of changes'))] + commands.walkopts,
790 _('hg shelve [OPTION]... [FILE]...'))
811 _('hg shelve [OPTION]... [FILE]...'))
791 def shelvecmd(ui, repo, *pats, **opts):
812 def shelvecmd(ui, repo, *pats, **opts):
792 '''save and set aside changes from the working directory
813 '''save and set aside changes from the working directory
793
814
794 Shelving takes files that "hg status" reports as not clean, saves
815 Shelving takes files that "hg status" reports as not clean, saves
795 the modifications to a bundle (a shelved change), and reverts the
816 the modifications to a bundle (a shelved change), and reverts the
796 files so that their state in the working directory becomes clean.
817 files so that their state in the working directory becomes clean.
797
818
798 To restore these changes to the working directory, using "hg
819 To restore these changes to the working directory, using "hg
799 unshelve"; this will work even if you switch to a different
820 unshelve"; this will work even if you switch to a different
800 commit.
821 commit.
801
822
802 When no files are specified, "hg shelve" saves all not-clean
823 When no files are specified, "hg shelve" saves all not-clean
803 files. If specific files or directories are named, only changes to
824 files. If specific files or directories are named, only changes to
804 those files are shelved.
825 those files are shelved.
805
826
806 Each shelved change has a name that makes it easier to find later.
827 Each shelved change has a name that makes it easier to find later.
807 The name of a shelved change defaults to being based on the active
828 The name of a shelved change defaults to being based on the active
808 bookmark, or if there is no active bookmark, the current named
829 bookmark, or if there is no active bookmark, the current named
809 branch. To specify a different name, use ``--name``.
830 branch. To specify a different name, use ``--name``.
810
831
811 To see a list of existing shelved changes, use the ``--list``
832 To see a list of existing shelved changes, use the ``--list``
812 option. For each shelved change, this will print its name, age,
833 option. For each shelved change, this will print its name, age,
813 and description; use ``--patch`` or ``--stat`` for more details.
834 and description; use ``--patch`` or ``--stat`` for more details.
814
835
815 To delete specific shelved changes, use ``--delete``. To delete
836 To delete specific shelved changes, use ``--delete``. To delete
816 all shelved changes, use ``--cleanup``.
837 all shelved changes, use ``--cleanup``.
817 '''
838 '''
818 allowables = [
839 allowables = [
819 ('addremove', set(['create'])), # 'create' is pseudo action
840 ('addremove', set(['create'])), # 'create' is pseudo action
820 ('unknown', set(['create'])),
841 ('unknown', set(['create'])),
821 ('cleanup', set(['cleanup'])),
842 ('cleanup', set(['cleanup'])),
822 # ('date', set(['create'])), # ignored for passing '--date "0 0"' in tests
843 # ('date', set(['create'])), # ignored for passing '--date "0 0"' in tests
823 ('delete', set(['delete'])),
844 ('delete', set(['delete'])),
824 ('edit', set(['create'])),
845 ('edit', set(['create'])),
825 ('list', set(['list'])),
846 ('list', set(['list'])),
826 ('message', set(['create'])),
847 ('message', set(['create'])),
827 ('name', set(['create'])),
848 ('name', set(['create'])),
828 ('patch', set(['patch', 'list'])),
849 ('patch', set(['patch', 'list'])),
829 ('stat', set(['stat', 'list'])),
850 ('stat', set(['stat', 'list'])),
830 ]
851 ]
831 def checkopt(opt):
852 def checkopt(opt):
832 if opts[opt]:
853 if opts[opt]:
833 for i, allowable in allowables:
854 for i, allowable in allowables:
834 if opts[i] and opt not in allowable:
855 if opts[i] and opt not in allowable:
835 raise error.Abort(_("options '--%s' and '--%s' may not be "
856 raise error.Abort(_("options '--%s' and '--%s' may not be "
836 "used together") % (opt, i))
857 "used together") % (opt, i))
837 return True
858 return True
838 if checkopt('cleanup'):
859 if checkopt('cleanup'):
839 if pats:
860 if pats:
840 raise error.Abort(_("cannot specify names when using '--cleanup'"))
861 raise error.Abort(_("cannot specify names when using '--cleanup'"))
841 return cleanupcmd(ui, repo)
862 return cleanupcmd(ui, repo)
842 elif checkopt('delete'):
863 elif checkopt('delete'):
843 return deletecmd(ui, repo, pats)
864 return deletecmd(ui, repo, pats)
844 elif checkopt('list'):
865 elif checkopt('list'):
845 return listcmd(ui, repo, pats, opts)
866 return listcmd(ui, repo, pats, opts)
846 elif checkopt('patch'):
867 elif checkopt('patch'):
847 return singlepatchcmds(ui, repo, pats, opts, subcommand='patch')
868 return singlepatchcmds(ui, repo, pats, opts, subcommand='patch')
848 elif checkopt('stat'):
869 elif checkopt('stat'):
849 return singlepatchcmds(ui, repo, pats, opts, subcommand='stat')
870 return singlepatchcmds(ui, repo, pats, opts, subcommand='stat')
850 else:
871 else:
851 return createcmd(ui, repo, pats, opts)
872 return createcmd(ui, repo, pats, opts)
852
873
853 def extsetup(ui):
874 def extsetup(ui):
854 cmdutil.unfinishedstates.append(
875 cmdutil.unfinishedstates.append(
855 [shelvedstate._filename, False, False,
876 [shelvedstate._filename, False, False,
856 _('unshelve already in progress'),
877 _('unshelve already in progress'),
857 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
878 _("use 'hg unshelve --continue' or 'hg unshelve --abort'")])
858 cmdutil.afterresolvedstates.append(
879 cmdutil.afterresolvedstates.append(
859 [shelvedstate._filename, _('hg unshelve --continue')])
880 [shelvedstate._filename, _('hg unshelve --continue')])
@@ -1,149 +1,148 b''
1 #require test-repo
1 #require test-repo
2
2
3 $ cd "$TESTDIR"/..
3 $ cd "$TESTDIR"/..
4
4
5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
5 $ hg files 'set:(**.py)' | sed 's|\\|/|g' | xargs python contrib/check-py3-compat.py
6 contrib/check-code.py not using absolute_import
6 contrib/check-code.py not using absolute_import
7 contrib/check-code.py requires print_function
7 contrib/check-code.py requires print_function
8 contrib/debugshell.py not using absolute_import
8 contrib/debugshell.py not using absolute_import
9 contrib/hgfixes/fix_bytes.py not using absolute_import
9 contrib/hgfixes/fix_bytes.py not using absolute_import
10 contrib/hgfixes/fix_bytesmod.py not using absolute_import
10 contrib/hgfixes/fix_bytesmod.py not using absolute_import
11 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
11 contrib/hgfixes/fix_leftover_imports.py not using absolute_import
12 contrib/import-checker.py not using absolute_import
12 contrib/import-checker.py not using absolute_import
13 contrib/import-checker.py requires print_function
13 contrib/import-checker.py requires print_function
14 contrib/memory.py not using absolute_import
14 contrib/memory.py not using absolute_import
15 contrib/perf.py not using absolute_import
15 contrib/perf.py not using absolute_import
16 contrib/python-hook-examples.py not using absolute_import
16 contrib/python-hook-examples.py not using absolute_import
17 contrib/revsetbenchmarks.py not using absolute_import
17 contrib/revsetbenchmarks.py not using absolute_import
18 contrib/revsetbenchmarks.py requires print_function
18 contrib/revsetbenchmarks.py requires print_function
19 contrib/showstack.py not using absolute_import
19 contrib/showstack.py not using absolute_import
20 contrib/synthrepo.py not using absolute_import
20 contrib/synthrepo.py not using absolute_import
21 contrib/win32/hgwebdir_wsgi.py not using absolute_import
21 contrib/win32/hgwebdir_wsgi.py not using absolute_import
22 doc/check-seclevel.py not using absolute_import
22 doc/check-seclevel.py not using absolute_import
23 doc/gendoc.py not using absolute_import
23 doc/gendoc.py not using absolute_import
24 doc/hgmanpage.py not using absolute_import
24 doc/hgmanpage.py not using absolute_import
25 hgext/__init__.py not using absolute_import
25 hgext/__init__.py not using absolute_import
26 hgext/color.py not using absolute_import
26 hgext/color.py not using absolute_import
27 hgext/convert/__init__.py not using absolute_import
27 hgext/convert/__init__.py not using absolute_import
28 hgext/convert/bzr.py not using absolute_import
28 hgext/convert/bzr.py not using absolute_import
29 hgext/convert/common.py not using absolute_import
29 hgext/convert/common.py not using absolute_import
30 hgext/convert/convcmd.py not using absolute_import
30 hgext/convert/convcmd.py not using absolute_import
31 hgext/convert/cvs.py not using absolute_import
31 hgext/convert/cvs.py not using absolute_import
32 hgext/convert/subversion.py not using absolute_import
32 hgext/convert/subversion.py not using absolute_import
33 hgext/convert/transport.py not using absolute_import
33 hgext/convert/transport.py not using absolute_import
34 hgext/eol.py not using absolute_import
34 hgext/eol.py not using absolute_import
35 hgext/extdiff.py not using absolute_import
35 hgext/extdiff.py not using absolute_import
36 hgext/factotum.py not using absolute_import
36 hgext/factotum.py not using absolute_import
37 hgext/fetch.py not using absolute_import
37 hgext/fetch.py not using absolute_import
38 hgext/gpg.py not using absolute_import
38 hgext/gpg.py not using absolute_import
39 hgext/graphlog.py not using absolute_import
39 hgext/graphlog.py not using absolute_import
40 hgext/hgcia.py not using absolute_import
40 hgext/hgcia.py not using absolute_import
41 hgext/hgk.py not using absolute_import
41 hgext/hgk.py not using absolute_import
42 hgext/highlight/__init__.py not using absolute_import
42 hgext/highlight/__init__.py not using absolute_import
43 hgext/highlight/highlight.py not using absolute_import
43 hgext/highlight/highlight.py not using absolute_import
44 hgext/histedit.py not using absolute_import
44 hgext/histedit.py not using absolute_import
45 hgext/largefiles/__init__.py not using absolute_import
45 hgext/largefiles/__init__.py not using absolute_import
46 hgext/largefiles/basestore.py not using absolute_import
46 hgext/largefiles/basestore.py not using absolute_import
47 hgext/largefiles/lfcommands.py not using absolute_import
47 hgext/largefiles/lfcommands.py not using absolute_import
48 hgext/largefiles/lfutil.py not using absolute_import
48 hgext/largefiles/lfutil.py not using absolute_import
49 hgext/largefiles/localstore.py not using absolute_import
49 hgext/largefiles/localstore.py not using absolute_import
50 hgext/largefiles/overrides.py not using absolute_import
50 hgext/largefiles/overrides.py not using absolute_import
51 hgext/largefiles/proto.py not using absolute_import
51 hgext/largefiles/proto.py not using absolute_import
52 hgext/largefiles/remotestore.py not using absolute_import
52 hgext/largefiles/remotestore.py not using absolute_import
53 hgext/largefiles/reposetup.py not using absolute_import
53 hgext/largefiles/reposetup.py not using absolute_import
54 hgext/largefiles/uisetup.py not using absolute_import
54 hgext/largefiles/uisetup.py not using absolute_import
55 hgext/largefiles/wirestore.py not using absolute_import
55 hgext/largefiles/wirestore.py not using absolute_import
56 hgext/mq.py not using absolute_import
56 hgext/mq.py not using absolute_import
57 hgext/notify.py not using absolute_import
57 hgext/notify.py not using absolute_import
58 hgext/patchbomb.py not using absolute_import
58 hgext/patchbomb.py not using absolute_import
59 hgext/purge.py not using absolute_import
59 hgext/purge.py not using absolute_import
60 hgext/rebase.py not using absolute_import
60 hgext/rebase.py not using absolute_import
61 hgext/record.py not using absolute_import
61 hgext/record.py not using absolute_import
62 hgext/relink.py not using absolute_import
62 hgext/relink.py not using absolute_import
63 hgext/schemes.py not using absolute_import
63 hgext/schemes.py not using absolute_import
64 hgext/share.py not using absolute_import
64 hgext/share.py not using absolute_import
65 hgext/shelve.py not using absolute_import
66 hgext/transplant.py not using absolute_import
65 hgext/transplant.py not using absolute_import
67 hgext/win32mbcs.py not using absolute_import
66 hgext/win32mbcs.py not using absolute_import
68 hgext/win32text.py not using absolute_import
67 hgext/win32text.py not using absolute_import
69 i18n/check-translation.py not using absolute_import
68 i18n/check-translation.py not using absolute_import
70 i18n/polib.py not using absolute_import
69 i18n/polib.py not using absolute_import
71 setup.py not using absolute_import
70 setup.py not using absolute_import
72 tests/filterpyflakes.py requires print_function
71 tests/filterpyflakes.py requires print_function
73 tests/generate-working-copy-states.py requires print_function
72 tests/generate-working-copy-states.py requires print_function
74 tests/get-with-headers.py requires print_function
73 tests/get-with-headers.py requires print_function
75 tests/heredoctest.py requires print_function
74 tests/heredoctest.py requires print_function
76 tests/hypothesishelpers.py not using absolute_import
75 tests/hypothesishelpers.py not using absolute_import
77 tests/hypothesishelpers.py requires print_function
76 tests/hypothesishelpers.py requires print_function
78 tests/killdaemons.py not using absolute_import
77 tests/killdaemons.py not using absolute_import
79 tests/md5sum.py not using absolute_import
78 tests/md5sum.py not using absolute_import
80 tests/mockblackbox.py not using absolute_import
79 tests/mockblackbox.py not using absolute_import
81 tests/printenv.py not using absolute_import
80 tests/printenv.py not using absolute_import
82 tests/readlink.py not using absolute_import
81 tests/readlink.py not using absolute_import
83 tests/readlink.py requires print_function
82 tests/readlink.py requires print_function
84 tests/revlog-formatv0.py not using absolute_import
83 tests/revlog-formatv0.py not using absolute_import
85 tests/run-tests.py not using absolute_import
84 tests/run-tests.py not using absolute_import
86 tests/seq.py not using absolute_import
85 tests/seq.py not using absolute_import
87 tests/seq.py requires print_function
86 tests/seq.py requires print_function
88 tests/silenttestrunner.py not using absolute_import
87 tests/silenttestrunner.py not using absolute_import
89 tests/silenttestrunner.py requires print_function
88 tests/silenttestrunner.py requires print_function
90 tests/sitecustomize.py not using absolute_import
89 tests/sitecustomize.py not using absolute_import
91 tests/svn-safe-append.py not using absolute_import
90 tests/svn-safe-append.py not using absolute_import
92 tests/svnxml.py not using absolute_import
91 tests/svnxml.py not using absolute_import
93 tests/test-ancestor.py requires print_function
92 tests/test-ancestor.py requires print_function
94 tests/test-atomictempfile.py not using absolute_import
93 tests/test-atomictempfile.py not using absolute_import
95 tests/test-batching.py not using absolute_import
94 tests/test-batching.py not using absolute_import
96 tests/test-batching.py requires print_function
95 tests/test-batching.py requires print_function
97 tests/test-bdiff.py not using absolute_import
96 tests/test-bdiff.py not using absolute_import
98 tests/test-bdiff.py requires print_function
97 tests/test-bdiff.py requires print_function
99 tests/test-context.py not using absolute_import
98 tests/test-context.py not using absolute_import
100 tests/test-context.py requires print_function
99 tests/test-context.py requires print_function
101 tests/test-demandimport.py not using absolute_import
100 tests/test-demandimport.py not using absolute_import
102 tests/test-demandimport.py requires print_function
101 tests/test-demandimport.py requires print_function
103 tests/test-dispatch.py not using absolute_import
102 tests/test-dispatch.py not using absolute_import
104 tests/test-dispatch.py requires print_function
103 tests/test-dispatch.py requires print_function
105 tests/test-doctest.py not using absolute_import
104 tests/test-doctest.py not using absolute_import
106 tests/test-duplicateoptions.py not using absolute_import
105 tests/test-duplicateoptions.py not using absolute_import
107 tests/test-duplicateoptions.py requires print_function
106 tests/test-duplicateoptions.py requires print_function
108 tests/test-filecache.py not using absolute_import
107 tests/test-filecache.py not using absolute_import
109 tests/test-filecache.py requires print_function
108 tests/test-filecache.py requires print_function
110 tests/test-filelog.py not using absolute_import
109 tests/test-filelog.py not using absolute_import
111 tests/test-filelog.py requires print_function
110 tests/test-filelog.py requires print_function
112 tests/test-hg-parseurl.py not using absolute_import
111 tests/test-hg-parseurl.py not using absolute_import
113 tests/test-hg-parseurl.py requires print_function
112 tests/test-hg-parseurl.py requires print_function
114 tests/test-hgweb-auth.py not using absolute_import
113 tests/test-hgweb-auth.py not using absolute_import
115 tests/test-hgweb-auth.py requires print_function
114 tests/test-hgweb-auth.py requires print_function
116 tests/test-hgwebdir-paths.py not using absolute_import
115 tests/test-hgwebdir-paths.py not using absolute_import
117 tests/test-hybridencode.py not using absolute_import
116 tests/test-hybridencode.py not using absolute_import
118 tests/test-hybridencode.py requires print_function
117 tests/test-hybridencode.py requires print_function
119 tests/test-lrucachedict.py not using absolute_import
118 tests/test-lrucachedict.py not using absolute_import
120 tests/test-lrucachedict.py requires print_function
119 tests/test-lrucachedict.py requires print_function
121 tests/test-manifest.py not using absolute_import
120 tests/test-manifest.py not using absolute_import
122 tests/test-minirst.py not using absolute_import
121 tests/test-minirst.py not using absolute_import
123 tests/test-minirst.py requires print_function
122 tests/test-minirst.py requires print_function
124 tests/test-parseindex2.py not using absolute_import
123 tests/test-parseindex2.py not using absolute_import
125 tests/test-parseindex2.py requires print_function
124 tests/test-parseindex2.py requires print_function
126 tests/test-pathencode.py not using absolute_import
125 tests/test-pathencode.py not using absolute_import
127 tests/test-pathencode.py requires print_function
126 tests/test-pathencode.py requires print_function
128 tests/test-propertycache.py not using absolute_import
127 tests/test-propertycache.py not using absolute_import
129 tests/test-propertycache.py requires print_function
128 tests/test-propertycache.py requires print_function
130 tests/test-revlog-ancestry.py not using absolute_import
129 tests/test-revlog-ancestry.py not using absolute_import
131 tests/test-revlog-ancestry.py requires print_function
130 tests/test-revlog-ancestry.py requires print_function
132 tests/test-run-tests.py not using absolute_import
131 tests/test-run-tests.py not using absolute_import
133 tests/test-simplemerge.py not using absolute_import
132 tests/test-simplemerge.py not using absolute_import
134 tests/test-status-inprocess.py not using absolute_import
133 tests/test-status-inprocess.py not using absolute_import
135 tests/test-status-inprocess.py requires print_function
134 tests/test-status-inprocess.py requires print_function
136 tests/test-symlink-os-yes-fs-no.py not using absolute_import
135 tests/test-symlink-os-yes-fs-no.py not using absolute_import
137 tests/test-trusted.py not using absolute_import
136 tests/test-trusted.py not using absolute_import
138 tests/test-trusted.py requires print_function
137 tests/test-trusted.py requires print_function
139 tests/test-ui-color.py not using absolute_import
138 tests/test-ui-color.py not using absolute_import
140 tests/test-ui-color.py requires print_function
139 tests/test-ui-color.py requires print_function
141 tests/test-ui-config.py not using absolute_import
140 tests/test-ui-config.py not using absolute_import
142 tests/test-ui-config.py requires print_function
141 tests/test-ui-config.py requires print_function
143 tests/test-ui-verbosity.py not using absolute_import
142 tests/test-ui-verbosity.py not using absolute_import
144 tests/test-ui-verbosity.py requires print_function
143 tests/test-ui-verbosity.py requires print_function
145 tests/test-url.py not using absolute_import
144 tests/test-url.py not using absolute_import
146 tests/test-url.py requires print_function
145 tests/test-url.py requires print_function
147 tests/test-walkrepo.py requires print_function
146 tests/test-walkrepo.py requires print_function
148 tests/test-wireproto.py requires print_function
147 tests/test-wireproto.py requires print_function
149 tests/tinyproxy.py requires print_function
148 tests/tinyproxy.py requires print_function
General Comments 0
You need to be logged in to leave comments. Login now