cat: increase perf when catting single files
Special case the single file case in hg cat. This allows us to avoid
parsing the manifest, which shaves 15% off hg cat perf. This is worth
it, since automation often uses hg cat for retrieving single files.
--- a/mercurial/commands.py Tue Jan 14 13:49:19 2014 -0800
+++ b/mercurial/commands.py Tue Jan 14 13:38:16 2014 -0800
@@ -1168,14 +1168,28 @@
ctx = scmutil.revsingle(repo, opts.get('rev'))
err = 1
m = scmutil.match(ctx, (file1,) + pats, opts)
- for abs in ctx.walk(m):
+
+ def write(path):
fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
- pathname=abs)
- data = ctx[abs].data()
+ pathname=path)
+ data = ctx[path].data()
if opts.get('decode'):
- data = repo.wwritedata(abs, data)
+ data = repo.wwritedata(path, data)
fp.write(data)
fp.close()
+
+ # Automation often uses hg cat on single files, so special case it
+ # for performance to avoid the cost of parsing the manifest.
+ if len(m.files()) == 1 and not m.anypats():
+ file = m.files()[0]
+ mf = repo.manifest
+ mfnode = ctx._changeset[0]
+ if mf.find(mfnode, file)[0]:
+ write(file)
+ return 0
+
+ for abs in ctx.walk(m):
+ write(abs)
err = 0
return err