241 """subcommand that creates a new shelve""" |
241 """subcommand that creates a new shelve""" |
242 with repo.wlock(): |
242 with repo.wlock(): |
243 cmdutil.checkunfinished(repo) |
243 cmdutil.checkunfinished(repo) |
244 return _docreatecmd(ui, repo, pats, opts) |
244 return _docreatecmd(ui, repo, pats, opts) |
245 |
245 |
|
246 def getshelvename(repo, parent, opts): |
|
247 """Decide on the name this shelve is going to have""" |
|
248 def gennames(): |
|
249 yield label |
|
250 for i in xrange(1, 100): |
|
251 yield '%s-%02d' % (label, i) |
|
252 name = opts.get('name') |
|
253 label = repo._activebookmark or parent.branch() or 'default' |
|
254 # slashes aren't allowed in filenames, therefore we rename it |
|
255 label = label.replace('/', '_') |
|
256 |
|
257 if name: |
|
258 if shelvedfile(repo, name, 'hg').exists(): |
|
259 e = _("a shelved change named '%s' already exists") % name |
|
260 raise error.Abort(e) |
|
261 else: |
|
262 for n in gennames(): |
|
263 if not shelvedfile(repo, n, 'hg').exists(): |
|
264 name = n |
|
265 break |
|
266 else: |
|
267 raise error.Abort(_("too many shelved changes named '%s'") % label) |
|
268 |
|
269 # ensure we are not creating a subdirectory or a hidden file |
|
270 if '/' in name or '\\' in name: |
|
271 raise error.Abort(_('shelved change names may not contain slashes')) |
|
272 if name.startswith('.'): |
|
273 raise error.Abort(_("shelved change names may not start with '.'")) |
|
274 return name |
|
275 |
246 def _docreatecmd(ui, repo, pats, opts): |
276 def _docreatecmd(ui, repo, pats, opts): |
247 def mutableancestors(ctx): |
277 def mutableancestors(ctx): |
248 """return all mutable ancestors for ctx (included) |
278 """return all mutable ancestors for ctx (included) |
249 |
279 |
250 Much faster than the revset ancestors(ctx) & draft()""" |
280 Much faster than the revset ancestors(ctx) & draft()""" |
268 parent = parents[0] |
298 parent = parents[0] |
269 origbranch = wctx.branch() |
299 origbranch = wctx.branch() |
270 |
300 |
271 # we never need the user, so we use a generic user for all shelve operations |
301 # we never need the user, so we use a generic user for all shelve operations |
272 user = 'shelve@localhost' |
302 user = 'shelve@localhost' |
273 label = repo._activebookmark or parent.branch() or 'default' |
|
274 |
|
275 # slashes aren't allowed in filenames, therefore we rename it |
|
276 label = label.replace('/', '_') |
|
277 |
|
278 def gennames(): |
|
279 yield label |
|
280 for i in xrange(1, 100): |
|
281 yield '%s-%02d' % (label, i) |
|
282 |
303 |
283 if parent.node() != nodemod.nullid: |
304 if parent.node() != nodemod.nullid: |
284 desc = "changes to: %s" % parent.description().split('\n', 1)[0] |
305 desc = "changes to: %s" % parent.description().split('\n', 1)[0] |
285 else: |
306 else: |
286 desc = '(changes in empty repository)' |
307 desc = '(changes in empty repository)' |
287 |
308 |
288 if not opts.get('message'): |
309 if not opts.get('message'): |
289 opts['message'] = desc |
310 opts['message'] = desc |
290 |
311 |
291 name = opts.get('name') |
|
292 |
|
293 lock = tr = None |
312 lock = tr = None |
294 try: |
313 try: |
295 lock = repo.lock() |
314 lock = repo.lock() |
296 |
315 |
297 # use an uncommitted transaction to generate the bundle to avoid |
316 # use an uncommitted transaction to generate the bundle to avoid |
298 # pull races. ensure we don't print the abort message to stderr. |
317 # pull races. ensure we don't print the abort message to stderr. |
299 tr = repo.transaction('commit', report=lambda x: None) |
318 tr = repo.transaction('commit', report=lambda x: None) |
300 |
319 |
301 if name: |
|
302 if shelvedfile(repo, name, 'hg').exists(): |
|
303 raise error.Abort(_("a shelved change named '%s' already exists" |
|
304 ) % name) |
|
305 else: |
|
306 for n in gennames(): |
|
307 if not shelvedfile(repo, n, 'hg').exists(): |
|
308 name = n |
|
309 break |
|
310 else: |
|
311 raise error.Abort(_("too many shelved changes named '%s'") % |
|
312 label) |
|
313 |
|
314 # ensure we are not creating a subdirectory or a hidden file |
|
315 if '/' in name or '\\' in name: |
|
316 raise error.Abort(_('shelved change names may not contain slashes')) |
|
317 if name.startswith('.'): |
|
318 raise error.Abort(_("shelved change names may not start with '.'")) |
|
319 interactive = opts.get('interactive', False) |
320 interactive = opts.get('interactive', False) |
320 includeunknown = (opts.get('unknown', False) and |
321 includeunknown = (opts.get('unknown', False) and |
321 not opts.get('addremove', False)) |
322 not opts.get('addremove', False)) |
322 |
323 |
|
324 name = getshelvename(repo, parent, opts) |
323 extra={} |
325 extra={} |
324 if includeunknown: |
326 if includeunknown: |
325 s = repo.status(match=scmutil.match(repo[None], pats, opts), |
327 s = repo.status(match=scmutil.match(repo[None], pats, opts), |
326 unknown=True) |
328 unknown=True) |
327 if s.unknown: |
329 if s.unknown: |