Integration of Mercurial into LXR
Simon King
simon at simonking.org.uk
Thu Dec 13 09:02:41 CST 2012
On Thu, Dec 13, 2012 at 1:07 PM, andre-littoz <page74010-sf at yahoo.fr> wrote:
> Hello,
>
> I am the present LXR (Linux Cross-Referencer - see
> http://lxr/sourceforge.net) administrator/developer and trying to extend LXR
> beyond plain files/CVS/Git/svn storage engine.
>
> I succeeded in implementing an experimental backend storage engine to work
> with local Mercurial repositories. Unhappily, it runs horribly slow
> (approximately 10 times slower than git or Subversion on the same test
> case). Certainly because that's my first contact with hg.
>
> One of the first LXR tasks is to display a directory view, same as hgweb
> does. To retrieve directory content, I found nothing else than the following
> command:
> hg locate -r "revision of interest" a_directory/**
>
> This implies to traverse the full repository, where I only want the present
> directory, without its subdirectories. I can't use * pattern because I want
> to build a list of the subdirectories. The command reports the complete
> sub-tree rooted at the requested directory. I must then filter out the
> sublevels. This is a double waste: first inside Mercurial to report the
> tree, next inside LXR to prune unwanted information.
>
> When it comes to compute file size, I had to
> hg cat -r "revision of interest" "a_file" | wc
>
> which means extract the file and throw it away for every line in the
> directory list.
>
> This is really inefficient.
>
> I had a look at the source of hgweb to discover it used internal templates
> names fentries and dentries which contain apparently the information needed
> by LXR.
>
>
> Is there a simple and efficient command line to
> 1- get a "standard" directory list like ls or ls -F
> 2- retrieve a file size
> or
> 3- have access to information supplied by {fentries} and {dentries}
> templates?
>
> Thanks for your help
> André Littoz
> LXR administrator
>
I'm not aware of any way of retrieving the information that you want,
so instead here's an extension based on the guts of the
mercurial.hgweb.webcommands:manifest function. If you save it as
"lxr.py" and add it to your [extensions], then you'll get an "hg ls"
command which behaves like this in the mercurial repository:
$: hg ls -r tip
dir contrib
dir doc
dir hgext
dir i18n
dir mercurial
dir tests
727 .hgignore
8468 .hgsigs
3530 .hgtags
1663 CONTRIBUTORS
18092 COPYING
4009 Makefile
547 README
1056 hg
1225 hgeditor
683 hgweb.cgi
19397 setup.py
$: hg ls -r 1
dir mercurial
4 .hgignore
233 PKG-INFO
2753 README
7801 hg
6581 notes.txt
491 setup.py
45 tkmerge
$: hg ls -r 1 mercurial
0 __init__.py
16806 byterange.py
1484 fancyopts.py
17064 hg.py
1603 mdiff.py
6329 revlog.py
1804 transaction.py
Completely untested other than what you see above.
#------------------------------------------------
from mercurial import cmdutil
import mercurial.hgweb.webcommands
cmdtable = {}
command = cmdutil.command(cmdtable)
@command('ls',
[('r', 'rev', '.',
'revision to list')],
'hg ls [-r REV] [path]')
def lxrls(ui, repo, path='', rev='.'):
# largely copied from mercurial.hgweb.webcommands:manifest
ctx = repo[rev]
mf = ctx.manifest()
if path and not path.endswith('/'):
path += '/'
l = len(path)
files = {}
dirs = {}
for full, n in mf.iteritems():
f = mercurial.hgweb.webcommands.decodepath(full)
if f[:l] != path:
continue
remain = f[l:]
elements = remain.split('/')
if len(elements) == 1:
files[remain] = full
else:
h = dirs # need to retain ref to dirs (root)
for elem in elements[0:-1]:
if elem not in h:
h[elem] = {}
h = h[elem]
if len(h) > 1:
break
h[None] = None # denotes files present
continue
remain = f[l:]
for d in sorted(dirs):
ui.write('%-8s %s\n' % ('dir', d))
for f in sorted(files):
full = files[f]
fctx = ctx.filectx(full)
ui.write('%-8d %s\n' % (fctx.size(), f))
#------------------------------------------------
Hope that helps,
Simon
More information about the Mercurial-devel
mailing list