sapling/eden/scm/tests/test-fb-hgext-dirsync-amend-t.py
Jun Wu 5ceeb5311d dirsync: improve in-memory commit compatibility
Summary:
Previously, dirsync wraps `repo.commit`, requires an on-disk working copy,
and dirstate to work properly. This diff updates dirsync to wrap
`repo.commitctx` instead, do commit edits purely in memory, then sync the
commit back to disk. It makes dirsync compatible with absorb and in-memory
rebase (and potentially other things like drawdag, if drawdag's context APIs
are improved).

To sync the changes made in-memory back to the filesystem, a dirstate callback
is added to write back mirrored files from commit to disk. This works for both
amend and absorb so the special wrapper about amend is dropped. It is
also optimal for absorb, because it only writes the mirrored files once for
the "final" commit, instead of writing the files for each commit in the stack.

Some `O(N^2)`s (N: len(status)) complexities were avoided:
- `applytomirrors` was called N times.
- `allchanges = set(status.modified + status.removed + status.added)` in
  `applytomirrors` was O(N).
- `sourcepath in status.removed` in `applytomirrors` was O(N).
- `mirrorpath in status.removed` in `applytomirrors` was O(N).

Note there is still a suboptimal complexity of `getmirrors` called per changed
path, `O(N*M)` (N: len(status), M: len(dirsync_conig)). That will be addressed
in a later diff.

Reviewed By: DurhamG

Differential Revision: D26726479

fbshipit-source-id: 482c6c830ab65cc0d9cd569a51ec610a1dac49cc
2021-03-02 18:12:34 -08:00

247 lines
5.2 KiB
Python

# Copyright (c) Facebook, Inc. and its affiliates.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
from testutil.dott import feature, sh, testtmp # noqa: F401
sh % "cat" << r"""
[extensions]
dirsync=
""" >> "$HGRCPATH"
sh % "hg init repo"
sh % "cd repo"
sh % "cat" << r"""
[ui]
verbose=true
[dirsync]
sync1.1=dir1/
sync1.2=dir2/subdir/
""" >> ".hg/hgrc"
# Add multiple files
sh % "mkdir dir1"
sh % "echo a" > "dir1/a"
sh % "echo b" > "dir1/b"
sh % "hg commit -Am 'Adding a and b'" == r"""
adding dir1/a
adding dir1/b
mirrored adding 'dir1/a' to 'dir2/subdir/a'
mirrored adding 'dir1/b' to 'dir2/subdir/b'
committing files:
dir1/a
dir1/b
dir2/subdir/a
dir2/subdir/b
committing manifest
committing changelog
committed 32bc2a06fd26"""
sh % "hg diff --git -r null -r ." == r"""
diff --git a/dir1/a b/dir1/a
new file mode 100644
--- /dev/null
+++ b/dir1/a
@@ -0,0 +1,1 @@
+a
diff --git a/dir1/b b/dir1/b
new file mode 100644
--- /dev/null
+++ b/dir1/b
@@ -0,0 +1,1 @@
+b
diff --git a/dir2/subdir/a b/dir2/subdir/a
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/a
@@ -0,0 +1,1 @@
+a
diff --git a/dir2/subdir/b b/dir2/subdir/b
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/b
@@ -0,0 +1,1 @@
+b"""
# Include only changes to particular file
sh % "echo a" >> "dir1/a"
sh % "echo b" >> "dir1/b"
sh % "hg commit --amend -I dir1/a" == r"""
amending changeset 32bc2a06fd26
mirrored changes in 'dir1/a' to 'dir2/subdir/a'
committing files:
dir1/a
dir1/b
dir2/subdir/a
dir2/subdir/b
committing manifest
committing changelog
committed e9cce3b53a7c"""
sh % "hg diff --git -r null -r ." == r"""
diff --git a/dir1/a b/dir1/a
new file mode 100644
--- /dev/null
+++ b/dir1/a
@@ -0,0 +1,2 @@
+a
+a
diff --git a/dir1/b b/dir1/b
new file mode 100644
--- /dev/null
+++ b/dir1/b
@@ -0,0 +1,1 @@
+b
diff --git a/dir2/subdir/a b/dir2/subdir/a
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/a
@@ -0,0 +1,2 @@
+a
+a
diff --git a/dir2/subdir/b b/dir2/subdir/b
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/b
@@ -0,0 +1,1 @@
+b"""
sh % "echo a" >> "dir1/a"
sh % "hg commit --amend dir1/b" == r"""
amending changeset e9cce3b53a7c
mirrored changes in 'dir1/b' to 'dir2/subdir/b'
committing files:
dir1/a
dir1/b
dir2/subdir/a
dir2/subdir/b
committing manifest
committing changelog
committed a70e8a6cacdd"""
sh % "hg diff --git -r null -r ." == r"""
diff --git a/dir1/a b/dir1/a
new file mode 100644
--- /dev/null
+++ b/dir1/a
@@ -0,0 +1,2 @@
+a
+a
diff --git a/dir1/b b/dir1/b
new file mode 100644
--- /dev/null
+++ b/dir1/b
@@ -0,0 +1,2 @@
+b
+b
diff --git a/dir2/subdir/a b/dir2/subdir/a
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/a
@@ -0,0 +1,2 @@
+a
+a
diff --git a/dir2/subdir/b b/dir2/subdir/b
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/b
@@ -0,0 +1,2 @@
+b
+b"""
# Exclude changes to particular file
sh % "echo b" >> "dir1/b"
sh % "hg commit --amend -X dir1/a" == r"""
amending changeset a70e8a6cacdd
mirrored changes in 'dir1/b' to 'dir2/subdir/b'
committing files:
dir1/a
dir1/b
dir2/subdir/a
dir2/subdir/b
committing manifest
committing changelog
committed 4af805a433df"""
sh % "hg diff --git -r null -r ." == r"""
diff --git a/dir1/a b/dir1/a
new file mode 100644
--- /dev/null
+++ b/dir1/a
@@ -0,0 +1,2 @@
+a
+a
diff --git a/dir1/b b/dir1/b
new file mode 100644
--- /dev/null
+++ b/dir1/b
@@ -0,0 +1,3 @@
+b
+b
+b
diff --git a/dir2/subdir/a b/dir2/subdir/a
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/a
@@ -0,0 +1,2 @@
+a
+a
diff --git a/dir2/subdir/b b/dir2/subdir/b
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/b
@@ -0,0 +1,3 @@
+b
+b
+b"""
# Check the addremove flag
sh % "echo c" > "dir1/c"
sh % "rm dir1/a"
sh % "hg commit --amend -A" == r"""
amending changeset 4af805a433df
removing dir1/a
adding dir1/c
mirrored adding 'dir1/c' to 'dir2/subdir/c'
mirrored remove of 'dir1/a' to 'dir2/subdir/a'
committing files:
dir1/b
dir1/c
dir2/subdir/b
dir2/subdir/c
committing manifest
committing changelog
committed 55c6a18e7d57"""
sh % "hg diff --git -r null -r ." == r"""
diff --git a/dir1/b b/dir1/b
new file mode 100644
--- /dev/null
+++ b/dir1/b
@@ -0,0 +1,3 @@
+b
+b
+b
diff --git a/dir1/c b/dir1/c
new file mode 100644
--- /dev/null
+++ b/dir1/c
@@ -0,0 +1,1 @@
+c
diff --git a/dir2/subdir/b b/dir2/subdir/b
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/b
@@ -0,0 +1,3 @@
+b
+b
+b
diff --git a/dir2/subdir/c b/dir2/subdir/c
new file mode 100644
--- /dev/null
+++ b/dir2/subdir/c
@@ -0,0 +1,1 @@
+c"""