help: support loading sub-topics
If a sub-topic/section is requested and the main topic corresponds to
a topic with sub-topics, we now look for and return content for a
sub-topic if found.
With this patch, `hg help internals.X` now works. hgweb does not yet
render sub-topics, however.
--- a/mercurial/help.py Sun Dec 13 11:29:01 2015 -0800
+++ b/mercurial/help.py Sun Dec 13 11:19:55 2015 -0800
@@ -206,6 +206,11 @@
internalshelp),
])
+# Maps topics with sub-topics to a list of their sub-topics.
+subtopics = {
+ 'internals': internalstable,
+}
+
# Map topics to lists of callable taking the current topic help and
# returning the updated version
helphooks = {}
@@ -433,11 +438,19 @@
return rst
def helptopic(name, subtopic=None):
- for names, header, doc in helptable:
- if name in names:
- break
- else:
- raise error.UnknownCommand(name)
+ # Look for sub-topic entry first.
+ header, doc = None, None
+ if subtopic and name in subtopics:
+ for names, header, doc in subtopics[name]:
+ if subtopic in names:
+ break
+
+ if not header:
+ for names, header, doc in helptable:
+ if name in names:
+ break
+ else:
+ raise error.UnknownCommand(name)
rst = [minirst.section(header)]
--- a/tests/test-help.t Sun Dec 13 11:29:01 2015 -0800
+++ b/tests/test-help.t Sun Dec 13 11:19:55 2015 -0800
@@ -874,6 +874,151 @@
bundles container for exchange of repository data
changegroups representation of revlog data
+sub-topics can be accessed
+
+ $ hg help internals.changegroups
+ Changegroups
+ ============
+
+ Changegroups are representations of repository revlog data, specifically
+ the changelog, manifest, and filelogs.
+
+ There are 2 versions of changegroups: "1" and "2". From a high-level, they
+ are almost exactly the same, with the only difference being a header on
+ entries in the changeset segment.
+
+ Changegroups consists of 3 logical segments:
+
+ +---------------------------------+
+ | | | |
+ | changeset | manifest | filelogs |
+ | | | |
+ +---------------------------------+
+
+ The principle building block of each segment is a *chunk*. A *chunk* is a
+ framed piece of data:
+
+ +---------------------------------------+
+ | | |
+ | length | data |
+ | (32 bits) | <length> bytes |
+ | | |
+ +---------------------------------------+
+
+ Each chunk starts with a 32-bit big-endian signed integer indicating the
+ length of the raw data that follows.
+
+ There is a special case chunk that has 0 length ("0x00000000"). We call
+ this an *empty chunk*.
+
+ Delta Groups
+ ------------
+
+ A *delta group* expresses the content of a revlog as a series of deltas,
+ or patches against previous revisions.
+
+ Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
+ to signal the end of the delta group:
+
+ +------------------------------------------------------------------------+
+ | | | | | |
+ | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
+ | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
+ | | | | | |
+ +------------------------------------------------------------+-----------+
+
+ Each *chunk*'s data consists of the following:
+
+ +-----------------------------------------+
+ | | | |
+ | delta header | mdiff header | delta |
+ | (various) | (12 bytes) | (various) |
+ | | | |
+ +-----------------------------------------+
+
+ The *length* field is the byte length of the remaining 3 logical pieces of
+ data. The *delta* is a diff from an existing entry in the changelog.
+
+ The *delta header* is different between versions "1" and "2" of the
+ changegroup format.
+
+ Version 1:
+
+ +------------------------------------------------------+
+ | | | | |
+ | node | p1 node | p2 node | link node |
+ | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
+ | | | | |
+ +------------------------------------------------------+
+
+ Version 2:
+
+ +------------------------------------------------------------------+
+ | | | | | |
+ | node | p1 node | p2 node | base node | link node |
+ | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
+ | | | | | |
+ +------------------------------------------------------------------+
+
+ The *mdiff header* consists of 3 32-bit big-endian signed integers
+ describing offsets at which to apply the following delta content:
+
+ +-------------------------------------+
+ | | | |
+ | offset | old length | new length |
+ | (32 bits) | (32 bits) | (32 bits) |
+ | | | |
+ +-------------------------------------+
+
+ In version 1, the delta is always applied against the previous node from
+ the changegroup or the first parent if this is the first entry in the
+ changegroup.
+
+ In version 2, the delta base node is encoded in the entry in the
+ changegroup. This allows the delta to be expressed against any parent,
+ which can result in smaller deltas and more efficient encoding of data.
+
+ Changeset Segment
+ -----------------
+
+ The *changeset segment* consists of a single *delta group* holding
+ changelog data. It is followed by an *empty chunk* to denote the boundary
+ to the *manifests segment*.
+
+ Manifest Segment
+ ----------------
+
+ The *manifest segment* consists of a single *delta group* holding manifest
+ data. It is followed by an *empty chunk* to denote the boundary to the
+ *filelogs segment*.
+
+ Filelogs Segment
+ ----------------
+
+ The *filelogs* segment consists of multiple sub-segments, each
+ corresponding to an individual file whose data is being described:
+
+ +--------------------------------------+
+ | | | | |
+ | filelog0 | filelog1 | filelog2 | ... |
+ | | | | |
+ +--------------------------------------+
+
+ The final filelog sub-segment is followed by an *empty chunk* to denote
+ the end of the segment and the overall changegroup.
+
+ Each filelog sub-segment consists of the following:
+
+ +------------------------------------------+
+ | | | |
+ | filename size | filename | delta group |
+ | (32 bits) | (various) | (various) |
+ | | | |
+ +------------------------------------------+
+
+ That is, a *chunk* consisting of the filename (not terminated or padded)
+ followed by N chunks constituting the *delta group* for this file.
+
Test list of commands with command with no help text
$ hg help helpext