Patchwork [1,of,4,V2] serve: add support for Mercurial subrepositories

login
register
mail settings
Submitter Matt Harbison
Date Feb. 16, 2017, 9:41 p.m.
Message ID <4f2862487d789edc1f36.1487281268@Envy>
Download mbox | patch
Permalink /patch/18573/
State Changes Requested
Delegated to: Yuya Nishihara
Headers show

Comments

Matt Harbison - Feb. 16, 2017, 9:41 p.m.
# HG changeset patch
# User Matt Harbison <matt_harbison@yahoo.com>
# Date 1486875517 18000
#      Sat Feb 11 23:58:37 2017 -0500
# Node ID 4f2862487d789edc1f36b5687d828a2914e1dc32
# Parent  afaf3c2b129c8940387fd9928ae4fdc28259d13c
serve: add support for Mercurial subrepositories

I've been using `hg serve --web-conf ...` with a simple '/=projects/**' [paths]
configuration for awhile without issue.  Let's ditch the need for the manual
configuration in this case, and limit the repos served to the actual subrepos.

This doesn't attempt to handle the case where a new subrepo appears while the
server is running.  That could probably be handled with a hook if somebody wants
it.  But it's such a rare case, it probably doesn't matter for the temporary
serves.

Unfortunately, the root of the webserver when serving multiple repos is the html
index file.  This makes the URL different for `hg serve` vs `hg serve -S`,
because the top level repo then needs to be part of the path.  That can be
fixed later.
Yuya Nishihara - Feb. 20, 2017, 2:27 p.m.
On Thu, 16 Feb 2017 16:41:08 -0500, Matt Harbison wrote:
> # HG changeset patch
> # User Matt Harbison <matt_harbison@yahoo.com>
> # Date 1486875517 18000
> #      Sat Feb 11 23:58:37 2017 -0500
> # Node ID 4f2862487d789edc1f36b5687d828a2914e1dc32
> # Parent  afaf3c2b129c8940387fd9928ae4fdc28259d13c
> serve: add support for Mercurial subrepositories
> 
> I've been using `hg serve --web-conf ...` with a simple '/=projects/**' [paths]
> configuration for awhile without issue.  Let's ditch the need for the manual
> configuration in this case, and limit the repos served to the actual subrepos.
> 
> This doesn't attempt to handle the case where a new subrepo appears while the
> server is running.  That could probably be handled with a hook if somebody wants
> it.  But it's such a rare case, it probably doesn't matter for the temporary
> serves.
> 
> Unfortunately, the root of the webserver when serving multiple repos is the html
> index file.  This makes the URL different for `hg serve` vs `hg serve -S`,
> because the top level repo then needs to be part of the path.  That can be
> fixed later.

I'm puzzled by this new version which extensively relies on somewhat magical
HTTP redirection. Instead, can't we fix hgwebdir to be able to host hgweb at
'/' URL, and add explicit URL to show the index page hidden by it?

That will be useful without subrepos. Currently we can't see the index page
'/foo' if we have a repository '/foo' and '/foo/bar'.
Matt Harbison - Feb. 21, 2017, 3 a.m.
On Mon, 20 Feb 2017 09:27:44 -0500, Yuya Nishihara <yuya@tcha.org> wrote:

> On Thu, 16 Feb 2017 16:41:08 -0500, Matt Harbison wrote:
>> # HG changeset patch
>> # User Matt Harbison <matt_harbison@yahoo.com>
>> # Date 1486875517 18000
>> #      Sat Feb 11 23:58:37 2017 -0500
>> # Node ID 4f2862487d789edc1f36b5687d828a2914e1dc32
>> # Parent  afaf3c2b129c8940387fd9928ae4fdc28259d13c
>> serve: add support for Mercurial subrepositories
>>
>> I've been using `hg serve --web-conf ...` with a simple '/=projects/**'  
>> [paths]
>> configuration for awhile without issue.  Let's ditch the need for the  
>> manual
>> configuration in this case, and limit the repos served to the actual  
>> subrepos.
>>
>> This doesn't attempt to handle the case where a new subrepo appears  
>> while the
>> server is running.  That could probably be handled with a hook if  
>> somebody wants
>> it.  But it's such a rare case, it probably doesn't matter for the  
>> temporary
>> serves.
>>
>> Unfortunately, the root of the webserver when serving multiple repos is  
>> the html
>> index file.  This makes the URL different for `hg serve` vs `hg serve  
>> -S`,
>> because the top level repo then needs to be part of the path.  That can  
>> be
>> fixed later.
>
> I'm puzzled by this new version which extensively relies on somewhat  
> magical
> HTTP redirection. Instead, can't we fix hgwebdir to be able to host  
> hgweb at
> '/' URL, and add explicit URL to show the index page hidden by it?

This patch is the same as the first in V1, except that I dropped forcing  
the web.staticurl config, and I globbed away a bunch of the http  
parameters in the tests, since only the URI and status is of interest.

The first version did host the parent at '/', and the subrepos relative to  
it.  I switched from that, not because of the index hiding, but because of  
all the problems I ran into.

First were problems (I don't remember all of the details, but eventually  
managed to fix) with `hg` commands.  And then I noticed that the initial  
repo view wasn't rendering properly in the browser.  There was output from  
the server like this:

127.0.0.1 - - [20/Feb/2017 21:02:36] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/Feb/2017 21:02:42] "GET /favicon.ico HTTP/1.1" 404 -

That seemed to be fixed by the staticurl config.  I was also able to load  
"http://localhost:8000/subrepo" and get it to display properly, so I  
submitted it.  But I waved Augie off because then I noticed more problems  
in the browser:

- At http://localhost:8000, the links on the left side were corrupt (graph  
is simply 'graph/tip', tags is 'http://tags', etc.)  The pattern seemed to  
be that things ending in 'tip' are relative URLs, and the rest get an  
http: prefix.  It looks from the sources like it is just a matter of '/'  
not translating for the {repo} template.

- At http://localhost:8000/subrepo, all of the links on the left look  
proper.  But if you click on one that ends in 'tip' (like 'graph'), the  
page doesn't render properly (like when 'staticurl' wasn't set on the  
parent repo).  It does properly render pages that don't end in 'tip', like  
'branches'.

I also had a different failed attempt at hosting the parent at '/' a few  
years ago, which had the same rendering issues.  And I didn't check  
anything other than paper.  All in all, a week or so of nonstop problems  
convinced me that I was going about this the wrong way.

To me, the benefits of this series over the original is:

1) The repos aren't moved, and therefore don't incur these subtle bugs
2) These changes are totally isolated to subrepo serving, so there should  
be no risk to mainstream hgweb usage
3) This is completely compatible with existing serves with a simple  
'/=$projects_dir/**' config file, because the real repos are not anchored  
to '/'.

>
> That will be useful without subrepos. Currently we can't see the index  
> page '/foo' if we have a repository '/foo' and '/foo/bar'.

I actually wondered why there wasn't an explicit index.html handled where  
needed, and maybe a redirect to it.  I don't think doing that is  
incompatible with this series though.
Yuya Nishihara - Feb. 21, 2017, 2:33 p.m.
On Mon, 20 Feb 2017 22:00:20 -0500, Matt Harbison wrote:
> On Mon, 20 Feb 2017 09:27:44 -0500, Yuya Nishihara <yuya@tcha.org> wrote:
> > On Thu, 16 Feb 2017 16:41:08 -0500, Matt Harbison wrote:
> >> # HG changeset patch
> >> # User Matt Harbison <matt_harbison@yahoo.com>
> >> # Date 1486875517 18000
> >> #      Sat Feb 11 23:58:37 2017 -0500
> >> # Node ID 4f2862487d789edc1f36b5687d828a2914e1dc32
> >> # Parent  afaf3c2b129c8940387fd9928ae4fdc28259d13c
> >> serve: add support for Mercurial subrepositories
> >>
> >> I've been using `hg serve --web-conf ...` with a simple '/=projects/**'  
> >> [paths]
> >> configuration for awhile without issue.  Let's ditch the need for the  
> >> manual
> >> configuration in this case, and limit the repos served to the actual  
> >> subrepos.
> >>
> >> This doesn't attempt to handle the case where a new subrepo appears  
> >> while the
> >> server is running.  That could probably be handled with a hook if  
> >> somebody wants
> >> it.  But it's such a rare case, it probably doesn't matter for the  
> >> temporary
> >> serves.
> >>
> >> Unfortunately, the root of the webserver when serving multiple repos is  
> >> the html
> >> index file.  This makes the URL different for `hg serve` vs `hg serve  
> >> -S`,
> >> because the top level repo then needs to be part of the path.  That can  
> >> be
> >> fixed later.
> >
> > I'm puzzled by this new version which extensively relies on somewhat  
> > magical
> > HTTP redirection. Instead, can't we fix hgwebdir to be able to host  
> > hgweb at
> > '/' URL, and add explicit URL to show the index page hidden by it?
> 
> This patch is the same as the first in V1, except that I dropped forcing  
> the web.staticurl config, and I globbed away a bunch of the http  
> parameters in the tests, since only the URI and status is of interest.
> 
> The first version did host the parent at '/', and the subrepos relative to  
> it.

Yes, that seems intuitive way to serve a repo and its subrepos behind. I
thought there wasn't redirection magic as the parent repo was served at '/',
was there?

> - At http://localhost:8000, the links on the left side were corrupt (graph  
> is simply 'graph/tip', tags is 'http://tags', etc.)  The pattern seemed to  
> be that things ending in 'tip' are relative URLs, and the rest get an  
> http: prefix.  It looks from the sources like it is just a matter of '/'  
> not translating for the {repo} template.

[snip]

I saw some of these problems in V1. However, the standalone hgweb can host
a repository at '/', so I don't think it's quite difficult to host the subrepo
parent at '/'.

> To me, the benefits of this series over the original is:
> 
> 1) The repos aren't moved, and therefore don't incur these subtle bugs
> 2) These changes are totally isolated to subrepo serving, so there should  
> be no risk to mainstream hgweb usage
> 3) This is completely compatible with existing serves with a simple  
> '/=$projects_dir/**' config file, because the real repos are not anchored  
> to '/'.

I think (2) and (3) are up to how we build a repository map. If a map has no
'/' entry, hgweb would serve nothing at '/' and is compatible with the current
behavior.
Matt Harbison - Feb. 25, 2017, 8:25 p.m.
Sorry for the delay- I was swamped the last few days.

On Tue, 21 Feb 2017 09:33:58 -0500, Yuya Nishihara <yuya@tcha.org> wrote:

> On Mon, 20 Feb 2017 22:00:20 -0500, Matt Harbison wrote:
>> On Mon, 20 Feb 2017 09:27:44 -0500, Yuya Nishihara <yuya@tcha.org>  
>> wrote:
>> > On Thu, 16 Feb 2017 16:41:08 -0500, Matt Harbison wrote:
>> >> # HG changeset patch
>> >> # User Matt Harbison <matt_harbison@yahoo.com>
>> >> # Date 1486875517 18000
>> >> #      Sat Feb 11 23:58:37 2017 -0500
>> >> # Node ID 4f2862487d789edc1f36b5687d828a2914e1dc32
>> >> # Parent  afaf3c2b129c8940387fd9928ae4fdc28259d13c
>> >> serve: add support for Mercurial subrepositories
>> >>
>> >> I've been using `hg serve --web-conf ...` with a simple  
>> '/=projects/**'
>> >> [paths]
>> >> configuration for awhile without issue.  Let's ditch the need for the
>> >> manual
>> >> configuration in this case, and limit the repos served to the actual
>> >> subrepos.
>> >>
>> >> This doesn't attempt to handle the case where a new subrepo appears
>> >> while the
>> >> server is running.  That could probably be handled with a hook if
>> >> somebody wants
>> >> it.  But it's such a rare case, it probably doesn't matter for the
>> >> temporary
>> >> serves.
>> >>
>> >> Unfortunately, the root of the webserver when serving multiple repos  
>> is
>> >> the html
>> >> index file.  This makes the URL different for `hg serve` vs `hg serve
>> >> -S`,
>> >> because the top level repo then needs to be part of the path.  That  
>> can
>> >> be
>> >> fixed later.
>> >
>> > I'm puzzled by this new version which extensively relies on somewhat
>> > magical
>> > HTTP redirection. Instead, can't we fix hgwebdir to be able to host
>> > hgweb at
>> > '/' URL, and add explicit URL to show the index page hidden by it?
>>
>> This patch is the same as the first in V1, except that I dropped forcing
>> the web.staticurl config, and I globbed away a bunch of the http
>> parameters in the tests, since only the URI and status is of interest.
>>
>> The first version did host the parent at '/', and the subrepos relative  
>> to
>> it.
>
> Yes, that seems intuitive way to serve a repo and its subrepos behind. I
> thought there wasn't redirection magic as the parent repo was served at  
> '/',
> was there?

Correct. Redirection was only introduced in V2.

>> - At http://localhost:8000, the links on the left side were corrupt  
>> (graph
>> is simply 'graph/tip', tags is 'http://tags', etc.)  The pattern seemed  
>> to
>> be that things ending in 'tip' are relative URLs, and the rest get an
>> http: prefix.  It looks from the sources like it is just a matter of '/'
>> not translating for the {repo} template.
>
> [snip]
>
> I saw some of these problems in V1. However, the standalone hgweb can  
> host
> a repository at '/', so I don't think it's quite difficult to host the  
> subrepo
> parent at '/'.

That's a good point, so now I'm really puzzled over the subtle  
differences.  It looks like when it finds a hosted repo, it just farms out  
to hgweb, like the single serve would do.

>> To me, the benefits of this series over the original is:
>>
>> 1) The repos aren't moved, and therefore don't incur these subtle bugs
>> 2) These changes are totally isolated to subrepo serving, so there  
>> should
>> be no risk to mainstream hgweb usage
>> 3) This is completely compatible with existing serves with a simple
>> '/=$projects_dir/**' config file, because the real repos are not  
>> anchored
>> to '/'.
>
> I think (2) and (3) are up to how we build a repository map.

What I mean for (2) is that in V2, none of the code changes are hit  
without -S.  That seems like a good thing, given the subtle breakage in V1.

What I mean by (3) is that the transition for current clones is to simply  
drop --web-conf=.. and start using -S on the server side.  Clients won't  
see a difference.

I assume that the hardcoded web.staticurl in V1 also means that it won't  
be able to serve a subrepo named 'static'?  (That's admittedly an edge  
case.)

I only see the two ways to build the repo map, so I'm not sure what you  
are saying here.

> If a map has no
> '/' entry, hgweb would serve nothing at '/' and is compatible with the  
> current
> behavior.

Patch

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -2294,6 +2294,15 @@ 
         bad.extend(f for f in rejected if f in match.files())
     return bad
 
+def addwebdirpath(repo, serverpath, webconf):
+    webconf[serverpath] = repo.root
+    repo.ui.debug('adding %s = %s\n' % (serverpath, repo.root))
+
+    for r in repo.revs('filelog("path:.hgsub")'):
+        ctx = repo[r]
+        for subpath in ctx.substate:
+            ctx.sub(subpath).addwebdirpath(serverpath, webconf)
+
 def forget(ui, repo, match, prefix, explicitonly):
     join = lambda f: os.path.join(prefix, f)
     bad = []
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -4607,7 +4607,8 @@ 
     ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
     ('', 'style', '', _('template style to use'), _('STYLE')),
     ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
-    ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
+    ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
+     + subrepoopts,
     _('[OPTION]...'),
     optionalrepo=True)
 def serve(ui, repo, **opts):
diff --git a/mercurial/help/subrepos.txt b/mercurial/help/subrepos.txt
--- a/mercurial/help/subrepos.txt
+++ b/mercurial/help/subrepos.txt
@@ -136,6 +136,11 @@ 
     subrepository changes are available when referenced by top-level
     repositories.  Push is a no-op for Subversion subrepositories.
 
+:serve: serve does not recurse into subrepositories unless
+    -S/--subrepos is specified.  Git and Subversion subrepositories
+    are currently silently ignored.  Mercurial subrepositories with a
+    URL source are also silently ignored.
+
 :status: status does not recurse into subrepositories unless
     -S/--subrepos is specified. Subrepository changes are displayed as
     regular Mercurial changes on the subrepository
diff --git a/mercurial/server.py b/mercurial/server.py
--- a/mercurial/server.py
+++ b/mercurial/server.py
@@ -16,6 +16,7 @@ 
 
 from . import (
     chgserver,
+    cmdutil,
     commandserver,
     error,
     hgweb,
@@ -135,11 +136,24 @@ 
         baseui = ui
     webconf = opts.get('web_conf') or opts.get('webdir_conf')
     if webconf:
+        if opts.get('subrepos'):
+            raise error.Abort(_('--web-conf cannot be used with --subrepos'))
+
         # load server settings (e.g. web.port) to "copied" ui, which allows
         # hgwebdir to reload webconf cleanly
         servui = ui.copy()
         servui.readconfig(webconf, sections=['web'])
         alluis.add(servui)
+    elif opts.get('subrepos'):
+        servui = ui.copy()
+        alluis.add(servui)
+
+        # If repo is None, hgweb.createapp() already raises a proper abort
+        # message as long as webconf is None.
+        if repo:
+            webconf = dict()
+            cmdutil.addwebdirpath(repo, repo.wvfs.basename(repo.root) + '/',
+                                  webconf)
     else:
         servui = ui
 
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -438,6 +438,15 @@ 
         self._ctx = ctx
         self._path = path
 
+    def addwebdirpath(self, serverpath, webconf):
+        """Add the hgwebdir entries for this subrepo, and any of its subrepos.
+
+        ``serverpath`` is the path component of the URL for this repo.
+
+        ``webconf`` is the dictionary of hgwebdir entries.
+        """
+        pass
+
     def storeclean(self, path):
         """
         returns true if the repository has not changed since it was last
@@ -645,6 +654,17 @@ 
         self.ui.setconfig('ui', '_usedassubrepo', 'True', 'subrepo')
         self._initrepo(r, state[0], create)
 
+    @annotatesubrepoerror
+    def addwebdirpath(self, serverpath, webconf):
+        # The URL request contains the subrepo source path, not the local
+        # subrepo path.  The distinction matters for 'foo = ../foo' type
+        # entries.  It isn't possible to serve up 'foo = http://..' type
+        # entries, because the server path is relative to this local server.
+        src = self._state[0]
+        if util.url(src).islocal():
+            path = util.normpath(serverpath + src)
+            cmdutil.addwebdirpath(self._repo, path + '/', webconf)
+
     def storeclean(self, path):
         with self._repo.lock():
             return self._storeclean(path)
diff --git a/tests/test-completion.t b/tests/test-completion.t
--- a/tests/test-completion.t
+++ b/tests/test-completion.t
@@ -179,6 +179,7 @@ 
   --repository
   --stdio
   --style
+  --subrepos
   --templates
   --time
   --traceback
@@ -189,6 +190,7 @@ 
   -A
   -E
   -R
+  -S
   -a
   -d
   -h
@@ -220,7 +222,7 @@ 
   pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
   push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
   remove: after, force, subrepos, include, exclude
-  serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
+  serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate, subrepos
   status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
   summary: remote
   update: clean, check, date, rev, tool
diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t
--- a/tests/test-subrepo-deep-nested-change.t
+++ b/tests/test-subrepo-deep-nested-change.t
@@ -73,6 +73,53 @@ 
   adding main/main (glob)
   $ hg commit -R main -m "main import"
 
+#if serve
+  $ hg serve -R main --debug -S -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log
+  adding main/ = $TESTTMP/main (glob)
+  adding sub1/ = $TESTTMP/main/sub1 (glob)
+  adding sub2/ = $TESTTMP/main/sub1/sub2 (glob)
+  listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob)
+  adding main/ = $TESTTMP/main (glob)
+  adding sub1/ = $TESTTMP/main/sub1 (glob)
+  adding sub2/ = $TESTTMP/main/sub1/sub2 (glob)
+  $ cat hg1.pid >> $DAEMON_PIDS
+
+  $ hg clone http://localhost:$HGPORT/main httpclone --config progress.disable=True
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 3 changes to 3 files
+  updating to branch default
+  cloning subrepo sub1 from http://localhost:$HGPORT/sub1
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 3 changes to 3 files
+  cloning subrepo sub1/sub2 from http://localhost:$HGPORT/sub2 (glob)
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ cat access.log
+  * "GET /main?cmd=capabilities HTTP/1.1" 200 - (glob)
+  * "GET /main?cmd=batch HTTP/1.1" 200 - * (glob)
+  * "GET /main?cmd=getbundle HTTP/1.1" 200 - * (glob)
+  * "GET /sub1?cmd=capabilities HTTP/1.1" 200 - (glob)
+  * "GET /sub1?cmd=batch HTTP/1.1" 200 - * (glob)
+  * "GET /sub1?cmd=getbundle HTTP/1.1" 200 - * (glob)
+  * "GET /sub2?cmd=capabilities HTTP/1.1" 200 - (glob)
+  * "GET /sub2?cmd=batch HTTP/1.1" 200 - * (glob)
+  * "GET /sub2?cmd=getbundle HTTP/1.1" 200 - * (glob)
+
+  $ killdaemons.py
+  $ rm hg1.pid error.log access.log
+#endif
+
 Cleaning both repositories, just as a clone -U
 
   $ hg up -C -R sub2 null
diff --git a/tests/test-subrepo-recursion.t b/tests/test-subrepo-recursion.t
--- a/tests/test-subrepo-recursion.t
+++ b/tests/test-subrepo-recursion.t
@@ -251,6 +251,60 @@ 
    z1
   +z2
 
+#if serve
+  $ cd ..
+  $ hg serve -R repo --debug -S -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log
+  adding repo/ = $TESTTMP/repo (glob)
+  adding repo/foo/ = $TESTTMP/repo/foo (glob)
+  adding repo/foo/bar/ = $TESTTMP/repo/foo/bar (glob)
+  listening at http://*:$HGPORT/ (bound to *:$HGPORT) (glob)
+  adding repo/ = $TESTTMP/repo (glob)
+  adding repo/foo/ = $TESTTMP/repo/foo (glob)
+  adding repo/foo/bar/ = $TESTTMP/repo/foo/bar (glob)
+  $ cat hg1.pid >> $DAEMON_PIDS
+
+  $ hg clone http://localhost:$HGPORT/repo clone  --config progress.disable=True
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 3 changesets with 5 changes to 3 files
+  updating to branch default
+  cloning subrepo foo from http://localhost:$HGPORT/repo/foo
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 4 changesets with 7 changes to 3 files
+  cloning subrepo foo/bar from http://localhost:$HGPORT/repo/foo/bar (glob)
+  requesting all changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 3 changesets with 3 changes to 1 files
+  3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ cat clone/foo/bar/z.txt
+  z1
+  z2
+  z3
+
+  $ cat access.log
+  * "GET /repo?cmd=capabilities HTTP/1.1" 200 - (glob)
+  * "GET /repo?cmd=batch HTTP/1.1" 200 - * (glob)
+  * "GET /repo?cmd=getbundle HTTP/1.1" 200 - * (glob)
+  * "GET /repo/foo?cmd=capabilities HTTP/1.1" 200 - (glob)
+  * "GET /repo/foo?cmd=batch HTTP/1.1" 200 - * (glob)
+  * "GET /repo/foo?cmd=getbundle HTTP/1.1" 200 - * (glob)
+  * "GET /repo/foo/bar?cmd=capabilities HTTP/1.1" 200 - (glob)
+  * "GET /repo/foo/bar?cmd=batch HTTP/1.1" 200 - * (glob)
+  * "GET /repo/foo/bar?cmd=getbundle HTTP/1.1" 200 - * (glob)
+
+  $ killdaemons.py
+  $ rm hg1.pid error.log access.log
+  $ cd repo
+#endif
+
 Enable progress extension for archive tests:
 
   $ cp $HGRCPATH $HGRCPATH.no-progress