Before this patch, "import-checker.py" just replaces "/" in specified
filenames by ".". This makes modules for pure Python build belong to
"mercurial.pure" package, and prevents "import-checker.py" from
correctly checking about cyclic dependency in them.
This patch discards "pure" component from fully qualified name of such
modules.
To avoid discarding "pure" from the module name of standard libraries
unexpectedly, this patch allows "dotted_name_of_path" to discard
"pure" only from Mercurial specific modules, which are specified via
command line arguments.
Before this patch, "import-checker.py" assumes that the name of
Mercurial module recognized by "imported_modules" doesn't have package
part: for example, "util".
This is reason why "import-checker.py" always builds fully qualified
module name up relatively, if the given module doesn't belong to
standard Python library.
But in fact, modules imported in "from mercurial import XXXX" style
already have fully qualified name: for example, "mercurial.util"
module imported by "mercurial.parsers" is treated as
"mercurial.mercurial.util" because of building module name up
relatively.
This prevents "import-checker.py" from correctly checking about cyclic
dependency in them.
This patch avoids building module name up relatively, also if module
name starts with "mercurial.", to treat modules imported in "from
mercurial import XXXX" style correctly.
39fbe33f95fa brought "asciilower" and "import parsers" into
"encoding.py".
This works fine with "parsers" module in C implementation, but doesn't
with one in pure Python implementation, because the latter causes
cyclic dependency below and aborting execution:
util => i18n => encoding => parsers => util
This patch delays importing "parsers" module until it is really
needed, to avoid cyclic dependency around "parsers" in pure Python
build.
The source information can, should be applied once when opening the transaction
for the pull. This will lets element processed within a bundle2 be aware of them
and open the door to running a set of hooks when closing this pull transaction.
This is similar to what is done in server's unbundle call.
We store the source and url of the current data into `transaction.hookargs` this
let us inherit it from upper layers that may have created a much wider
transaction. We have to modify bundle2 at the same time to register the source
and url in the transaction. We have to do it in the same patch otherwise, the
`addchangegroup` call would fill these values and the hook calling will crash
because of the duplicated 'source' and 'url' arguments passed to the hook call.
We want to reused some possible information stored in the transaction
`hookargs` dict that may be stored by something handling the transaction at an
upper level (eg: bundle2) So we move the running of the hooks after transaction
creation. This has no visible effects (but an empty transaction roolback if the
hook fails) because nothing had happened in the transaction yet.
The transaction is now carrying hook-related informations. So we use it to
retrieve the `node` argument. This will also carry around all kinds of other useful
informations (like: "are we in a bundle2 processing")
From manifest.diff(), we return a dict from filename to pairs of pairs
of file nodeids and flags (values of the form ((n1,n2),(fl1,fl2))). To
create this dict, we currently generate one dict for files (with
(n1,n2) values) and one for flags (with (fl1,fl2) values) and then
join these dicts. Missing files are represented by None and missing
flags by '', but due to the dict joining, the inner pairs themselves
can also be None. The only caller, merge.manifestmerge(), then unpacks
these values while checking for None values.
By inlining the calls to dicthelpers and simplifying it to only
iterate over files (ignoring flags-only differences), we can simplify
life for our caller.
The manifestdict class already has a method for diff flags between two
manifests (presumably because there is no full access to the private
_flags field). The only caller is merge.manifestmerge(), which also
wants a diff of files between the same manifests. Let's combine the
code for diffing files and flags into a single method on
manifestdict. This puts all the manifest diffing in one place and will
allow for further simplification. It might also be useful for it to be
encapsulated in manifestdict if we later decide to to shard
manifests. The docstring is intentionally unclear about missing
entries for now.
A bundle2 may contain multiple parts adding changegroups, in which case there
are multiple operation records for changegroups, each with its own return
value. Those multiple return values are aggregated in a single cgresult value
for the whole operation.
As can be seen in the associated test case, the situation with hooks is not
really the best, but without deeper thoughts and changes, we can't do much
better. Hopefully, things will be improved before bundle2 is enabled by default.
In the meanwhile, multiple changegroups is not expected to be in widespread
use, and even less expected to be used for pushes. Also, not many clients
cloning or pulling bundle2 with multiple changesets are not expected to have
changegroup hooks anyways.
addchangegroup creates a runhook function that is used to invoke the
changegroup and incoming hooks, but at the time the function is called,
the contents of hookargs associated with the transaction may have been
modified externally. For instance, bundle2 code affects it with
obsolescence markers and bookmarks info.
It also creates problems when a single transaction is used with multiple
changegroups added (as per an upcoming change), whereby the contents
of hookargs are that of after adding a latter changegroup when invoking
the hook for the first changegroup.
There are currently two different tests using roughly the same code to
create temporary scripts acting as HTTP servers. As there is going to
be at least one more in an upcoming change, factor those out in a
standalone dumbhttp.py script.
This effectively backs out changeset 7582042d6cce.
The API change is done so that both util.sha1 and util.md5 can be called the
same way. The function is moved in order to use it for md5 checksumming for
an upcoming bundle2 feature.
This test actually used the obs.py file as part of the test, so we need to fix
up the test a little more than usual to work with the new obsolete option flags.
The obsolete._enabled flag has become a config option. This updates all but one
of the tests to use the minimal number of flags necessary for them to pass. For
most tests this is just 'createmarkers', for a couple tests it's
'allowunstable', and for even fewer it's 'exchange'.
The basic obsolete option is allowing the creation of obsolete markers. This
does not enable other features, such as allowing unstable commits or exchanging
obsolete markers.
Previously, obstore read the obsolete._enabled flag to determine whether to
allow writes to the obstore. Since obsolete._enabled will be moving into a repo
specific config, we can't read it globally, and therefore must pass the
information into the constructor.
Previously, obsolete used the module level _enabled flag to determine whether it
was on or off. We need a bit more granular control, so we'll be introducing
toggle options. The isenabled() function is how you check if a particular option
is enabled for the given repository.
Future patches will add options such as 'createmarkers', 'allowunstable', and
'exchange' to enable various features of obsolete markers.
We also track execution of the changegroup hook. The important information here
is to make sure the information that the transaction was processing a bundle2 is passed to
hook. This will let most hooks disable themselves while waiting for the hook
concluding bundle2 processing (the one we discovered to be not called for
pull in the previous changesets).
We can notice that this transaction wide hook is only happening during push and
it is missing changegroup-related information. We'll want to fix this but this
is not what this patch is about.
The push process uses a `stepsdone` attribute instead of a `todosteps` one (with
the logic swapped). We unify the two process by picking the `stepsdone` version.
I feel like `stepsdone` better fits extensions that would want to extend the push
exchange process.
We apply the same approach as for push and make the discovery extensible. There
is only one user in core right now, but we already know we'll need something
smarter for obsmarkers. In fact the evolve extension could use this to cleanly
extend discovery.
The main motivation for this change is consistency between push and pull.
This change allows a revision log to not fail integrity checks when applying a
changegroup delta (eg from a bundle) results in a censored file tombstone. The
tombstone is inserted as-is, so future integrity verification will observe the
tombstone. Deltas based on the tombstone will also remain correct.
The new code path is encountered for *exactly* the cases where _addrevision is
importing a tombstone from a changegroup. When committing a file containing
the "magic" tombstone text, the "text" parameter will be non-empty and the
checkhash call is not executed (and when committing, the node will be computed
to match the "magic" tombstone text).
Two possible behaviors are defined for handling censored data: abort, and
ignore. When we ignore censored data we return an empty file to callers
requesting the file data.
We do modify the lists that make up the status in several places, so
it seems risky to use the same instance of a list for several
different status types. Use a separate empty list for each type
instead.
In commands.summary(), we currently zip a list of labels with a list
of statuses. This means the order of the status list has to match the
list of the labels, which in turn means the status elements have to be
inserted into specific places in the list. Let's instead group the
labels and status data we want to display in a single list of pairs.