hgweb: teach archive how to download a specific directory or file
The archive web command now takes into account the "file" request entry, if one
is provided.
The provided "file" is processed as a "path" corresponding to a directory or
file that will be downloaded.
With this change hgweb can to process requests such as:
http://mercurial.selenic.com/hg/archive/tip.zip/mercurial/templates
This will download all files on the mercurial/templates directory as a zip file.
It is not possible to specify file patterns ('glob', 'relglob', 'path',
'relpath', 're', 'relre' nor 'set'). The server will reject those with a
403 HTTP error response.
Note that this is a first step to add support for downloading directories from
the web interface. A following patch will modify the archiveentry map entry on
the different templates so that it adds the current folder path to the archive
links.
--- a/mercurial/hgweb/webcommands.py Wed Feb 06 10:06:45 2013 +0100
+++ b/mercurial/hgweb/webcommands.py Sun Feb 10 11:52:05 2013 +0100
@@ -816,6 +816,19 @@
if cnode == key or key == 'tip':
arch_version = short(cnode)
name = "%s-%s" % (reponame, arch_version)
+
+ ctx = webutil.changectx(web.repo, req)
+ pats = []
+ file = req.form.get('file', None)
+ if file:
+ file = file[0]
+ patandfile = file.split(':')
+ if len(patandfile) > 1 and patandfile[0].lower() in ('glob', 'relglob',
+ 'path', 'relpath', 're', 'relre', 'set'):
+ msg = 'Archive pattern not allowed: %s' % file
+ raise ErrorResponse(HTTP_FORBIDDEN, msg)
+ pats = ['path:' + file]
+
mimetype, artype, extension, encoding = web.archive_specs[type_]
headers = [
('Content-Disposition', 'attachment; filename=%s%s' % (name, extension))
@@ -825,9 +838,9 @@
req.headers.extend(headers)
req.respond(HTTP_OK, mimetype)
- ctx = webutil.changectx(web.repo, req)
+ matchfn = scmutil.match(ctx, pats, default='path')
archival.archive(web.repo, req, cnode, artype, prefix=name,
- matchfn=scmutil.match(ctx, []),
+ matchfn=matchfn,
subrepos=web.configbool("web", "archivesubrepos"))
return []
--- a/tests/test-archive.t Wed Feb 06 10:06:45 2013 +0100
+++ b/tests/test-archive.t Sun Feb 10 11:52:05 2013 +0100
@@ -101,6 +101,18 @@
testing: test-archive-2c0277f05ed4/foo OK
No errors detected in compressed data of archive.zip.
+test that we can download single directories and files
+
+ $ python getarchive.py "$TIP" gz baz | gunzip | tar tf - 2>/dev/null
+ test-archive-2c0277f05ed4/baz/bletch
+ $ python getarchive.py "$TIP" gz foo | gunzip | tar tf - 2>/dev/null
+ test-archive-2c0277f05ed4/foo
+
+test that we reject unsafe patterns
+
+ $ python getarchive.py "$TIP" gz relre:baz
+ HTTP Error 403: Archive pattern not allowed: relre:baz
+
$ "$TESTDIR/killdaemons.py" $DAEMON_PIDS
$ hg archive -t tar test.tar