mercurial/cmdutil.py
changeset 45827 8d72e29ad1e0
parent 45812 976b26bdd0d8
child 45840 527ce85c2e60
equal deleted inserted replaced
45826:21733e8c924f 45827:8d72e29ad1e0
   277 
   277 
   278     previous = None
   278     previous = None
   279     for x in args:
   279     for x in args:
   280         if opts.get(x):
   280         if opts.get(x):
   281             if previous:
   281             if previous:
   282                 raise error.Abort(
   282                 raise error.InputError(
   283                     _(b'cannot specify both --%s and --%s')
   283                     _(b'cannot specify both --%s and --%s')
   284                     % (to_display(previous), to_display(x))
   284                     % (to_display(previous), to_display(x))
   285                 )
   285                 )
   286             previous = x
   286             previous = x
   287     return previous
   287     return previous
   330     note = opts.get(b'note')
   330     note = opts.get(b'note')
   331     if not note:
   331     if not note:
   332         return
   332         return
   333 
   333 
   334     if len(note) > 255:
   334     if len(note) > 255:
   335         raise error.Abort(_(b"cannot store a note of more than 255 bytes"))
   335         raise error.InputError(_(b"cannot store a note of more than 255 bytes"))
   336     if b'\n' in note:
   336     if b'\n' in note:
   337         raise error.Abort(_(b"note cannot contain a newline"))
   337         raise error.InputError(_(b"note cannot contain a newline"))
   338 
   338 
   339 
   339 
   340 def ishunk(x):
   340 def ishunk(x):
   341     hunkclasses = (crecordmod.uihunk, patch.recordhunk)
   341     hunkclasses = (crecordmod.uihunk, patch.recordhunk)
   342     return isinstance(x, hunkclasses)
   342     return isinstance(x, hunkclasses)
   424     if not ui.interactive():
   424     if not ui.interactive():
   425         if cmdsuggest:
   425         if cmdsuggest:
   426             msg = _(b'running non-interactively, use %s instead') % cmdsuggest
   426             msg = _(b'running non-interactively, use %s instead') % cmdsuggest
   427         else:
   427         else:
   428             msg = _(b'running non-interactively')
   428             msg = _(b'running non-interactively')
   429         raise error.Abort(msg)
   429         raise error.InputError(msg)
   430 
   430 
   431     # make sure username is set before going interactive
   431     # make sure username is set before going interactive
   432     if not opts.get(b'user'):
   432     if not opts.get(b'user'):
   433         ui.username()  # raise exception, username not provided
   433         ui.username()  # raise exception, username not provided
   434 
   434 
   449         if not opts.get(b'interactive-unshelve'):
   449         if not opts.get(b'interactive-unshelve'):
   450             checkunfinished(repo, commit=True)
   450             checkunfinished(repo, commit=True)
   451         wctx = repo[None]
   451         wctx = repo[None]
   452         merge = len(wctx.parents()) > 1
   452         merge = len(wctx.parents()) > 1
   453         if merge:
   453         if merge:
   454             raise error.Abort(
   454             raise error.InputError(
   455                 _(
   455                 _(
   456                     b'cannot partially commit a merge '
   456                     b'cannot partially commit a merge '
   457                     b'(use "hg commit" instead)'
   457                     b'(use "hg commit" instead)'
   458                 )
   458                 )
   459             )
   459             )
   508 
   508 
   509         # 1. filter patch, since we are intending to apply subset of it
   509         # 1. filter patch, since we are intending to apply subset of it
   510         try:
   510         try:
   511             chunks, newopts = filterfn(ui, originalchunks, match)
   511             chunks, newopts = filterfn(ui, originalchunks, match)
   512         except error.PatchError as err:
   512         except error.PatchError as err:
   513             raise error.Abort(_(b'error parsing patch: %s') % err)
   513             raise error.InputError(_(b'error parsing patch: %s') % err)
   514         opts.update(newopts)
   514         opts.update(newopts)
   515 
   515 
   516         # We need to keep a backup of files that have been newly added and
   516         # We need to keep a backup of files that have been newly added and
   517         # modified during the recording process because there is a previous
   517         # modified during the recording process because there is a previous
   518         # version without the edit in the workdir. We also will need to restore
   518         # version without the edit in the workdir. We also will need to restore
   598                 try:
   598                 try:
   599                     ui.debug(b'applying patch\n')
   599                     ui.debug(b'applying patch\n')
   600                     ui.debug(fp.getvalue())
   600                     ui.debug(fp.getvalue())
   601                     patch.internalpatch(ui, repo, fp, 1, eolmode=None)
   601                     patch.internalpatch(ui, repo, fp, 1, eolmode=None)
   602                 except error.PatchError as err:
   602                 except error.PatchError as err:
   603                     raise error.Abort(pycompat.bytestr(err))
   603                     raise error.InputError(pycompat.bytestr(err))
   604             del fp
   604             del fp
   605 
   605 
   606             # 4. We prepared working directory according to filtered
   606             # 4. We prepared working directory according to filtered
   607             #    patch. Now is the time to delegate the job to
   607             #    patch. Now is the time to delegate the job to
   608             #    commit/qrefresh or the like!
   608             #    commit/qrefresh or the like!
   760     allst = (b'm', b'a', b'r', b'd', b'u', b'i', b'c')
   760     allst = (b'm', b'a', b'r', b'd', b'u', b'i', b'c')
   761 
   761 
   762     # checking the argument validity
   762     # checking the argument validity
   763     for s in pycompat.bytestr(terseargs):
   763     for s in pycompat.bytestr(terseargs):
   764         if s not in allst:
   764         if s not in allst:
   765             raise error.Abort(_(b"'%s' not recognized") % s)
   765             raise error.InputError(_(b"'%s' not recognized") % s)
   766 
   766 
   767     # creating a dirnode object for the root of the repo
   767     # creating a dirnode object for the root of the repo
   768     rootobj = dirnode(b'')
   768     rootobj = dirnode(b'')
   769     pstatus = (
   769     pstatus = (
   770         b'modified',
   770         b'modified',
   966     with repo.wlock(), repo.lock(), repo.transaction(b'branches'):
   966     with repo.wlock(), repo.lock(), repo.transaction(b'branches'):
   967         # abort in case of uncommitted merge or dirty wdir
   967         # abort in case of uncommitted merge or dirty wdir
   968         bailifchanged(repo)
   968         bailifchanged(repo)
   969         revs = scmutil.revrange(repo, revs)
   969         revs = scmutil.revrange(repo, revs)
   970         if not revs:
   970         if not revs:
   971             raise error.Abort(b"empty revision set")
   971             raise error.InputError(b"empty revision set")
   972         roots = repo.revs(b'roots(%ld)', revs)
   972         roots = repo.revs(b'roots(%ld)', revs)
   973         if len(roots) > 1:
   973         if len(roots) > 1:
   974             raise error.Abort(
   974             raise error.InputError(
   975                 _(b"cannot change branch of non-linear revisions")
   975                 _(b"cannot change branch of non-linear revisions")
   976             )
   976             )
   977         rewriteutil.precheck(repo, revs, b'change branch of')
   977         rewriteutil.precheck(repo, revs, b'change branch of')
   978 
   978 
   979         root = repo[roots.first()]
   979         root = repo[roots.first()]
   981         if (
   981         if (
   982             not opts.get(b'force')
   982             not opts.get(b'force')
   983             and label not in rpb
   983             and label not in rpb
   984             and label in repo.branchmap()
   984             and label in repo.branchmap()
   985         ):
   985         ):
   986             raise error.Abort(_(b"a branch of the same name already exists"))
   986             raise error.InputError(
       
   987                 _(b"a branch of the same name already exists")
       
   988             )
   987 
   989 
   988         if repo.revs(b'obsolete() and %ld', revs):
   990         if repo.revs(b'obsolete() and %ld', revs):
   989             raise error.Abort(
   991             raise error.InputError(
   990                 _(b"cannot change branch of a obsolete changeset")
   992                 _(b"cannot change branch of a obsolete changeset")
   991             )
   993             )
   992 
   994 
   993         # make sure only topological heads
   995         # make sure only topological heads
   994         if repo.revs(b'heads(%ld) - head()', revs):
   996         if repo.revs(b'heads(%ld) - head()', revs):
   995             raise error.Abort(_(b"cannot change branch in middle of a stack"))
   997             raise error.InputError(
       
   998                 _(b"cannot change branch in middle of a stack")
       
   999             )
   996 
  1000 
   997         replacements = {}
  1001         replacements = {}
   998         # avoid import cycle mercurial.cmdutil -> mercurial.context ->
  1002         # avoid import cycle mercurial.cmdutil -> mercurial.context ->
   999         # mercurial.subrepo -> mercurial.cmdutil
  1003         # mercurial.subrepo -> mercurial.cmdutil
  1000         from . import context
  1004         from . import context
  1371             msg = _(
  1375             msg = _(
  1372                 b'cannot specify --changelog or --manifest or --dir '
  1376                 b'cannot specify --changelog or --manifest or --dir '
  1373                 b'without a repository'
  1377                 b'without a repository'
  1374             )
  1378             )
  1375     if msg:
  1379     if msg:
  1376         raise error.Abort(msg)
  1380         raise error.InputError(msg)
  1377 
  1381 
  1378     r = None
  1382     r = None
  1379     if repo:
  1383     if repo:
  1380         if cl:
  1384         if cl:
  1381             r = repo.unfiltered().changelog
  1385             r = repo.unfiltered().changelog
  1382         elif dir:
  1386         elif dir:
  1383             if not scmutil.istreemanifest(repo):
  1387             if not scmutil.istreemanifest(repo):
  1384                 raise error.Abort(
  1388                 raise error.InputError(
  1385                     _(
  1389                     _(
  1386                         b"--dir can only be used on repos with "
  1390                         b"--dir can only be used on repos with "
  1387                         b"treemanifest enabled"
  1391                         b"treemanifest enabled"
  1388                     )
  1392                     )
  1389                 )
  1393                 )
  1405             if isinstance(r, revlog.revlog):
  1409             if isinstance(r, revlog.revlog):
  1406                 pass
  1410                 pass
  1407             elif util.safehasattr(r, b'_revlog'):
  1411             elif util.safehasattr(r, b'_revlog'):
  1408                 r = r._revlog  # pytype: disable=attribute-error
  1412                 r = r._revlog  # pytype: disable=attribute-error
  1409             elif r is not None:
  1413             elif r is not None:
  1410                 raise error.Abort(_(b'%r does not appear to be a revlog') % r)
  1414                 raise error.InputError(
       
  1415                     _(b'%r does not appear to be a revlog') % r
       
  1416                 )
  1411 
  1417 
  1412     if not r:
  1418     if not r:
  1413         if not returnrevlog:
  1419         if not returnrevlog:
  1414             raise error.Abort(_(b'cannot give path to non-revlog'))
  1420             raise error.InputError(_(b'cannot give path to non-revlog'))
  1415 
  1421 
  1416         if not file_:
  1422         if not file_:
  1417             raise error.CommandError(cmd, _(b'invalid arguments'))
  1423             raise error.CommandError(cmd, _(b'invalid arguments'))
  1418         if not os.path.isfile(file_):
  1424         if not os.path.isfile(file_):
  1419             raise error.Abort(_(b"revlog '%s' not found") % file_)
  1425             raise error.InputError(_(b"revlog '%s' not found") % file_)
  1420         r = revlog.revlog(
  1426         r = revlog.revlog(
  1421             vfsmod.vfs(encoding.getcwd(), audit=False), file_[:-2] + b".i"
  1427             vfsmod.vfs(encoding.getcwd(), audit=False), file_[:-2] + b".i"
  1422         )
  1428         )
  1423     return r
  1429     return r
  1424 
  1430 
  1451     rev = opts.get(b'at_rev')
  1457     rev = opts.get(b'at_rev')
  1452     if rev:
  1458     if rev:
  1453         if not forget and not after:
  1459         if not forget and not after:
  1454             # TODO: Remove this restriction and make it also create the copy
  1460             # TODO: Remove this restriction and make it also create the copy
  1455             #       targets (and remove the rename source if rename==True).
  1461             #       targets (and remove the rename source if rename==True).
  1456             raise error.Abort(_(b'--at-rev requires --after'))
  1462             raise error.InputError(_(b'--at-rev requires --after'))
  1457         ctx = scmutil.revsingle(repo, rev)
  1463         ctx = scmutil.revsingle(repo, rev)
  1458         if len(ctx.parents()) > 1:
  1464         if len(ctx.parents()) > 1:
  1459             raise error.Abort(_(b'cannot mark/unmark copy in merge commit'))
  1465             raise error.InputError(
       
  1466                 _(b'cannot mark/unmark copy in merge commit')
       
  1467             )
  1460     else:
  1468     else:
  1461         ctx = repo[None]
  1469         ctx = repo[None]
  1462 
  1470 
  1463     pctx = ctx.p1()
  1471     pctx = ctx.p1()
  1464 
  1472 
  1467     if forget:
  1475     if forget:
  1468         if ctx.rev() is None:
  1476         if ctx.rev() is None:
  1469             new_ctx = ctx
  1477             new_ctx = ctx
  1470         else:
  1478         else:
  1471             if len(ctx.parents()) > 1:
  1479             if len(ctx.parents()) > 1:
  1472                 raise error.Abort(_(b'cannot unmark copy in merge commit'))
  1480                 raise error.InputError(_(b'cannot unmark copy in merge commit'))
  1473             # avoid cycle context -> subrepo -> cmdutil
  1481             # avoid cycle context -> subrepo -> cmdutil
  1474             from . import context
  1482             from . import context
  1475 
  1483 
  1476             rewriteutil.precheck(repo, [ctx.rev()], b'uncopy')
  1484             rewriteutil.precheck(repo, [ctx.rev()], b'uncopy')
  1477             new_ctx = context.overlayworkingctx(repo)
  1485             new_ctx = context.overlayworkingctx(repo)
  1510 
  1518 
  1511         return
  1519         return
  1512 
  1520 
  1513     pats = scmutil.expandpats(pats)
  1521     pats = scmutil.expandpats(pats)
  1514     if not pats:
  1522     if not pats:
  1515         raise error.Abort(_(b'no source or destination specified'))
  1523         raise error.InputError(_(b'no source or destination specified'))
  1516     if len(pats) == 1:
  1524     if len(pats) == 1:
  1517         raise error.Abort(_(b'no destination specified'))
  1525         raise error.InputError(_(b'no destination specified'))
  1518     dest = pats.pop()
  1526     dest = pats.pop()
  1519 
  1527 
  1520     def walkpat(pat):
  1528     def walkpat(pat):
  1521         srcs = []
  1529         srcs = []
  1522         # TODO: Inline and simplify the non-working-copy version of this code
  1530         # TODO: Inline and simplify the non-working-copy version of this code
  1552 
  1560 
  1553     if ctx.rev() is not None:
  1561     if ctx.rev() is not None:
  1554         rewriteutil.precheck(repo, [ctx.rev()], b'uncopy')
  1562         rewriteutil.precheck(repo, [ctx.rev()], b'uncopy')
  1555         absdest = pathutil.canonpath(repo.root, cwd, dest)
  1563         absdest = pathutil.canonpath(repo.root, cwd, dest)
  1556         if ctx.hasdir(absdest):
  1564         if ctx.hasdir(absdest):
  1557             raise error.Abort(
  1565             raise error.InputError(
  1558                 _(b'%s: --at-rev does not support a directory as destination')
  1566                 _(b'%s: --at-rev does not support a directory as destination')
  1559                 % uipathfn(absdest)
  1567                 % uipathfn(absdest)
  1560             )
  1568             )
  1561         if absdest not in ctx:
  1569         if absdest not in ctx:
  1562             raise error.Abort(
  1570             raise error.InputError(
  1563                 _(b'%s: copy destination does not exist in %s')
  1571                 _(b'%s: copy destination does not exist in %s')
  1564                 % (uipathfn(absdest), ctx)
  1572                 % (uipathfn(absdest), ctx)
  1565             )
  1573             )
  1566 
  1574 
  1567         # avoid cycle context -> subrepo -> cmdutil
  1575         # avoid cycle context -> subrepo -> cmdutil
  1574                 continue
  1582                 continue
  1575             for abs, rel, exact in srcs:
  1583             for abs, rel, exact in srcs:
  1576                 copylist.append(abs)
  1584                 copylist.append(abs)
  1577 
  1585 
  1578         if not copylist:
  1586         if not copylist:
  1579             raise error.Abort(_(b'no files to copy'))
  1587             raise error.InputError(_(b'no files to copy'))
  1580         # TODO: Add support for `hg cp --at-rev . foo bar dir` and
  1588         # TODO: Add support for `hg cp --at-rev . foo bar dir` and
  1581         # `hg cp --at-rev . dir1 dir2`, preferably unifying the code with the
  1589         # `hg cp --at-rev . dir1 dir2`, preferably unifying the code with the
  1582         # existing functions below.
  1590         # existing functions below.
  1583         if len(copylist) != 1:
  1591         if len(copylist) != 1:
  1584             raise error.Abort(_(b'--at-rev requires a single source'))
  1592             raise error.InputError(_(b'--at-rev requires a single source'))
  1585 
  1593 
  1586         new_ctx = context.overlayworkingctx(repo)
  1594         new_ctx = context.overlayworkingctx(repo)
  1587         new_ctx.setbase(ctx.p1())
  1595         new_ctx.setbase(ctx.p1())
  1588         mergemod.graft(repo, ctx, wctx=new_ctx)
  1596         mergemod.graft(repo, ctx, wctx=new_ctx)
  1589 
  1597 
  1807         return res
  1815         return res
  1808 
  1816 
  1809     destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
  1817     destdirexists = os.path.isdir(dest) and not os.path.islink(dest)
  1810     if not destdirexists:
  1818     if not destdirexists:
  1811         if len(pats) > 1 or matchmod.patkind(pats[0]):
  1819         if len(pats) > 1 or matchmod.patkind(pats[0]):
  1812             raise error.Abort(
  1820             raise error.InputError(
  1813                 _(
  1821                 _(
  1814                     b'with multiple sources, destination must be an '
  1822                     b'with multiple sources, destination must be an '
  1815                     b'existing directory'
  1823                     b'existing directory'
  1816                 )
  1824                 )
  1817             )
  1825             )
  1818         if util.endswithsep(dest):
  1826         if util.endswithsep(dest):
  1819             raise error.Abort(_(b'destination %s is not a directory') % dest)
  1827             raise error.InputError(
       
  1828                 _(b'destination %s is not a directory') % dest
       
  1829             )
  1820 
  1830 
  1821     tfn = targetpathfn
  1831     tfn = targetpathfn
  1822     if after:
  1832     if after:
  1823         tfn = targetpathafterfn
  1833         tfn = targetpathafterfn
  1824     copylist = []
  1834     copylist = []
  1826         srcs = walkpat(pat)
  1836         srcs = walkpat(pat)
  1827         if not srcs:
  1837         if not srcs:
  1828             continue
  1838             continue
  1829         copylist.append((tfn(pat, dest, srcs), srcs))
  1839         copylist.append((tfn(pat, dest, srcs), srcs))
  1830     if not copylist:
  1840     if not copylist:
  1831         raise error.Abort(_(b'no files to copy'))
  1841         raise error.InputError(_(b'no files to copy'))
  1832 
  1842 
  1833     errors = 0
  1843     errors = 0
  1834     for targetpath, srcs in copylist:
  1844     for targetpath, srcs in copylist:
  1835         for abssrc, relsrc, exact in srcs:
  1845         for abssrc, relsrc, exact in srcs:
  1836             if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
  1846             if copyfile(abssrc, relsrc, targetpath(abssrc), exact):
  1917 
  1927 
  1918     if len(parents) == 1:
  1928     if len(parents) == 1:
  1919         parents.append(repo[nullid])
  1929         parents.append(repo[nullid])
  1920     if opts.get(b'exact'):
  1930     if opts.get(b'exact'):
  1921         if not nodeid or not p1:
  1931         if not nodeid or not p1:
  1922             raise error.Abort(_(b'not a Mercurial patch'))
  1932             raise error.InputError(_(b'not a Mercurial patch'))
  1923         p1 = repo[p1]
  1933         p1 = repo[p1]
  1924         p2 = repo[p2 or nullid]
  1934         p2 = repo[p2 or nullid]
  1925     elif p2:
  1935     elif p2:
  1926         try:
  1936         try:
  1927             p1 = repo[p1]
  1937             p1 = repo[p1]
  2253     """Find the tipmost changeset that matches the given date spec"""
  2263     """Find the tipmost changeset that matches the given date spec"""
  2254     mrevs = repo.revs(b'date(%s)', date)
  2264     mrevs = repo.revs(b'date(%s)', date)
  2255     try:
  2265     try:
  2256         rev = mrevs.max()
  2266         rev = mrevs.max()
  2257     except ValueError:
  2267     except ValueError:
  2258         raise error.Abort(_(b"revision matching date not found"))
  2268         raise error.InputError(_(b"revision matching date not found"))
  2259 
  2269 
  2260     ui.status(
  2270     ui.status(
  2261         _(b"found revision %d from %s\n")
  2271         _(b"found revision %d from %s\n")
  2262         % (rev, dateutil.datestr(repo[rev].date()))
  2272         % (rev, dateutil.datestr(repo[rev].date()))
  2263     )
  2273     )
  2336 
  2346 
  2337 def forget(
  2347 def forget(
  2338     ui, repo, match, prefix, uipathfn, explicitonly, dryrun, interactive
  2348     ui, repo, match, prefix, uipathfn, explicitonly, dryrun, interactive
  2339 ):
  2349 ):
  2340     if dryrun and interactive:
  2350     if dryrun and interactive:
  2341         raise error.Abort(_(b"cannot specify both --dry-run and --interactive"))
  2351         raise error.InputError(
       
  2352             _(b"cannot specify both --dry-run and --interactive")
       
  2353         )
  2342     bad = []
  2354     bad = []
  2343     badfn = lambda x, y: bad.append(x) or match.bad(x, y)
  2355     badfn = lambda x, y: bad.append(x) or match.bad(x, y)
  2344     wctx = repo[None]
  2356     wctx = repo[None]
  2345     forgot = []
  2357     forgot = []
  2346 
  2358 
  3048     os.chdir(olddir)
  3060     os.chdir(olddir)
  3049 
  3061 
  3050     if finishdesc:
  3062     if finishdesc:
  3051         text = finishdesc(text)
  3063         text = finishdesc(text)
  3052     if not text.strip():
  3064     if not text.strip():
  3053         raise error.Abort(_(b"empty commit message"))
  3065         raise error.InputError(_(b"empty commit message"))
  3054     if unchangedmessagedetection and editortext == templatetext:
  3066     if unchangedmessagedetection and editortext == templatetext:
  3055         raise error.Abort(_(b"commit message unchanged"))
  3067         raise error.InputError(_(b"commit message unchanged"))
  3056 
  3068 
  3057     return text
  3069     return text
  3058 
  3070 
  3059 
  3071 
  3060 def buildcommittemplate(repo, ctx, subs, extramsg, ref):
  3072 def buildcommittemplate(repo, ctx, subs, extramsg, ref):