Commit Graph

466 Commits

Author SHA1 Message Date
Mateusz Kwapich
016e1e5ef8 dirstate: rebuild should update dirstate properly
Updating dirstate by simply adding and dropping files from self._map doesn't
keep the other maps updated (think: _dirs, _copymap, _foldmap, _nonormalset)
thus introducing cache inconsistency.

This is also affecting the debugstate tests since now we don't even try to set
correct mode and mtime for the files because they are marked dirty anyway and
will be checked during next status call.
2016-08-30 15:16:28 -07:00
Martin von Zweigbergk
2fbf01764c util: rename checkcase() to fscasesensitive() (API)
I always read the name "checkcase(path)" as "do we need to check for
case folding at this path", but it's actually (I think) meant to be
read "check if the file system cares about case at this path". I'm
clearly not the only one confused by this as the dirstate has this
property:

  def _checkcase(self):
      return not util.checkcase(self._join('.hg'))

Maybe we should even inverse the function and call it fscasefolding()
since that's what all callers care about?
2016-08-30 09:22:53 -07:00
Mateusz Kwapich
de44e608e1 dirstate: add callback to notify extensions about wd parent change
The journal extension had to touch the dirstate internals to be notified about
wd parent change. To make that detection cleaner and reusable let's move it core.
Now the extension can register to be notified about parent changes.
2016-08-11 08:00:41 -07:00
Pierre-Yves David
9652a8ad03 deprecation: enforce thew 'tr' argument of 'dirstate.write' (API)
Compatibility was meant to be drop after 3.9 is released.
2016-08-02 16:51:27 +02:00
FUJIWARA Katsunori
19907e427c dirstate: make restoring from backup avoid ambiguity of file stat
File .hg/dirstate is restored by renaming from backup in failure
inside scopes below. If renaming keeps ctime, mtime and size of a
file, restoring is overlooked, and old contents cached before
restoring isn't invalidated as expected.

  - dirstateguard scope (from '.hg/dirstate.SUFFIX')
  - transaction scope (from '.hg/journal.dirstate')

To avoid ambiguity of file stat at restoring, this patch invokes
vfs.rename() with checkambig=True.

This patch is a part of "Exact Cache Validation Plan":

    https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
2016-06-13 05:11:56 +09:00
FUJIWARA Katsunori
f90241706d dirstate: make writing branch file out avoid ambiguity of file stat
Cached attribute dirstate._branch uses stat of '.hg/branch' file to
examine validity of cached contents. If writing '.hg/branch' file out
keeps ctime, mtime and size of it, change is overlooked, and old
contents cached before change isn't invalidated as expected.

To avoid ambiguity of file stat, this patch writes '.hg/branch' file
out with checkambig=True.

This patch is a part of "Exact Cache Validation Plan":

    https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
2016-06-03 00:44:20 +09:00
FUJIWARA Katsunori
00e016ed43 dirstate: make writing dirstate file out avoid ambiguity of file stat
Cached attribute repo.dirstate uses stat of '.hg/dirstate' file to
examine validity of cached contents. If writing '.hg/dirstate' file
out keeps ctime, mtime and size of it, change is overlooked, and old
contents cached before change isn't invalidated as expected.

To avoid ambiguity of file stat, this patch writes '.hg/dirstate' file
out with checkambig=True.

The former diff hunk changes the code path for "dirstate.write()", and
the latter changes the code path for "dirstate.savebackup()".

This patch is a part of "Exact Cache Validation Plan":

    https://www.mercurial-scm.org/wiki/ExactCacheValidationPlan
2016-06-03 00:44:20 +09:00
Mateusz Kwapich
6a0946ae30 distate: add assertions to backup functions
Those assertions will prevent the backup functions from overwriting
the dirstate file in case both: suffix and prefix are empty.

(foozy suggested making that change and I agree with him)
2016-05-26 17:36:44 -07:00
Mateusz Kwapich
3f38941482 dirstate: don't use actualfilename to name the backup file
The issue with using actualfilename is that dirstate saved during transaction
with "pending" in filename will be impossible to recover from outside of the
transaction because the recover method will be looking for the name without
"pending".
2016-05-25 16:36:16 -07:00
Mateusz Kwapich
c2a06fee01 dirstate: remove file from copymap on drop
As the copymap is short-lived object regenerated from dirstate on each
read this didn't affect us in any serious way. But since I've started working
on permanent storage of copymap in my experiments with sqldirstate[1] I've seen
this bug leaving the copy information in copymap after reverting the file
moves and copies.

[1] https://www.mercurial-scm.org/wiki/SQLDirstatePlan
2016-05-25 16:09:07 -07:00
Mateusz Kwapich
2ac744860e dirstate: add prefix and suffix arguments to backup
This would allow the code explicitly copying dirstate to use this method instead.
Use of this method will increase encapsulation (the dirstate class will be sole
owner of its on-disk storage).
2016-05-13 13:28:09 -07:00
Pierre-Yves David
47ac7dc0f8 cleanup: replace False identity testing with an explicit token object
The recommended way to check default value (when None is not as option) is a
token object. Identity testing to integer is less explicit and not guaranteed to
work in all implementations.
2016-05-05 19:32:51 +02:00
Pierre-Yves David
917636e516 devel: officially deprecate dirstate.write without transaction argument
When we introduce the develwarning, we did not had an official deprecation API
and infrastructure. We can now officially deprecate the old way with a version
deadline.
2016-05-11 09:31:47 +02:00
Mateusz Kwapich
fc3f152c3e dirstate: make backup methods public
They are called from outside of dirstate anyway and I want the localrepo to
use them too.
2016-05-05 17:06:54 -07:00
Pierre-Yves David
6a42d00a81 devel: use the new 'config' argument for the dirstate develwarn 2016-05-08 10:43:41 +02:00
Laurent Charignon
59af678158 dirstate: add a way to get the ignore file/line matching an ignored file
This information will be used to improve debugignore (issue4856).
2016-01-05 07:52:04 -08:00
Laurent Charignon
64fb638545 dirstate: extract logic to compute the list of ignorefiles
We are going to reuse this logic to improve debugignore in the next patches
of the series.
2015-12-23 11:52:54 -08:00
Laurent Charignon
0657cb64cb dirstate: call the C implementation of nonnonormalentries when available
Before this patch, we were using python code for computing the nonnormal
dirstate entries. This patch makes us use the C implementation of the function
when it is available.

Using the nonnormal set in hgwatchman improves hg status performance. Below
are the numbers for mozilla-central.

with the changes:
$ hg perfstatus
    ! wall 0.010632 comb 0.000000 user 0.000000 sys 0.000000 (best of 246)

without the changes:
$ hg perfstatus
    ! wall 0.036442 comb 0.030000 user 0.030000 sys 0.000000 (best of 100)

On mozilla-central the improvement to hg status is ~20% (0.25s to 0.2s),
on our big repos at Facebook, the win is ~40% (1.2s to 0.72s).
2015-12-23 13:16:03 -08:00
Laurent Charignon
f7e5157f49 dirstate: add code to update the non-normal set
Before this patch, we were only populating the non-normal set when parsing
or packing the dirstate. This was not enough to keep the non-normal set up to
date at all time as we don't write and read the dirstate whenever a change
happens. This patch solves this issue by updating the non-normal set when it
should be updated. note: pack_dirstate changes the dmap and we have it keep
it unchanged for retrocompatibility so we are forced to recompute the
non-normal set after calling it.
2016-01-01 23:40:54 +01:00
Laurent Charignon
c8798d976e dirstate: attach the nonnormalset to a propertycache
This patch attaches the nonnormalset to a property cache so that we build it
only when needed.
2015-12-23 13:13:22 -08:00
Laurent Charignon
cca2d0e30d dirstate: add a function to compute non-normal entries from the dmap
This patch adds a new python function in the dirstate to compute the set of
non-normal files from the dmap. These files are useful to compute the repository
status.
2015-12-21 16:22:43 -08:00
Gregory Szorc
061e8691b5 dirstate: use absolute_import 2015-12-21 21:38:53 -08:00
Matt Mackall
48434b4246 dirstate: make delaywrite sleep until the next multiple of n seconds
Rather than sleep for 2 seconds, we sleep until the next even-numbered
second, which has the same effect, but makes tests faster. This
removes test-largefiles-update as the long pole of the test suite.
2015-12-16 20:58:26 -06:00
Matt Mackall
476828ae86 dirstate: only invoke delaywrite if relevant
This avoids a significant amount of sleeping in some of our longest
tests.
2015-12-16 20:49:18 -06:00
Matt Mackall
105f68a336 dirstate: move delaywrite logic from write to _write
This will allow us to be smarter in upcoming patches.
2015-12-16 20:46:53 -06:00
Christian Delahousse
2a005d816a dirstate: change debugrebuilddirstate --minimal to use dirstate.rebuild
When debugrebuilddirstate --minimal is called, rebuilding the dirstate was done
outside of the appropriate rebuild function. This patch makes
debugrebuilddirstate use dirstate.rebuild.

This was done to allow our extension to become aware debugrebuilddirstate
--minimal
2015-11-30 11:23:15 -08:00
Matt Mackall
ab46ec3b99 util: drop statmtimesec
We've globablly forced stat to return integer times which agrees with
our extension code, so this is no longer needed.

This speeds up status on mozilla-central substantially:

$ hg perfstatus
! wall 0.190179 comb 0.180000 user 0.120000 sys 0.060000 (best of 53)
$ hg perfstatus
! wall 0.275729 comb 0.270000 user 0.210000 sys 0.060000 (best of 36)
2015-11-19 13:15:17 -06:00
Bryan O'Sullivan
9d37a5f6b4 dirstate: back out dd36f84bd784
Superseded by the parent of this commit.
2015-11-17 13:47:16 -08:00
Mateusz Kwapich
266a6f869e dirstate: fix filefoldmap incosistency on file delete
The _filefoldmap is not updated in when files are deleted from dirstate. In the
case where the file with the same but differently cased name is added afterwards
it renders _filefoldmap incorrect.  Those steps must occur to for a problem to
reproduce:
 - call status (with listunknown=True),
 - update working rectory to a commit which does a casefolding change (A -> a)
 - call status again (it will show the file "a" as deleted)

Unfortunately I'm unable to write a test for it because I don't know any
core-mercurial command able to reproduce those steps.

The bug was originally spotted when hgwatchman was enabled. It caused the
changeset contents change during hg rebase (one file unrelarted to changeset
was deleted in it after rebase).

The hgwatchman is able to hit it because when hgignore changes the hgwatchmans
overridestatus is calling original status with listunknown=True.
2015-11-09 10:43:23 -08:00
James Mills
9a53147d94 dirstate: fix invalid reference to self.ui 2015-10-19 12:07:17 -07:00
Mads Kiilerich
09567db49a spelling: trivial spell checking 2015-10-17 00:58:46 +02:00
FUJIWARA Katsunori
54ce7de850 dirstate: show develwarn for write() invocation without transaction
This is used to detect 'dirstate.write()' invocation without the value
gotten by 'repo.currenttransaction()' (mainly focused on 3rd party
extensions).
2015-10-17 01:15:34 +09:00
FUJIWARA Katsunori
2f787b04df dirstate: remove layering violation around writing dirstate out
This violation, which passes repo object to dirstate, was introduced
by dc3ddedecae7.

This patch uses 'False' instead of 'None' as default value of 'tr'
argument, to distinguish "None as repo.currenttransaction() result"
from "legacy invocation without explicit tr passing".
2015-10-17 01:15:34 +09:00
FUJIWARA Katsunori
811ef7c75f dirstateguard: remove layering violation around saving/restoring backup
This violation, which passes 'repo' object to dirstate, was introduced
by afd0ae63d624 and c26227275f1e.
2015-10-17 01:15:33 +09:00
FUJIWARA Katsunori
5e2a0f5090 dirstate: read from pending file under HG_PENDING mode if it exists
True/False value of '_pendingmode' means whether 'dirstate.pending' is
used to initialize own '_map' and so on. When it is None, neither
'dirstate' nor 'dirstate.pending' is read in yet.

This is used to keep consistent view between '_pl()' and '_read()'.

Once '_pendingmode' is determined by reading one of 'dirstate' or
'dirstate.pending' in, '_pendingmode' is kept even if 'invalidate()'
is invoked. This should be reasonable, because:

  - effective 'invalidate()' invocation should occur only in wlock scope, and
  - wlock can't be gotten under HG_PENDING mode

'_trypending()' is defined as a normal function to factor similar code
path (in bookmarks and phases) out in the future easily.
2015-10-14 02:49:17 +09:00
FUJIWARA Katsunori
2ef2ab5d6d dirstate: make writing in-memory changes aware of transaction activity
This patch delays writing in-memory changes out, if transaction is
running.

'_getfsnow()' is defined as a function, to hook it easily for
ambiguous timestamp tests (see also fakedirstatewritetime.py)

'if tr:' code path in this patch is still disabled at this revision,
because there is no client invoking 'dirstate.write()' with repo
object.

BTW, this patch changes 'dirstate.invalidate()' semantics around
'dirstate.write()' in a transaction scope:

  before:
    with repo.transaction():
        dirstate.CHANGE('A')
        dirstate.write() # change for A is written out here
        dirstate.CHANGE('B')
        dirstate.invalidate() # discards only change for B

  after:
    with repo.transaction():
        dirstate.CHANGE('A')
        dirstate.write() # change for A is still kept in memory
        dirstate.CHANGE('B')
        dirstate.invalidate() # discards changes for A and B

Fortunately, there is no code path expecting the former, at least, in
Mercurial itself, because 'dirstateguard' was introduced to remove
such 'dirstate.invalidate()'.
2015-10-14 02:49:17 +09:00
FUJIWARA Katsunori
bde9721b18 dirstate: make functions for backup aware of transaction activity
Some comments in this patch assume that subsequent patch changes
'dirstate.write()' like as below:

    def write(self, repo):
        if not self._dirty:
            return
        tr = repo.currenttransaction()
        if tr:
            tr.addfilegenerator('dirstate', (self._filename,),
                                self._writedirstate, location='plain')
            return # omit actual writing out
        st = self._opener('dirstate', "w", atomictemp=True)
        self._writedirstate(st)

This patch makes '_savebackup()' write in-memory changes out, and it
causes clearing 'self._dirty'. If dirstate isn't changed after
'_savebackup()', subsequent 'dirstate.write()' never invokes
'tr.addfilegenerator()' because 'not self._dirty' is true.

Then, 'tr.writepending()' unintentionally returns False, if there is
no other (e.g. changelog) changes pending, even though dirstate
changes are already written out at '_savebackup()'.

To avoid such situation, this patch makes '_savebackup()' explicitly
invoke 'tr.addfilegenerator()', if transaction is running.

'_savebackup()' should get awareness of transaction before 'write()',
because the former depends on the behavior of the latter before this
patch.
2015-10-14 02:49:17 +09:00
FUJIWARA Katsunori
af664f3cc0 dirstate: move code paths for backup from dirstateguard to dirstate
This can centralize the logic to write in-memory changes out correctly
according to transaction activity into dirstate.

Passing 'repo' object to newly added functions is needed to examine
current transaction activity in subsequent patches, because 'dirstate'
itself doesn't have direct reference to it.
2015-10-14 02:49:17 +09:00
FUJIWARA Katsunori
77975f1ce1 parsers: make pack_dirstate take now in integer for consistency
On recent OS, 'stat.st_mtime' has a double precision floating point
value to represent nano seconds, but it is not wide enough for actual
file timestamp: nowadays, only 52 - 32 = 20 bit width is available for
decimal places in sec.

Therefore, casting it to 'int' may cause unexpected result. See also
changeset 8102a3981272 fixing issue4836 for detail.

For example, changed file A may be treated as "clean" unexpectedly in
steps below. "rounded now" is the value gotten by rounding via
'int(st.st_mtime)' or so.

    ---------------------+--------------------+------------------------
    "now"                |                    | timestamp of A (time_t)
    float  rounded time_t| action             | FS       dirstate
    ------ ------- ------+--------------------+-------- ---------------
    N+.nnn   N       N   |                    | ---      ---
                         | update file A      |  N
                         | dirstate.normal(A) |           N
    N+.999   N+1     N   |                    |
                         | dirstate.write()   |           N (*1)
                         |    :               |
                         | change file A      |  N
                         |    :               |
    N+1.00   N+1    N+1  |                    |
                         | "hg status" (*2)   |  N        N
    ------ ------- ------+--------------------+-------- ---------------

Timestamp N of A in dirstate isn't dropped at (*1), because "rounded
now" is N+1 at that time, even if 'st_mtime' in 'time_t' is still N.

Then, file A is unexpectedly treated as "clean" at (*2) in this case.

For consistent handling of 'stat.st_mtime', this patch makes
'pack_dirstate()' take 'now' argument not in floating point but in
integer.

This patch makes 'PyArg_ParseTuple()' in 'pack_dirstate()' use format
'i' (= checking type mismatch or overflow), even though it is ensured
that 'now' is in the range of 32bit signed integer by masking with
'_rangemask' (= 0x7fffffff) on caller side.

It should be cheaper enough than packing itself, and useful to
detect that legacy code invokes 'pack_dirstate()' with 'now' in
floating point value.
2015-10-14 02:40:04 +09:00
Matt Mackall
74b31a11a1 dirstate: batch calls to statfiles (issue4878)
This makes it more interruptible.
2015-10-06 16:26:20 -05:00
Pierre-Yves David
30913031d4 error: get Abort from 'error' instead of 'util'
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.
2015-10-08 12:55:45 -07:00
FUJIWARA Katsunori
0602f8209b dirstate: split write to write changes into files other than .hg/dirstate
'_writedirstate()' is used mainly for "transactional dirstate". See
the wiki page below for detail about it.

    https://mercurial.selenic.com/wiki/DirstateTransactionPlan
2015-10-08 01:41:30 +09:00
Yuya Nishihara
ea5724ad42 util: extract stub function to get mtime with second accuracy
This function is trivial but will need a long comment why it can't use
st.st_mtime. See the next patch for details.
2015-10-04 22:25:29 +09:00
Yuya Nishihara
d7b6a95763 hgweb: overwrite cwd to resolve file patterns relative to repo (issue4568)
It's useless to handle file patterns as relative to the cwd of the server
process. The only sensible way in hgweb is to resolve paths relative to the
repository root.

It seems dirstate.getcwd() isn't used to get a real file path, so this patch
won't cause problem.
2015-09-20 20:11:31 +09:00
Yuya Nishihara
46aef63790 dirstate: state that getcwd() shouldn't be used to get real file path
hgweb will force it to be '' so that file patterns can be resolved relative
to the repository root. I want to clarify that is correct.
2015-09-20 20:08:22 +09:00
Matt Harbison
e8c6c3b443 dirstate: ensure mv source is marked deleted when walking icasefs (issue4760)
Previously, importing a case-only rename patch on a case insensitive filesystem
caused the original file to be marked as '!' in status.  The source was being
forgotten properly in patch.workingbackend.close(), but the call it makes to
scmutil.marktouched() then put the file back into the 'n' state (but it was
still missing from the filesystem).

The cause of this was scmutil._interestingfiles() would walk dirstate,
and since dirstate was able to lstat() the old file via the new name,
was treating this as a forgotten file, not a removed file.
scmutil.marktouched() re-adds forgotten files, so dirstate got out of
sync with the filesystem.

This could be handled with less code in the "kind == regkind or kind
== lnkkind" branch of dirstate._walkexplicit(), but this avoids
filesystem accesses unless case collisions occur. _discoverpath() is
used instead of normalize(), since the dirstate case is given first
precedence, and the old file is still in it. What matters is the
actual case in the filesystem.
2015-07-27 21:27:24 -04:00
Gregory Szorc
5380dea2a7 global: mass rewrite to use modern exception syntax
Python 2.6 introduced the "except type as instance" syntax, replacing
the "except type, instance" syntax that came before. Python 3 dropped
support for the latter syntax. Since we no longer support Python 2.4 or
2.5, we have no need to continue supporting the "except type, instance".

This patch mass rewrites the exception syntax to be Python 2.6+ and
Python 3 compatible.

This patch was produced by running `2to3 -f except -w -n .`.
2015-06-23 22:20:08 -07:00
Gregory Szorc
3aa1c73868 global: mass rewrite to use modern octal syntax
Python 2.6 introduced a new octal syntax: "0oXXX", replacing "0XXX". The
old syntax is not recognized in Python 3 and will result in a parse
error.

Mass rewrite all instances of the old octal syntax to the new syntax.

This patch was generated by `2to3 -f numliterals -w -n .` and the diff
was selectively recorded to exclude changes to "<N>l" syntax conversion,
which will be handled separately.
2015-06-23 22:30:33 -07:00
Siddharth Agarwal
2da9583582 dirstate: use a presized dict for the dirstate
This uses a simple heuristic to avoid expensive resizes.

On a real-world repo with around 400,000 files, perfdirstate:

before: ! wall 0.155562 comb 0.160000 user 0.150000 sys 0.010000 (best of 64)
after:  ! wall 0.132638 comb 0.130000 user 0.120000 sys 0.010000 (best of 75)

On another real-world repo with around 250,000 files:

before: ! wall 0.098459 comb 0.100000 user 0.090000 sys 0.010000 (best of 100)
after:  ! wall 0.089084 comb 0.090000 user 0.080000 sys 0.010000 (best of 100)
2015-06-16 00:46:01 -07:00
Pierre-Yves David
4bbda309c5 dirstate: avoid invalidating every entries when list is empty
Default value was not tested with 'is None', this made empty list seen as
default value and result the invalidation of every single entry in the
dirstate. On repos with hundred of thousand of files, this results in minutes
of lookup time instead nothing.

This is a text book example of why we should test 'is None' if this is what we
mean.
2015-06-04 22:10:32 -07:00