Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/cmdutil.py @ 5589:9981b6b19ecf
move commands.docopy to cmdutil.copy
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Sun, 02 Dec 2007 18:11:59 -0600 |
parents | db6633f11d59 |
children | 4b7b21acede0 |
comparison
equal
deleted
inserted
replaced
5588:083b6e3142a2 | 5589:9981b6b19ecf |
---|---|
6 # of the GNU General Public License, incorporated herein by reference. | 6 # of the GNU General Public License, incorporated herein by reference. |
7 | 7 |
8 from node import * | 8 from node import * |
9 from i18n import _ | 9 from i18n import _ |
10 import os, sys, bisect, stat | 10 import os, sys, bisect, stat |
11 import mdiff, bdiff, util, templater, patch | 11 import mdiff, bdiff, util, templater, patch, errno |
12 | 12 |
13 revrangesep = ':' | 13 revrangesep = ':' |
14 | 14 |
15 class UnknownCommand(Exception): | 15 class UnknownCommand(Exception): |
16 """Exception raised if command is not in the command table.""" | 16 """Exception raised if command is not in the command table.""" |
283 repo.ui.status(_('recording removal of %s as rename to %s ' | 283 repo.ui.status(_('recording removal of %s as rename to %s ' |
284 '(%d%% similar)\n') % | 284 '(%d%% similar)\n') % |
285 (oldrel, newrel, score * 100)) | 285 (oldrel, newrel, score * 100)) |
286 if not dry_run: | 286 if not dry_run: |
287 repo.copy(old, new) | 287 repo.copy(old, new) |
288 | |
289 def copy(ui, repo, pats, opts): | |
290 # called with the repo lock held | |
291 # | |
292 # hgsep => pathname that uses "/" to separate directories | |
293 # ossep => pathname that uses os.sep to separate directories | |
294 cwd = repo.getcwd() | |
295 errors = 0 | |
296 copied = [] | |
297 targets = {} | |
298 | |
299 # abs: hgsep | |
300 # rel: ossep | |
301 # return: hgsep | |
302 def okaytocopy(abs, rel, exact): | |
303 reasons = {'?': _('is not managed'), | |
304 'r': _('has been marked for remove')} | |
305 state = repo.dirstate[abs] | |
306 reason = reasons.get(state) | |
307 if reason: | |
308 if exact: | |
309 ui.warn(_('%s: not copying - file %s\n') % (rel, reason)) | |
310 else: | |
311 if state == 'a': | |
312 origsrc = repo.dirstate.copied(abs) | |
313 if origsrc is not None: | |
314 return origsrc | |
315 return abs | |
316 | |
317 # origsrc: hgsep | |
318 # abssrc: hgsep | |
319 # relsrc: ossep | |
320 # otarget: ossep | |
321 def copy(origsrc, abssrc, relsrc, otarget, exact): | |
322 abstarget = util.canonpath(repo.root, cwd, otarget) | |
323 reltarget = repo.pathto(abstarget, cwd) | |
324 prevsrc = targets.get(abstarget) | |
325 src = repo.wjoin(abssrc) | |
326 target = repo.wjoin(abstarget) | |
327 if prevsrc is not None: | |
328 ui.warn(_('%s: not overwriting - %s collides with %s\n') % | |
329 (reltarget, repo.pathto(abssrc, cwd), | |
330 repo.pathto(prevsrc, cwd))) | |
331 return | |
332 if (not opts['after'] and os.path.exists(target) or | |
333 opts['after'] and repo.dirstate[abstarget] in 'mn'): | |
334 if not opts['force']: | |
335 ui.warn(_('%s: not overwriting - file exists\n') % | |
336 reltarget) | |
337 return | |
338 if not opts['after'] and not opts.get('dry_run'): | |
339 os.unlink(target) | |
340 if opts['after']: | |
341 if not os.path.exists(target): | |
342 return | |
343 else: | |
344 targetdir = os.path.dirname(target) or '.' | |
345 if not os.path.isdir(targetdir) and not opts.get('dry_run'): | |
346 os.makedirs(targetdir) | |
347 try: | |
348 restore = repo.dirstate[abstarget] == 'r' | |
349 if restore and not opts.get('dry_run'): | |
350 repo.undelete([abstarget]) | |
351 try: | |
352 if not opts.get('dry_run'): | |
353 util.copyfile(src, target) | |
354 restore = False | |
355 finally: | |
356 if restore: | |
357 repo.remove([abstarget]) | |
358 except IOError, inst: | |
359 if inst.errno == errno.ENOENT: | |
360 ui.warn(_('%s: deleted in working copy\n') % relsrc) | |
361 else: | |
362 ui.warn(_('%s: cannot copy - %s\n') % | |
363 (relsrc, inst.strerror)) | |
364 errors += 1 | |
365 return | |
366 if ui.verbose or not exact: | |
367 ui.status(_('copying %s to %s\n') % (relsrc, reltarget)) | |
368 targets[abstarget] = abssrc | |
369 if abstarget != origsrc: | |
370 if repo.dirstate[origsrc] == 'a': | |
371 if not ui.quiet: | |
372 ui.warn(_("%s has not been committed yet, so no copy " | |
373 "data will be stored for %s.\n") | |
374 % (repo.pathto(origsrc, cwd), reltarget)) | |
375 if abstarget not in repo.dirstate and not opts.get('dry_run'): | |
376 repo.add([abstarget]) | |
377 elif not opts.get('dry_run'): | |
378 repo.copy(origsrc, abstarget) | |
379 copied.append((abssrc, relsrc, exact)) | |
380 | |
381 # pat: ossep | |
382 # dest ossep | |
383 # srcs: list of (hgsep, hgsep, ossep, bool) | |
384 # return: function that takes hgsep and returns ossep | |
385 def targetpathfn(pat, dest, srcs): | |
386 if os.path.isdir(pat): | |
387 abspfx = util.canonpath(repo.root, cwd, pat) | |
388 abspfx = util.localpath(abspfx) | |
389 if destdirexists: | |
390 striplen = len(os.path.split(abspfx)[0]) | |
391 else: | |
392 striplen = len(abspfx) | |
393 if striplen: | |
394 striplen += len(os.sep) | |
395 res = lambda p: os.path.join(dest, util.localpath(p)[striplen:]) | |
396 elif destdirexists: | |
397 res = lambda p: os.path.join(dest, | |
398 os.path.basename(util.localpath(p))) | |
399 else: | |
400 res = lambda p: dest | |
401 return res | |
402 | |
403 # pat: ossep | |
404 # dest ossep | |
405 # srcs: list of (hgsep, hgsep, ossep, bool) | |
406 # return: function that takes hgsep and returns ossep | |
407 def targetpathafterfn(pat, dest, srcs): | |
408 if util.patkind(pat, None)[0]: | |
409 # a mercurial pattern | |
410 res = lambda p: os.path.join(dest, | |
411 os.path.basename(util.localpath(p))) | |
412 else: | |
413 abspfx = util.canonpath(repo.root, cwd, pat) | |
414 if len(abspfx) < len(srcs[0][0]): | |
415 # A directory. Either the target path contains the last | |
416 # component of the source path or it does not. | |
417 def evalpath(striplen): | |
418 score = 0 | |
419 for s in srcs: | |
420 t = os.path.join(dest, util.localpath(s[0])[striplen:]) | |
421 if os.path.exists(t): | |
422 score += 1 | |
423 return score | |
424 | |
425 abspfx = util.localpath(abspfx) | |
426 striplen = len(abspfx) | |
427 if striplen: | |
428 striplen += len(os.sep) | |
429 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])): | |
430 score = evalpath(striplen) | |
431 striplen1 = len(os.path.split(abspfx)[0]) | |
432 if striplen1: | |
433 striplen1 += len(os.sep) | |
434 if evalpath(striplen1) > score: | |
435 striplen = striplen1 | |
436 res = lambda p: os.path.join(dest, | |
437 util.localpath(p)[striplen:]) | |
438 else: | |
439 # a file | |
440 if destdirexists: | |
441 res = lambda p: os.path.join(dest, | |
442 os.path.basename(util.localpath(p))) | |
443 else: | |
444 res = lambda p: dest | |
445 return res | |
446 | |
447 | |
448 pats = util.expand_glob(pats) | |
449 if not pats: | |
450 raise util.Abort(_('no source or destination specified')) | |
451 if len(pats) == 1: | |
452 raise util.Abort(_('no destination specified')) | |
453 dest = pats.pop() | |
454 destdirexists = os.path.isdir(dest) | |
455 if not destdirexists: | |
456 if len(pats) > 1 or util.patkind(pats[0], None)[0]: | |
457 raise util.Abort(_('with multiple sources, destination must be an ' | |
458 'existing directory')) | |
459 if dest.endswith(os.sep) or os.altsep and dest.endswith(os.altsep): | |
460 raise util.Abort(_('destination %s is not a directory') % dest) | |
461 if opts['after']: | |
462 tfn = targetpathafterfn | |
463 else: | |
464 tfn = targetpathfn | |
465 copylist = [] | |
466 for pat in pats: | |
467 srcs = [] | |
468 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts, | |
469 globbed=True): | |
470 origsrc = okaytocopy(abssrc, relsrc, exact) | |
471 if origsrc: | |
472 srcs.append((origsrc, abssrc, relsrc, exact)) | |
473 if not srcs: | |
474 continue | |
475 copylist.append((tfn(pat, dest, srcs), srcs)) | |
476 if not copylist: | |
477 raise util.Abort(_('no files to copy')) | |
478 | |
479 for targetpath, srcs in copylist: | |
480 for origsrc, abssrc, relsrc, exact in srcs: | |
481 copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact) | |
482 | |
483 if errors: | |
484 ui.warn(_('(consider using --after)\n')) | |
485 return errors, copied | |
288 | 486 |
289 def service(opts, parentfn=None, initfn=None, runfn=None): | 487 def service(opts, parentfn=None, initfn=None, runfn=None): |
290 '''Run a command as a service.''' | 488 '''Run a command as a service.''' |
291 | 489 |
292 if opts['daemon'] and not opts['daemon_pipefds']: | 490 if opts['daemon'] and not opts['daemon_pipefds']: |