mercurial/commands.py
changeset 1065 6e94c0365d98
parent 1062 6d5a62a549fa
child 1066 ea878688221e
equal deleted inserted replaced
1064:8d791bea49d4 1065:6e94c0365d98
    42             yield src, fn, util.pathto(cwd, fn), fn in exact
    42             yield src, fn, util.pathto(cwd, fn), fn in exact
    43     return files, matchfn, walk()
    43     return files, matchfn, walk()
    44 
    44 
    45 def walk(repo, pats, opts, head=''):
    45 def walk(repo, pats, opts, head=''):
    46     files, matchfn, results = makewalk(repo, pats, opts, head)
    46     files, matchfn, results = makewalk(repo, pats, opts, head)
    47     for r in results: yield r
    47     for r in results:
       
    48         yield r
    48 
    49 
    49 def walkchangerevs(ui, repo, cwd, pats, opts):
    50 def walkchangerevs(ui, repo, cwd, pats, opts):
    50     # This code most commonly needs to iterate backwards over the
    51     # This code most commonly needs to iterate backwards over the
    51     # history it is interested in.  Doing so has awful
    52     # history it is interested in.  Doing so has awful
    52     # (quadratic-looking) performance, so we use iterators in a
    53     # (quadratic-looking) performance, so we use iterators in a
    86             if filelog.count() == 0:
    87             if filelog.count() == 0:
    87                 slowpath = True
    88                 slowpath = True
    88                 break
    89                 break
    89             for rev in filerevgen(filelog):
    90             for rev in filerevgen(filelog):
    90                 if rev <= maxrev:
    91                 if rev <= maxrev:
    91                     if rev < minrev: break
    92                     if rev < minrev:
       
    93                         break
    92                     fncache.setdefault(rev, [])
    94                     fncache.setdefault(rev, [])
    93                     fncache[rev].append(file)
    95                     fncache[rev].append(file)
    94                     wanted[rev] = 1
    96                     wanted[rev] = 1
    95     if slowpath:
    97     if slowpath:
    96         # The slow path checks files modified in every changeset.
    98         # The slow path checks files modified in every changeset.
   105                 fncache[rev] = matches
   107                 fncache[rev] = matches
   106                 wanted[rev] = 1
   108                 wanted[rev] = 1
   107 
   109 
   108     for i in xrange(0, len(revs), window):
   110     for i in xrange(0, len(revs), window):
   109         yield 'window', revs[0] < revs[-1], revs[-1]
   111         yield 'window', revs[0] < revs[-1], revs[-1]
   110         nrevs = [rev for rev in revs[i : min(i + window, len(revs))]
   112         nrevs = [rev for rev in revs[i:min(i+window, len(revs))]
   111                  if rev in wanted]
   113                  if rev in wanted]
   112         srevs = list(nrevs)
   114         srevs = list(nrevs)
   113         srevs.sort()
   115         srevs.sort()
   114         for rev in srevs:
   116         for rev in srevs:
   115             fns = fncache.get(rev)
   117             fns = fncache.get(rev)
   203                     inst.args[0])
   205                     inst.args[0])
   204 
   206 
   205 def make_file(repo, r, pat, node=None,
   207 def make_file(repo, r, pat, node=None,
   206               total=None, seqno=None, revwidth=None, mode='wb'):
   208               total=None, seqno=None, revwidth=None, mode='wb'):
   207     if not pat or pat == '-':
   209     if not pat or pat == '-':
   208         if 'w' in mode: return sys.stdout
   210         return 'w' in mode and sys.stdout or sys.stdin
   209         else: return sys.stdin
       
   210     if hasattr(pat, 'write') and 'w' in mode:
   211     if hasattr(pat, 'write') and 'w' in mode:
   211         return pat
   212         return pat
   212     if hasattr(pat, 'read') and 'r' in mode:
   213     if hasattr(pat, 'read') and 'r' in mode:
   213         return pat
   214         return pat
   214     return open(make_filename(repo, r, pat, node, total, seqno, revwidth),
   215     return open(make_filename(repo, r, pat, node, total, seqno, revwidth),
   453     """add all new files, delete all missing files"""
   454     """add all new files, delete all missing files"""
   454     add, remove = [], []
   455     add, remove = [], []
   455     for src, abs, rel, exact in walk(repo, pats, opts):
   456     for src, abs, rel, exact in walk(repo, pats, opts):
   456         if src == 'f' and repo.dirstate.state(abs) == '?':
   457         if src == 'f' and repo.dirstate.state(abs) == '?':
   457             add.append(abs)
   458             add.append(abs)
   458             if not exact: ui.status('adding ', rel, '\n')
   459             if not exact:
       
   460                 ui.status('adding ', rel, '\n')
   459         if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
   461         if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
   460             remove.append(abs)
   462             remove.append(abs)
   461             if not exact: ui.status('removing ', rel, '\n')
   463             if not exact:
       
   464                 ui.status('removing ', rel, '\n')
   462     repo.add(add)
   465     repo.add(add)
   463     repo.remove(remove)
   466     repo.remove(remove)
   464 
   467 
   465 def annotate(ui, repo, *pats, **opts):
   468 def annotate(ui, repo, *pats, **opts):
   466     """show changeset information per file line"""
   469     """show changeset information per file line"""
   670 
   673 
   671 def debugconfig(ui):
   674 def debugconfig(ui):
   672     """show combined config settings from all hgrc files"""
   675     """show combined config settings from all hgrc files"""
   673     try:
   676     try:
   674         repo = hg.repository(ui)
   677         repo = hg.repository(ui)
   675     except: pass
   678     except hg.RepoError:
       
   679         pass
   676     for section, name, value in ui.walkconfig():
   680     for section, name, value in ui.walkconfig():
   677         ui.write('%s.%s=%s\n' % (section, name, value))
   681         ui.write('%s.%s=%s\n' % (section, name, value))
   678 
   682 
   679 def debugstate(ui, repo):
   683 def debugstate(ui, repo):
   680     """show the contents of the current dirstate"""
   684     """show the contents of the current dirstate"""
   716     ui.write("}\n")
   720     ui.write("}\n")
   717 
   721 
   718 def debugwalk(ui, repo, *pats, **opts):
   722 def debugwalk(ui, repo, *pats, **opts):
   719     """show how files match on given patterns"""
   723     """show how files match on given patterns"""
   720     items = list(walk(repo, pats, opts))
   724     items = list(walk(repo, pats, opts))
   721     if not items: return
   725     if not items:
       
   726         return
   722     fmt = '%%s  %%-%ds  %%-%ds  %%s\n' % (
   727     fmt = '%%s  %%-%ds  %%-%ds  %%s\n' % (
   723         max([len(abs) for (src, abs, rel, exact) in items]),
   728         max([len(abs) for (src, abs, rel, exact) in items]),
   724         max([len(rel) for (src, abs, rel, exact) in items]))
   729         max([len(rel) for (src, abs, rel, exact) in items]))
   725     exactly = {True: 'exact', False: ''}
       
   726     for src, abs, rel, exact in items:
   730     for src, abs, rel, exact in items:
   727         ui.write(fmt % (src, abs, rel, exactly[exact]))
   731         ui.write(fmt % (src, abs, rel, exact and 'exact' or ''))
   728 
   732 
   729 def diff(ui, repo, *pats, **opts):
   733 def diff(ui, repo, *pats, **opts):
   730     """diff working directory (or selected files)"""
   734     """diff working directory (or selected files)"""
   731     node1, node2 = None, None
   735     node1, node2 = None, None
   732     revs = [repo.lookup(x) for x in opts['rev']]
   736     revs = [repo.lookup(x) for x in opts['rev']]
   767         fp.write("# Parent  %s\n" % hg.hex(other))
   771         fp.write("# Parent  %s\n" % hg.hex(other))
   768     fp.write(change[4].rstrip())
   772     fp.write(change[4].rstrip())
   769     fp.write("\n\n")
   773     fp.write("\n\n")
   770 
   774 
   771     dodiff(fp, ui, repo, prev, node, text=opts['text'])
   775     dodiff(fp, ui, repo, prev, node, text=opts['text'])
   772     if fp != sys.stdout: fp.close()
   776     if fp != sys.stdout:
       
   777         fp.close()
   773 
   778 
   774 def export(ui, repo, *changesets, **opts):
   779 def export(ui, repo, *changesets, **opts):
   775     """dump the header and diffs for one or more changesets"""
   780     """dump the header and diffs for one or more changesets"""
   776     if not changesets:
   781     if not changesets:
   777         raise util.Abort("export requires at least one changeset")
   782         raise util.Abort("export requires at least one changeset")
   788     """don't add the specified files on the next commit"""
   793     """don't add the specified files on the next commit"""
   789     forget = []
   794     forget = []
   790     for src, abs, rel, exact in walk(repo, pats, opts):
   795     for src, abs, rel, exact in walk(repo, pats, opts):
   791         if repo.dirstate.state(abs) == 'a':
   796         if repo.dirstate.state(abs) == 'a':
   792             forget.append(abs)
   797             forget.append(abs)
   793             if not exact: ui.status('forgetting ', rel, '\n')
   798             if not exact:
       
   799                 ui.status('forgetting ', rel, '\n')
   794     repo.forget(forget)
   800     repo.forget(forget)
   795 
   801 
   796 def grep(ui, repo, pattern=None, *pats, **opts):
   802 def grep(ui, repo, pattern=None, *pats, **opts):
   797     """search for a pattern in specified files and revisions"""
   803     """search for a pattern in specified files and revisions"""
   798     if pattern is None: pattern = opts['regexp']
   804     if pattern is None:
   799     if not pattern: raise util.Abort('no pattern to search for')
   805         pattern = opts['regexp']
       
   806     if not pattern:
       
   807         raise util.Abort('no pattern to search for')
   800     reflags = 0
   808     reflags = 0
   801     if opts['ignore_case']: reflags |= re.I
   809     if opts['ignore_case']:
       
   810         reflags |= re.I
   802     regexp = re.compile(pattern, reflags)
   811     regexp = re.compile(pattern, reflags)
   803     sep, end = ':', '\n'
   812     sep, end = ':', '\n'
   804     if opts['null'] or opts['print0']: sep = end = '\0'
   813     if opts['null'] or opts['print0']:
       
   814         sep = end = '\0'
   805 
   815 
   806     fcache = {}
   816     fcache = {}
   807     def getfile(fn):
   817     def getfile(fn):
   808         if fn not in fcache:
   818         if fn not in fcache:
   809             fcache[fn] = repo.file(fn)
   819             fcache[fn] = repo.file(fn)
   812     def matchlines(body):
   822     def matchlines(body):
   813         begin = 0
   823         begin = 0
   814         linenum = 0
   824         linenum = 0
   815         while True:
   825         while True:
   816             match = regexp.search(body, begin)
   826             match = regexp.search(body, begin)
   817             if not match: break
   827             if not match:
       
   828                 break
   818             mstart, mend = match.span()
   829             mstart, mend = match.span()
   819             linenum += body.count('\n', begin, mstart) + 1
   830             linenum += body.count('\n', begin, mstart) + 1
   820             lstart = body.rfind('\n', begin, mstart) + 1 or begin
   831             lstart = body.rfind('\n', begin, mstart) + 1 or begin
   821             lend = body.find('\n', mend)
   832             lend = body.find('\n', mend)
   822             yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
   833             yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
   826         def __init__(self, line, linenum, colstart, colend):
   837         def __init__(self, line, linenum, colstart, colend):
   827             self.line = line
   838             self.line = line
   828             self.linenum = linenum
   839             self.linenum = linenum
   829             self.colstart = colstart
   840             self.colstart = colstart
   830             self.colend = colend
   841             self.colend = colend
   831         def __eq__(self, other): return self.line == other.line
   842         def __eq__(self, other):
   832         def __hash__(self): return hash(self.line)
   843             return self.line == other.line
       
   844         def __hash__(self):
       
   845             return hash(self.line)
   833 
   846 
   834     matches = {}
   847     matches = {}
   835     def grepbody(fn, rev, body):
   848     def grepbody(fn, rev, body):
   836         matches[rev].setdefault(fn, {})
   849         matches[rev].setdefault(fn, {})
   837         m = matches[rev][fn]
   850         m = matches[rev][fn]
   997         os.mkdir(dest)
  1010         os.mkdir(dest)
   998     hg.repository(ui, dest, create=1)
  1011     hg.repository(ui, dest, create=1)
   999 
  1012 
  1000 def locate(ui, repo, *pats, **opts):
  1013 def locate(ui, repo, *pats, **opts):
  1001     """locate files matching specific patterns"""
  1014     """locate files matching specific patterns"""
  1002     end = '\n'
  1015     end = opts['print0'] and '\0' or '\n'
  1003     if opts['print0']: end = '\0'
       
  1004 
  1016 
  1005     for src, abs, rel, exact in walk(repo, pats, opts, '(?:.*/|)'):
  1017     for src, abs, rel, exact in walk(repo, pats, opts, '(?:.*/|)'):
  1006         if repo.dirstate.state(abs) == '?': continue
  1018         if repo.dirstate.state(abs) == '?':
       
  1019             continue
  1007         if opts['fullpath']:
  1020         if opts['fullpath']:
  1008             ui.write(os.path.join(repo.root, abs), end)
  1021             ui.write(os.path.join(repo.root, abs), end)
  1009         else:
  1022         else:
  1010             ui.write(rel, end)
  1023             ui.write(rel, end)
  1011 
  1024 
  1019             self.hunk = {}
  1032             self.hunk = {}
  1020         def bump(self, rev):
  1033         def bump(self, rev):
  1021             self.rev = rev
  1034             self.rev = rev
  1022             self.hunk[rev] = []
  1035             self.hunk[rev] = []
  1023         def note(self, *args):
  1036         def note(self, *args):
  1024             if self.verbose: self.write(*args)
  1037             if self.verbose:
       
  1038                 self.write(*args)
  1025         def status(self, *args):
  1039         def status(self, *args):
  1026             if not self.quiet: self.write(*args)
  1040             if not self.quiet:
       
  1041                 self.write(*args)
  1027         def write(self, *args):
  1042         def write(self, *args):
  1028             self.hunk[self.rev].append(args)
  1043             self.hunk[self.rev].append(args)
  1029         def __getattr__(self, key):
  1044         def __getattr__(self, key):
  1030             return getattr(self.ui, key)
  1045             return getattr(self.ui, key)
  1031     cwd = repo.getcwd()
  1046     cwd = repo.getcwd()
  1091 
  1106 
  1092 def paths(ui, search=None):
  1107 def paths(ui, search=None):
  1093     """show definition of symbolic path names"""
  1108     """show definition of symbolic path names"""
  1094     try:
  1109     try:
  1095         repo = hg.repository(ui=ui)
  1110         repo = hg.repository(ui=ui)
  1096     except:
  1111     except hg.RepoError:
  1097         pass
  1112         pass
  1098 
  1113 
  1099     if search:
  1114     if search:
  1100         for name, path in ui.configitems("paths"):
  1115         for name, path in ui.configitems("paths"):
  1101             if name == search:
  1116             if name == search:
  1518     "forget":
  1533     "forget":
  1519         (forget,
  1534         (forget,
  1520          [('I', 'include', [], 'include path in search'),
  1535          [('I', 'include', [], 'include path in search'),
  1521           ('X', 'exclude', [], 'exclude path from search')],
  1536           ('X', 'exclude', [], 'exclude path from search')],
  1522          "hg forget [OPTION]... FILE..."),
  1537          "hg forget [OPTION]... FILE..."),
  1523     "grep": (grep,
  1538     "grep":
  1524              [('0', 'print0', None, 'terminate file names with NUL'),
  1539         (grep,
  1525               ('I', 'include', [], 'include path in search'),
  1540          [('0', 'print0', None, 'terminate file names with NUL'),
  1526               ('X', 'exclude', [], 'include path in search'),
  1541           ('I', 'include', [], 'include path in search'),
  1527               ('Z', 'null', None, 'terminate file names with NUL'),
  1542           ('X', 'exclude', [], 'include path in search'),
  1528               ('a', 'all-revs', '', 'search all revs'),
  1543           ('Z', 'null', None, 'terminate file names with NUL'),
  1529               ('e', 'regexp', '', 'pattern to search for'),
  1544           ('a', 'all-revs', '', 'search all revs'),
  1530               ('f', 'full-path', None, 'print complete paths'),
  1545           ('e', 'regexp', '', 'pattern to search for'),
  1531               ('i', 'ignore-case', None, 'ignore case when matching'),
  1546           ('f', 'full-path', None, 'print complete paths'),
  1532               ('l', 'files-with-matches', None, 'print names of files with matches'),
  1547           ('i', 'ignore-case', None, 'ignore case when matching'),
  1533               ('n', 'line-number', '', 'print line numbers'),
  1548           ('l', 'files-with-matches', None, 'print names of files with matches'),
  1534               ('r', 'rev', [], 'search in revision rev'),
  1549           ('n', 'line-number', '', 'print line numbers'),
  1535               ('s', 'no-messages', None, 'do not print error messages'),
  1550           ('r', 'rev', [], 'search in revision rev'),
  1536               ('v', 'invert-match', None, 'select non-matching lines')],
  1551           ('s', 'no-messages', None, 'do not print error messages'),
  1537              "hg grep [options] [pat] [files]"),
  1552           ('v', 'invert-match', None, 'select non-matching lines')],
       
  1553          "hg grep [options] [pat] [files]"),
  1538     "heads":
  1554     "heads":
  1539         (heads,
  1555         (heads,
  1540          [('b', 'branches', None, 'find branch info')],
  1556          [('b', 'branches', None, 'find branch info')],
  1541          'hg heads [-b]'),
  1557          'hg heads [-b]'),
  1542     "help": (help_, [], 'hg help [COMMAND]'),
  1558     "help": (help_, [], 'hg help [COMMAND]'),
  1652     ('', 'profile', None, 'profile'),
  1668     ('', 'profile', None, 'profile'),
  1653     ('', 'version', None, 'output version information and exit'),
  1669     ('', 'version', None, 'output version information and exit'),
  1654     ('h', 'help', None, 'display help and exit'),
  1670     ('h', 'help', None, 'display help and exit'),
  1655 ]
  1671 ]
  1656 
  1672 
  1657 norepo = "clone init version help debugconfig debugdata" + \
  1673 norepo = ("clone init version help debugconfig debugdata"
  1658          " debugindex debugindexdot paths"
  1674           " debugindex debugindexdot paths")
  1659 
  1675 
  1660 def find(cmd):
  1676 def find(cmd):
  1661     for e in table.keys():
  1677     for e in table.keys():
  1662         if re.match("(%s)$" % e, cmd):
  1678         if re.match("(%s)$" % e, cmd):
  1663             return e, table[e]
  1679             return e, table[e]
  1810         if hasattr(inst, "code"):
  1826         if hasattr(inst, "code"):
  1811             u.warn("abort: %s\n" % inst)
  1827             u.warn("abort: %s\n" % inst)
  1812         elif hasattr(inst, "reason"):
  1828         elif hasattr(inst, "reason"):
  1813             u.warn("abort: error: %s\n" % inst.reason[1])
  1829             u.warn("abort: error: %s\n" % inst.reason[1])
  1814         elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
  1830         elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
  1815             if u.debugflag: u.warn("broken pipe\n")
  1831             if u.debugflag:
       
  1832                 u.warn("broken pipe\n")
  1816         else:
  1833         else:
  1817             raise
  1834             raise
  1818     except OSError, inst:
  1835     except OSError, inst:
  1819         if hasattr(inst, "filename"):
  1836         if hasattr(inst, "filename"):
  1820             u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename))
  1837             u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename))