[PATCH 3 of 3 RFC] hgweb: handle obsolete changesets gracefully

Pierre-Yves David pierre-yves.david at ens-lyon.org
Thu Aug 15 18:57:19 CDT 2013


On 8 août 2013, at 09:48, Dan Villiom Podlaski Christiansen wrote:

> # HG changeset patch
> # User Dan Villiom Podlaski Christiansen  <danchr at gmail.com>
> # Date 1375624663 -7200
> #      Sun Aug 04 15:57:43 2013 +0200
> # Node ID 5507e2af80f5e8026a054ce440c0c8958134eefe
> # Parent  b1f7ae28c3e371a70ee363a4fbe5d50063a224fc
> hgweb: handle obsolete changesets gracefully
> 
> If the changeset has any successors, issue a 403 Moved Permanently;
> otherwise we issue a 410 Gone. Please note that this is slightly
> misleading for 'secret' changesets, as they may appear later on.

You are going too fast here.

1) issue 410 for filtered changeset
1.1) (403 or 404 for secret ?)
2) issue a smarter message with potential link to successors (could include information about who and when it was rewritten)
3) use redirect (does not like the idea yet)

> diff --git a/mercurial/hgweb/common.py b/mercurial/hgweb/common.py
> --- a/mercurial/hgweb/common.py
> +++ b/mercurial/hgweb/common.py
> @@ -9,12 +9,14 @@
> import errno, mimetypes, os
> 
> HTTP_OK = 200
> +HTTP_MOVED_PERMANENTLY = 301
> HTTP_NOT_MODIFIED = 304
> HTTP_BAD_REQUEST = 400
> HTTP_UNAUTHORIZED = 401
> HTTP_FORBIDDEN = 403
> HTTP_NOT_FOUND = 404
> HTTP_METHOD_NOT_ALLOWED = 405
> +HTTP_GONE = 410
> HTTP_SERVER_ERROR = 500
> 
> 
> diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
> --- a/mercurial/hgweb/hgweb_mod.py
> +++ b/mercurial/hgweb/hgweb_mod.py
> @@ -8,11 +8,13 @@
> 
> import os
> from mercurial import ui, hg, hook, error, encoding, templater, util, repoview
> +from mercurial import obsolete
> +from mercurial.node import short
> from mercurial.templatefilters import websub
> from mercurial.i18n import _
> from common import get_stat, ErrorResponse, permhooks, caching
> -from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST
> -from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR
> +from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST, HTTP_GONE
> +from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR, HTTP_MOVED_PERMANENTLY
> from request import wsgirequest
> import webcommands, protocol, webutil, re
> 
> @@ -249,6 +251,33 @@ class hgweb(object):
> 
>             return content
> 
> +        except error.FilteredLookupError, err:
> +            succsets = obsolete.successorssets(self.repo, err.rev)
> +
> +            if not succsets:
> +                req.respond(HTTP_GONE, ctype)
> +
> +                return tmpl('error', error=err.message)
> +
> +            elif len(succsets) != 1:
> +                # TODO: changeset has divergent successors
> +                req.respond(HTTP_SERVER_ERROR, ctype)

divergent successors are not "server error" (my best guest for now would be "GONE")

> +
> +                return tmpl('error', error=err.message)
> +
> +            location = [req.url.rstrip('/')]
> +            location += req.form['cmd']
> +
> +            location.append(short(succsets[0][-1]))
> +
> +            if 'file' in req.form:
> +                location += req.form['file']
> +
> +            req.headers.extend([('Location', '/'.join(location))])
> +            req.respond(HTTP_MOVED_PERMANENTLY, ctype)
> +
> +            return tmpl('error', error=err.message)
> +
>         except (error.LookupError, error.RepoLookupError), err:
>             req.respond(HTTP_NOT_FOUND, ctype)
>             msg = str(err)
> diff --git a/mercurial/hgweb/webutil.py b/mercurial/hgweb/webutil.py
> --- a/mercurial/hgweb/webutil.py
> +++ b/mercurial/hgweb/webutil.py
> @@ -201,6 +201,9 @@ def cleanpath(repo, path):
> def changeidctx (repo, changeid):
>     try:
>         ctx = repo[changeid]
> +    except error.FilteredLookupError:
> +        raise
> +
>     except error.RepoError:
>         man = repo.manifest
>         ctx = repo[man.linkrev(man.rev(man.lookup(changeid)))]
> diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t
> --- a/tests/test-hgweb-commands.t
> +++ b/tests/test-hgweb-commands.t
> @@ -1385,7 +1385,7 @@ proper status for filtered revision
>   $ PATH_INFO=/rev/5; export PATH_INFO
>   $ QUERY_STRING='style=raw'
>   $ python hgweb.cgi #> search
> -  Status: 404 Not Found\r (esc)
> +  Status: 410 Gone\r (esc)
>   ETag: *\r (glob) (esc)
>   Content-Type: text/plain; charset=ascii\r (esc)
>   \r (esc)
> @@ -1399,7 +1399,7 @@ proper status for filtered revision
>   $ PATH_INFO=/rev/4; export PATH_INFO
>   $ QUERY_STRING='style=raw'
>   $ python hgweb.cgi #> search
> -  Status: 404 Not Found\r (esc)
> +  Status: 410 Gone\r (esc)
>   ETag: *\r (glob) (esc)
>   Content-Type: text/plain; charset=ascii\r (esc)
>   \r (esc)
> @@ -1498,6 +1498,47 @@ filtered '0' changeset
> 
> 
> 
> +Test obsolete redirection
> +
> +  $ cat > ../obs.py << EOF
> +  > import mercurial.obsolete
> +  > mercurial.obsolete._enabled = True
> +  > EOF
> +  $ echo '[extensions]' >> $HGRCPATH
> +  $ echo "rebase=" >> $HGRCPATH
> +  $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
> +  $ hg up 12
> +  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ echo B > b; hg add b
> +  $ hg ci -m 6
> +
> +Use a rebase to obsolete r13, and test redirection
> +
> +  $ hg rebase -r 13 -d 11
> +  $ PATH_INFO=/rev/13; export PATH_INFO
> +  $ QUERY_STRING='style=raw'
> +  $ python hgweb.cgi #> search
> +  Status: 301 Moved Permanently\r (esc)
> +  ETag: *\r (glob) (esc)
> +  Location: /test/rev/0d601cf5c587\r (esc)
> +  Content-Type: text/plain; charset=ascii\r (esc)
> +  \r (esc)
> +  
> +  error: revision 13 is hidden
> +
> +Rebase r13 once more, testing divergent changesets
> +
> +  $ hg --hidden rebase -r 13 -d 9
> +  $ PATH_INFO=/rev/13; export PATH_INFO
> +  $ QUERY_STRING='style=raw'
> +  $ python hgweb.cgi #> search
> +  Status: 500 Internal Server Error\r (esc)
> +  ETag: *\r (glob) (esc)
> +  Content-Type: text/plain; charset=ascii\r (esc)
> +  \r (esc)
> +  
> +  error: revision 13 is hidden
> +
> 
> 
>   $ cd ..
> diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
> --- a/tests/test-obsolete.t
> +++ b/tests/test-obsolete.t
> @@ -747,7 +747,7 @@ check filelog view
>   $ "$TESTDIR/get-with-headers.py" --headeronly localhost:$HGPORT 'rev/68'
>   200 Script output follows
>   $ "$TESTDIR/get-with-headers.py" --headeronly localhost:$HGPORT 'rev/67'
> -  404 Not Found
> +  410 Gone
>   [1]
> 
> check that web.view config option:
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel



More information about the Mercurial-devel mailing list