comparison mercurial/commands.py @ 1249:a5355fa5e33a

Fix up copy command to behave more like regular "cp". In addition to recording changes, copy now updates the working directory.
author Bryan O'Sullivan <bos@serpentine.com>
date Wed, 14 Sep 2005 14:29:02 -0700
parents 7a70dafbf4b9
children 0ad3f9b27260
comparison
equal deleted inserted replaced
1248:2534b41ce0c5 1249:a5355fa5e33a
683 try: 683 try:
684 repo.commit(files, message, opts['user'], opts['date'], match) 684 repo.commit(files, message, opts['user'], opts['date'], match)
685 except ValueError, inst: 685 except ValueError, inst:
686 raise util.Abort(str(inst)) 686 raise util.Abort(str(inst))
687 687
688 def copy(ui, repo, source, dest): 688 def copy(ui, repo, *pats, **opts):
689 """mark a file as copied or renamed for the next commit""" 689 """mark files as copied for the next commit"""
690 return repo.copy(*relpath(repo, (source, dest))) 690 if not pats:
691 raise util.Abort('no source or destination specified')
692 elif len(pats) == 1:
693 raise util.Abort('no destination specified')
694 pats = list(pats)
695 dest = pats.pop()
696 sources = []
697
698 def okaytocopy(abs, rel, exact):
699 reasons = {'?': 'is not managed',
700 'a': 'has been marked for add'}
701 reason = reasons.get(repo.dirstate.state(abs))
702 if reason:
703 if exact: ui.warn('%s: not copying - file %s\n' % (rel, reason))
704 else:
705 return True
706
707 for src, abs, rel, exact in walk(repo, pats, opts):
708 if okaytocopy(abs, rel, exact):
709 sources.append((abs, rel, exact))
710 if not sources:
711 raise util.Abort('no files to copy')
712
713 cwd = repo.getcwd()
714 absdest = util.canonpath(repo.root, cwd, dest)
715 reldest = util.pathto(cwd, absdest)
716 if os.path.exists(reldest):
717 destisfile = not os.path.isdir(reldest)
718 else:
719 destisfile = len(sources) == 1 or repo.dirstate.state(absdest) != '?'
720
721 if destisfile:
722 if opts['parents']:
723 raise util.Abort('with --parents, destination must be a directory')
724 elif len(sources) > 1:
725 raise util.Abort('with multiple sources, destination must be a '
726 'directory')
727 errs = 0
728 for abs, rel, exact in sources:
729 if opts['parents']:
730 mydest = os.path.join(dest, rel)
731 elif destisfile:
732 mydest = reldest
733 else:
734 mydest = os.path.join(dest, os.path.basename(rel))
735 myabsdest = util.canonpath(repo.root, cwd, mydest)
736 myreldest = util.pathto(cwd, myabsdest)
737 if not opts['force'] and repo.dirstate.state(myabsdest) not in 'a?':
738 ui.warn('%s: not overwriting - file already managed\n' % myreldest)
739 continue
740 mydestdir = os.path.dirname(myreldest) or '.'
741 if not opts['after']:
742 try:
743 if opts['parents']: os.makedirs(mydestdir)
744 elif not destisfile: os.mkdir(mydestdir)
745 except OSError, inst:
746 if inst.errno != errno.EEXIST: raise
747 if ui.verbose or not exact:
748 ui.status('copying %s to %s\n' % (rel, myreldest))
749 if not opts['after']:
750 try:
751 shutil.copyfile(rel, myreldest)
752 n = repo.manifest.tip()
753 mf = repo.manifest.readflags(n)
754 util.set_exec(myreldest, util.is_exec(rel, mf[abs]))
755 except IOError, inst:
756 if inst.errno == errno.ENOENT:
757 ui.warn('%s: deleted in working copy\n' % rel)
758 else:
759 ui.warn('%s: cannot copy - %s\n' % (rel, inst.strerror))
760 errs += 1
761 continue
762 repo.copy(abs, myabsdest)
763 if errs:
764 ui.warn('(consider using --after to record failed copies)\n')
765 return errs
691 766
692 def debugcheckstate(ui, repo): 767 def debugcheckstate(ui, repo):
693 """validate the correctness of the current dirstate""" 768 """validate the correctness of the current dirstate"""
694 parent1, parent2 = repo.dirstate.parents() 769 parent1, parent2 = repo.dirstate.parents()
695 repo.dirstate.read() 770 repo.dirstate.read()
1675 ('t', 'text', "", 'commit message (deprecated: use -m)'), 1750 ('t', 'text', "", 'commit message (deprecated: use -m)'),
1676 ('l', 'logfile', "", 'commit message file'), 1751 ('l', 'logfile', "", 'commit message file'),
1677 ('d', 'date', "", 'date code'), 1752 ('d', 'date', "", 'date code'),
1678 ('u', 'user', "", 'user')], 1753 ('u', 'user', "", 'user')],
1679 'hg commit [OPTION]... [FILE]...'), 1754 'hg commit [OPTION]... [FILE]...'),
1680 "copy": (copy, [], 'hg copy SOURCE DEST'), 1755 "copy|cp": (copy,
1756 [('I', 'include', [], 'include path in search'),
1757 ('X', 'exclude', [], 'exclude path from search'),
1758 ('A', 'after', None, 'record a copy after it has happened'),
1759 ('f', 'force', None, 'replace destination if it exists'),
1760 ('p', 'parents', None, 'append source path to dest')],
1761 'hg copy [OPTION]... [SOURCE]... DEST'),
1681 "debugcheckstate": (debugcheckstate, [], 'debugcheckstate'), 1762 "debugcheckstate": (debugcheckstate, [], 'debugcheckstate'),
1682 "debugconfig": (debugconfig, [], 'debugconfig'), 1763 "debugconfig": (debugconfig, [], 'debugconfig'),
1683 "debugstate": (debugstate, [], 'debugstate'), 1764 "debugstate": (debugstate, [], 'debugstate'),
1684 "debugdata": (debugdata, [], 'debugdata FILE REV'), 1765 "debugdata": (debugdata, [], 'debugdata FILE REV'),
1685 "debugindex": (debugindex, [], 'debugindex FILE'), 1766 "debugindex": (debugindex, [], 'debugindex FILE'),