Mercurial > hg
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'), |