Before this patch, "hg unshelve" uses aborting a current transaction
to discard temporary changes while unshelving.
This assumes that dirstate changes in a transaction scope are kept
even after aborting it. But this assumption will be broken by
"transactional dirstate". See the wiki page below for detail about it.
https://mercurial.selenic.com/wiki/DirstateTransactionPlan
This patch explicitly saves shelved dirstate just before aborting
current transaction, and restore dirstate with it after aborting by
utility function '_aborttransaction()' added by previous patch.
Before this patch, "hg shelve" uses aborting a current transaction to
discard temporary changes while shelving.
This assumes that dirstate changes in a transaction scope are kept
even after aborting it. But this assumption will be broken by
"transactional dirstate". See the wiki page below for detail about it.
https://mercurial.selenic.com/wiki/DirstateTransactionPlan
This patch explicitly saves shelved dirstate just before aborting
current transaction, and restore dirstate with it after aborting by
utility function '_aborttransaction()' added by previous patch.
This patch replaces 'if tr: tr.abort()' by 'lockmod.release(tr)',
because the former is already done in '_aborttransaction()' (and the
latter has no effect), if current transaction is aborted in it
successfully. Otherwise, the latter is enough to trigger aborting.
"hg shelve" and "hg unshelve" use aborting a current transaction to
discard temporary changes while (un)shelving.
This assumes that dirstate changes in a transaction scope are kept
even after aborting it. But this assumption will be broken by
"transactional dirstate". See the wiki page below for detail about it.
https://mercurial.selenic.com/wiki/DirstateTransactionPlan
This patch adds utility function "_aborttransaction()" to abort
current transaction but keep dirstate changes for (un)shelving.
'dirstate.invalidate()' just after aborting a transaction should be
removed soon by subsequent patch, which writes or discards in-memory
dirstate changes at releasing transaction according to the result of
it.
BTW, there are some other ways below, which (seem to, at first glance)
resolve this issue. But this patch chose straightforward way for ease
of review and future refactorring.
- commit transaction at first, and then rollback it
It causes unintentional "dirty read" of running transaction to
other processes at committing it.
- use dirstateguard to save and restore shelved dirstate
After DirstateTransactionPlan, making 'dirstate.write()' write
in-memory changes into actual file requires
'transaction.writepending()' while transaction running.
It causes meaningless writing other in-memory changes out, even
though they are never referred.
In addition to it, it isn't desirable that scope of dirstateguard
and transaction intersects each other.
- get list of files changed from the parent, keep it in memory, and
emulate that changes after aborting transaction
This additional memory consumption may block aborting transaction
in large repository (on small resource environment).
Before this patch, 'bmstore.write()' always write in-memory bookmark
changes into '.hg/bookmarks' regardless of transaction activity.
If 'bmstore.write()' is invoked inside a transaction and it writes
changes into '.hg/bookmarks', then:
- original bookmarks aren't restored at failure of that transaction
This breaks "all or nothing" policy of the transaction.
BTW, "hg rollback" can restore bookmarks successfully even before
this patch, because original bookmarks are saved into
'.hg/journal.bookmarks' at the beginning of the transaction, and
it (actually renamed as '.hg/undo.bookmarks') is used by "hg
rollback".
- uncommitted bookmark changes are visible to other processes
This is a kind of "dirty read"
For example, 'rebase.rebase()' implies 'bmstore.write()', and it may
be executed inside the transaction of "hg unshelve". Then, intentional
aborting at the end of "hg unshelve" transaction doesn't restore
original bookmarks (this is obviously a bug).
This patch uses 'bmstore.recordchange()' instead of actual writing by
'bmstore._writerepo()', if any transaction is active
This patch also removes meaningless restoring bmstore explicitly at
the end of "hg shelve".
This patch doesn't choose fixing each 'bmstore.write()' callers as
like below, because writing similar code here and there is very
redundant.
before:
bmstore.write()
after:
tr = repo.currenttransaction()
if tr:
bmstore.recordchange(tr)
else:
bmstore.write()
Even though 'bmstore.write()' itself may have to be discarded by
putting bookmark operations into transaction scope, this patch chose
fixing it to implement "transactional dirstate" at first.
We're going to separate the pre-merge and merge steps for merge tools. The
merge step will be specific to the tool, but the pre-merge step will be common
to all merge tools that need it.
However, some merge tools run checks *before* the pre-merge step. This callback
will allow that to continue to work.
We are going to introduce significant extensions of the bundle parsing code to
support creation of bundle2 through the bundle command. As an early step, we
extract the logic in its own function.
For some obscure reasons (probably upsetting a Greek goddess),
getchangegroup did not had a 'version' argument to control the changegroup
version. We fixes this to allow cg02 to be used with 'hg bundle' in the future.
For some obscure reasons (probably upsetting a Greek goddess),
getlocalchangegroup did not have a 'version' argument to control the
changegroup version. We fix this to allow cg02 to be used with 'hg
bundle' in the future.
We will generate different changegroup if general delta is enabled so we gather
this in the lower level function. There wasn't any good reason to have it in
the main code anyway.
Review feedback from Pierre-Yves David. A separate line of work is working to
ensure that dirstate writes are written to a separate 'pending' file while a
transaction is active. Lock inheritance currently conflicts with that, so dodge
the issue by simply preventing inheritance while a transaction is running.
Custom merge drivers aren't going to run inside a transaction, so this doesn't
affect that.
We want to prevent locks from being inherited sometimes (e.g. when there's a
currently running transaction, which will break a lot of assumptions we're
making in here.)
Because st.st_mtime is computed as 'sec + 1e-9 * nsec' and double is too narrow
to represent nanoseconds, int(st.st_mtime) can be 'sec + 1'. Therefore, that
value could be different from the one got by osutils.listdir().
This patch fixes the problem by accessing to raw st_mtime by tuple index.
It catches TypeError to fall back to st.st_mtime because our osutil.stat does
not support tuple index. In dirstate.normal(), 'st' is always a Python stat,
but in dirstate.status(), it can be either a Python stat or an osutil.stat.
Thanks to vgatien-baron@janestreet.com for finding the root cause of this
subtle problem.
This is part of a series that will allow locks to be inherited by subprocesses
in limited circumstances.
In the future, we'll call this for custom merge drivers.
This is part of a series that will allow locks to be inherited by subprocesses
in limited circumstances.
In an upcoming patch, we'll add an API for the wlock to be inherited.
This will be useful to pass around a reference to the lock to some functions
we're going to add to scmutil. We don't want those functions to live in
localrepo to avoid bloat.
This regressed in f07f4c45a8f2, when trying to conditionally disable archiving
of largefiles.
I'm not sure if wrapfunction() is the right way to do this, but it seems to
work. The mysterious issue with lfstatus getting out of sync in the proxy and
the unfiltered view crops up again here. See the referenced cset for more info.
Because _phaserevs and _phasesets cache revision numbers, they must be
invalidated if there are new commits or stripped revisions. We could do
that by calling _phasecache.invalidate(), but it wasn't simple to be
integrated with the filecache mechanism.
So for now, phasecache will be recreated after repo.invalidate() if
00changelog.i was modified before.