##// END OF EJS Templates
transaction: register summary callbacks only at start of transaction (BC)...
transaction: register summary callbacks only at start of transaction (BC) We currently register summary callbacks every time localrepo.transaction() is called, so both when the transaction is started and when a nested transaction is created. That seems a little weirdly asymmetric, because the summary callbacks are thus not necessarily registred at the beginning of the outermost transaction, but they are only called when the outermost transaction closes (not when a nested transaction closes). I want to add another summary callback that records the repo state at the beginning of the transaction and compares to that when the transaction closes. However, because of the registration that happens when a nested transaction is created, that would need to go through extra trouble to not overwrite the callback and report the difference from the start time of the innermost transaction to the close of the outermost transaction. Also, the callbacks are registered with a name based on the order they are defined in the registersummarycallback(). For example, if both the "new changesets %s" and the "obsoleted %i changesets" hooks are registered, the first would be called 00-txnreport and the second would be called 01-txnreport. That gets really weird if registersummarycallback() gets called multiple times, because the last one wins, and a depending on which of the two callbacks get registered, we might hypothetically even overwrite on type of callback with another. For example, if when the outer transaction was started, we registered the "new changesets %s" callback first, and when the inner transaction was started, we registered only the "obsoleted %i changesets" callback, then only the latter message would get printed. What makes it hypothetical is that what gets registered depends on the transaction name, and the set of transaction names that we match on for the former latter message is a subset of the set of names we match on for the former. Still, that seems like a bug waiting to happen. That second issue could be solved independently, but the first issue seems enough for me to consider it a bug (affecting developers, not users), so this patch simply drops that extra registration. Note that this affects "hg transplant" in a user-visible way. When "hg transplant" is asked to transplant from a remote repo so it involves a pull, then the outermost transaction name is "transplant" and an inner transaction is created for "pull". That inner transaction is what led us to sometimes report "new changesets %s" from "hg transplant". After this patch, that no longer happens. That seems fine to me. We can make it instead print the message for all "hg transplant" invocations if we want (not just those involving a remote), but I'll leave that for someone else to do if they think it's important. Differential Revision: https://phab.mercurial-scm.org/D1866

File last commit:

r32139:de86a687 stable
r35726:03e92194 default
Show More
changegroups.txt
188 lines | 8.2 KiB | text/plain | TextLexer
Gregory Szorc
help: add documentation for changegroup formats...
r27372 Changegroups are representations of repository revlog data, specifically
Kyle Lippincott
help: fix internals.changegroups...
r31213 the changelog data, root/flat manifest data, treemanifest data, and
filelogs.
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Augie Fackler
changegroups: add documentation for cg3
r27434 There are 3 versions of changegroups: ``1``, ``2``, and ``3``. From a
Kyle Lippincott
help: fix internals.changegroups...
r31213 high-level, versions ``1`` and ``2`` are almost exactly the same, with the
only difference being an additional item in the *delta header*. Version
``3`` adds support for revlog flags in the *delta header* and optionally
exchanging treemanifests (enabled by setting an option on the
``changegroup`` part in the bundle2).
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Kyle Lippincott
help: fix internals.changegroups...
r31213 Changegroups when not exchanging treemanifests consist of 3 logical
segments::
Gregory Szorc
help: add documentation for changegroup formats...
r27372
+---------------------------------+
| | | |
| changeset | manifest | filelogs |
| | | |
Kyle Lippincott
help: fix internals.changegroups...
r31213 | | | |
Gregory Szorc
help: add documentation for changegroup formats...
r27372 +---------------------------------+
Kyle Lippincott
help: fix internals.changegroups...
r31213 When exchanging treemanifests, there are 4 logical segments::
+-------------------------------------------------+
| | | | |
| changeset | root | treemanifests | filelogs |
| | manifest | | |
| | | | |
+-------------------------------------------------+
Gregory Szorc
help: add documentation for changegroup formats...
r27372 The principle building block of each segment is a *chunk*. A *chunk*
is a framed piece of data::
+---------------------------------------+
| | |
| length | data |
Kyle Lippincott
help: fix internals.changegroups...
r31213 | (4 bytes) | (<length - 4> bytes) |
Gregory Szorc
help: add documentation for changegroup formats...
r27372 | | |
+---------------------------------------+
Kyle Lippincott
help: fix internals.changegroups...
r31213 All integers are big-endian signed integers. Each chunk starts with a 32-bit
integer indicating the length of the entire chunk (including the length field
itself).
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Kyle Lippincott
help: fix internals.changegroups...
r31213 There is a special case chunk that has a value of 0 for the length
(``0x00000000``). We call this an *empty chunk*.
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Delta Groups
Gregory Szorc
help: don't try to render a section on sub-topics...
r29747 ============
Gregory Szorc
help: add documentation for changegroup formats...
r27372
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 |
Kyle Lippincott
help: fix internals.changegroups...
r31213 | (4 bytes) | (various) | (4 bytes) | (various) | (4 bytes) |
Gregory Szorc
help: add documentation for changegroup formats...
r27372 | | | | | |
Kyle Lippincott
help: fix internals.changegroups...
r31213 +------------------------------------------------------------------------+
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Each *chunk*'s data consists of the following::
Kyle Lippincott
help: fix internals.changegroups...
r31213 +---------------------------------------+
| | |
| delta header | delta data |
| (various by version) | (various) |
| | |
+---------------------------------------+
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Kyle Lippincott
help: fix internals.changegroups...
r31213 The *delta data* is a series of *delta*s that describe a diff from an existing
entry (either that the recipient already has, or previously specified in the
Matt Harbison
help: spelling fixes
r32139 bundle/changegroup).
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Augie Fackler
changegroups: add documentation for cg3
r27434 The *delta header* is different between versions ``1``, ``2``, and
``3`` of the changegroup format.
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Kyle Lippincott
help: fix internals.changegroups...
r31213 Version 1 (headerlen=80)::
Gregory Szorc
help: add documentation for changegroup formats...
r27372
+------------------------------------------------------+
| | | | |
| node | p1 node | p2 node | link node |
| (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
| | | | |
+------------------------------------------------------+
Kyle Lippincott
help: fix internals.changegroups...
r31213 Version 2 (headerlen=100)::
Gregory Szorc
help: add documentation for changegroup formats...
r27372
+------------------------------------------------------------------+
| | | | | |
| node | p1 node | p2 node | base node | link node |
| (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
| | | | | |
+------------------------------------------------------------------+
Kyle Lippincott
help: fix internals.changegroups...
r31213 Version 3 (headerlen=102)::
Augie Fackler
changegroups: add documentation for cg3
r27434
+------------------------------------------------------------------------------+
| | | | | | |
Kyle Lippincott
help: fix internals.changegroups...
r31213 | node | p1 node | p2 node | base node | link node | flags |
Augie Fackler
changegroups: add documentation for cg3
r27434 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
| | | | | | |
+------------------------------------------------------------------------------+
Kyle Lippincott
help: fix internals.changegroups...
r31213 The *delta data* consists of ``chunklen - 4 - headerlen`` bytes, which contain a
series of *delta*s, densely packed (no separators). These deltas describe a diff
from an existing entry (either that the recipient already has, or previously
specified in the bundle/changegroup). The format is described more fully in
Yuya Nishihara
help: fix layout of pre-formatted text
r31287 ``hg help internals.bdiff``, but briefly::
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Kyle Lippincott
help: fix internals.changegroups...
r31213 +---------------------------------------------------------------+
| | | | |
| start offset | end offset | new length | content |
| (4 bytes) | (4 bytes) | (4 bytes) | (<new length> bytes) |
| | | | |
+---------------------------------------------------------------+
Please note that the length field in the delta data does *not* include itself.
Gregory Szorc
help: add documentation for changegroup formats...
r27372
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.
Kyle Lippincott
help: fix internals.changegroups...
r31213 In version 2 and up, the delta base node is encoded in the entry in the
Gregory Szorc
help: add documentation for changegroup formats...
r27372 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
Gregory Szorc
help: don't try to render a section on sub-topics...
r29747 =================
Gregory Szorc
help: add documentation for changegroup formats...
r27372
The *changeset segment* consists of a single *delta group* holding
Kyle Lippincott
help: fix internals.changegroups...
r31213 changelog data. The *empty chunk* at the end of the *delta group* denotes
the boundary to the *manifest segment*.
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Manifest Segment
Gregory Szorc
help: don't try to render a section on sub-topics...
r29747 ================
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Kyle Lippincott
help: fix internals.changegroups...
r31213 The *manifest segment* consists of a single *delta group* holding manifest
data. If treemanifests are in use, it contains only the manifest for the
root directory of the repository. Otherwise, it contains the entire
manifest data. The *empty chunk* at the end of the *delta group* denotes
the boundary to the next segment (either the *treemanifests segment* or the
*filelogs segment*, depending on version and the request options).
Treemanifests Segment
---------------------
The *treemanifests segment* only exists in changegroup version ``3``, and
only if the 'treemanifest' param is part of the bundle2 changegroup part
(it is not possible to use changegroup version 3 outside of bundle2).
Aside from the filenames in the *treemanifests segment* containing a
trailing ``/`` character, it behaves identically to the *filelogs segment*
(see below). The final sub-segment is followed by an *empty chunk* (logically,
a sub-segment with filename size 0). This denotes the boundary to the
*filelogs segment*.
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Filelogs Segment
Gregory Szorc
help: don't try to render a section on sub-topics...
r29747 ================
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Kyle Lippincott
help: fix internals.changegroups...
r31213 The *filelogs segment* consists of multiple sub-segments, each
Gregory Szorc
help: add documentation for changegroup formats...
r27372 corresponding to an individual file whose data is being described::
Kyle Lippincott
help: fix internals.changegroups...
r31213 +--------------------------------------------------+
| | | | | |
| filelog0 | filelog1 | filelog2 | ... | 0x0 |
| | | | | (4 bytes) |
| | | | | |
+--------------------------------------------------+
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Kyle Lippincott
help: fix internals.changegroups...
r31213 The final filelog sub-segment is followed by an *empty chunk* (logically,
a sub-segment with filename size 0). This denotes the end of the segment
and of the overall changegroup.
Gregory Szorc
help: add documentation for changegroup formats...
r27372
Each filelog sub-segment consists of the following::
Kyle Lippincott
help: fix internals.changegroups...
r31213 +------------------------------------------------------+
| | | |
| filename length | filename | delta group |
| (4 bytes) | (<length - 4> bytes) | (various) |
| | | |
+------------------------------------------------------+
Gregory Szorc
help: add documentation for changegroup formats...
r27372
That is, a *chunk* consisting of the filename (not terminated or padded)
Kyle Lippincott
help: fix internals.changegroups...
r31213 followed by N chunks constituting the *delta group* for this file. The
*empty chunk* at the end of each *delta group* denotes the boundary to the
next filelog sub-segment.