changelog: disable delta chains
This patch disables delta chains on changelogs. After this patch, new
entries on changelogs - including existing changelogs - will be stored
as the fulltext of that data (likely compressed). No delta computation
will be performed.
An overview of delta chains and data justifying this change follows.
Revlogs try to store entries as a delta against a previous entry (either
a parent revision in the case of generaldelta or the previous physical
revision when not using generaldelta). Most of the time this is the
correct thing to do: it frequently results in less CPU usage and smaller
storage.
Delta chains are most effective when the base revision being deltad
against is similar to the current data. This tends to occur naturally
for manifests and file data, since only small parts of each tend to
change with each revision. Changelogs, however, are a different story.
Changelog entries represent changesets/commits. And unless commits in a
repository are homogonous (same author, changing same files, similar
commit messages, etc), a delta from one entry to the next tends to be
relatively large compared to the size of the entry. This means that
delta chains tend to be short. How short? Here is the full vs delta
revision breakdown on some real world repos:
Repo % Full % Delta Max Length
hg 45.8 54.2 6
mozilla-central 42.4 57.6 8
mozilla-unified 42.5 57.5 17
pypy 46.1 53.9 6
python-zstandard 46.1 53.9 3
(I threw in python-zstandard as an example of a repo that is homogonous.
It contains a small Python project with changes all from the same
author.)
Contrast this with the manifest revlog for these repos, where 99+% of
revisions are deltas and delta chains run into the thousands.
So delta chains aren't as useful on changelogs. But even a short delta
chain may provide benefits. Let's measure that.
Delta chains may require less CPU to read revisions if the CPU time
spent reading smaller deltas is less than the CPU time used to
decompress larger individual entries. We can measure this via
`hg perfrevlog -c -d 1` to iterate a revlog to resolve each revision's
fulltext. Here are the results of that command on a repo using delta
chains in its changelog and on a repo without delta chains:
hg (forward)
! wall 0.407008 comb 0.410000 user 0.410000 sys 0.000000 (best of 25)
! wall 0.390061 comb 0.390000 user 0.390000 sys 0.000000 (best of 26)
hg (reverse)
! wall 0.515221 comb 0.520000 user 0.520000 sys 0.000000 (best of 19)
! wall 0.400018 comb 0.400000 user 0.390000 sys 0.010000 (best of 25)
mozilla-central (forward)
! wall 4.508296 comb 4.490000 user 4.490000 sys 0.000000 (best of 3)
! wall 4.370222 comb 4.370000 user 4.350000 sys 0.020000 (best of 3)
mozilla-central (reverse)
! wall 5.758995 comb 5.760000 user 5.720000 sys 0.040000 (best of 3)
! wall 4.346503 comb 4.340000 user 4.320000 sys 0.020000 (best of 3)
mozilla-unified (forward)
! wall 4.957088 comb 4.950000 user 4.940000 sys 0.010000 (best of 3)
! wall 4.660528 comb 4.650000 user 4.630000 sys 0.020000 (best of 3)
mozilla-unified (reverse)
! wall 6.119827 comb 6.110000 user 6.090000 sys 0.020000 (best of 3)
! wall 4.675136 comb 4.670000 user 4.670000 sys 0.000000 (best of 3)
pypy (forward)
! wall 1.231122 comb 1.240000 user 1.230000 sys 0.010000 (best of 8)
! wall 1.164896 comb 1.160000 user 1.160000 sys 0.000000 (best of 9)
pypy (reverse)
! wall 1.467049 comb 1.460000 user 1.460000 sys 0.000000 (best of 7)
! wall 1.160200 comb 1.170000 user 1.160000 sys 0.010000 (best of 9)
The data clearly shows that it takes less wall and CPU time to resolve
revisions when there are no delta chains in the changelogs, regardless
of the direction of traversal. Furthermore, not using a delta chain
means that fulltext resolution in reverse is as fast as iterating
forward. So not using delta chains on the changelog is a clear CPU win
for reading operations.
An example of a user-visible operation showing this speed-up is revset
evaluation. Here are results for
`hg perfrevset 'author(gps) or author(mpm)'`:
hg
! wall 1.655506 comb 1.660000 user 1.650000 sys 0.010000 (best of 6)
! wall 1.612723 comb 1.610000 user 1.600000 sys 0.010000 (best of 7)
mozilla-central
! wall 17.629826 comb 17.640000 user 17.600000 sys 0.040000 (best of 3)
! wall 17.311033 comb 17.300000 user 17.260000 sys 0.040000 (best of 3)
What about 00changelog.i size?
Repo Delta Chains No Delta Chains
hg 7,033,250 6,976,771
mozilla-central 82,978,748 81,574,623
mozilla-unified 88,112,349 86,702,162
pypy 20,740,699 20,659,741
The data shows that removing delta chains from the changelog makes the
changelog smaller.
Delta chains are also used during changegroup generation. This
operation essentially converts a series of revisions to one large
delta chain. And changegroup generation is smart: if the delta in
the revlog matches what the changegroup is emitting, it will reuse
the delta instead of recalculating it. We can measure the impact
removing changelog delta chains has on changegroup generation via
`hg perfchangegroupchangelog`:
hg
! wall 1.589245 comb 1.590000 user 1.590000 sys 0.000000 (best of 7)
! wall 1.788060 comb 1.790000 user 1.790000 sys 0.000000 (best of 6)
mozilla-central
! wall 17.382585 comb 17.380000 user 17.340000 sys 0.040000 (best of 3)
! wall 20.161357 comb 20.160000 user 20.120000 sys 0.040000 (best of 3)
mozilla-unified
! wall 18.722839 comb 18.720000 user 18.680000 sys 0.040000 (best of 3)
! wall 21.168075 comb 21.170000 user 21.130000 sys 0.040000 (best of 3)
pypy
! wall 4.828317 comb 4.830000 user 4.820000 sys 0.010000 (best of 3)
! wall 5.415455 comb 5.420000 user 5.410000 sys 0.010000 (best of 3)
The data shows eliminating delta chains makes the changelog part of
changegroup generation slower. This is expected since we now have to
compute deltas for revisions where we could recycle the delta before.
It is worth putting this regression into context of overall changegroup
times. Here is the rough total CPU time spent in changegroup generation
for various repos while using delta chains on the changelog:
Repo CPU Time (s) CPU Time w/ compression
hg 4.50 7.05
mozilla-central 111.1 222.0
pypy 28.68 75.5
Before compression, removing delta chains from the changegroup adds
~4.4% overhead to hg changegroup generation, 1.3% to mozilla-central,
and 2.0% to pypy. When you factor in zlib compression, these percentages
are roughly divided by 2.
While the increased CPU usage for changegroup generation is unfortunate,
I think it is acceptable because the percentage is small, server
operators (those likely impacted most by this) have other mechanisms
to mitigate CPU consumption (namely reducing zlib compression level and
pre-generated clone bundles), and because there is room to optimize this
in the future. For example, we could use the nullid as the base revision,
effectively encoding the full revision for each entry in the changegroup.
When doing this, `hg perfchangegroupchangelog` nearly halves:
mozilla-unified
! wall 21.168075 comb 21.170000 user 21.130000 sys 0.040000 (best of 3)
! wall 11.196461 comb 11.200000 user 11.190000 sys 0.010000 (best of 3)
This looks very promising as a future optimization opportunity.
It's worth that the changes in test-acl.t to the changegroup part size.
This is because revision 6 in the changegroup had a delta chain of
length 2 before and after this patch the base revision is nullrev.
When the base revision is nullrev, cg2packer.deltaparent() hardcodes
the *previous* revision from the changegroup as the delta parent.
This caused the delta in the changegroup to switch base revisions,
the delta to change, and the size to change accordingly. While the
size increased in this case, I think sizes will remain the same
on average, as the delta base for changelog revisions doesn't matter
too much (as this patch shows). So, I don't consider this a regression.
Let commit recurse into subrepos by default to match pre-2.0 behavior:
$ echo "[ui]" >> $HGRCPATH
$ echo "commitsubrepos = Yes" >> $HGRCPATH
$ hg init t
$ cd t
first revision, no sub
$ echo a > a
$ hg ci -Am0
adding a
add first sub
$ echo s = s > .hgsub
$ hg add .hgsub
$ hg init s
$ echo a > s/a
Issue2232: committing a subrepo without .hgsub
$ hg ci -mbad s
abort: can't commit subrepos without .hgsub
[255]
$ hg -R s add s/a
$ hg files -S
.hgsub
a
s/a (glob)
$ hg -R s ci -Ams0
$ hg sum
parent: 0:f7b1eb17ad24 tip
0
branch: default
commit: 1 added, 1 subrepos
update: (current)
phases: 1 draft
$ hg ci -m1
test handling .hgsubstate "added" explicitly.
$ hg parents --template '{node}\n{files}\n'
7cf8cfea66e410e8e3336508dfeec07b3192de51
.hgsub .hgsubstate
$ hg rollback -q
$ hg add .hgsubstate
$ hg ci -m1
$ hg parents --template '{node}\n{files}\n'
7cf8cfea66e410e8e3336508dfeec07b3192de51
.hgsub .hgsubstate
Subrepopath which overlaps with filepath, does not change warnings in remove()
$ mkdir snot
$ touch snot/file
$ hg remove -S snot/file
not removing snot/file: file is untracked
[1]
$ hg cat snot/filenot
snot/filenot: no such file in rev 7cf8cfea66e4
[1]
$ rm -r snot
Revert subrepo and test subrepo fileset keyword:
$ echo b > s/a
$ hg revert --dry-run "set:subrepo('glob:s*')"
reverting subrepo s
reverting s/a (glob)
$ cat s/a
b
$ hg revert "set:subrepo('glob:s*')"
reverting subrepo s
reverting s/a (glob)
$ cat s/a
a
$ rm s/a.orig
Revert subrepo with no backup. The "reverting s/a" line is gone since
we're really running 'hg update' in the subrepo:
$ echo b > s/a
$ hg revert --no-backup s
reverting subrepo s
Issue2022: update -C
$ echo b > s/a
$ hg sum
parent: 1:7cf8cfea66e4 tip
1
branch: default
commit: 1 subrepos
update: (current)
phases: 2 draft
$ hg co -C 1
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg sum
parent: 1:7cf8cfea66e4 tip
1
branch: default
commit: (clean)
update: (current)
phases: 2 draft
commands that require a clean repo should respect subrepos
$ echo b >> s/a
$ hg backout tip
abort: uncommitted changes in subrepository 's'
[255]
$ hg revert -C -R s s/a
add sub sub
$ echo ss = ss > s/.hgsub
$ hg init s/ss
$ echo a > s/ss/a
$ hg -R s add s/.hgsub
$ hg -R s/ss add s/ss/a
$ hg sum
parent: 1:7cf8cfea66e4 tip
1
branch: default
commit: 1 subrepos
update: (current)
phases: 2 draft
$ hg ci -m2
committing subrepository s
committing subrepository s/ss (glob)
$ hg sum
parent: 2:df30734270ae tip
2
branch: default
commit: (clean)
update: (current)
phases: 3 draft
test handling .hgsubstate "modified" explicitly.
$ hg parents --template '{node}\n{files}\n'
df30734270ae757feb35e643b7018e818e78a9aa
.hgsubstate
$ hg rollback -q
$ hg status -A .hgsubstate
M .hgsubstate
$ hg ci -m2
$ hg parents --template '{node}\n{files}\n'
df30734270ae757feb35e643b7018e818e78a9aa
.hgsubstate
bump sub rev (and check it is ignored by ui.commitsubrepos)
$ echo b > s/a
$ hg -R s ci -ms1
$ hg --config ui.commitsubrepos=no ci -m3
leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
$ echo c > s/a
$ hg --config ui.commitsubrepos=no ci -m4
abort: uncommitted changes in subrepository 's'
(use --subrepos for recursive commit)
[255]
$ hg id
f6affe3fbfaa+ tip
$ hg -R s ci -mc
$ hg id
f6affe3fbfaa+ tip
$ echo d > s/a
$ hg ci -m4
committing subrepository s
$ hg tip -R s
changeset: 4:02dcf1d70411
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: 4
check caching
$ hg co 0
0 files updated, 0 files merged, 2 files removed, 0 files unresolved
$ hg debugsub
restore
$ hg co
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg debugsub
path s
source s
revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
new branch for merge tests
$ hg co 1
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo t = t >> .hgsub
$ hg init t
$ echo t > t/t
$ hg -R t add t
adding t/t (glob)
5
$ hg ci -m5 # add sub
committing subrepository t
created new head
$ echo t2 > t/t
6
$ hg st -R s
$ hg ci -m6 # change sub
committing subrepository t
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
path t
source t
revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
$ echo t3 > t/t
7
$ hg ci -m7 # change sub again for conflict test
committing subrepository t
$ hg rm .hgsub
8
$ hg ci -m8 # remove sub
test handling .hgsubstate "removed" explicitly.
$ hg parents --template '{node}\n{files}\n'
96615c1dad2dc8e3796d7332c77ce69156f7b78e
.hgsub .hgsubstate
$ hg rollback -q
$ hg remove .hgsubstate
$ hg ci -m8
$ hg parents --template '{node}\n{files}\n'
96615c1dad2dc8e3796d7332c77ce69156f7b78e
.hgsub .hgsubstate
merge tests
$ hg co -C 3
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge 5 # test adding
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg debugsub
path s
source s
revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
path t
source t
revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
$ hg ci -m9
created new head
$ hg merge 6 --debug # test change
searching for copies back to rev 2
resolving manifests
branchmerge: True, force: False, partial: False
ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
starting 4 threads for background file closing (?)
.hgsubstate: versions differ -> m (premerge)
subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
getting subrepo t
resolving manifests
branchmerge: False, force: False, partial: False
ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
t: remote is newer -> g
getting t
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg debugsub
path s
source s
revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
path t
source t
revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
$ echo conflict > t/t
$ hg ci -m10
committing subrepository t
$ HGMERGE=internal:merge hg merge --debug 7 # test conflict
searching for copies back to rev 2
resolving manifests
branchmerge: True, force: False, partial: False
ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
starting 4 threads for background file closing (?)
.hgsubstate: versions differ -> m (premerge)
subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
subrepo t: both sides changed
subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
starting 4 threads for background file closing (?)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [merge rev]? m
merging subrepo t
searching for copies back to rev 2
resolving manifests
branchmerge: True, force: False, partial: False
ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
preserving t for resolve of t
t: versions differ -> m (premerge)
picked tool ':merge' for t (binary False symlink False changedelete False)
merging t
my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
t: versions differ -> m (merge)
picked tool ':merge' for t (binary False symlink False changedelete False)
my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
warning: conflicts while merging t! (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
subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
should conflict
$ cat t/t
<<<<<<< local: 20a0db6fbf6c - test: 10
conflict
=======
t3
>>>>>>> other: 7af322bc1198 - test: 7
11: remove subrepo t
$ hg co -C 5
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg revert -r 4 .hgsub # remove t
$ hg ci -m11
created new head
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
local removed, remote changed, keep changed
$ hg merge 6
remote [merge rev] changed subrepository s which local [working copy] removed
use (c)hanged version or (d)elete? c
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
BROKEN: should include subrepo t
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
$ cat .hgsubstate
e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
6747d179aa9a688023c4b0cad32e4c92bb7f34ad t
$ hg ci -m 'local removed, remote changed, keep changed'
BROKEN: should include subrepo t
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
BROKEN: should include subrepo t
$ cat .hgsubstate
e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
$ cat t/t
t2
local removed, remote changed, keep removed
$ hg co -C 11
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge --config ui.interactive=true 6 <<EOF
> d
> EOF
remote [merge rev] changed subrepository s which local [working copy] removed
use (c)hanged version or (d)elete? d
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
$ cat .hgsubstate
e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
$ hg ci -m 'local removed, remote changed, keep removed'
created new head
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
$ cat .hgsubstate
e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
local changed, remote removed, keep changed
$ hg co -C 6
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge 11
local [working copy] changed subrepository s which remote [merge rev] removed
use (c)hanged version or (d)elete? c
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
BROKEN: should include subrepo t
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
BROKEN: should include subrepo t
$ cat .hgsubstate
e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
$ hg ci -m 'local changed, remote removed, keep changed'
created new head
BROKEN: should include subrepo t
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
BROKEN: should include subrepo t
$ cat .hgsubstate
e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
$ cat t/t
t2
local changed, remote removed, keep removed
$ hg co -C 6
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge --config ui.interactive=true 11 <<EOF
> d
> EOF
local [working copy] changed subrepository s which remote [merge rev] removed
use (c)hanged version or (d)elete? d
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
$ cat .hgsubstate
e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
$ hg ci -m 'local changed, remote removed, keep removed'
created new head
$ hg debugsub
path s
source s
revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
$ cat .hgsubstate
e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
clean up to avoid having to fix up the tests below
$ hg co -C 10
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat >> $HGRCPATH <<EOF
> [extensions]
> strip=
> EOF
$ hg strip -r 11:15
saved backup bundle to $TESTTMP/t/.hg/strip-backup/*-backup.hg (glob)
clone
$ cd ..
$ hg clone t tc
updating to branch default
cloning subrepo s from $TESTTMP/t/s
cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
cloning subrepo t from $TESTTMP/t/t
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd tc
$ hg debugsub
path s
source s
revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
path t
source t
revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
push
$ echo bah > t/t
$ hg ci -m11
committing subrepository t
$ hg push
pushing to $TESTTMP/t (glob)
no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
no changes made to subrepo s since last push to $TESTTMP/t/s
pushing subrepo t to $TESTTMP/t/t
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
push -f
$ echo bah > s/a
$ hg ci -m12
committing subrepository s
$ hg push
pushing to $TESTTMP/t (glob)
no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
pushing subrepo s to $TESTTMP/t/s
searching for changes
abort: push creates new remote head 12a213df6fa9! (in subrepo s)
(merge or see 'hg help push' for details about pushing new heads)
[255]
$ hg push -f
pushing to $TESTTMP/t (glob)
pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
searching for changes
no changes found
pushing subrepo s to $TESTTMP/t/s
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files (+1 heads)
pushing subrepo t to $TESTTMP/t/t
searching for changes
no changes found
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
check that unmodified subrepos are not pushed
$ hg clone . ../tcc
updating to branch default
cloning subrepo s from $TESTTMP/tc/s
cloning subrepo s/ss from $TESTTMP/tc/s/ss (glob)
cloning subrepo t from $TESTTMP/tc/t
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
the subrepos on the new clone have nothing to push to its source
$ hg push -R ../tcc .
pushing to .
no changes made to subrepo s/ss since last push to s/ss (glob)
no changes made to subrepo s since last push to s
no changes made to subrepo t since last push to t
searching for changes
no changes found
[1]
the subrepos on the source do not have a clean store versus the clone target
because they were never explicitly pushed to the source
$ hg push ../tcc
pushing to ../tcc
pushing subrepo s/ss to ../tcc/s/ss (glob)
searching for changes
no changes found
pushing subrepo s to ../tcc/s
searching for changes
no changes found
pushing subrepo t to ../tcc/t
searching for changes
no changes found
searching for changes
no changes found
[1]
after push their stores become clean
$ hg push ../tcc
pushing to ../tcc
no changes made to subrepo s/ss since last push to ../tcc/s/ss (glob)
no changes made to subrepo s since last push to ../tcc/s
no changes made to subrepo t since last push to ../tcc/t
searching for changes
no changes found
[1]
updating a subrepo to a different revision or changing
its working directory does not make its store dirty
$ hg -R s update '.^'
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg push
pushing to $TESTTMP/t (glob)
no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
no changes made to subrepo s since last push to $TESTTMP/t/s
no changes made to subrepo t since last push to $TESTTMP/t/t
searching for changes
no changes found
[1]
$ echo foo >> s/a
$ hg push
pushing to $TESTTMP/t (glob)
no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
no changes made to subrepo s since last push to $TESTTMP/t/s
no changes made to subrepo t since last push to $TESTTMP/t/t
searching for changes
no changes found
[1]
$ hg -R s update -C tip
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
committing into a subrepo makes its store (but not its parent's store) dirty
$ echo foo >> s/ss/a
$ hg -R s/ss commit -m 'test dirty store detection'
$ hg out -S -r `hg log -r tip -T "{node|short}"`
comparing with $TESTTMP/t (glob)
searching for changes
no changes found
comparing with $TESTTMP/t/s
searching for changes
no changes found
comparing with $TESTTMP/t/s/ss
searching for changes
changeset: 1:79ea5566a333
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: test dirty store detection
comparing with $TESTTMP/t/t
searching for changes
no changes found
$ hg push
pushing to $TESTTMP/t (glob)
pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
no changes made to subrepo s since last push to $TESTTMP/t/s
no changes made to subrepo t since last push to $TESTTMP/t/t
searching for changes
no changes found
[1]
a subrepo store may be clean versus one repo but not versus another
$ hg push
pushing to $TESTTMP/t (glob)
no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
no changes made to subrepo s since last push to $TESTTMP/t/s
no changes made to subrepo t since last push to $TESTTMP/t/t
searching for changes
no changes found
[1]
$ hg push ../tcc
pushing to ../tcc
pushing subrepo s/ss to ../tcc/s/ss (glob)
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
no changes made to subrepo s since last push to ../tcc/s
no changes made to subrepo t since last push to ../tcc/t
searching for changes
no changes found
[1]
update
$ cd ../t
$ hg up -C # discard our earlier merge
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 other heads for branch "default"
$ echo blah > t/t
$ hg ci -m13
committing subrepository t
backout calls revert internally with minimal opts, which should not raise
KeyError
$ hg backout ".^" --no-commit
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
changeset c373c8102e68 backed out, don't forget to commit.
$ hg up -C # discard changes
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 other heads for branch "default"
pull
$ cd ../tc
$ hg pull
pulling from $TESTTMP/t (glob)
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
(run 'hg update' to get a working copy)
should pull t
$ hg incoming -S -r `hg log -r tip -T "{node|short}"`
comparing with $TESTTMP/t (glob)
no changes found
comparing with $TESTTMP/t/s
searching for changes
no changes found
comparing with $TESTTMP/t/s/ss
searching for changes
no changes found
comparing with $TESTTMP/t/t
searching for changes
changeset: 5:52c0adc0515a
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
summary: 13
$ hg up
pulling subrepo t from $TESTTMP/t/t
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 other heads for branch "default"
$ cat t/t
blah
bogus subrepo path aborts
$ echo 'bogus=[boguspath' >> .hgsub
$ hg ci -m 'bogus subrepo path'
abort: missing ] in subrepo source
[255]
Issue1986: merge aborts when trying to merge a subrepo that
shouldn't need merging
# subrepo layout
#
# o 5 br
# /|
# o | 4 default
# | |
# | o 3 br
# |/|
# o | 2 default
# | |
# | o 1 br
# |/
# o 0 default
$ cd ..
$ rm -rf sub
$ hg init main
$ cd main
$ hg init s
$ cd s
$ echo a > a
$ hg ci -Am1
adding a
$ hg branch br
marked working directory as branch br
(branches are permanent and global, did you want a bookmark?)
$ echo a >> a
$ hg ci -m1
$ hg up default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo b > b
$ hg ci -Am1
adding b
$ hg up br
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg merge tip
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg ci -m1
$ hg up 2
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo c > c
$ hg ci -Am1
adding c
$ hg up 3
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg merge 4
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg ci -m1
# main repo layout:
#
# * <-- try to merge default into br again
# .`|
# . o 5 br --> substate = 5
# . |
# o | 4 default --> substate = 4
# | |
# | o 3 br --> substate = 2
# |/|
# o | 2 default --> substate = 2
# | |
# | o 1 br --> substate = 3
# |/
# o 0 default --> substate = 2
$ cd ..
$ echo 's = s' > .hgsub
$ hg -R s up 2
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg ci -Am1
adding .hgsub
$ hg branch br
marked working directory as branch br
(branches are permanent and global, did you want a bookmark?)
$ echo b > b
$ hg -R s up 3
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg ci -Am1
adding b
$ hg up default
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ echo c > c
$ hg ci -Am1
adding c
$ hg up 1
2 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg merge 2
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg ci -m1
$ hg up 2
1 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg -R s up 4
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo d > d
$ hg ci -Am1
adding d
$ hg up 3
2 files updated, 0 files merged, 1 files removed, 0 files unresolved
$ hg -R s up 5
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo e > e
$ hg ci -Am1
adding e
$ hg up 5
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg merge 4 # try to merge default into br again
subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [merge rev]? m
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ cd ..
test subrepo delete from .hgsubstate
$ hg init testdelete
$ mkdir testdelete/nested testdelete/nested2
$ hg init testdelete/nested
$ hg init testdelete/nested2
$ echo test > testdelete/nested/foo
$ echo test > testdelete/nested2/foo
$ hg -R testdelete/nested add
adding testdelete/nested/foo (glob)
$ hg -R testdelete/nested2 add
adding testdelete/nested2/foo (glob)
$ hg -R testdelete/nested ci -m test
$ hg -R testdelete/nested2 ci -m test
$ echo nested = nested > testdelete/.hgsub
$ echo nested2 = nested2 >> testdelete/.hgsub
$ hg -R testdelete add
adding testdelete/.hgsub (glob)
$ hg -R testdelete ci -m "nested 1 & 2 added"
$ echo nested = nested > testdelete/.hgsub
$ hg -R testdelete ci -m "nested 2 deleted"
$ cat testdelete/.hgsubstate
bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
$ hg -R testdelete remove testdelete/.hgsub
$ hg -R testdelete ci -m ".hgsub deleted"
$ cat testdelete/.hgsubstate
bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
test repository cloning
$ mkdir mercurial mercurial2
$ hg init nested_absolute
$ echo test > nested_absolute/foo
$ hg -R nested_absolute add
adding nested_absolute/foo (glob)
$ hg -R nested_absolute ci -mtest
$ cd mercurial
$ hg init nested_relative
$ echo test2 > nested_relative/foo2
$ hg -R nested_relative add
adding nested_relative/foo2 (glob)
$ hg -R nested_relative ci -mtest2
$ hg init main
$ echo "nested_relative = ../nested_relative" > main/.hgsub
$ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
$ hg -R main add
adding main/.hgsub (glob)
$ hg -R main ci -m "add subrepos"
$ cd ..
$ hg clone mercurial/main mercurial2/main
updating to branch default
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat mercurial2/main/nested_absolute/.hg/hgrc \
> mercurial2/main/nested_relative/.hg/hgrc
[paths]
default = $TESTTMP/mercurial/nested_absolute
[paths]
default = $TESTTMP/mercurial/nested_relative
$ rm -rf mercurial mercurial2
Issue1977: multirepo push should fail if subrepo push fails
$ hg init repo
$ hg init repo/s
$ echo a > repo/s/a
$ hg -R repo/s ci -Am0
adding a
$ echo s = s > repo/.hgsub
$ hg -R repo ci -Am1
adding .hgsub
$ hg clone repo repo2
updating to branch default
cloning subrepo s from $TESTTMP/repo/s
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg -q -R repo2 pull -u
$ echo 1 > repo2/s/a
$ hg -R repo2/s ci -m2
$ hg -q -R repo2/s push
$ hg -R repo2/s up -C 0
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo 2 > repo2/s/b
$ hg -R repo2/s ci -m3 -A
adding b
created new head
$ hg -R repo2 ci -m3
$ hg -q -R repo2 push
abort: push creates new remote head cc505f09a8b2! (in subrepo s)
(merge or see 'hg help push' for details about pushing new heads)
[255]
$ hg -R repo update
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
test if untracked file is not overwritten
(this also tests that updated .hgsubstate is treated as "modified",
when 'merge.update()' is aborted before 'merge.recordupdates()', even
if none of mode, size and timestamp of it isn't changed on the
filesystem (see also issue4583))
$ echo issue3276_ok > repo/s/b
$ hg -R repo2 push -f -q
$ touch -t 200001010000 repo/.hgsubstate
$ cat >> repo/.hg/hgrc <<EOF
> [fakedirstatewritetime]
> # emulate invoking dirstate.write() via repo.status()
> # at 2000-01-01 00:00
> fakenow = 200001010000
>
> [extensions]
> fakedirstatewritetime = $TESTDIR/fakedirstatewritetime.py
> EOF
$ hg -R repo update
b: untracked file differs
abort: untracked files in working directory differ from files in requested revision (in subrepo s)
[255]
$ cat >> repo/.hg/hgrc <<EOF
> [extensions]
> fakedirstatewritetime = !
> EOF
$ cat repo/s/b
issue3276_ok
$ rm repo/s/b
$ touch -t 200001010000 repo/.hgsubstate
$ hg -R repo revert --all
reverting repo/.hgsubstate (glob)
reverting subrepo s
$ hg -R repo update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat repo/s/b
2
$ rm -rf repo2 repo
Issue1852 subrepos with relative paths always push/pull relative to default
Prepare a repo with subrepo
$ hg init issue1852a
$ cd issue1852a
$ hg init sub/repo
$ echo test > sub/repo/foo
$ hg -R sub/repo add sub/repo/foo
$ echo sub/repo = sub/repo > .hgsub
$ hg add .hgsub
$ hg ci -mtest
committing subrepository sub/repo (glob)
$ echo test >> sub/repo/foo
$ hg ci -mtest
committing subrepository sub/repo (glob)
$ hg cat sub/repo/foo
test
test
$ mkdir -p tmp/sub/repo
$ hg cat -r 0 --output tmp/%p_p sub/repo/foo
$ cat tmp/sub/repo/foo_p
test
$ mv sub/repo sub_
$ hg cat sub/repo/baz
skipping missing subrepository: sub/repo
[1]
$ rm -rf sub/repo
$ mv sub_ sub/repo
$ cd ..
Create repo without default path, pull top repo, and see what happens on update
$ hg init issue1852b
$ hg -R issue1852b pull issue1852a
pulling from issue1852a
requesting all changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 3 changes to 2 files
(run 'hg update' to get a working copy)
$ hg -R issue1852b update
abort: default path for subrepository not found (in subrepo sub/repo) (glob)
[255]
Ensure a full traceback, not just the SubrepoAbort part
$ hg -R issue1852b update --traceback 2>&1 | grep 'raise error\.Abort'
raise error.Abort(_("default path for subrepository not found"))
Pull -u now doesn't help
$ hg -R issue1852b pull -u issue1852a
pulling from issue1852a
searching for changes
no changes found
Try the same, but with pull -u
$ hg init issue1852c
$ hg -R issue1852c pull -r0 -u issue1852a
pulling from issue1852a
adding changesets
adding manifests
adding file changes
added 1 changesets with 2 changes to 2 files
cloning subrepo sub/repo from issue1852a/sub/repo (glob)
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
Try to push from the other side
$ hg -R issue1852a push `pwd`/issue1852c
pushing to $TESTTMP/issue1852c (glob)
pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
searching for changes
no changes found
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
Incoming and outgoing should not use the default path:
$ hg clone -q issue1852a issue1852d
$ hg -R issue1852d outgoing --subrepos issue1852c
comparing with issue1852c
searching for changes
no changes found
comparing with issue1852c/sub/repo
searching for changes
no changes found
[1]
$ hg -R issue1852d incoming --subrepos issue1852c
comparing with issue1852c
searching for changes
no changes found
comparing with issue1852c/sub/repo
searching for changes
no changes found
[1]
Check that merge of a new subrepo doesn't write the uncommitted state to
.hgsubstate (issue4622)
$ hg init issue1852a/addedsub
$ echo zzz > issue1852a/addedsub/zz.txt
$ hg -R issue1852a/addedsub ci -Aqm "initial ZZ"
$ hg clone issue1852a/addedsub issue1852d/addedsub
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ echo def > issue1852a/sub/repo/foo
$ hg -R issue1852a ci -SAm 'tweaked subrepo'
adding tmp/sub/repo/foo_p
committing subrepository sub/repo (glob)
$ echo 'addedsub = addedsub' >> issue1852d/.hgsub
$ echo xyz > issue1852d/sub/repo/foo
$ hg -R issue1852d pull -u
pulling from $TESTTMP/issue1852a (glob)
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 2 changes to 2 files
subrepository sub/repo diverged (local revision: f42d5c7504a8, remote revision: 46cd4aac504c)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
pulling subrepo sub/repo from $TESTTMP/issue1852a/sub/repo (glob)
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
subrepository sources for sub/repo differ (glob)
use (l)ocal source (f42d5c7504a8) or (r)emote source (46cd4aac504c)? l
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cat issue1852d/.hgsubstate
f42d5c7504a811dda50f5cf3e5e16c3330b87172 sub/repo
Check status of files when none of them belong to the first
subrepository:
$ hg init subrepo-status
$ cd subrepo-status
$ hg init subrepo-1
$ hg init subrepo-2
$ cd subrepo-2
$ touch file
$ hg add file
$ cd ..
$ echo subrepo-1 = subrepo-1 > .hgsub
$ echo subrepo-2 = subrepo-2 >> .hgsub
$ hg add .hgsub
$ hg ci -m 'Added subrepos'
committing subrepository subrepo-2
$ hg st subrepo-2/file
Check that share works with subrepo
$ hg --config extensions.share= share . ../shared
updating working directory
cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ test -f ../shared/subrepo-1/.hg/sharedpath
[1]
$ hg -R ../shared in
abort: repository default not found!
[255]
$ hg -R ../shared/subrepo-2 showconfig paths
paths.default=$TESTTMP/subrepo-status/subrepo-2
$ hg -R ../shared/subrepo-1 sum --remote
parent: -1:000000000000 tip (empty repository)
branch: default
commit: (clean)
update: (current)
remote: (synced)
Check hg update --clean
$ cd $TESTTMP/t
$ rm -r t/t.orig
$ hg status -S --all
C .hgsub
C .hgsubstate
C a
C s/.hgsub
C s/.hgsubstate
C s/a
C s/ss/a
C t/t
$ echo c1 > s/a
$ cd s
$ echo c1 > b
$ echo c1 > c
$ hg add b
$ cd ..
$ hg status -S
M s/a
A s/b
? s/c
$ hg update -C
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2 other heads for branch "default"
$ hg status -S
? s/b
? s/c
Sticky subrepositories, no changes
$ cd $TESTTMP/t
$ hg id
925c17564ef8 tip
$ hg -R s id
12a213df6fa9 tip
$ hg -R t id
52c0adc0515a tip
$ hg update 11
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id
365661e5936a
$ hg -R s id
fc627a69481f
$ hg -R t id
e95bcfa18a35
Sticky subrepositories, file changes
$ touch s/f1
$ touch t/f1
$ hg add -S s/f1
$ hg add -S t/f1
$ hg id
365661e5936a+
$ hg -R s id
fc627a69481f+
$ hg -R t id
e95bcfa18a35+
$ hg update tip
subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
subrepository sources for s differ
use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)? l
subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
subrepository sources for t differ
use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)? l
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id
925c17564ef8+ tip
$ hg -R s id
fc627a69481f+
$ hg -R t id
e95bcfa18a35+
$ hg update --clean tip
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Sticky subrepository, revision updates
$ hg id
925c17564ef8 tip
$ hg -R s id
12a213df6fa9 tip
$ hg -R t id
52c0adc0515a tip
$ cd s
$ hg update -r -2
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd ../t
$ hg update -r 2
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd ..
$ hg update 10
subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
subrepository sources for t differ (in checked out version)
use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)? l
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id
e45c8b14af55+
$ hg -R s id
02dcf1d70411
$ hg -R t id
7af322bc1198
Sticky subrepository, file changes and revision updates
$ touch s/f1
$ touch t/f1
$ hg add -S s/f1
$ hg add -S t/f1
$ hg id
e45c8b14af55+
$ hg -R s id
02dcf1d70411+
$ hg -R t id
7af322bc1198+
$ hg update tip
subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
subrepository sources for s differ
use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)? l
subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
subrepository sources for t differ
use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)? l
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id
925c17564ef8+ tip
$ hg -R s id
02dcf1d70411+
$ hg -R t id
7af322bc1198+
Sticky repository, update --clean
$ hg update --clean tip
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id
925c17564ef8 tip
$ hg -R s id
12a213df6fa9 tip
$ hg -R t id
52c0adc0515a tip
Test subrepo already at intended revision:
$ cd s
$ hg update fc627a69481f
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd ..
$ hg update 11
subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
(M)erge, keep (l)ocal [working copy] or keep (r)emote [destination]? m
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg id -n
11+
$ hg -R s id
fc627a69481f
$ hg -R t id
e95bcfa18a35
Test that removing .hgsubstate doesn't break anything:
$ hg rm -f .hgsubstate
$ hg ci -mrm
nothing changed
[1]
$ hg log -vr tip
changeset: 13:925c17564ef8
tag: tip
user: test
date: Thu Jan 01 00:00:00 1970 +0000
files: .hgsubstate
description:
13
Test that removing .hgsub removes .hgsubstate:
$ hg rm .hgsub
$ hg ci -mrm2
created new head
$ hg log -vr tip
changeset: 14:2400bccd50af
tag: tip
parent: 11:365661e5936a
user: test
date: Thu Jan 01 00:00:00 1970 +0000
files: .hgsub .hgsubstate
description:
rm2
Test issue3153: diff -S with deleted subrepos
$ hg diff --nodates -S -c .
diff -r 365661e5936a -r 2400bccd50af .hgsub
--- a/.hgsub
+++ /dev/null
@@ -1,2 +0,0 @@
-s = s
-t = t
diff -r 365661e5936a -r 2400bccd50af .hgsubstate
--- a/.hgsubstate
+++ /dev/null
@@ -1,2 +0,0 @@
-fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
-e95bcfa18a358dc4936da981ebf4147b4cad1362 t
Test behavior of add for explicit path in subrepo:
$ cd ..
$ hg init explicit
$ cd explicit
$ echo s = s > .hgsub
$ hg add .hgsub
$ hg init s
$ hg ci -m0
Adding with an explicit path in a subrepo adds the file
$ echo c1 > f1
$ echo c2 > s/f2
$ hg st -S
? f1
? s/f2
$ hg add s/f2
$ hg st -S
A s/f2
? f1
$ hg ci -R s -m0
$ hg ci -Am1
adding f1
Adding with an explicit path in a subrepo with -S has the same behavior
$ echo c3 > f3
$ echo c4 > s/f4
$ hg st -S
? f3
? s/f4
$ hg add -S s/f4
$ hg st -S
A s/f4
? f3
$ hg ci -R s -m1
$ hg ci -Ama2
adding f3
Adding without a path or pattern silently ignores subrepos
$ echo c5 > f5
$ echo c6 > s/f6
$ echo c7 > s/f7
$ hg st -S
? f5
? s/f6
? s/f7
$ hg add
adding f5
$ hg st -S
A f5
? s/f6
? s/f7
$ hg ci -R s -Am2
adding f6
adding f7
$ hg ci -m3
Adding without a path or pattern with -S also adds files in subrepos
$ echo c8 > f8
$ echo c9 > s/f9
$ echo c10 > s/f10
$ hg st -S
? f8
? s/f10
? s/f9
$ hg add -S
adding f8
adding s/f10 (glob)
adding s/f9 (glob)
$ hg st -S
A f8
A s/f10
A s/f9
$ hg ci -R s -m3
$ hg ci -m4
Adding with a pattern silently ignores subrepos
$ echo c11 > fm11
$ echo c12 > fn12
$ echo c13 > s/fm13
$ echo c14 > s/fn14
$ hg st -S
? fm11
? fn12
? s/fm13
? s/fn14
$ hg add 'glob:**fm*'
adding fm11
$ hg st -S
A fm11
? fn12
? s/fm13
? s/fn14
$ hg ci -R s -Am4
adding fm13
adding fn14
$ hg ci -Am5
adding fn12
Adding with a pattern with -S also adds matches in subrepos
$ echo c15 > fm15
$ echo c16 > fn16
$ echo c17 > s/fm17
$ echo c18 > s/fn18
$ hg st -S
? fm15
? fn16
? s/fm17
? s/fn18
$ hg add -S 'glob:**fm*'
adding fm15
adding s/fm17 (glob)
$ hg st -S
A fm15
A s/fm17
? fn16
? s/fn18
$ hg ci -R s -Am5
adding fn18
$ hg ci -Am6
adding fn16
Test behavior of forget for explicit path in subrepo:
Forgetting an explicit path in a subrepo untracks the file
$ echo c19 > s/f19
$ hg add s/f19
$ hg st -S
A s/f19
$ hg forget s/f19
$ hg st -S
? s/f19
$ rm s/f19
$ cd ..
Courtesy phases synchronisation to publishing server does not block the push
(issue3781)
$ cp -r main issue3781
$ cp -r main issue3781-dest
$ cd issue3781-dest/s
$ hg phase tip # show we have draft changeset
5: draft
$ chmod a-w .hg/store/phaseroots # prevent phase push
$ cd ../../issue3781
$ cat >> .hg/hgrc << EOF
> [paths]
> default=../issue3781-dest/
> EOF
$ hg push --config devel.legacy.exchange=bundle1
pushing to $TESTTMP/issue3781-dest (glob)
pushing subrepo s to $TESTTMP/issue3781-dest/s
searching for changes
no changes found
searching for changes
no changes found
[1]
# clean the push cache
$ rm s/.hg/cache/storehash/*
$ hg push # bundle2+
pushing to $TESTTMP/issue3781-dest (glob)
pushing subrepo s to $TESTTMP/issue3781-dest/s
searching for changes
no changes found
searching for changes
no changes found
[1]
$ cd ..
Test phase choice for newly created commit with "phases.subrepochecks"
configuration
$ cd t
$ hg update -q -r 12
$ cat >> s/ss/.hg/hgrc <<EOF
> [phases]
> new-commit = secret
> EOF
$ cat >> s/.hg/hgrc <<EOF
> [phases]
> new-commit = draft
> EOF
$ echo phasecheck1 >> s/ss/a
$ hg -R s commit -S --config phases.checksubrepos=abort -m phasecheck1
committing subrepository ss
transaction abort!
rollback completed
abort: can't commit in draft phase conflicting secret from subrepository ss
[255]
$ echo phasecheck2 >> s/ss/a
$ hg -R s commit -S --config phases.checksubrepos=ignore -m phasecheck2
committing subrepository ss
$ hg -R s/ss phase tip
3: secret
$ hg -R s phase tip
6: draft
$ echo phasecheck3 >> s/ss/a
$ hg -R s commit -S -m phasecheck3
committing subrepository ss
warning: changes are committed in secret phase from subrepository ss
$ hg -R s/ss phase tip
4: secret
$ hg -R s phase tip
7: secret
$ cat >> t/.hg/hgrc <<EOF
> [phases]
> new-commit = draft
> EOF
$ cat >> .hg/hgrc <<EOF
> [phases]
> new-commit = public
> EOF
$ echo phasecheck4 >> s/ss/a
$ echo phasecheck4 >> t/t
$ hg commit -S -m phasecheck4
committing subrepository s
committing subrepository s/ss (glob)
warning: changes are committed in secret phase from subrepository ss
committing subrepository t
warning: changes are committed in secret phase from subrepository s
created new head
$ hg -R s/ss phase tip
5: secret
$ hg -R s phase tip
8: secret
$ hg -R t phase tip
6: draft
$ hg phase tip
15: secret
$ cd ..
Test that commit --secret works on both repo and subrepo (issue4182)
$ cd main
$ echo secret >> b
$ echo secret >> s/b
$ hg commit --secret --subrepo -m "secret"
committing subrepository s
$ hg phase -r .
6: secret
$ cd s
$ hg phase -r .
6: secret
$ cd ../../
Test "subrepos" template keyword
$ cd t
$ hg update -q 15
$ cat > .hgsub <<EOF
> s = s
> EOF
$ hg commit -m "16"
warning: changes are committed in secret phase from subrepository s
(addition of ".hgsub" itself)
$ hg diff --nodates -c 1 .hgsubstate
diff -r f7b1eb17ad24 -r 7cf8cfea66e4 .hgsubstate
--- /dev/null
+++ b/.hgsubstate
@@ -0,0 +1,1 @@
+e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
$ hg log -r 1 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
f7b1eb17ad24 000000000000
s
(modification of existing entry)
$ hg diff --nodates -c 2 .hgsubstate
diff -r 7cf8cfea66e4 -r df30734270ae .hgsubstate
--- a/.hgsubstate
+++ b/.hgsubstate
@@ -1,1 +1,1 @@
-e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
+dc73e2e6d2675eb2e41e33c205f4bdab4ea5111d s
$ hg log -r 2 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
7cf8cfea66e4 000000000000
s
(addition of entry)
$ hg diff --nodates -c 5 .hgsubstate
diff -r 7cf8cfea66e4 -r 1f14a2e2d3ec .hgsubstate
--- a/.hgsubstate
+++ b/.hgsubstate
@@ -1,1 +1,2 @@
e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
+60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
$ hg log -r 5 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
7cf8cfea66e4 000000000000
t
(removal of existing entry)
$ hg diff --nodates -c 16 .hgsubstate
diff -r 8bec38d2bd0b -r f2f70bc3d3c9 .hgsubstate
--- a/.hgsubstate
+++ b/.hgsubstate
@@ -1,2 +1,1 @@
0731af8ca9423976d3743119d0865097c07bdc1b s
-e202dc79b04c88a636ea8913d9182a1346d9b3dc t
$ hg log -r 16 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
8bec38d2bd0b 000000000000
t
(merging)
$ hg diff --nodates -c 9 .hgsubstate
diff -r f6affe3fbfaa -r f0d2028bf86d .hgsubstate
--- a/.hgsubstate
+++ b/.hgsubstate
@@ -1,1 +1,2 @@
fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
+60ca1237c19474e7a3978b0dc1ca4e6f36d51382 t
$ hg log -r 9 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
f6affe3fbfaa 1f14a2e2d3ec
t
(removal of ".hgsub" itself)
$ hg diff --nodates -c 8 .hgsubstate
diff -r f94576341bcf -r 96615c1dad2d .hgsubstate
--- a/.hgsubstate
+++ /dev/null
@@ -1,2 +0,0 @@
-e4ece1bf43360ddc8f6a96432201a37b7cd27ae4 s
-7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4 t
$ hg log -r 8 --template "{p1node|short} {p2node|short}\n{subrepos % '{subrepo}\n'}"
f94576341bcf 000000000000
Test that '[paths]' is configured correctly at subrepo creation
$ cd $TESTTMP/tc
$ cat > .hgsub <<EOF
> # to clear bogus subrepo path 'bogus=[boguspath'
> s = s
> t = t
> EOF
$ hg update -q --clean null
$ rm -rf s t
$ cat >> .hg/hgrc <<EOF
> [paths]
> default-push = /foo/bar
> EOF
$ hg update -q
$ cat s/.hg/hgrc
[paths]
default = $TESTTMP/t/s
default-push = /foo/bar/s
$ cat s/ss/.hg/hgrc
[paths]
default = $TESTTMP/t/s/ss
default-push = /foo/bar/s/ss
$ cat t/.hg/hgrc
[paths]
default = $TESTTMP/t/t
default-push = /foo/bar/t
$ cd $TESTTMP/t
$ hg up -qC 0
$ echo 'bar' > bar.txt
$ hg ci -Am 'branch before subrepo add'
adding bar.txt
created new head
$ hg merge -r "first(subrepo('s'))"
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
$ hg status -S -X '.hgsub*'
A s/a
? s/b
? s/c
? s/f1
$ hg status -S --rev 'p2()'
A bar.txt
? s/b
? s/c
? s/f1
$ hg diff -S -X '.hgsub*' --nodates
diff -r 000000000000 s/a
--- /dev/null
+++ b/s/a
@@ -0,0 +1,1 @@
+a
$ hg diff -S --rev 'p2()' --nodates
diff -r 7cf8cfea66e4 bar.txt
--- /dev/null
+++ b/bar.txt
@@ -0,0 +1,1 @@
+bar
$ cd ..