The home of 'Abort' is 'error' not 'util' however, a lot of code seems to be
confused about that and gives all the credit to 'util' instead of the
hardworking 'error'. In a spirit of equity, we break the cycle of injustice and
give back to 'error' the respect it deserves. And screw that 'util' poser.
For great justice.
When an user aborts a histedit, many things could go wrong. At a minimum, after
a histedit abort failure, their repository should be out of that state. We've
found situations where the user could not exit the histedit state without
manually deleting the histedit state file. This patch ensures that if any
exception happens during an abort, the histedit statefile will be deleted so
that users are out of the histedit state and can at least manually get the repo
back to a workable condition.
When the histeditstate class instance has it's clear() method called, there is
nothing to check to see if the state file exists before deleting it. It may not
exist, which would create an exception. This patch allows clear to be called at
any time.
This will be needed for the following patch.
If a histedit is progress, the 'histedit-state' file should exist. The patch
implements a convenience function to do check if a histedit is in progress.
This method will be use in next patch in the series.
Before this patch, "hg backout" uses 'begin'/'end'-'parentchange()'
of 'dirstate' class to avoid writing incomplete dirstate changes out
at failure.
But this framework doesn't work as expected, if 'dirstate.write()' is
invoked between them. In fact, in-memory dirstate changes may be
written out at 'repo.status()' implied by 'merge.update()', even
before this patch.
To restore dirstate as expected at failure of "hg backout", this patch
uses 'dirstateguard' instead of 'begin'/'end'-'parentchange()'.
Previous patch made dirstate changes in a transaction scope "all or
nothing". Therefore, 'dirstateguard' is meaningless, if its scope is
as same as one of the related transaction.
Before this patch, "hg import" uses 'dirstateguard' always, but
transaction is also started if '--no-commit' isn't specified.
To avoid redundancy, this patch makes "hg import" use dirstateguard
only if transaction isn't started (= '--no-commit' is specified).
In this patch, 'if dsguard' can be examined safely, because 'dsguard'
is initialized (with None) before outermost 'try'.
There is no user of 'cmdutil.tryimportone()' other than
'commands.import_()', which can restore dirstate at failure of
applying patches by transaction or dirstateguard.
Therefore, it is reasonable to stop 'tryimportone()' from using
redundant 'dirstateguard', even though it changes behavior of
'tryimportone()'.
After this patch, 3rd party extensions should use 'dirstateguard' or
so explicitly, if they want to restore dirstate at failure of
importing a patch.
Previous patch made dirstate changes in a transaction scope "all or
nothing". Therefore, 'dirstateguard' is meaningless, if its scope is
as same as one of the related transaction.
This patch removes such meaningless 'dirstateguard' usage.
Before this patch, in-memory dirstate changes are still kept over a
transaction scope boundary regardless of the result of it.
For "all or nothing" policy of the transaction, in-memory dirstate
changes should be:
- written out at successful closing a transaction, because
subsequent 'dirstate.invalidate()' can lose them
- discarded at failure of a transaction, because outer
'wlock.release()' or so may write them out
To discard all changes in a transaction completely, this patch also
restores '.hg/dirstate' by '.hg/journal.dirstate' at failure, because
'transaction' itself does nothing for files related to '.hg/journal.*'
in such case (therefore, renaming in this patch is safe enough).
This is a part of preparations for "transactional dirstate". See also
the wiki page below for detail about it.
https://mercurial.selenic.com/wiki/DirstateTransactionPlan
This patch also removes redundant 'dirstate.invalidate()' just before
aborting a transaction for shelve/unshelve.
'releasefn' is used by subsequent patch, to do appropriate action
according to the result of it at the end of a transaction scope.
To ensure that 'releasefn' is invoked only once, this patch invokes it
after assignment 'self.journal = None', because such assignment
prevents from invoked 'transaction._abort()' again via '__del__()'.
def __del__(self):
if self.journal:
self._abort()
We ultimately want this to be accessible through a revset, but there is too
much complexity here for that to work. Especially we'll have to return more
than just the destination to control the behavior (eg: bookmarks to activate,
etc).
To prevent cycle, a new module is created, it will receive other
destination/behavior function in the future.
This is a backout of 0f1a7b0ccb69. The stdlib implementation of
multiprocessing.cpu_count() attempts to invoke a process on BSD and
Darwin platforms (at least on 2.7). Under certain conditions (such as
cwd being removed) this could raise. Our old code was silently catching
the exception.
The old code was more robust, so restore it.
The merge code currently does (in pseudocode):
for f in tomerge:
premerge f
merge f
We'd like to change this to look more like:
for f in tomerge:
premerge f
for f in tomerge:
merge f
This makes sure as many files are resolved as possible before prompting for the
others. This restructuring is also necessary for custom merge drivers.
This function separates out the premerge step from the merge step. In future
patches we'll actually turn these into separate steps in the merge driver.
The 'if r:' occurrences will be cleaned up in subsequent patches.
In the external pushrebase extension, it is valuable to be able to do some work
without taking the lock (like running expensive hooks). This enables
significantly higher commit throughput.
This patch adds an option to lazily acquire the lock. It means that all bundle2
part handlers that require writing to the repo must first call
op.gettransction(), when in this mode.
A future patch will allow the bundle2 lock be taken lazily. We need to
introduce transaction-gets to each handler that needs the lock.
The tests caught these issues when I added lazy locking.
It was introduced by 236440938a03, but the important code was removed by
fcf2407610f4. So there was no positive effect other than exhausting memory.
The problem spotted by 236440938a03 is that you can't use a generator keyword
more than once. For example, in hgweb template, "{child} {child}" doesn't work
because the first "{child}" consumes the generator. But as fcf2407610f4 says,
the fix was wrong because it could overwrite a callable keyword that returns
a generator. Also the fix didn't work for a generator of generator such as
"{diff}" keyword. So, the proper fix for that problem would be to not put
a generator in a keyword table. Instead, it should be a factory of a generator.
Note that this should fix the memory issue in hgweb, but my firefox killed by
OOM in place. Be careful to not use a modern web browser to test the issue4868.
patchbomb relies on the 'hg bundle' command to generate an attached bundle using
--bundle. However, while 'hg bundle' has a --type option, patchbomb did not.
This is becoming very relevant since we are about to issue bundle2 for
general-delta repository.
This was tracked as issue4863
As we have a way for extension to add more header, we need a way for them to
actually process them. We add a basic hook point to do extra work after the
import have been committed.
As we have a way for extension to add more header, we need a way for them to
actually process them. We add a basic hook points to alter the changeset
(especially extra) before we commit. There would be more to do for a full
featured hooking, but this currently fit my needs.
The final goal here is to be able to parse, return and process arbitrary data
from patch. This mirror the recently added ability to add arbitrary data to
patch headers.
The first step is to return something more flexible, so we return a dict without
changing any other logic.
This config allows to specify a public location where your changeset can be
found. It then include a dedicated patch header show a command to be used to
retrieve the change. See the test for example.
This is flagged as experimental because this feature is not safe until we have
more logic to test that:
- changeset actually exists on destination
- changeset is draft on destination.
As all this is experimental, bike shedding can happily happens before we remove
the experimental flag.
Extensions currently have no easy way to add data to exported
patch. This is now fixed using a generic mechanism in the same fashion
used by bundle2. Tests are coming in the next changeset with its first
user.
Incoming was using bundle1 in all cases, as bundle1 is restricted to
changegroup1 and does not support general delta, this can lead to significant
CPU overhead if the server is using general delta storage. We now properly
request and store a bundle2 to disk.
If the server include any output or error in the bundle, they will be stored on
disk and replayed when the bundle is read. As 'hg incoming' is going to read the
bundle right away, we call that 'good' enough and go back to the bigger plan of
having general delta on by default.
This was tracked as 4864
There is use case for directly forward and bundle2 stream from the peer to a
file (eg: 'hg incoming --bundle'), However ssh peers have no way to know the
'getbundle' is over except for actually interpreting the bundle. So we need to
have the unbundle do the interpreting and forward job.
The function is marked as private to highlight that this is terrible and that we
are sorry.
We want to introduce a simple way to forward the content of a bundle2 stream.
For this purpose, we will need to both yield the parameters block and process it
(to apply any behavior change it might indicate).