mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 07:17:55 +03:00
5ceeb5311d
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
247 lines
5.2 KiB
Python
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"""
|