mercurial/commands.py
changeset 4959 97b734fb9c6f
parent 4958 9a2a73ea6135
child 4961 126f527b3ba3
equal deleted inserted replaced
4958:9a2a73ea6135 4959:97b734fb9c6f
   674 
   674 
   675     This command takes effect in the next commit. To undo a copy
   675     This command takes effect in the next commit. To undo a copy
   676     before that, see hg revert.
   676     before that, see hg revert.
   677     """
   677     """
   678     wlock = repo.wlock(False)
   678     wlock = repo.wlock(False)
   679     errs, copied = docopy(ui, repo, pats, opts, wlock)
   679     try:
       
   680         errs, copied = docopy(ui, repo, pats, opts, wlock)
       
   681     finally:
       
   682         del wlock
   680     return errs
   683     return errs
   681 
   684 
   682 def debugancestor(ui, index, rev1, rev2):
   685 def debugancestor(ui, index, rev1, rev2):
   683     """find the ancestor revision of two revisions in a given index"""
   686     """find the ancestor revision of two revisions in a given index"""
   684     r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
   687     r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
   711     if rev == "":
   714     if rev == "":
   712         rev = repo.changelog.tip()
   715         rev = repo.changelog.tip()
   713     ctx = repo.changectx(rev)
   716     ctx = repo.changectx(rev)
   714     files = ctx.manifest()
   717     files = ctx.manifest()
   715     wlock = repo.wlock()
   718     wlock = repo.wlock()
   716     repo.dirstate.rebuild(rev, files)
   719     try:
       
   720         repo.dirstate.rebuild(rev, files)
       
   721     finally:
       
   722         del wlock
   717 
   723 
   718 def debugcheckstate(ui, repo):
   724 def debugcheckstate(ui, repo):
   719     """validate the correctness of the current dirstate"""
   725     """validate the correctness of the current dirstate"""
   720     parent1, parent2 = repo.dirstate.parents()
   726     parent1, parent2 = repo.dirstate.parents()
   721     m1 = repo.changectx(parent1).manifest()
   727     m1 = repo.changectx(parent1).manifest()
   780 
   786 
   781     wlock = repo.wlock()
   787     wlock = repo.wlock()
   782     try:
   788     try:
   783         repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
   789         repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
   784     finally:
   790     finally:
   785         wlock.release()
   791         del wlock
   786 
   792 
   787 def debugstate(ui, repo):
   793 def debugstate(ui, repo):
   788     """show the contents of the current dirstate"""
   794     """show the contents of the current dirstate"""
   789     dc = repo.dirstate._map
   795     dc = repo.dirstate._map
   790     k = dc.keys()
   796     k = dc.keys()
  1579     if opts.get('exact') or not opts['force']:
  1585     if opts.get('exact') or not opts['force']:
  1580         cmdutil.bail_if_changed(repo)
  1586         cmdutil.bail_if_changed(repo)
  1581 
  1587 
  1582     d = opts["base"]
  1588     d = opts["base"]
  1583     strip = opts["strip"]
  1589     strip = opts["strip"]
  1584 
  1590     wlock = lock = None
  1585     wlock = repo.wlock()
  1591     try:
  1586     lock = repo.lock()
  1592         wlock = repo.wlock()
  1587 
  1593         lock = repo.lock()
  1588     for p in patches:
  1594         for p in patches:
  1589         pf = os.path.join(d, p)
  1595             pf = os.path.join(d, p)
  1590 
  1596 
  1591         if pf == '-':
  1597             if pf == '-':
  1592             ui.status(_("applying patch from stdin\n"))
  1598                 ui.status(_("applying patch from stdin\n"))
  1593             tmpname, message, user, date, branch, nodeid, p1, p2 = patch.extract(ui, sys.stdin)
  1599                 data = patch.extract(ui, sys.stdin)
  1594         else:
       
  1595             ui.status(_("applying %s\n") % p)
       
  1596             tmpname, message, user, date, branch, nodeid, p1, p2 = patch.extract(ui, file(pf, 'rb'))
       
  1597 
       
  1598         if tmpname is None:
       
  1599             raise util.Abort(_('no diffs found'))
       
  1600 
       
  1601         try:
       
  1602             cmdline_message = cmdutil.logmessage(opts)
       
  1603             if cmdline_message:
       
  1604                 # pickup the cmdline msg
       
  1605                 message = cmdline_message
       
  1606             elif message:
       
  1607                 # pickup the patch msg
       
  1608                 message = message.strip()
       
  1609             else:
  1600             else:
  1610                 # launch the editor
  1601                 ui.status(_("applying %s\n") % p)
  1611                 message = None
  1602                 data = patch.extract(ui, file(pf, 'rb'))
  1612             ui.debug(_('message:\n%s\n') % message)
  1603 
  1613 
  1604             tmpname, message, user, date, branch, nodeid, p1, p2 = data
  1614             wp = repo.workingctx().parents()
  1605 
  1615             if opts.get('exact'):
  1606             if tmpname is None:
  1616                 if not nodeid or not p1:
  1607                 raise util.Abort(_('no diffs found'))
  1617                     raise util.Abort(_('not a mercurial patch'))
  1608 
  1618                 p1 = repo.lookup(p1)
  1609             try:
  1619                 p2 = repo.lookup(p2 or hex(nullid))
  1610                 cmdline_message = cmdutil.logmessage(opts)
  1620 
  1611                 if cmdline_message:
  1621                 if p1 != wp[0].node():
  1612                     # pickup the cmdline msg
  1622                     hg.clean(repo, p1, wlock=wlock)
  1613                     message = cmdline_message
  1623                 repo.dirstate.setparents(p1, p2)
  1614                 elif message:
  1624             elif p2:
  1615                     # pickup the patch msg
       
  1616                     message = message.strip()
       
  1617                 else:
       
  1618                     # launch the editor
       
  1619                     message = None
       
  1620                 ui.debug(_('message:\n%s\n') % message)
       
  1621 
       
  1622                 wp = repo.workingctx().parents()
       
  1623                 if opts.get('exact'):
       
  1624                     if not nodeid or not p1:
       
  1625                         raise util.Abort(_('not a mercurial patch'))
       
  1626                     p1 = repo.lookup(p1)
       
  1627                     p2 = repo.lookup(p2 or hex(nullid))
       
  1628 
       
  1629                     if p1 != wp[0].node():
       
  1630                         hg.clean(repo, p1, wlock=wlock)
       
  1631                     repo.dirstate.setparents(p1, p2)
       
  1632                 elif p2:
       
  1633                     try:
       
  1634                         p1 = repo.lookup(p1)
       
  1635                         p2 = repo.lookup(p2)
       
  1636                         if p1 == wp[0].node():
       
  1637                             repo.dirstate.setparents(p1, p2)
       
  1638                     except hg.RepoError:
       
  1639                         pass
       
  1640                 if opts.get('exact') or opts.get('import_branch'):
       
  1641                     repo.dirstate.setbranch(branch or 'default')
       
  1642 
       
  1643                 files = {}
  1625                 try:
  1644                 try:
  1626                     p1 = repo.lookup(p1)
  1645                     fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
  1627                     p2 = repo.lookup(p2)
  1646                                        files=files)
  1628                     if p1 == wp[0].node():
  1647                 finally:
  1629                         repo.dirstate.setparents(p1, p2)
  1648                     files = patch.updatedir(ui, repo, files, wlock=wlock)
  1630                 except hg.RepoError:
  1649                 n = repo.commit(files, message, user, date, wlock=wlock,
  1631                     pass
  1650                                 lock=lock)
  1632             if opts.get('exact') or opts.get('import_branch'):
  1651                 if opts.get('exact'):
  1633                 repo.dirstate.setbranch(branch or 'default')
  1652                     if hex(n) != nodeid:
  1634 
  1653                         repo.rollback(wlock=wlock, lock=lock)
  1635             files = {}
  1654                         raise util.Abort(_('patch is damaged' +
  1636             try:
  1655                                            ' or loses information'))
  1637                 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
       
  1638                                    files=files)
       
  1639             finally:
  1656             finally:
  1640                 files = patch.updatedir(ui, repo, files, wlock=wlock)
  1657                 os.unlink(tmpname)
  1641             n = repo.commit(files, message, user, date, wlock=wlock, lock=lock)
  1658     finally:
  1642             if opts.get('exact'):
  1659         del wlock, lock
  1643                 if hex(n) != nodeid:
       
  1644                     repo.rollback(wlock=wlock, lock=lock)
       
  1645                     raise util.Abort(_('patch is damaged or loses information'))
       
  1646         finally:
       
  1647             os.unlink(tmpname)
       
  1648 
  1660 
  1649 def incoming(ui, repo, source="default", **opts):
  1661 def incoming(ui, repo, source="default", **opts):
  1650     """show new changesets found in source
  1662     """show new changesets found in source
  1651 
  1663 
  1652     Show new changesets found in the specified path/URL or the default
  1664     Show new changesets found in the specified path/URL or the default
  2246 
  2258 
  2247     This command takes effect in the next commit. To undo a rename
  2259     This command takes effect in the next commit. To undo a rename
  2248     before that, see hg revert.
  2260     before that, see hg revert.
  2249     """
  2261     """
  2250     wlock = repo.wlock(False)
  2262     wlock = repo.wlock(False)
  2251     errs, copied = docopy(ui, repo, pats, opts, wlock)
  2263     try:
  2252     names = []
  2264         errs, copied = docopy(ui, repo, pats, opts, wlock)
  2253     for abs, rel, exact in copied:
  2265         names = []
  2254         if ui.verbose or not exact:
  2266         for abs, rel, exact in copied:
  2255             ui.status(_('removing %s\n') % rel)
  2267             if ui.verbose or not exact:
  2256         names.append(abs)
  2268                 ui.status(_('removing %s\n') % rel)
  2257     if not opts.get('dry_run'):
  2269             names.append(abs)
  2258         repo.remove(names, True, wlock=wlock)
  2270         if not opts.get('dry_run'):
  2259     return errs
  2271             repo.remove(names, True, wlock=wlock)
       
  2272         return errs
       
  2273     finally:
       
  2274         del wlock
  2260 
  2275 
  2261 def revert(ui, repo, *pats, **opts):
  2276 def revert(ui, repo, *pats, **opts):
  2262     """revert files or dirs to their states as of some revision
  2277     """revert files or dirs to their states as of some revision
  2263 
  2278 
  2264     With no revision specified, revert the named files or directories
  2279     With no revision specified, revert the named files or directories
  2308     if node == parent:
  2323     if node == parent:
  2309         pmf = mf
  2324         pmf = mf
  2310     else:
  2325     else:
  2311         pmf = None
  2326         pmf = None
  2312 
  2327 
  2313     wlock = repo.wlock()
       
  2314 
       
  2315     # need all matching names in dirstate and manifest of target rev,
  2328     # need all matching names in dirstate and manifest of target rev,
  2316     # so have to walk both. do not print errors if files exist in one
  2329     # so have to walk both. do not print errors if files exist in one
  2317     # but not other.
  2330     # but not other.
  2318 
  2331 
  2319     names = {}
  2332     names = {}
  2320     target_only = {}
  2333     target_only = {}
  2321 
  2334 
  2322     # walk dirstate.
  2335     wlock = repo.wlock()
  2323 
  2336     try:
  2324     for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
  2337         # walk dirstate.
  2325                                              badmatch=mf.has_key):
  2338         for src, abs, rel, exact in cmdutil.walk(repo, pats, opts,
  2326         names[abs] = (rel, exact)
  2339                                                  badmatch=mf.has_key):
  2327         if src == 'b':
  2340             names[abs] = (rel, exact)
       
  2341             if src == 'b':
       
  2342                 target_only[abs] = True
       
  2343 
       
  2344         # walk target manifest.
       
  2345 
       
  2346         def badmatch(path):
       
  2347             if path in names:
       
  2348                 return True
       
  2349             path_ = path + '/'
       
  2350             for f in names:
       
  2351                 if f.startswith(path_):
       
  2352                     return True
       
  2353             return False
       
  2354 
       
  2355         for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
       
  2356                                                  badmatch=badmatch):
       
  2357             if abs in names or src == 'b':
       
  2358                 continue
       
  2359             names[abs] = (rel, exact)
  2328             target_only[abs] = True
  2360             target_only[abs] = True
  2329 
  2361 
  2330     # walk target manifest.
  2362         changes = repo.status(match=names.has_key, wlock=wlock)[:5]
  2331 
  2363         modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
  2332     def badmatch(path):
  2364 
  2333         if path in names:
  2365         revert = ([], _('reverting %s\n'))
  2334             return True
  2366         add = ([], _('adding %s\n'))
  2335         path_ = path + '/'
  2367         remove = ([], _('removing %s\n'))
  2336         for f in names:
  2368         forget = ([], _('forgetting %s\n'))
  2337             if f.startswith(path_):
  2369         undelete = ([], _('undeleting %s\n'))
  2338                 return True
  2370         update = {}
  2339         return False
  2371 
  2340 
  2372         disptable = (
  2341     for src, abs, rel, exact in cmdutil.walk(repo, pats, opts, node=node,
  2373             # dispatch table:
  2342                                              badmatch=badmatch):
  2374             #   file state
  2343         if abs in names or src == 'b':
  2375             #   action if in target manifest
  2344             continue
  2376             #   action if not in target manifest
  2345         names[abs] = (rel, exact)
  2377             #   make backup if in target manifest
  2346         target_only[abs] = True
  2378             #   make backup if not in target manifest
  2347 
  2379             (modified, revert, remove, True, True),
  2348     changes = repo.status(match=names.has_key, wlock=wlock)[:5]
  2380             (added, revert, forget, True, False),
  2349     modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
  2381             (removed, undelete, None, False, False),
  2350 
  2382             (deleted, revert, remove, False, False),
  2351     revert = ([], _('reverting %s\n'))
  2383             (unknown, add, None, True, False),
  2352     add = ([], _('adding %s\n'))
  2384             (target_only, add, None, False, False),
  2353     remove = ([], _('removing %s\n'))
  2385             )
  2354     forget = ([], _('forgetting %s\n'))
  2386 
  2355     undelete = ([], _('undeleting %s\n'))
  2387         entries = names.items()
  2356     update = {}
  2388         entries.sort()
  2357 
  2389 
  2358     disptable = (
  2390         for abs, (rel, exact) in entries:
  2359         # dispatch table:
  2391             mfentry = mf.get(abs)
  2360         #   file state
  2392             target = repo.wjoin(abs)
  2361         #   action if in target manifest
  2393             def handle(xlist, dobackup):
  2362         #   action if not in target manifest
  2394                 xlist[0].append(abs)
  2363         #   make backup if in target manifest
  2395                 update[abs] = 1
  2364         #   make backup if not in target manifest
  2396                 if dobackup and not opts['no_backup'] and util.lexists(target):
  2365         (modified, revert, remove, True, True),
  2397                     bakname = "%s.orig" % rel
  2366         (added, revert, forget, True, False),
  2398                     ui.note(_('saving current version of %s as %s\n') %
  2367         (removed, undelete, None, False, False),
  2399                             (rel, bakname))
  2368         (deleted, revert, remove, False, False),
  2400                     if not opts.get('dry_run'):
  2369         (unknown, add, None, True, False),
  2401                         util.copyfile(target, bakname)
  2370         (target_only, add, None, False, False),
  2402                 if ui.verbose or not exact:
  2371         )
  2403                     ui.status(xlist[1] % rel)
  2372 
  2404             for table, hitlist, misslist, backuphit, backupmiss in disptable:
  2373     entries = names.items()
  2405                 if abs not in table: continue
  2374     entries.sort()
  2406                 # file has changed in dirstate
  2375 
  2407                 if mfentry:
  2376     for abs, (rel, exact) in entries:
  2408                     handle(hitlist, backuphit)
  2377         mfentry = mf.get(abs)
  2409                 elif misslist is not None:
  2378         target = repo.wjoin(abs)
  2410                     handle(misslist, backupmiss)
  2379         def handle(xlist, dobackup):
  2411                 else:
  2380             xlist[0].append(abs)
  2412                     if exact: ui.warn(_('file not managed: %s\n') % rel)
  2381             update[abs] = 1
  2413                 break
  2382             if dobackup and not opts['no_backup'] and util.lexists(target):
       
  2383                 bakname = "%s.orig" % rel
       
  2384                 ui.note(_('saving current version of %s as %s\n') %
       
  2385                         (rel, bakname))
       
  2386                 if not opts.get('dry_run'):
       
  2387                     util.copyfile(target, bakname)
       
  2388             if ui.verbose or not exact:
       
  2389                 ui.status(xlist[1] % rel)
       
  2390         for table, hitlist, misslist, backuphit, backupmiss in disptable:
       
  2391             if abs not in table: continue
       
  2392             # file has changed in dirstate
       
  2393             if mfentry:
       
  2394                 handle(hitlist, backuphit)
       
  2395             elif misslist is not None:
       
  2396                 handle(misslist, backupmiss)
       
  2397             else:
  2414             else:
  2398                 if exact: ui.warn(_('file not managed: %s\n') % rel)
  2415                 # file has not changed in dirstate
  2399             break
  2416                 if node == parent:
  2400         else:
  2417                     if exact: ui.warn(_('no changes needed to %s\n') % rel)
  2401             # file has not changed in dirstate
  2418                     continue
  2402             if node == parent:
  2419                 if pmf is None:
  2403                 if exact: ui.warn(_('no changes needed to %s\n') % rel)
  2420                     # only need parent manifest in this unlikely case,
  2404                 continue
  2421                     # so do not read by default
  2405             if pmf is None:
  2422                     pmf = repo.changectx(parent).manifest()
  2406                 # only need parent manifest in this unlikely case,
  2423                 if abs in pmf:
  2407                 # so do not read by default
  2424                     if mfentry:
  2408                 pmf = repo.changectx(parent).manifest()
  2425                         # if version of file is same in parent and target
  2409             if abs in pmf:
  2426                         # manifests, do nothing
  2410                 if mfentry:
  2427                         if pmf[abs] != mfentry:
  2411                     # if version of file is same in parent and target
  2428                             handle(revert, False)
  2412                     # manifests, do nothing
  2429                     else:
  2413                     if pmf[abs] != mfentry:
  2430                         handle(remove, False)
  2414                         handle(revert, False)
  2431 
  2415                 else:
  2432         if not opts.get('dry_run'):
  2416                     handle(remove, False)
  2433             for f in forget[0]:
  2417 
  2434                 repo.dirstate.forget(f)
  2418     if not opts.get('dry_run'):
  2435             r = hg.revert(repo, node, update.has_key, wlock)
  2419         for f in forget[0]:
  2436             for f in add[0]:
  2420             repo.dirstate.forget(f)
  2437                 repo.dirstate.add(f)
  2421         r = hg.revert(repo, node, update.has_key, wlock)
  2438             for f in undelete[0]:
  2422         for f in add[0]:
  2439                 repo.dirstate.normal(f)
  2423             repo.dirstate.add(f)
  2440             for f in remove[0]:
  2424         for f in undelete[0]:
  2441                 repo.dirstate.remove(f)
  2425             repo.dirstate.normal(f)
  2442             return r
  2426         for f in remove[0]:
  2443     finally:
  2427             repo.dirstate.remove(f)
  2444         del wlock
  2428         return r
       
  2429 
  2445 
  2430 def rollback(ui, repo):
  2446 def rollback(ui, repo):
  2431     """roll back the last transaction in this repository
  2447     """roll back the last transaction in this repository
  2432 
  2448 
  2433     Roll back the last transaction in this repository, restoring the
  2449     Roll back the last transaction in this repository, restoring the