Surpringly, the templates didn't receive an unmodified version of the
line numbers. Expose it to make implementing the JSON templates easier.
In theory, we could post-process an existing template variable. But
extra string manipulation seems quite wasteful, especially on items that
could occur hundreds or even thousands of times in output.
It's pretty surprising phase wasn't part of this template call already.
We now expose {phase} to the {changeset} template and we expose this
data to JSON.
This brings JSON output in line with the output from `hg log -Tjson`.
The lone exception is hweb doesn't print the numeric rev. As has been
stated previously, I don't believe hgweb should be exposing these
unstable identifiers. (We can add them later if we really want them.)
There is still work to bring hgweb in parity with --verbose and
--debug output from the CLI.
Although Python supports `X = Y if COND else Z`, this was only
introduced in Python 2.5. Since we have to support Python 2.4, it was
a very common thing to write instead `X = COND and Y or Z`, which is a
bit obscure at a glance. It requires some intricate knowledge of
Python to understand how to parse these one-liners.
We change instead all of these one-liners to 4-liners. This was
executed with the following perlism:
find -name "*.py" -exec perl -pi -e 's,(\s*)([\.\w]+) = \(?(\S+)\s+and\s+(\S*)\)?\s+or\s+(\S*)$,$1if $3:\n$1 $2 = $4\n$1else:\n$1 $2 = $5,' {} \;
I tweaked the following cases from the automatic Perl output:
prev = (parents and parents[0]) or nullid
port = (use_ssl and 443 or 80)
cwd = (pats and repo.getcwd()) or ''
rename = fctx and webutil.renamelink(fctx) or []
ctx = fctx and fctx or ctx
self.base = (mapfile and os.path.dirname(mapfile)) or ''
I also added some newlines wherever they seemd appropriate for readability
There are probably a few ersatz ternary operators still in the code
somewhere, lurking away from the power of a simple regex.
Similar in spirit to df435ff00d29, I want to write an extension to
make available extra template keywords so hgweb templates can include
extra data.
To do this today requires monkeypatching the templater, which I think is
the wrong place to perform this modification.
This patch extracts the creation of the templater arguments to a
standalone function - one that can be monkeypatched by extensions.
I would very much like for extensions to be able to inject extra
templater parameters into *any* template. However, I'm not sure the best
way to facilitate this, as hgweb commands invoke the templater before
returning and we want the extensions to have access to rich data
structures like the context instances. We need cooperation inside hgweb
command functions. The use case screams for something like internal-only
"hooks." This is exactly what my (rejected) "events" patch series
provided. Perhaps that feature should be reconsidered...
The issue is titled "filtered revision 'XXX' (not in 'served' subset)" and that
is the error message you sometimes get when trying to look at a file (/file or
/annotate) in hgweb. For example:
http://hg.intevation.org/mercurial/crew/file/8414f8487b33/mercurial/cmdutil.py
This happens when a parent revision for a file is hidden, thus it is
not 'served' and isn't accessible in hgweb by default. When hgweb tries to
access such changeset, it produces the error and HTTP status code 404.
Another detail is that the parents() function, that is used in multiple places
in hgweb, sometimes returned changesets that were obsoleted by the current
changeset for the file. For example, when using rebase with evolve and rebasing
a divergent changeset that introduces a file on top of current branch. Or
grafting a change and making the new grafted changeset obsolete the source
(shown in the test case). The result is the same - the obsoleted changeset was
mistakingly returned from parents(), even though it's not a parent and the only
link to the new changeset is an obsoletion marker (and rebase/graft metadata?
not sure it matters).
The problem is fixed by using introrev() instead of linkrev() for finding
parents. This prevents parents() function from returning unrelated obsolete
changesets.
The test case prepares a separate repo because (afaict) all other test cases
never reuse file names, so there are no files that were changed in multiple
changesets. So no previously available files have obsolete changesets in their
history.
This change is intended to avoid exposing the implementation detail to
callers. I'm going to extend fullreposet to support "null" revision, so
these mfunc calls will have to use fullreposet() instead of spanset().
A subsequent patch will introduce an import cycle between mercurial.help
and mercurial.hgweb.webcommands. Break the cycle by moving the import of
mercurial.help into the web command that actually needs it.
I want to supplement changelist entries (used by shortlog and changelog
endpoints) with custom metadata from an extension. i.e. I have extra
per-changeset metadata that I wish to make available to templates so it
can be rendered on hgweb.
To facilitate this, I've extracted the logic for creating a changeset
data structure into its own function, where it can be wrapped by
extensions.
Ideally, hgweb would use the same templater as the command line and have
full access to templatekw.keywords. But that's a lot of work. This patch
gets us some of the benefit without all the work.
Many other hgweb commands could benefit from similar refactorings. I'm
going to wait to see how this patch is received before I go crazy on
extracting inline functions.
This adds UI portion of the feature that has resided in mercurial since 2012.
Back then the interface was added together with the code, but was shortly
backed out because it was deemed "not ready". Code, however, stayed.
For the original feature and its implementation, see issue2810 and
3ff83729b63f.
In short, the backed-out interface had two outstanding issues:
1. it was introducing an entirely new term (baseline) and
2. it was present on every changeset's page, even for changesets with 1 parent
(or no parents), which didn't make sense
This patch implements a hopefully better interface because:
1. it uses the usual terms (diff) and
2. it only shows up when there actually are 2 parents.
This patch fixes a bug where hgweb would send an incomplete HTTP
response.
If an uncaught exception is raised when hgweb is processing a request,
hgweb attempts to send a generic error response and log that exception.
The server defaults to chunked transfer coding. If an uncaught exception
occurred, it was sending the error response string / chunk properly.
However, RFC 7230 Section 4.1 mandates a 0 size last chunk be sent to
indicate end of the entity body. hgweb was failing to send this last
chunk. As a result, properly written HTTP clients would assume more data
was coming and they would likely time out waiting for another chunk to
arrive.
Mercurial's own test harness was paving over the improper HTTP behavior
by not attempting to read the response body if the status code was 500.
This incorrect workaround was added in faced8f5c2af and has been removed
with this patch.
A matcher is required when enabling the subrepo option on archival.archive(),
because that calls match.narrowmatcher(), which accesses fields on the object.
It's therefore probably a bad idea to default the matcher to None on archive(),
but that's a fix for default.
Make hgweb.refresh() also look at phaseroots file (in addition to 00changelog.i
file) and reload the repo when os.stat returns different mtime or size than
cached, signifying the file was modified.
This way if user changes phase of a changeset (secret <-> draft), there's no
need to restart hg serve to see the change.
Traditionally, the way to specify a command for hgweb was to use url query
arguments (e.g. "?cmd=batch"). If the command is unknown to hgweb, it gives an
error (e.g. "400 no such method: badcmd").
But there's also another way to specify a command: as a url path fragment (e.g.
"/graph"). Before, hgweb was made forgiving (looks like it was made in
cd356f4efd91) and user could put any unknown command in the url. If hgweb
couldn't understand it, it would just silently fall back to the default
command, which depends on the actual style (e.g. for paper it's shortlog, for
monoblue it's summary). This was inconsistent and was breaking some tools that
rely on http status codes (as noted in the issue4071). So this patch changes
that behavior to the more consistent one, i.e. hgweb will now return "400 no
such method: badcmd".
So if some tool was relying on having an invalid command return http status
code 200 and also have some information, then it will stop working. That is, if
somebody typed foobar when they really meant shortlog (and the user was lucky
enough to choose a style where the default command is shortlog too), that fact
will now be revealed.
Code-wise, the changed if block is only relevant when there's no "?cmd" query
parameter (i.e. only when command is specified as a url path fragment), and
looks like the removed else branch was there only for falling back to default
command. With that removed, the rest of the code works as expected: it looks at
the command, and if it's not known, raises a proper ErrorResponse exception
with an appropriate message.
Evidently, there were no tests that required the old behavior. But, frankly, I
don't know any way to tell if anyone actually exploited such forgiving behavior
in some in-house tool.
hgweb detects out-of-date repository instances (using a highly
suspect mechanism that should probably be fixed) and obtains a new
repository object if needed.
This patch changes the repository object copy to use the repo URL
(instead of path). This preserves more information about the source
repository and allows bundles to be served through hgweb.
A test verifying that bundles can now be served properly via
`hg serve` has been added.
_ is usually used for i18n markup but we also used it for I-don't-care
variables.
Instead, name don't-care variables in a slightly descriptive way but use the _
prefix to designate unused variable.
This will mute some pyflakes "import '_' ... shadowed by loop variable"
warnings.
Before this patch, revision numbers and hash values in "comparison"
page are gotten from not changelog but filelog.
Such filelog information is useful only for hgweb debugging, and may
confuse users.
This patch shows revision numbers and hash values gotten from
changelog in "comparison" page.
Before this patch, "parents" in pages for file doesn't show as same
parents as "hg parents -r REV FILE", when the specified file is not
modified in the specified revision.
For example, it is assumed that revision A, B and D change file "f".
changelog (A) ---> (B) ---> (C) ---> (D)
filelog "f" (x) ---> (y) ------------> (z)
"/file/D/f" invokes "webutil.parents()" with filectx(z) gotten from
changectx(D), and it returns changectx(B). This is as same result as
"hg parents -r D f".
In the other hand, "/file/C/f" invokes "webutil.parents()" with
filectx(y') gotten from changectx(C), and it returns changectx(A),
because filectx(y') is linked to changectx(B), and works like
filectx(y) in some cases.
In this case, revision B is hidden from users browsing file "f" in
revision C.
This patch shows as same parents as "hg parents -r REV FILE" in pages
for file, by making "webutil.parents()" return:
- "linkrev()"-ed revision only, if:
- specified context instance is "filectx" (because
"webutil.parents()" is invoked with changectx, too), and
- (1) the revision from which filectx is gotten and (2) the one to
which filectx is linked are different from each other
- revision gotten from "ctx.parents()", otherwise
Before this patch, "comparison" shows unexpected result, when the
specified file is not modified in the specified revision, even though
"diff" shows empty result.
When REV doesn't change specified FILE, "diff" shows:
"hg diff -c REV FILE"
but "comparison" shows:
"hg diff -c `hg parents -r REV FILE` FILE"
In other words, the former gets parent from changelog, but the latter
gets one from filelog.
This may confuse users browsing (and switching "diff" and
"comparison" of) files in the specified revision.
This patch makes "comparison" get parent from not filelog but
changelog, to show "hg diff -c REV FILE" in both "diff" and
"comparison" pages.
Some extensions set configuration settings that showed up in 'hg showconfig
--debug' with 'none' as source. That was confusing.
Instead, they will now tell which extension they come from.
This change tries to be consistent and specify a source everywhere - also where
it perhaps is less relevant.
This needs to be changed to use a baseset since dagwalker now expects to
receive a smartset. This is basically wrapping revs into a baseset to be
compatible with smartset implementations.