mercurial/commands.py
changeset 727 acee766fcb79
parent 726 809a870a0e73
child 729 626aa658e2a9
equal deleted inserted replaced
726:809a870a0e73 727:acee766fcb79
    11 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
    11 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
    12 demandload(globals(), "errno socket version struct")
    12 demandload(globals(), "errno socket version struct")
    13 
    13 
    14 class UnknownCommand(Exception):
    14 class UnknownCommand(Exception):
    15     """Exception raised if command is not in the command table."""
    15     """Exception raised if command is not in the command table."""
       
    16 
       
    17 class Abort(Exception):
       
    18     """Raised if a command needs to print an error and exit."""
    16 
    19 
    17 def filterfiles(filters, files):
    20 def filterfiles(filters, files):
    18     l = [x for x in files if x in filters]
    21     l = [x for x in files if x in filters]
    19 
    22 
    20     for t in filters:
    23     for t in filters:
    91                 num = repo.changelog.rev(repo.lookup(val))
    94                 num = repo.changelog.rev(repo.lookup(val))
    92             except KeyError:
    95             except KeyError:
    93                 try:
    96                 try:
    94                     num = revlog.rev(revlog.lookup(val))
    97                     num = revlog.rev(revlog.lookup(val))
    95                 except KeyError:
    98                 except KeyError:
    96                     ui.warn('abort: invalid revision identifier %s\n' % val)
    99                     raise Abort('invalid revision identifier %s', val)
    97                     sys.exit(1)
       
    98         return num
   100         return num
    99     for spec in revs:
   101     for spec in revs:
   100         if spec.find(revrangesep) >= 0:
   102         if spec.find(revrangesep) >= 0:
   101             start, end = spec.split(revrangesep, 1)
   103             start, end = spec.split(revrangesep, 1)
   102             start = fix(start, 0)
   104             start = fix(start, 0)
   122     expander = {
   124     expander = {
   123         '%': lambda: '%',
   125         '%': lambda: '%',
   124         'b': lambda: os.path.basename(repo.root),
   126         'b': lambda: os.path.basename(repo.root),
   125         }
   127         }
   126 
   128 
   127     if node:
   129     try:
   128         expander.update(node_expander)
   130         if node:
   129     if node and revwidth is not None:
   131             expander.update(node_expander)
   130         expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
   132         if node and revwidth is not None:
   131     if total is not None:
   133             expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
   132         expander['N'] = lambda: str(total)
   134         if total is not None:
   133     if seqno is not None:
   135             expander['N'] = lambda: str(total)
   134         expander['n'] = lambda: str(seqno)
   136         if seqno is not None:
   135     if total is not None and seqno is not None:
   137             expander['n'] = lambda: str(seqno)
   136         expander['n'] = lambda:str(seqno).zfill(len(str(total)))
   138         if total is not None and seqno is not None:
   137 
   139             expander['n'] = lambda:str(seqno).zfill(len(str(total)))
   138     newname = []
   140 
   139     patlen = len(pat)
   141         newname = []
   140     i = 0
   142         patlen = len(pat)
   141     while i < patlen:
   143         i = 0
   142         c = pat[i]
   144         while i < patlen:
   143         if c == '%':
   145             c = pat[i]
       
   146             if c == '%':
       
   147                 i += 1
       
   148                 c = pat[i]
       
   149                 c = expander[c]()
       
   150             newname.append(c)
   144             i += 1
   151             i += 1
   145             c = pat[i]
   152         return ''.join(newname)
   146             c = expander[c]()
   153     except KeyError, inst:
   147         newname.append(c)
   154         raise Abort("invalid format spec '%%%s' in output file name",
   148         i += 1
   155                     inst.args[0])
   149     return ''.join(newname)
       
   150 
   156 
   151 def dodiff(fp, ui, repo, files=None, node1=None, node2=None):
   157 def dodiff(fp, ui, repo, files=None, node1=None, node2=None):
   152     def date(c):
   158     def date(c):
   153         return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
   159         return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
   154 
   160 
   402     if rev:
   408     if rev:
   403         n = r.lookup(rev)
   409         n = r.lookup(rev)
   404     else:
   410     else:
   405         n = r.tip()
   411         n = r.tip()
   406     if opts['output'] and opts['output'] != '-':
   412     if opts['output'] and opts['output'] != '-':
   407         try:
   413         fp = open(make_filename(repo, r, opts['output'], node=n), 'wb')
   408             outname = make_filename(repo, r, opts['output'], node=n)
       
   409             fp = open(outname, 'wb')
       
   410         except KeyError, inst:
       
   411             ui.warn("error: invlaid format spec '%%%s' in output file name\n" %
       
   412                     inst.args[0])
       
   413             sys.exit(1);
       
   414     else:
   414     else:
   415         fp = sys.stdout
   415         fp = sys.stdout
   416     fp.write(r.read(n))
   416     fp.write(r.read(n))
   417 
   417 
   418 def clone(ui, source, dest=None, **opts):
   418 def clone(ui, source, dest=None, **opts):
   514         state = repo.dirstate.state(f)
   514         state = repo.dirstate.state(f)
   515         if state not in "nrm":
   515         if state not in "nrm":
   516             ui.warn("%s in manifest1, but listed as state %s" % (f, state))
   516             ui.warn("%s in manifest1, but listed as state %s" % (f, state))
   517             errors += 1
   517             errors += 1
   518     if errors:
   518     if errors:
   519         ui.warn(".hg/dirstate inconsistent with current parent's manifest\n")
   519         raise Abort(".hg/dirstate inconsistent with current parent's manifest")
   520         sys.exit(1)
       
   521 
   520 
   522 def debugstate(ui, repo):
   521 def debugstate(ui, repo):
   523     """show the contents of the current dirstate"""
   522     """show the contents of the current dirstate"""
   524     repo.dirstate.read()
   523     repo.dirstate.read()
   525     dc = repo.dirstate.map
   524     dc = repo.dirstate.map
   555     revs = []
   554     revs = []
   556     if opts['rev']:
   555     if opts['rev']:
   557         revs = map(lambda x: repo.lookup(x), opts['rev'])
   556         revs = map(lambda x: repo.lookup(x), opts['rev'])
   558 
   557 
   559     if len(revs) > 2:
   558     if len(revs) > 2:
   560         ui.warn("too many revisions to diff\n")
   559         raise Abort("too many revisions to diff")
   561         sys.exit(1)
       
   562 
   560 
   563     if files:
   561     if files:
   564         files = relpath(repo, files)
   562         files = relpath(repo, files)
   565     else:
   563     else:
   566         files = relpath(repo, [""])
   564         files = relpath(repo, [""])
   571     node = repo.lookup(changeset)
   569     node = repo.lookup(changeset)
   572     prev, other = repo.changelog.parents(node)
   570     prev, other = repo.changelog.parents(node)
   573     change = repo.changelog.read(node)
   571     change = repo.changelog.read(node)
   574 
   572 
   575     if opts['output'] and opts['output'] != '-':
   573     if opts['output'] and opts['output'] != '-':
   576         try:
   574         outname = make_filename(repo, repo.changelog, opts['output'],
   577             outname = make_filename(repo, repo.changelog, opts['output'],
   575                                 node=node, total=total, seqno=seqno,
   578                                     node=node, total=total, seqno=seqno,
   576                                 revwidth=revwidth)
   579                                     revwidth=revwidth)
   577         ui.note("Exporting patch to '%s'.\n" % outname)
   580             ui.note("Exporting patch to '%s'.\n" % outname)
   578         fp = open(outname, 'wb')
   581             fp = open(outname, 'wb')
       
   582         except KeyError, inst:
       
   583             ui.warn("error: invalid format spec '%%%s' in output file name\n" %
       
   584                     inst.args[0])
       
   585             sys.exit(1)
       
   586     else:
   579     else:
   587         fp = sys.stdout
   580         fp = sys.stdout
   588 
   581 
   589     fp.write("# HG changeset patch\n")
   582     fp.write("# HG changeset patch\n")
   590     fp.write("# User %s\n" % change[1])
   583     fp.write("# User %s\n" % change[1])
   598     dodiff(fp, ui, repo, None, prev, node)
   591     dodiff(fp, ui, repo, None, prev, node)
   599 
   592 
   600 def export(ui, repo, *changesets, **opts):
   593 def export(ui, repo, *changesets, **opts):
   601     """dump the header and diffs for one or more changesets"""
   594     """dump the header and diffs for one or more changesets"""
   602     if not changesets:
   595     if not changesets:
   603         ui.warn("error: export requires at least one changeset\n")
   596         raise Abort("export requires at least one changeset")
   604         sys.exit(1)
       
   605     seqno = 0
   597     seqno = 0
   606     revs = list(revrange(ui, repo, changesets))
   598     revs = list(revrange(ui, repo, changesets))
   607     total = len(revs)
   599     total = len(revs)
   608     revwidth = max(len(revs[0]), len(revs[-1]))
   600     revwidth = max(len(revs[0]), len(revs[-1]))
   609     for cset in revs:
   601     for cset in revs:
   693                 pf = l[14:]
   685                 pf = l[14:]
   694                 if pf not in files:
   686                 if pf not in files:
   695                     files.append(pf)
   687                     files.append(pf)
   696         patcherr = f.close()
   688         patcherr = f.close()
   697         if patcherr:
   689         if patcherr:
   698             sys.stderr.write("patch failed")
   690             raise Abort("patch failed")
   699             sys.exit(1)
       
   700 
   691 
   701         if len(files) > 0:
   692         if len(files) > 0:
   702             addremove(ui, repo, *files)
   693             addremove(ui, repo, *files)
   703         repo.commit(files, text, user)
   694         repo.commit(files, text, user)
   704 
   695 
   705 def init(ui, source=None):
   696 def init(ui, source=None):
   706     """create a new repository in the current directory"""
   697     """create a new repository in the current directory"""
   707 
   698 
   708     if source:
   699     if source:
   709         ui.warn("no longer supported: use \"hg clone\" instead\n")
   700         raise Abort("no longer supported: use \"hg clone\" instead")
   710         sys.exit(1)
       
   711     hg.repository(ui, ".", create=1)
   701     hg.repository(ui, ".", create=1)
   712 
   702 
   713 def locate(ui, repo, *pats, **opts):
   703 def locate(ui, repo, *pats, **opts):
   714     """locate files matching specific patterns"""
   704     """locate files matching specific patterns"""
   715     if opts['print0']: end = '\0'
   705     if opts['print0']: end = '\0'
   753                 i = filelog.linkrev(filenode)
   743                 i = filelog.linkrev(filenode)
   754             changenode = repo.changelog.node(i)
   744             changenode = repo.changelog.node(i)
   755             prev, other = repo.changelog.parents(changenode)
   745             prev, other = repo.changelog.parents(changenode)
   756             dodiff(sys.stdout, ui, repo, files, prev, changenode)
   746             dodiff(sys.stdout, ui, repo, files, prev, changenode)
   757             ui.write("\n\n")
   747             ui.write("\n\n")
       
   748 
       
   749 def ls(ui, repo, *pats, **opts):
       
   750     """list files"""
       
   751     for src, abs, rel in walk(repo, pats, opts):
       
   752         ui.write(rel, '\n')
   758 
   753 
   759 def manifest(ui, repo, rev=None):
   754 def manifest(ui, repo, rev=None):
   760     """output the latest or given revision of the project manifest"""
   755     """output the latest or given revision of the project manifest"""
   761     if rev:
   756     if rev:
   762         try:
   757         try:
  1160     "^log|history":
  1155     "^log|history":
  1161         (log,
  1156         (log,
  1162          [('r', 'rev', [], 'revision'),
  1157          [('r', 'rev', [], 'revision'),
  1163           ('p', 'patch', None, 'show patch')],
  1158           ('p', 'patch', None, 'show patch')],
  1164          'hg log [-r REV1 [-r REV2]] [-p] [FILE]'),
  1159          'hg log [-r REV1 [-r REV2]] [-p] [FILE]'),
       
  1160     "list|ls": (ls,
       
  1161                 [('I', 'include', [], 'include path in search'),
       
  1162                  ('X', 'exclude', [], 'exclude path from search')],
       
  1163                 "hg ls [OPTION]... [PATTERN]...."),
  1165     "manifest": (manifest, [], 'hg manifest [REV]'),
  1164     "manifest": (manifest, [], 'hg manifest [REV]'),
  1166     "parents": (parents, [], 'hg parents [REV]'),
  1165     "parents": (parents, [], 'hg parents [REV]'),
  1167     "^pull":
  1166     "^pull":
  1168         (pull,
  1167         (pull,
  1169          [('u', 'update', None, 'update working directory')],
  1168          [('u', 'update', None, 'update working directory')],
  1355     except OSError, inst:
  1354     except OSError, inst:
  1356         if hasattr(inst, "filename"):
  1355         if hasattr(inst, "filename"):
  1357             u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename))
  1356             u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename))
  1358         else:
  1357         else:
  1359             u.warn("abort: %s\n" % inst.strerror)
  1358             u.warn("abort: %s\n" % inst.strerror)
       
  1359     except Abort, inst:
       
  1360         u.warn('abort: ', inst.args[0] % inst.args[1:], '\n')
       
  1361         sys.exit(1)
  1360     except TypeError, inst:
  1362     except TypeError, inst:
  1361         # was this an argument error?
  1363         # was this an argument error?
  1362         tb = traceback.extract_tb(sys.exc_info()[2])
  1364         tb = traceback.extract_tb(sys.exc_info()[2])
  1363         if len(tb) > 2: # no
  1365         if len(tb) > 2: # no
  1364             raise
  1366             raise