comparison mercurial/commands.py @ 1253:a45e717c61a8

Add rename/mv command. This is the logical equivalent of copy and remove, and is in fact implemented as such. It doesn't use the remove command directly.
author Bryan O'Sullivan <bos@serpentine.com>
date Wed, 14 Sep 2005 16:34:22 -0700
parents 0ad3f9b27260
children e6560042b7b8
comparison
equal deleted inserted replaced
1252:94f38724283f 1253:a45e717c61a8
694 try: 694 try:
695 repo.commit(files, message, opts['user'], opts['date'], match) 695 repo.commit(files, message, opts['user'], opts['date'], match)
696 except ValueError, inst: 696 except ValueError, inst:
697 raise util.Abort(str(inst)) 697 raise util.Abort(str(inst))
698 698
699 def copy(ui, repo, *pats, **opts): 699 def docopy(ui, repo, pats, opts):
700 """mark files as copied for the next commit"""
701 if not pats: 700 if not pats:
702 raise util.Abort('no source or destination specified') 701 raise util.Abort('no source or destination specified')
703 elif len(pats) == 1: 702 elif len(pats) == 1:
704 raise util.Abort('no destination specified') 703 raise util.Abort('no destination specified')
705 pats = list(pats) 704 pats = list(pats)
733 if opts['parents']: 732 if opts['parents']:
734 raise util.Abort('with --parents, destination must be a directory') 733 raise util.Abort('with --parents, destination must be a directory')
735 elif len(sources) > 1: 734 elif len(sources) > 1:
736 raise util.Abort('with multiple sources, destination must be a ' 735 raise util.Abort('with multiple sources, destination must be a '
737 'directory') 736 'directory')
738 errs = 0 737 errs, copied = 0, []
739 for abs, rel, exact in sources: 738 for abs, rel, exact in sources:
740 if opts['parents']: 739 if opts['parents']:
741 mydest = os.path.join(dest, rel) 740 mydest = os.path.join(dest, rel)
742 elif destisfile: 741 elif destisfile:
743 mydest = reldest 742 mydest = reldest
761 try: 760 try:
762 shutil.copyfile(rel, myreldest) 761 shutil.copyfile(rel, myreldest)
763 n = repo.manifest.tip() 762 n = repo.manifest.tip()
764 mf = repo.manifest.readflags(n) 763 mf = repo.manifest.readflags(n)
765 util.set_exec(myreldest, util.is_exec(rel, mf[abs])) 764 util.set_exec(myreldest, util.is_exec(rel, mf[abs]))
765 except shutil.Error, inst:
766 raise util.Abort(str(inst))
766 except IOError, inst: 767 except IOError, inst:
767 if inst.errno == errno.ENOENT: 768 if inst.errno == errno.ENOENT:
768 ui.warn('%s: deleted in working copy\n' % rel) 769 ui.warn('%s: deleted in working copy\n' % rel)
769 else: 770 else:
770 ui.warn('%s: cannot copy - %s\n' % (rel, inst.strerror)) 771 ui.warn('%s: cannot copy - %s\n' % (rel, inst.strerror))
771 errs += 1 772 errs += 1
772 continue 773 continue
773 repo.copy(abs, myabsdest) 774 repo.copy(abs, myabsdest)
775 copied.append((abs, rel, exact))
774 if errs: 776 if errs:
775 ui.warn('(consider using --after to record failed copies)\n') 777 ui.warn('(consider using --after)\n')
778 return errs, copied
779
780 def copy(ui, repo, *pats, **opts):
781 """mark files as copied for the next commit"""
782 errs, copied = docopy(ui, repo, pats, opts)
776 return errs 783 return errs
777 784
778 def debugcheckstate(ui, repo): 785 def debugcheckstate(ui, repo):
779 """validate the correctness of the current dirstate""" 786 """validate the correctness of the current dirstate"""
780 parent1, parent2 = repo.dirstate.parents() 787 parent1, parent2 = repo.dirstate.parents()
1388 def okaytoremove(abs, rel, exact): 1395 def okaytoremove(abs, rel, exact):
1389 c, a, d, u = repo.changes(files = [abs]) 1396 c, a, d, u = repo.changes(files = [abs])
1390 reason = None 1397 reason = None
1391 if c: reason = 'is modified' 1398 if c: reason = 'is modified'
1392 elif a: reason = 'has been marked for add' 1399 elif a: reason = 'has been marked for add'
1393 elif u: reason = 'not managed' 1400 elif u: reason = 'is not managed'
1394 if reason and exact: 1401 if reason and exact:
1395 ui.warn('not removing %s: file %s\n' % (rel, reason)) 1402 ui.warn('not removing %s: file %s\n' % (rel, reason))
1396 else: 1403 else:
1397 return True 1404 return True
1398 for src, abs, rel, exact in walk(repo, (pat,) + pats, opts): 1405 for src, abs, rel, exact in walk(repo, (pat,) + pats, opts):
1399 if okaytoremove(abs, rel, exact): 1406 if okaytoremove(abs, rel, exact):
1400 if not exact: ui.status('removing %s\n' % rel) 1407 if ui.verbose or not exact: ui.status('removing %s\n' % rel)
1401 names.append(abs) 1408 names.append(abs)
1402 for name in names: 1409 for name in names:
1403 try: 1410 try:
1404 os.unlink(name) 1411 os.unlink(name)
1405 except OSError, inst: 1412 except OSError, inst:
1406 if inst.errno != errno.ENOENT: raise 1413 if inst.errno != errno.ENOENT: raise
1407 repo.remove(names) 1414 repo.remove(names)
1415
1416 def rename(ui, repo, *pats, **opts):
1417 """rename files; equivalent of copy + remove"""
1418 errs, copied = docopy(ui, repo, pats, opts)
1419 names = []
1420 for abs, rel, exact in copied:
1421 if ui.verbose or not exact: ui.status('removing %s\n' % rel)
1422 try:
1423 os.unlink(rel)
1424 except OSError, inst:
1425 if inst.errno != errno.ENOENT: raise
1426 names.append(abs)
1427 repo.remove(names)
1428 return errs
1408 1429
1409 def revert(ui, repo, *names, **opts): 1430 def revert(ui, repo, *names, **opts):
1410 """revert modified files or dirs back to their unmodified states""" 1431 """revert modified files or dirs back to their unmodified states"""
1411 node = opts['rev'] and repo.lookup(opts['rev']) or \ 1432 node = opts['rev'] and repo.lookup(opts['rev']) or \
1412 repo.dirstate.parents()[0] 1433 repo.dirstate.parents()[0]
1821 (import_, 1842 (import_,
1822 [('p', 'strip', 1, 'path strip'), 1843 [('p', 'strip', 1, 'path strip'),
1823 ('f', 'force', None, 'skip check for outstanding changes'), 1844 ('f', 'force', None, 'skip check for outstanding changes'),
1824 ('b', 'base', "", 'base path')], 1845 ('b', 'base', "", 'base path')],
1825 "hg import [-f] [-p NUM] [-b BASE] PATCH..."), 1846 "hg import [-f] [-p NUM] [-b BASE] PATCH..."),
1826 "incoming|in": (incoming, 1847 "incoming|in": (incoming,
1827 [('p', 'patch', None, 'show patch')], 1848 [('p', 'patch', None, 'show patch')],
1828 'hg incoming [-p] [SOURCE]'), 1849 'hg incoming [-p] [SOURCE]'),
1829 "^init": (init, [], 'hg init [DEST]'), 1850 "^init": (init, [], 'hg init [DEST]'),
1830 "locate": 1851 "locate":
1831 (locate, 1852 (locate,
1842 ('b', 'branch', None, 'show branches'), 1863 ('b', 'branch', None, 'show branches'),
1843 ('r', 'rev', [], 'revision'), 1864 ('r', 'rev', [], 'revision'),
1844 ('p', 'patch', None, 'show patch')], 1865 ('p', 'patch', None, 'show patch')],
1845 'hg log [-I] [-X] [-r REV]... [-p] [FILE]'), 1866 'hg log [-I] [-X] [-r REV]... [-p] [FILE]'),
1846 "manifest": (manifest, [], 'hg manifest [REV]'), 1867 "manifest": (manifest, [], 'hg manifest [REV]'),
1847 "outgoing|out": (outgoing, 1868 "outgoing|out": (outgoing,
1848 [('p', 'patch', None, 'show patch')], 1869 [('p', 'patch', None, 'show patch')],
1849 'hg outgoing [-p] [DEST]'), 1870 'hg outgoing [-p] [DEST]'),
1850 "parents": (parents, [], 'hg parents [REV]'), 1871 "parents": (parents, [], 'hg parents [REV]'),
1851 "paths": (paths, [], 'hg paths [NAME]'), 1872 "paths": (paths, [], 'hg paths [NAME]'),
1852 "^pull": 1873 "^pull":
1874 "recover": (recover, [], "hg recover"), 1895 "recover": (recover, [], "hg recover"),
1875 "^remove|rm": (remove, 1896 "^remove|rm": (remove,
1876 [('I', 'include', [], 'include path in search'), 1897 [('I', 'include', [], 'include path in search'),
1877 ('X', 'exclude', [], 'exclude path from search')], 1898 ('X', 'exclude', [], 'exclude path from search')],
1878 "hg remove [OPTION]... FILE..."), 1899 "hg remove [OPTION]... FILE..."),
1900 "rename|mv": (rename,
1901 [('I', 'include', [], 'include path in search'),
1902 ('X', 'exclude', [], 'exclude path from search'),
1903 ('A', 'after', None, 'record a copy after it has happened'),
1904 ('f', 'force', None, 'replace destination if it exists'),
1905 ('p', 'parents', None, 'append source path to dest')],
1906 'hg rename [OPTION]... [SOURCE]... DEST'),
1879 "^revert": 1907 "^revert":
1880 (revert, 1908 (revert,
1881 [("n", "nonrecursive", None, "don't recurse into subdirs"), 1909 [("n", "nonrecursive", None, "don't recurse into subdirs"),
1882 ("r", "rev", "", "revision")], 1910 ("r", "rev", "", "revision")],
1883 "hg revert [-n] [-r REV] [NAME]..."), 1911 "hg revert [-n] [-r REV] [NAME]..."),