diff --git a/mercurial/hgweb/hgwebdir_mod.py b/mercurial/hgweb/hgwebdir_mod.py --- a/mercurial/hgweb/hgwebdir_mod.py +++ b/mercurial/hgweb/hgwebdir_mod.py @@ -428,7 +428,10 @@ uenv.iteritems()} req = requestmod.parserequestfromenv( uenv, reponame=virtualrepo, - altbaseurl=self.ui.config('web', 'baseurl')) + altbaseurl=self.ui.config('web', 'baseurl'), + # Reuse wrapped body file object otherwise state + # tracking can get confused. + bodyfh=req.bodyfh) try: # ensure caller gets private copy of ui repo = hg.repository(self.ui.copy(), real) diff --git a/mercurial/hgweb/request.py b/mercurial/hgweb/request.py --- a/mercurial/hgweb/request.py +++ b/mercurial/hgweb/request.py @@ -124,7 +124,7 @@ # WSGI environment dict, unmodified. rawenv = attr.ib() -def parserequestfromenv(env, reponame=None, altbaseurl=None): +def parserequestfromenv(env, reponame=None, altbaseurl=None, bodyfh=None): """Parse URL components from environment variables. WSGI defines request attributes via environment variables. This function @@ -144,6 +144,9 @@ if the request were to ``http://myserver:9000/prefix/rev/@``. In other words, ``wsgi.url_scheme``, ``SERVER_NAME``, ``SERVER_PORT``, and ``SCRIPT_NAME`` are all effectively replaced by components from this URL. + + ``bodyfh`` can be used to specify a file object to read the request body + from. If not defined, ``wsgi.input`` from the environment dict is used. """ # PEP 3333 defines the WSGI spec and is a useful reference for this code. @@ -307,9 +310,10 @@ if 'CONTENT_TYPE' in env and 'HTTP_CONTENT_TYPE' not in env: headers['Content-Type'] = env['CONTENT_TYPE'] - bodyfh = env['wsgi.input'] - if 'Content-Length' in headers: - bodyfh = util.cappedreader(bodyfh, int(headers['Content-Length'])) + if bodyfh is None: + bodyfh = env['wsgi.input'] + if 'Content-Length' in headers: + bodyfh = util.cappedreader(bodyfh, int(headers['Content-Length'])) return parsedrequest(method=env['REQUEST_METHOD'], url=fullurl, baseurl=baseurl, diff --git a/tests/test-push-http.t b/tests/test-push-http.t --- a/tests/test-push-http.t +++ b/tests/test-push-http.t @@ -380,3 +380,49 @@ #endif $ cd .. + +Pushing via hgwebdir works + + $ hg init hgwebdir + $ cd hgwebdir + $ echo 0 > a + $ hg -q commit -A -m initial + $ cd .. + + $ cat > web.conf << EOF + > [paths] + > / = * + > [web] + > push_ssl = false + > allow_push = * + > [extensions] + > showstack = $TESTDIR/../contrib/showstack.py + > EOF + + $ hg serve --web-conf web.conf -p $HGPORT -d --pid-file hg.pid + $ cat hg.pid > $DAEMON_PIDS + + $ hg clone http://localhost:$HGPORT/hgwebdir hgwebdir-local + requesting all changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets 98a3f8f02ba7 + updating to branch default + 1 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ cd hgwebdir-local + $ echo commit > a + $ hg commit -m 'local commit' + + $ hg push + pushing to http://localhost:$HGPORT/hgwebdir + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + + $ killdaemons.py + + $ cd ..