mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 06:47:41 +03:00
treestate: backout making it a hard requirement
Summary: It turns out some old repos are still using the legacy treedirstate format, which broke when I made this a hard requirement. Let's roll this back for now. Reviewed By: singhsrb Differential Revision: D19313773 fbshipit-source-id: ded78be033cb04323a2e1d237059947dee509df9
This commit is contained in:
parent
43550ca5bb
commit
d8663cb534
@ -723,6 +723,7 @@ def perfdirs(ui, repo, **opts):
|
||||
|
||||
def d():
|
||||
dirstate.hasdir("a")
|
||||
del dirstate._map._dirs
|
||||
|
||||
timer(d)
|
||||
fm.end()
|
||||
@ -748,6 +749,7 @@ def perfdirstatedirs(ui, repo, **opts):
|
||||
|
||||
def d():
|
||||
repo.dirstate.hasdir("a")
|
||||
del repo.dirstate._map._dirs
|
||||
|
||||
timer(d)
|
||||
fm.end()
|
||||
@ -761,7 +763,7 @@ def perfdirstatefoldmap(ui, repo, **opts):
|
||||
|
||||
def d():
|
||||
dirstate._map.filefoldmap.get("a")
|
||||
dirstate._map.filefoldmap.clear()
|
||||
del dirstate._map.filefoldmap
|
||||
|
||||
timer(d)
|
||||
fm.end()
|
||||
@ -775,7 +777,8 @@ def perfdirfoldmap(ui, repo, **opts):
|
||||
|
||||
def d():
|
||||
dirstate._map.dirfoldmap.get("a")
|
||||
dirstate._map.dirfoldmap.clear()
|
||||
del dirstate._map.dirfoldmap
|
||||
del dirstate._map._dirs
|
||||
|
||||
timer(d)
|
||||
fm.end()
|
||||
|
@ -902,12 +902,6 @@ class localrepository(object):
|
||||
return self._eden_dirstate
|
||||
|
||||
istreestate = "treestate" in self.requirements
|
||||
# Block nontreestate repos entirely. Add a config to bypass in case we
|
||||
# break something.
|
||||
if not istreestate and self.ui.configbool("treestate", "required", True):
|
||||
raise errormod.RequirementError(
|
||||
"legacy dirstate implementations are no longer supported"
|
||||
)
|
||||
istreedirstate = "treedirstate" in self.requirements
|
||||
|
||||
return dirstate.dirstate(
|
||||
@ -2632,8 +2626,11 @@ def newreporequirements(repo):
|
||||
% compengine,
|
||||
hint=_('run "hg debuginstall" to list available ' "compression engines"),
|
||||
)
|
||||
|
||||
requirements.add("treestate")
|
||||
dirstateversion = ui.configint("format", "dirstate")
|
||||
if dirstateversion == 1:
|
||||
requirements.add("treedirstate")
|
||||
elif dirstateversion == 2:
|
||||
requirements.add("treestate")
|
||||
|
||||
# zlib is the historical default and doesn't need an explicit requirement.
|
||||
if compengine != "zlib":
|
||||
|
@ -126,7 +126,6 @@ New errors are not allowed. Warnings are strongly discouraged.
|
||||
undocumented: ssl.signal_status (bool) [True]
|
||||
undocumented: ssl.timeout (int) [10]
|
||||
undocumented: treemanifest.verifyautocreate (bool)
|
||||
undocumented: treestate.required (bool) [True]
|
||||
undocumented: ui.editor.chunkselector (str)
|
||||
undocumented: ui.hyperlink (bool)
|
||||
undocumented: workingcopy.enablerustwalker (bool)
|
||||
|
@ -555,13 +555,13 @@ Test clone from the repository in (emulated) revlog format 0 (issue4203):
|
||||
$ mkdir -p src/.hg
|
||||
$ echo foo > src/foo
|
||||
$ hg -R src add src/foo
|
||||
abort: legacy dirstate implementations are no longer supported!
|
||||
abort: repo is corrupted: 00changelog.i
|
||||
[255]
|
||||
$ hg -R src commit -m '#0'
|
||||
abort: legacy dirstate implementations are no longer supported!
|
||||
abort: repo is corrupted: 00changelog.i
|
||||
[255]
|
||||
$ hg -R src log -q
|
||||
abort: legacy dirstate implementations are no longer supported!
|
||||
abort: repo is corrupted: 00changelog.i
|
||||
[255]
|
||||
$ hg clone -U -q src dst
|
||||
abort: repo is corrupted: 00changelog.i
|
||||
|
@ -11,6 +11,7 @@ Set vars:
|
||||
Prepare repo:
|
||||
|
||||
$ hg init
|
||||
$ hg debugtreedirstate off
|
||||
|
||||
$ echo this is file a > a
|
||||
$ hg add a
|
||||
|
92
eden/scm/tests/test-dirstate-migrate.t
Normal file
92
eden/scm/tests/test-dirstate-migrate.t
Normal file
@ -0,0 +1,92 @@
|
||||
#chg-compatible
|
||||
|
||||
$ for src in 0 1 2; do
|
||||
> for dst in 0 1 2; do
|
||||
> [ $src = $dst ] && continue
|
||||
> echo ==== Migrating dirstate v$src to v$dst ====
|
||||
> cd $TESTTMP
|
||||
> setconfig format.dirstate=$src
|
||||
> newrepo
|
||||
> touch normal modified removed deleted
|
||||
> hg ci -A . -q -m init
|
||||
> hg rm removed
|
||||
> rm deleted
|
||||
> touch untracked
|
||||
> echo 1 > modified
|
||||
> hg status
|
||||
> hg debugtreestate status
|
||||
> hg debugtreestate v$dst
|
||||
> hg status
|
||||
> hg debugtreestate status
|
||||
> done
|
||||
> done
|
||||
==== Migrating dirstate v0 to v1 ====
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v0 (flat dirstate, 4 files tracked)
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v1 (using dirstate.tree.*, 4 files tracked) (glob)
|
||||
==== Migrating dirstate v0 to v2 ====
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v0 (flat dirstate, 4 files tracked)
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v2 (using treestate*, offset *, 4 files tracked) (glob) (no-fsmonitor !)
|
||||
dirstate v2 (using treestate*, offset *, 5 files tracked) (glob) (fsmonitor !)
|
||||
==== Migrating dirstate v1 to v0 ====
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v1 (using dirstate.tree*, 4 files tracked) (glob)
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v0 (flat dirstate, 4 files tracked)
|
||||
==== Migrating dirstate v1 to v2 ====
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v1 (using dirstate.tree*, 4 files tracked) (glob)
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v2 (using treestate*, offset *, 4 files tracked) (glob) (no-fsmonitor !)
|
||||
dirstate v2 (using treestate*, offset *, 5 files tracked) (glob) (fsmonitor !)
|
||||
==== Migrating dirstate v2 to v0 ====
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v2 (using treestate*, offset *, 4 files tracked) (glob) (no-fsmonitor !)
|
||||
dirstate v2 (using treestate*, offset *, 5 files tracked) (glob) (fsmonitor !)
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v0 (flat dirstate, 4 files tracked)
|
||||
==== Migrating dirstate v2 to v1 ====
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v2 (using treestate*, offset *, 4 files tracked) (glob) (no-fsmonitor !)
|
||||
dirstate v2 (using treestate*, offset *, 5 files tracked) (glob) (fsmonitor !)
|
||||
M modified
|
||||
R removed
|
||||
! deleted
|
||||
? untracked
|
||||
dirstate v1 (using dirstate.tree*, 4 files tracked) (glob)
|
@ -1,6 +1,22 @@
|
||||
#chg-compatible
|
||||
|
||||
#chg-compatible
|
||||
|
||||
#chg-compatible
|
||||
|
||||
#testcases v0 v1 v2
|
||||
|
||||
#if v0
|
||||
$ setconfig format.dirstate=0
|
||||
#endif
|
||||
|
||||
#if v1
|
||||
$ setconfig format.dirstate=1
|
||||
#endif
|
||||
|
||||
#if v2
|
||||
$ setconfig format.dirstate=2
|
||||
#endif
|
||||
|
||||
------ Test dirstate._dirs refcounting
|
||||
|
||||
@ -47,6 +63,21 @@ Prepare test repo:
|
||||
adding a
|
||||
$ hg ci -m1
|
||||
|
||||
#if no-v2
|
||||
Set mtime of a into the future:
|
||||
|
||||
$ touch -t 202101011200 a
|
||||
|
||||
Status must not set a's entry to unset (issue1790):
|
||||
|
||||
$ hg status
|
||||
$ hg debugstate
|
||||
n 644 2 2021-01-01 12:00:00 a
|
||||
|
||||
Note: issue1790 is about thg compatibility. In this case, setting mtime to
|
||||
"unset" is also correct since "a" needs to be checked.
|
||||
#endif
|
||||
|
||||
Test modulo storage/comparison of absurd dates:
|
||||
|
||||
#if no-aix
|
||||
|
19
eden/scm/tests/test-fsmonitor-warn-fresh.t
Normal file
19
eden/scm/tests/test-fsmonitor-warn-fresh.t
Normal file
@ -0,0 +1,19 @@
|
||||
#require fsmonitor
|
||||
|
||||
$ setconfig fsmonitor.warn-fresh-instance=true
|
||||
$ newrepo
|
||||
|
||||
A warning is printed for the first use
|
||||
|
||||
$ hg status --debug
|
||||
warning: watchman has recently started (pid *) - operation will be slower than usual (glob)
|
||||
poststatusfixup decides to wait for wlock since watchman reported fresh instance
|
||||
|
||||
$ hg status --debug
|
||||
|
||||
Verify that we can fallback to walking
|
||||
- Migrate the dirstate to reset the clock
|
||||
$ hg debugtreestate v0
|
||||
$ hg debugtreestate on
|
||||
$ hg status --config fsmonitor.walk_on_invalidate=True --debug
|
||||
fsmonitor: fallback to core status, no clock
|
@ -16,7 +16,7 @@ sh % "hg add a"
|
||||
sh % "hg commit -m test"
|
||||
sh % "rm .hg/requires"
|
||||
sh % "hg tip" == r"""
|
||||
abort: legacy dirstate implementations are no longer supported!
|
||||
abort: index 00changelog.i is corrupted!
|
||||
[255]"""
|
||||
sh % "echo indoor-pool" > ".hg/requires"
|
||||
sh % "hg tip" == r"""
|
||||
|
211
eden/scm/tests/test-treedirstate.t
Normal file
211
eden/scm/tests/test-treedirstate.t
Normal file
@ -0,0 +1,211 @@
|
||||
#chg-compatible
|
||||
|
||||
$ setconfig extensions.treemanifest=!
|
||||
Setup
|
||||
|
||||
$ setconfig format.dirstate=1
|
||||
$ setconfig treestate.mingcage=0
|
||||
$ hg init repo
|
||||
$ cd repo
|
||||
$ echo base > base
|
||||
$ hg add base
|
||||
$ hg debugdirstate
|
||||
a 0 -1 unset base
|
||||
$ hg commit -m "base"
|
||||
$ hg debugdirstate
|
||||
n 644 5 * base (glob)
|
||||
|
||||
Create path-conflicting dirstates
|
||||
|
||||
$ hg up -q 0
|
||||
$ echo a > a
|
||||
$ hg add a
|
||||
$ hg commit -m a
|
||||
$ hg bookmark a
|
||||
$ hg up -q 0
|
||||
$ mkdir a
|
||||
$ echo a/a > a/a
|
||||
$ hg add a/a
|
||||
$ hg commit -m a/a
|
||||
$ hg bookmark a/a
|
||||
$ hg up -q a
|
||||
$ hg status
|
||||
$ hg rm a
|
||||
$ hg status
|
||||
R a
|
||||
$ hg merge --force a/a
|
||||
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
(branch merge, don't forget to commit)
|
||||
$ hg status
|
||||
M a/a
|
||||
R a
|
||||
$ hg rm --force a/a
|
||||
$ hg status
|
||||
R a
|
||||
R a/a
|
||||
$ hg up -Cq 0
|
||||
|
||||
Attempt to create a path conflict in the manifest
|
||||
|
||||
$ echo b > b
|
||||
$ hg add b
|
||||
$ hg commit -m b
|
||||
$ rm b
|
||||
$ mkdir b
|
||||
$ echo b/b > b/b
|
||||
$ hg add b/b
|
||||
abort: file 'b' in dirstate clashes with 'b/b'
|
||||
[255]
|
||||
$ rm -rf b
|
||||
$ hg up -Cq 0
|
||||
|
||||
Test warning when creating files that might give a casefold collision
|
||||
|
||||
#if no-icasefs
|
||||
$ echo data > FiLeNaMe
|
||||
$ hg add FiLeNaMe
|
||||
$ echo data > FILENAME
|
||||
$ hg add FILENAME
|
||||
warning: possible case-folding collision for FILENAME
|
||||
$ rm -f FiLeNaMe FILENAME
|
||||
$ hg up -Cq 0
|
||||
#endif
|
||||
|
||||
Test dirfoldmap and filefoldmap on case insensitive filesystems
|
||||
|
||||
#if icasefs
|
||||
$ mkdir -p dirA/dirB/dirC
|
||||
$ echo file1 > dira/File1
|
||||
$ echo file2 > dira/dirb/FILE2
|
||||
$ echo file3 > dira/dirb/dirc/FiLe3
|
||||
$ echo file4 > dira/dirb/dirc/file4
|
||||
$ hg add DIRA
|
||||
adding dirA/File1
|
||||
adding dirA/dirB/FILE2
|
||||
adding dirA/dirB/dirC/FiLe3
|
||||
adding dirA/dirB/dirC/file4
|
||||
$ hg status
|
||||
A dirA/File1
|
||||
A dirA/dirB/FILE2
|
||||
A dirA/dirB/dirC/FiLe3
|
||||
A dirA/dirB/dirC/file4
|
||||
$ hg forget dira/DIRB
|
||||
removing dirA/dirB/FILE2
|
||||
removing dirA/dirB/dirC/FiLe3
|
||||
removing dirA/dirB/dirC/file4
|
||||
$ hg status
|
||||
A dirA/File1
|
||||
? dirA/dirB/FILE2
|
||||
? dirA/dirB/dirC/FiLe3
|
||||
? dirA/dirB/dirC/file4
|
||||
$ hg add dira/dirb/file2
|
||||
$ hg status
|
||||
A dirA/File1
|
||||
A dirA/dirB/FILE2
|
||||
? dirA/dirB/dirC/FiLe3
|
||||
? dirA/dirB/dirC/file4
|
||||
$ rm -rf dirA
|
||||
#endif
|
||||
|
||||
Test autorepack
|
||||
|
||||
$ ls .hg/dirstate.tree.*
|
||||
.hg/dirstate.tree.* (glob)
|
||||
$ echo data > file
|
||||
|
||||
After the first repack, the old trees are kept around by the transaction undo backups.
|
||||
$ hg add file --config treestate.minrepackthreshold=1 --config treestate.repackfactor=0 --debug | grep -v 'in use by'
|
||||
adding file
|
||||
auto-repacking treedirstate
|
||||
$ ls .hg/dirstate.tree.*
|
||||
.hg/dirstate.tree.* (glob)
|
||||
.hg/dirstate.tree.* (glob)
|
||||
|
||||
After the second repack, the old trees are still kept around.
|
||||
$ hg forget file --config treestate.minrepackthreshold=1 --config treestate.repackfactor=0 --debug | grep -v 'in use by'
|
||||
removing file
|
||||
auto-repacking treedirstate
|
||||
$ ls .hg/dirstate.tree.*
|
||||
.hg/dirstate.tree.* (glob)
|
||||
.hg/dirstate.tree.* (glob)
|
||||
.hg/dirstate.tree.* (glob)
|
||||
|
||||
On the third repack, the original tree is removed.
|
||||
$ hg add file --config treestate.minrepackthreshold=1 --config treestate.repackfactor=0 --debug | grep -v 'in use by'
|
||||
adding file
|
||||
auto-repacking treedirstate
|
||||
removing old unreferenced dirstate tree * (glob)
|
||||
$ ls .hg/dirstate.tree.*
|
||||
.hg/dirstate.tree.* (glob)
|
||||
.hg/dirstate.tree.* (glob)
|
||||
.hg/dirstate.tree.* (glob)
|
||||
|
||||
On the fourth repack, the second tree is removed.
|
||||
$ hg forget file --config treestate.minrepackthreshold=1 --config treestate.repackfactor=0 --debug | grep -v 'in use by'
|
||||
removing file
|
||||
auto-repacking treedirstate
|
||||
removing old unreferenced dirstate tree * (glob)
|
||||
$ ls .hg/dirstate.tree.*
|
||||
.hg/dirstate.tree.* (glob)
|
||||
.hg/dirstate.tree.* (glob)
|
||||
.hg/dirstate.tree.* (glob)
|
||||
|
||||
Test downgrade on pull
|
||||
|
||||
$ for f in 1 2 3 4 5 ; do mkdir dir$f ; echo $f > dir$f/file$f ; hg add dir$f/file$f ; done
|
||||
$ echo x > a
|
||||
$ hg add a
|
||||
$ hg commit -m "add files"
|
||||
$ cd ..
|
||||
$ hg clone repo clone
|
||||
updating to branch default
|
||||
7 files updated, 0 files merged, 0 files removed, 0 files unresolved
|
||||
$ cd clone
|
||||
$ hg merge 1
|
||||
merging a
|
||||
warning: 1 conflicts while merging a! (edit, then use 'hg resolve --mark')
|
||||
0 files updated, 0 files merged, 0 files removed, 1 files unresolved
|
||||
use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
|
||||
[1]
|
||||
$ echo data > newfile
|
||||
$ hg add newfile
|
||||
$ hg rm dir3/file3
|
||||
$ grep treedirstate .hg/requires
|
||||
treedirstate
|
||||
$ hg pull --config treestate.automigrate=true --config format.dirstate=0
|
||||
downgrading dirstate format...
|
||||
pulling from $TESTTMP/repo (glob)
|
||||
searching for changes
|
||||
no changes found
|
||||
$ hg debugdirstate
|
||||
m 0 -2 * a (glob)
|
||||
n 644 5 * base (glob)
|
||||
n 644 2 * dir1/file1 (glob)
|
||||
n 644 2 * dir2/file2 (glob)
|
||||
r 0 0 * dir3/file3 (glob)
|
||||
n 644 2 * dir4/file4 (glob)
|
||||
n 644 2 * dir5/file5 (glob)
|
||||
a 0 -1 * newfile (glob)
|
||||
$ grep treedirstate .hg/requires
|
||||
[1]
|
||||
|
||||
Test upgrade on pull
|
||||
|
||||
$ hg pull --config treestate.automigrate=true --config format.dirstate=1
|
||||
please wait while we migrate dirstate format to version 1
|
||||
this will make your hg commands faster...
|
||||
pulling from $TESTTMP/repo (glob)
|
||||
searching for changes
|
||||
no changes found
|
||||
$ hg debugdirstate
|
||||
m 0 -2 * a (glob)
|
||||
n 644 5 * base (glob)
|
||||
n 644 2 * dir1/file1 (glob)
|
||||
n 644 2 * dir2/file2 (glob)
|
||||
r 0 0 * dir3/file3 (glob)
|
||||
n 644 2 * dir4/file4 (glob)
|
||||
n 644 2 * dir5/file5 (glob)
|
||||
a 0 -1 * newfile (glob)
|
||||
$ grep treedirstate .hg/requires
|
||||
treedirstate
|
||||
|
48
eden/scm/tests/test-treestate-downgrade.t
Normal file
48
eden/scm/tests/test-treestate-downgrade.t
Normal file
@ -0,0 +1,48 @@
|
||||
#require fsmonitor
|
||||
$ setconfig extensions.treemanifest=!
|
||||
|
||||
Fsmonitor is required for treestate to track untracked files.
|
||||
|
||||
Nonnormalset, otherparentset, copymap might have reference to untracked files.
|
||||
They should be filtered out when downgrading from treestate to treedirstate.
|
||||
|
||||
Create a treestate repo
|
||||
|
||||
$ hg init repo1 --config format.dirstate=2
|
||||
$ cd repo1
|
||||
$ touch x
|
||||
|
||||
Write the untracked file to treestate
|
||||
|
||||
$ hg status
|
||||
? x
|
||||
$ hg debugtree
|
||||
dirstate v2 (* 1 files tracked) (glob)
|
||||
|
||||
Downgrade to treedirstate
|
||||
|
||||
$ hg debugtree v1
|
||||
|
||||
Check nonnormalset
|
||||
|
||||
$ hg debugshell --command 'print(repr(sorted(repo.dirstate._map.nonnormalset)))'
|
||||
[]
|
||||
|
||||
Check downgrade with "hg pull"
|
||||
|
||||
$ hg init $TESTTMP/repo2 --config format.dirstate=2
|
||||
$ cd $TESTTMP/repo2
|
||||
$ touch x
|
||||
$ hg ci -m init -A x -q
|
||||
|
||||
$ hg init $TESTTMP/repo3 --config format.dirstate=2
|
||||
$ cd $TESTTMP/repo3
|
||||
$ hg pull ../repo2 --config format.dirstate=1 --config treestate.automigrate=true --config extensions.rebase= --rebase -q
|
||||
|
||||
fsmonitor state is invalidated after upgrade
|
||||
|
||||
$ ls .hg/fsmonitor.state
|
||||
.hg/fsmonitor.state
|
||||
$ hg pull ../repo2 --config format.dirstate=2 --config treestate.automigrate=true --config extensions.rebase= --rebase -q
|
||||
$ [ -f .hg/fsmonitor.state ]
|
||||
[1]
|
@ -457,7 +457,7 @@ test revlog format 0
|
||||
$ revlog-formatv0.py
|
||||
$ cd formatv0
|
||||
$ hg verify
|
||||
abort: legacy dirstate implementations are no longer supported!
|
||||
abort: repo is corrupted: 00changelog.i
|
||||
[255]
|
||||
$ cd ..
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user