--- a/doc/hg.1.txt
+++ b/doc/hg.1.txt
@@ -121,10 +121,23 @@ bundle <file> <other>::
Unlike import/export, this exactly preserves all changeset
contents including permissions, rename data, and revision history.
-cat <file> [revision]::
- Output to stdout the given revision for the specified file.
+cat [options] <file ...>::
+ Print the specified files as they were at the given revision.
+ If no revision is given then the tip is used.
+
+ Output may be to a file, in which case the name of the file is
+ given using a format string. The formatting rules are the same as
+ for the export command, with the following additions:
- If no revision is given then the tip is used.
+ %s basename of file being printed
+ %d dirname of file being printed, or '.' if in repo root
+ %p root-relative path name of file being printed
+
+ options:
+ -I, --include <pat> include names matching the given patterns
+ -X, --exclude <pat> exclude names matching the given patterns
+ -o, --output <filespec> print output to file with formatted name
+ -r, --rev <rev> print the given revision
clone [-U] <source> [dest]::
Create a copy of an existing repository in a new directory.
@@ -176,9 +189,11 @@ copy <source ...> <dest>::
This command takes effect in the next commit.
Options:
- -A, --after record a copy that has already occurred
- -f, --force forcibly copy over an existing managed file
- -p, --parents append source path to dest
+ -A, --after record a copy that has already occurred
+ -I, --include <pat> include names matching the given patterns
+ -X, --exclude <pat> exclude names matching the given patterns
+ -f, --force forcibly copy over an existing managed file
+ -p, --parents append source path to dest
aliases: cp
@@ -226,7 +241,7 @@ export [-o filespec] [revision] ...::
options:
-a, --text treat all files as text
- -o, --output <filespec> print output to file with formatted named
+ -o, --output <filespec> print output to file with formatted name
forget [options] [files]::
Undo an 'hg add' scheduled for the next commit.
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -194,7 +194,7 @@ def revrange(ui, repo, revs, revlog=None
yield str(rev)
def make_filename(repo, r, pat, node=None,
- total=None, seqno=None, revwidth=None):
+ total=None, seqno=None, revwidth=None, pathname=None):
node_expander = {
'H': lambda: hex(node),
'R': lambda: str(r.rev(node)),
@@ -216,6 +216,10 @@ def make_filename(repo, r, pat, node=Non
expander['n'] = lambda: str(seqno)
if total is not None and seqno is not None:
expander['n'] = lambda:str(seqno).zfill(len(str(total)))
+ if pathname is not None:
+ expander['s'] = lambda: os.path.basename(pathname)
+ expander['d'] = lambda: os.path.dirname(pathname) or '.'
+ expander['p'] = lambda: pathname
newname = []
patlen = len(pat)
@@ -234,14 +238,15 @@ def make_filename(repo, r, pat, node=Non
inst.args[0])
def make_file(repo, r, pat, node=None,
- total=None, seqno=None, revwidth=None, mode='wb'):
+ total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
if not pat or pat == '-':
return 'w' in mode and sys.stdout or sys.stdin
if hasattr(pat, 'write') and 'w' in mode:
return pat
if hasattr(pat, 'read') and 'r' in mode:
return pat
- return open(make_filename(repo, r, pat, node, total, seqno, revwidth),
+ return open(make_filename(repo, r, pat, node, total, seqno, revwidth,
+ pathname),
mode)
def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
@@ -569,25 +574,26 @@ def bundle(ui, repo, fname, dest="defaul
except:
os.unlink(fname)
-def cat(ui, repo, file1, rev=None, **opts):
- """output the latest or given revision of a file"""
- r = repo.file(relpath(repo, [file1])[0])
- if rev:
- try:
- # assume all revision numbers are for changesets
- n = repo.lookup(rev)
- change = repo.changelog.read(n)
- m = repo.manifest.read(change[0])
- n = m[relpath(repo, [file1])[0]]
- except (hg.RepoError, KeyError):
+def cat(ui, repo, file1, *pats, **opts):
+ """output the latest or given revisions of files"""
+ mf = {}
+ if opts['rev']:
+ change = repo.changelog.read(repo.lookup(opts['rev']))
+ mf = repo.manifest.read(change[0])
+ for src, abs, rel, exact in walk(repo, (file1,) + pats, opts):
+ r = repo.file(abs)
+ if opts['rev']:
try:
- n = r.lookup(rev)
- except KeyError, inst:
- raise util.Abort('cannot find file %s in rev %s', file1, rev)
- else:
- n = r.tip()
- fp = make_file(repo, r, opts['output'], node=n)
- fp.write(r.read(n))
+ n = mf[abs]
+ except (hg.RepoError, KeyError):
+ try:
+ n = r.lookup(rev)
+ except KeyError, inst:
+ raise util.Abort('cannot find file %s in rev %s', rel, rev)
+ else:
+ n = r.tip()
+ fp = make_file(repo, r, opts['output'], node=n, pathname=abs)
+ fp.write(r.read(n))
def clone(ui, source, dest=None, **opts):
"""make a copy of an existing repository"""
@@ -1765,8 +1771,11 @@ table = {
'hg bundle FILE DEST'),
"cat":
(cat,
- [('o', 'output', "", 'output to file')],
- 'hg cat [-o OUTFILE] FILE [REV]'),
+ [('I', 'include', [], 'include path in search'),
+ ('X', 'exclude', [], 'exclude path from search'),
+ ('o', 'output', "", 'output to file'),
+ ('r', 'rev', '', 'revision')],
+ 'hg cat [OPTION]... FILE...'),
"^clone":
(clone,
[('U', 'noupdate', None, 'skip update after cloning'),