<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Mar 24, 2015 at 9:46 PM, Gregory Szorc <span dir="ltr"><<a href="mailto:gregory.szorc@gmail.com" target="_blank">gregory.szorc@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"># HG changeset patch<br>
# User Gregory Szorc <<a href="mailto:gregory.szorc@gmail.com">gregory.szorc@gmail.com</a>><br>
# Date 1427258716 25200<br>
#      Tue Mar 24 21:45:16 2015 -0700<br>
# Node ID 314d22b3f6418885c3c395f57ce2b2a95e69b3c5<br>
# Parent  30988005a918c28154c77e98160bd6ea3a3b16a1<br>
tags: make tags cache compatible with future split of filenode cache<br>
<br>
Pierre-Yves has plans to establish separate, per-filter tags cache<br>
files.<br>
<br>
I have plans to establish a separate, shared cache file for .hgtags<br>
filenode data so we don't have redundant lookups of potentially<br>
expensive filenode data.<br>
<br>
This patch adds future-proofing to tags cache reading so per-filter<br>
tags cache can land in a way that doesn't make the transition to a<br>
separate .hgtags filenode cache painful.<br>
<br>
With this patch applied, clients are able to recognize the planned<br>
future format of the tags cache with external .hgtags filenode data.<br>
When support for that cache lands, clients can read existing .hgtags<br>
filenode data from the prior tags cache files and then write out the<br>
new file format without having to recompute .hgtags filenodes. For<br>
users of large repositories, this will potentially save minutes of<br>
wall time.<br>
<br>
Without this patch, we would have to create a new version of the tags<br>
cache files when rolling out the separate .hgtags filenode cache. This<br>
is because the file formats would need to be different. This is<br>
because we want the tags cache to record the tip rev and node for<br>
quick cache freshness checks. We can't simply add this data to an<br>
existing cache file because if an old client came along, it would<br>
choke when reading this data (the format would have to be different<br>
so it wouldn't be confused for a .hgtags filenode mapping of a single<br>
head).<br>
<br>
The assumption here is that per-filter tags caches will land shortly<br>
after this patch. If an old client talks to a future repository, that<br>
client is either going to:<br>
<br>
a) read the old .hg/cache/tags file<br>
b) read the per-filter tags cache<br>
<br>
The old/existing tags cache will *never* have external .hgtags<br>
filenodes, so it will always be able to read that file. (It will likely<br>
have to process a bunch of new heads, but that's the price for using an<br>
old client.)<br>
<br>
The new, per-filter tags cache *may* have external .hgtags filenodes.<br>
But, since the code for recognizing the declaration of external .hgtags<br>
(this patch) exists for all clients that support per-filter tags cache<br>
reading (which will land after this patch), all clients are guaranteed<br>
to parse per-filter tags cache files with or without external .hgtags<br>
filenodes. Thus, moving data to an external .hgtags filenodes cache<br>
can occur without backwards compatibility concerns and without<br>
potentially expensive recomputation of .hgtags filenodes values.<br>
<br>
diff --git a/mercurial/tags.py b/mercurial/tags.py<br>
--- a/mercurial/tags.py<br>
+++ b/mercurial/tags.py<br>
@@ -27,8 +27,16 @@ import time<br>
 # The first part consists of lines of the form:<br>
 #<br>
 #   <headrev> <headnode> [<hgtagsnode>]<br>
 #<br>
+# *OR* a line of the form:<br>
+#<br>
+#   "external" <tiprev> <tipnode><br>
+#<br>
+# The first form is the historical method of storing the .hgtags filenode<br>
+# mapping inline. The second form (which is reserved for future use) uses<br>
+# a separate file for this data.<br>
+#<br>
 # <headrev> is an integer revision and <headnode> is a 40 character hex<br>
 # node for that changeset. These redundantly identify a repository<br>
 # head from the time the cache was written.<br>
 #<br>
@@ -262,8 +270,13 @@ def _readtagcache(ui, repo):<br>
         try:<br>
             for line in cachelines:<br>
                 if line == "\n":<br>
                     break<br>
+<br>
+                # Future version of cache encountered. Do nothing yet.<br>
+                if line.startswith("external "):<br>
+                    continue<br>
+<br>
                 line = line.split()<br>
                 cacherevs.append(int(line[0]))<br>
                 headnode = bin(line[1])<br>
                 cacheheads.append(headnode)<br>
diff --git a/tests/test-tags.t b/tests/test-tags.t<br>
--- a/tests/test-tags.t<br>
+++ b/tests/test-tags.t<br>
@@ -224,8 +224,33 @@ Dump cache:<br>
   bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar<br>
   bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar<br>
   78391a272241d70354aa14c874552cad6b51bb42 bar<br>
<br>
+External .hgtags filenode cache marker is handled<br>
+<br>
+  $ cat > .hg/cache/tags << EOF<br>
+  > external 4 0c192d7d5e6b78a714de54a2e9627952a877e25a<br>
+  ><br>
+  > bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar<br>
+  > bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar<br>
+  > 78391a272241d70354aa14c874552cad6b51bb42 bar<br>
+  > EOF<br>
+<br>
+  $ hg tags<br>
+  tip                                4:0c192d7d5e6b<br>
+  bar                                1:78391a272241<br>
+<br>
+We should get an old style cache again<br>
+<br>
+  $ cat .hg/cache/tags<br>
+  4 0c192d7d5e6b78a714de54a2e9627952a877e25a 0c04f2a8af31de17fab7422878ee5a2dadbc943d<br>
+  3 6fa450212aeb2a21ed616a54aea39a4a27894cd7 7d3b718c964ef37b89e550ebdafd5789e76ce1b0<br>
+  2 7a94127795a33c10a370c93f731fd9fea0b79af6 0c04f2a8af31de17fab7422878ee5a2dadbc943d<br>
+<br>
+  bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar<br>
+  bbd179dfa0a71671c253b3ae0aa1513b60d199fa bar<br>
+  78391a272241d70354aa14c874552cad6b51bb42 bar<br>
+<br>
 Test tag removal:<br>
<br>
   $ hg tag --remove bar     # rev 5<br>
   $ hg tip -vp<br>
</blockquote></div><br>Please disregard this patch: I've got a new series consolidating Pierre-Yves's and my work. This patch will be rolled into that one.<br></div></div>