[Updated] D12097: branchmap: skip obsolete revisions while computing heads
av6 (Anton Shestakov)
phabricator at mercurial-scm.org
Thu Feb 3 16:55:38 UTC 2022
Closed by commit rHGf8f2ecdde4b5: branchmap: skip obsolete revisions while computing heads (authored by av6).
This revision was automatically updated to reflect the committed changes.
CHANGED PRIOR TO COMMIT
https://phab.mercurial-scm.org/D12097?vs=32038&id=32045#toc
REPOSITORY
rHG Mercurial
CHANGES SINCE LAST UPDATE
https://phab.mercurial-scm.org/D12097?vs=32038&id=32045
CHANGES SINCE LAST ACTION
https://phab.mercurial-scm.org/D12097/new/
REVISION DETAIL
https://phab.mercurial-scm.org/D12097
AFFECTED FILES
mercurial/branchmap.py
mercurial/destutil.py
mercurial/scmutil.py
tests/test-branch-change.t
tests/test-obsmarker-template.t
tests/test-obsolete.t
tests/test-rebase-obsolete.t
tests/test-rebase-obsolete2.t
tests/test-rebase-obsolete4.t
tests/test-static-http.t
CHANGE DETAILS
diff --git a/tests/test-static-http.t b/tests/test-static-http.t
--- a/tests/test-static-http.t
+++ b/tests/test-static-http.t
@@ -256,6 +256,7 @@
/remote-with-names/.hg/store/data/%7E2ehgtags.i (no-py37 !)
/remote-with-names/.hg/store/data/foo.i
/remote-with-names/.hg/store/data/~2ehgtags.i (py37 !)
+ /remote-with-names/.hg/store/obsstore
/remote-with-names/.hg/store/requires
/remote/.hg/bookmarks
/remote/.hg/bookmarks.current
@@ -276,6 +277,7 @@
/remote/.hg/store/data/quux.i
/remote/.hg/store/data/~2edotfile%20with%20spaces.i (py37 !)
/remote/.hg/store/data/~2ehgtags.i (py37 !)
+ /remote/.hg/store/obsstore
/remote/.hg/store/requires
/remotempty/.hg/bookmarks
/remotempty/.hg/bookmarks.current
diff --git a/tests/test-rebase-obsolete4.t b/tests/test-rebase-obsolete4.t
--- a/tests/test-rebase-obsolete4.t
+++ b/tests/test-rebase-obsolete4.t
@@ -169,7 +169,7 @@
D
branch: default
commit: 1 modified, 1 added, 1 unknown, 1 unresolved
- update: 1 new changesets, 2 branch heads (merge)
+ update: (current)
phases: 3 draft
rebase: 0 rebased, 2 remaining (rebase --continue)
diff --git a/tests/test-rebase-obsolete2.t b/tests/test-rebase-obsolete2.t
--- a/tests/test-rebase-obsolete2.t
+++ b/tests/test-rebase-obsolete2.t
@@ -47,6 +47,7 @@
$ hg add C
$ hg commit -m C
1 new orphan changesets
+ created new head
$ hg log -G
@ 4:212cb178bcbb C
|
@@ -73,6 +74,7 @@
$ hg add D
$ hg commit -m D
1 new orphan changesets
+ created new head
$ hg --hidden strip -r 'desc(B1)'
saved backup bundle to $TESTTMP/obsskip/.hg/strip-backup/86f6414ccda7-b1c452ee-backup.hg
1 new orphan changesets
@@ -194,6 +196,7 @@
$ hg add foo
$ hg commit -m "bar foo"
1 new orphan changesets
+ created new head
$ hg log -G
@ 14:73568ab6879d bar foo
|
diff --git a/tests/test-rebase-obsolete.t b/tests/test-rebase-obsolete.t
--- a/tests/test-rebase-obsolete.t
+++ b/tests/test-rebase-obsolete.t
@@ -650,6 +650,7 @@
$ hg add J
$ hg commit -m J
1 new orphan changesets
+ created new head
$ hg debugobsolete `hg log --rev . -T '{node}'`
1 new obsolescence markers
obsoleted 1 changesets
diff --git a/tests/test-obsolete.t b/tests/test-obsolete.t
--- a/tests/test-obsolete.t
+++ b/tests/test-obsolete.t
@@ -169,10 +169,6 @@
5:5601fb93a350 (draft) [tip ] add new_3_c
$ hg heads --hidden
5:5601fb93a350 (draft) [tip ] add new_3_c
- 4:ca819180edb9 (draft *obsolete*) [ ] add new_2_c [rewritten as 5:5601fb93a350]
- 3:cdbce2fbb163 (draft *obsolete*) [ ] add new_c [rewritten as 4:ca819180edb9]
- 2:245bde4270cd (draft *obsolete*) [ ] add original_c [rewritten as 3:cdbce2fbb163]
-
check that summary does not report them
@@ -193,7 +189,7 @@
add new_3_c
branch: default
commit: (clean)
- update: 3 new changesets, 4 branch heads (merge)
+ update: (current)
phases: 6 draft
remote: 3 outgoing
diff --git a/tests/test-obsmarker-template.t b/tests/test-obsmarker-template.t
--- a/tests/test-obsmarker-template.t
+++ b/tests/test-obsmarker-template.t
@@ -1762,7 +1762,7 @@
2 new obsolescence markers
obsoleted 1 changesets
new changesets 7a230b46bf61 (1 drafts)
- (run 'hg heads' to see heads, 'hg merge' to merge)
+ (run 'hg heads' to see heads)
$ hg log --hidden -G
o changeset: 2:7a230b46bf61
| tag: tip
diff --git a/tests/test-branch-change.t b/tests/test-branch-change.t
--- a/tests/test-branch-change.t
+++ b/tests/test-branch-change.t
@@ -185,6 +185,7 @@
changed branch on 2 changesets
updating the branch cache
invalid branch cache (served): tip differs
+ invalid branch cache (served.hidden): tip differs
$ hg glog -r '(.^)::'
@ 9:de1404b45a69 Added e
@@ -211,7 +212,7 @@
secret 11:38a9b2d53f98
foo 7:8a4729a5e2b8
wat 9:de1404b45a69 (inactive)
- default 2:28ad74487de9 (inactive)
+ default 1:29becc82797a (inactive)
$ hg branch
secret
diff --git a/mercurial/scmutil.py b/mercurial/scmutil.py
--- a/mercurial/scmutil.py
+++ b/mercurial/scmutil.py
@@ -349,7 +349,7 @@
self._newfiles.add(f)
-def filteredhash(repo, maxrev):
+def filteredhash(repo, maxrev, needobsolete=False):
"""build hash of filtered revisions in the current repoview.
Multiple caches perform up-to-date validation by checking that the
@@ -358,22 +358,33 @@
of revisions in the view may change without the repository tiprev and
tipnode changing.
- This function hashes all the revs filtered from the view and returns
- that SHA-1 digest.
+ This function hashes all the revs filtered from the view (and, optionally,
+ all obsolete revs) up to maxrev and returns that SHA-1 digest.
"""
cl = repo.changelog
- if not cl.filteredrevs:
- return None
- key = cl._filteredrevs_hashcache.get(maxrev)
- if not key:
- revs = sorted(r for r in cl.filteredrevs if r <= maxrev)
+ if needobsolete:
+ obsrevs = obsolete.getrevs(repo, b'obsolete')
+ if not cl.filteredrevs and not obsrevs:
+ return None
+ # TODO: obsrevs should be a frozenset, but right now obsolete.getrevs()
+ # may return a set, which is not a hashable type.
+ key = (maxrev, hash(cl.filteredrevs), hash(frozenset(obsrevs)))
+ else:
+ if not cl.filteredrevs:
+ return None
+ key = maxrev
+ obsrevs = frozenset()
+
+ result = cl._filteredrevs_hashcache.get(key)
+ if not result:
+ revs = sorted(r for r in cl.filteredrevs | obsrevs if r <= maxrev)
if revs:
s = hashutil.sha1()
for rev in revs:
s.update(b'%d;' % rev)
- key = s.digest()
- cl._filteredrevs_hashcache[maxrev] = key
- return key
+ result = s.digest()
+ cl._filteredrevs_hashcache[key] = result
+ return result
def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
diff --git a/mercurial/destutil.py b/mercurial/destutil.py
--- a/mercurial/destutil.py
+++ b/mercurial/destutil.py
@@ -79,6 +79,9 @@
node = repo.revs(b'max(%ln)', successors).first()
if bookmarks.isactivewdirparent(repo):
movemark = repo[b'.'].node()
+ else:
+ # TODO: copy hg prune logic
+ node = repo[b'.'].node()
return node, movemark, None
diff --git a/mercurial/branchmap.py b/mercurial/branchmap.py
--- a/mercurial/branchmap.py
+++ b/mercurial/branchmap.py
@@ -17,6 +17,7 @@
from . import (
encoding,
error,
+ obsolete,
pycompat,
scmutil,
util,
@@ -184,7 +185,7 @@
The first line is used to check if the cache is still valid. If the
branch cache is for a filtered repo view, an optional third hash is
- included that hashes the hashes of all filtered revisions.
+ included that hashes the hashes of all filtered and obsolete revisions.
The open/closed state is represented by a single letter 'o' or 'c'.
This field can be used to avoid changelog reads when determining if a
@@ -357,7 +358,8 @@
- True when cache is up to date or a subset of current repo."""
try:
return (self.tipnode == repo.changelog.node(self.tiprev)) and (
- self.filteredhash == scmutil.filteredhash(repo, self.tiprev)
+ self.filteredhash
+ == scmutil.filteredhash(repo, self.tiprev, needobsolete=True)
)
except IndexError:
return False
@@ -478,6 +480,9 @@
# use the faster unfiltered parent accessor.
parentrevs = repo.unfiltered().changelog.parentrevs
+ # Faster than using ctx.obsolete()
+ obsrevs = obsolete.getrevs(repo, b'obsolete')
+
for branch, newheadrevs in pycompat.iteritems(newbranches):
# For every branch, compute the new branchheads.
# A branchhead is a revision such that no descendant is on
@@ -518,6 +523,11 @@
bheadset = {cl.rev(node) for node in bheads}
uncertain = set()
for newrev in sorted(newheadrevs):
+ if newrev in obsrevs:
+ # We ignore obsolete changesets as they shouldn't be
+ # considered heads.
+ continue
+
if not bheadset:
bheadset.add(newrev)
continue
@@ -525,13 +535,22 @@
parents = [p for p in parentrevs(newrev) if p != nullrev]
samebranch = set()
otherbranch = set()
+ obsparents = set()
for p in parents:
- if p in bheadset or getbranchinfo(p)[0] == branch:
+ if p in obsrevs:
+ # We ignored this obsolete changeset earlier, but now
+ # that it has non-ignored children, we need to make
+ # sure their ancestors are not considered heads. To
+ # achieve that, we will simply treat this obsolete
+ # changeset as a parent from other branch.
+ obsparents.add(p)
+ elif p in bheadset or getbranchinfo(p)[0] == branch:
samebranch.add(p)
else:
otherbranch.add(p)
- if otherbranch and not (len(bheadset) == len(samebranch) == 1):
+ if not (len(bheadset) == len(samebranch) == 1):
uncertain.update(otherbranch)
+ uncertain.update(obsparents)
bheadset.difference_update(samebranch)
bheadset.add(newrev)
@@ -540,11 +559,12 @@
topoheads = set(cl.headrevs())
if bheadset - topoheads:
floorrev = min(bheadset)
- ancestors = set(cl.ancestors(newheadrevs, floorrev))
- bheadset -= ancestors
+ if floorrev <= max(uncertain):
+ ancestors = set(cl.ancestors(uncertain, floorrev))
+ bheadset -= ancestors
bheadrevs = sorted(bheadset)
self[branch] = [cl.node(rev) for rev in bheadrevs]
- tiprev = bheadrevs[-1]
+ tiprev = max(newheadrevs)
if tiprev > ntiprev:
ntiprev = tiprev
@@ -553,15 +573,24 @@
self.tipnode = cl.node(ntiprev)
if not self.validfor(repo):
- # cache key are not valid anymore
+ # old cache key is now invalid for the repo, but we've just updated
+ # the cache and we assume it's valid, so let's make the cache key
+ # valid as well by recomputing it from the cached data
self.tipnode = repo.nullid
self.tiprev = nullrev
for heads in self.iterheads():
+ if not heads:
+ # all revisions on a branch are obsolete
+ continue
+ # note: tiprev is not necessarily the tip revision of repo,
+ # because the tip could be obsolete (i.e. not a head)
tiprev = max(cl.rev(node) for node in heads)
if tiprev > self.tiprev:
self.tipnode = cl.node(tiprev)
self.tiprev = tiprev
- self.filteredhash = scmutil.filteredhash(repo, self.tiprev)
+ self.filteredhash = scmutil.filteredhash(
+ repo, self.tiprev, needobsolete=True
+ )
duration = util.timer() - starttime
repo.ui.log(
To: av6, #hg-reviewers, Alphare
Cc: marmoute, mercurial-patches
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-patches/attachments/20220203/f7641675/attachment-0002.html>
More information about the Mercurial-patches
mailing list