##// END OF EJS Templates
setdiscovery: don't call "heads" wire command when heads specified...
setdiscovery: don't call "heads" wire command when heads specified Our custom server has too many heads to announce (one per code review, plus a public head), but it still lets the user request one of them by doing hg pull -r <some expression> After the client has resolved the expression to a set of nodeids by calling the "lookup" wire command, it will start the discovery phase. Before this patch, that doesn't take the requested heads into account and unconditionally calls the server's "heads" command to find all its heads. One consequence of that the "all remote heads known locally" case triggers if the client already had the public head and the user will see a "no changes found" message that's unrelated to the head they requested. That message confused me for a while. More imporantly, it also means that pullop.cgresult incorrectly (given our arguably misbehaving server) gets set to 0 (no changesets added), which confused some of our extensions. This patch makes it so the client skips the "heads" command if the user requested specific revisions. Since the "heads" command is normally batched with the first "known" command and calculating the list of heads is probably cheap, I don't expect much improvement in speed from this. Differential Revision: https://phab.mercurial-scm.org/D1962

File last commit:

r35583:07769a04 default
r35867:5cfdf613 default
Show More
filelog.py
139 lines | 4.3 KiB | text/x-python | PythonLexer
mpm@selenic.com
Break apart hg.py...
r1089 # filelog.py - file history class for mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
mpm@selenic.com
Break apart hg.py...
r1089 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
mpm@selenic.com
Break apart hg.py...
r1089
Gregory Szorc
filelog: use absolute_import
r25948 from __future__ import absolute_import
import re
import struct
from . import (
error,
mdiff,
revlog,
)
mpm@selenic.com
Break apart hg.py...
r1089
Sune Foldager
filelog: extract metadata parsing and packing...
r14074 _mdre = re.compile('\1\n')
Mike Edgar
filelog: make parsemeta a public module function, to be used by censor module
r22421 def parsemeta(text):
Jun Wu
filelog: fix parsemeta docstring...
r32124 """return (metadatadict, metadatasize)"""
Sune Foldager
filelog: extract metadata parsing and packing...
r14074 # text can be buffer, so we can't use .startswith or .index
if text[:2] != '\1\n':
Mike Edgar
filelog: parsemeta stops returning unused key list...
r22422 return None, None
Sune Foldager
filelog: extract metadata parsing and packing...
r14074 s = _mdre.search(text, 2).start()
mtext = text[2:s]
meta = {}
for l in mtext.splitlines():
Matt Mackall
filelog: move metadata parsing to a helper function
r13240 k, v = l.split(": ", 1)
Sune Foldager
filelog: extract metadata parsing and packing...
r14074 meta[k] = v
Mike Edgar
filelog: parsemeta stops returning unused key list...
r22422 return meta, (s + 2)
Sune Foldager
filelog: extract metadata parsing and packing...
r14074
Mike Edgar
filelog: make packmeta a public module function, to be used by censor
r22420 def packmeta(meta, text):
Augie Fackler
python3: replace sorted(<dict>.iterkeys()) with sorted(<dict>)
r34025 keys = sorted(meta)
Mike Edgar
filelog: make packmeta a public module function, to be used by censor
r22420 metatext = "".join("%s: %s\n" % (k, meta[k]) for k in keys)
return "\1\n%s\1\n%s" % (metatext, text)
Matt Mackall
filelog: move metadata parsing to a helper function
r13240
Mike Edgar
filelog: raise CensoredNodeError when hash checks fail with censor metadata...
r22596 def _censoredtext(text):
m, offs = parsemeta(text)
Mike Edgar
filelog: allow censored files to contain padding data...
r24117 return m and "censored" in m
Mike Edgar
filelog: raise CensoredNodeError when hash checks fail with censor metadata...
r22596
Matt Mackall
revlog: kill from-style imports...
r7634 class filelog(revlog.revlog):
Matt Mackall
revlog: simplify revlog version handling...
r4258 def __init__(self, opener, path):
Durham Goode
filelog: use super() for calling base functions...
r19148 super(filelog, self).__init__(opener,
Benoit Boissinot
filelog encoding: move the encoding/decoding into store...
r8531 "/".join(("data", path + ".i")))
Matt Harbison
filelog: add the ability to report the user facing name...
r35583 # full name of the user visible file, relative to the repository root
self.filename = path
mpm@selenic.com
Break apart hg.py...
r1089
def read(self, node):
t = self.revision(node)
if not t.startswith('\1\n'):
return t
Benoit Boissinot
use __contains__, index or split instead of str.find...
r2579 s = t.index('\1\n', 2)
Matt Mackall
many, many trivial check-code fixups
r10282 return t[s + 2:]
mpm@selenic.com
Break apart hg.py...
r1089
def add(self, text, meta, transaction, link, p1=None, p2=None):
if meta or text.startswith('\1\n'):
Mike Edgar
filelog: make packmeta a public module function, to be used by censor
r22420 text = packmeta(meta, text)
mpm@selenic.com
Break apart hg.py...
r1089 return self.addrevision(text, transaction, link, p1, p2)
mpm@selenic.com
Add some rename debugging support
r1116 def renamed(self, node):
Matt Mackall
revlog: kill from-style imports...
r7634 if self.parents(node)[0] != revlog.nullid:
mpm@selenic.com
Add some rename debugging support
r1116 return False
Matt Mackall
filelog: move metadata parsing to a helper function
r13240 t = self.revision(node)
Mike Edgar
filelog: make parsemeta a public module function, to be used by censor module
r22421 m = parsemeta(t)[0]
Christian Ebert
Prefer i in d over d.has_key(i)
r5915 if m and "copy" in m:
Matt Mackall
revlog: kill from-style imports...
r7634 return (m["copy"], revlog.bin(m["copyrev"]))
mpm@selenic.com
Add some rename debugging support
r1116 return False
Matt Mackall
merge: use file size stored in revlog index...
r2898 def size(self, rev):
"""return the size of a given revision"""
# for revisions with renames, we have to go the slow way
node = self.node(rev)
if self.renamed(node):
return len(self.read(node))
Mike Edgar
revlog: add "iscensored()" to revlog public API...
r24118 if self.iscensored(rev):
Mike Edgar
filelog: censored files compare against empty data, have 0 size...
r22597 return 0
Matt Mackall
merge: use file size stored in revlog index...
r2898
Nicolas Dumazet
filelog: test behaviour for data starting with "\1\n"...
r11540 # XXX if self.read(node).startswith("\1\n"), this returns (size+4)
Durham Goode
filelog: use super() for calling base functions...
r19148 return super(filelog, self).size(rev)
Matt Mackall
merge: use file size stored in revlog index...
r2898
Matt Mackall
filelog: add hash-based comparisons...
r2887 def cmp(self, node, text):
Nicolas Dumazet
cmp: document the fact that we return True if content is different...
r11539 """compare text with a given file revision
returns True if text is different than what is stored.
"""
Matt Mackall
filelog: add hash-based comparisons...
r2887
Nicolas Dumazet
filelog: cmp: don't read data if hashes are identical (issue2273)...
r11541 t = text
if text.startswith('\1\n'):
t = '\1\n\1\n' + text
Durham Goode
filelog: use super() for calling base functions...
r19148 samehashes = not super(filelog, self).cmp(node, t)
Nicolas Dumazet
filelog: cmp: don't read data if hashes are identical (issue2273)...
r11541 if samehashes:
return False
Mike Edgar
filelog: censored files compare against empty data, have 0 size...
r22597 # censored files compare against the empty file
Mike Edgar
revlog: add "iscensored()" to revlog public API...
r24118 if self.iscensored(self.rev(node)):
Mike Edgar
filelog: censored files compare against empty data, have 0 size...
r22597 return text != ''
Nicolas Dumazet
filelog: cmp: don't read data if hashes are identical (issue2273)...
r11541 # renaming a file produces a different hash, even if the data
# remains unchanged. Check if it's the case (slow):
if self.renamed(node):
Matt Mackall
filelog: add hash-based comparisons...
r2887 t2 = self.read(node)
Matt Mackall
filelog.cmp: return 0 for equality...
r2895 return t2 != text
Matt Mackall
filelog: add hash-based comparisons...
r2887
Nicolas Dumazet
filelog: cmp: don't read data if hashes are identical (issue2273)...
r11541 return True
Sune Foldager
filelog: add file function to open other filelogs
r14287
Remi Chaintron
revlog: merge hash checking subfunctions...
r30584 def checkhash(self, text, node, p1=None, p2=None, rev=None):
Mike Edgar
filelog: raise CensoredNodeError when hash checks fail with censor metadata...
r22596 try:
Remi Chaintron
revlog: merge hash checking subfunctions...
r30584 super(filelog, self).checkhash(text, node, p1=p1, p2=p2, rev=rev)
Mike Edgar
filelog: raise CensoredNodeError when hash checks fail with censor metadata...
r22596 except error.RevlogError:
if _censoredtext(text):
Mike Edgar
changegroup: emit full-replacement deltas if either revision is censored...
r24190 raise error.CensoredNodeError(self.indexfile, node, text)
Mike Edgar
filelog: raise CensoredNodeError when hash checks fail with censor metadata...
r22596 raise
Mike Edgar
revlog: add "iscensored()" to revlog public API...
r24118 def iscensored(self, rev):
Mike Edgar
filelog: censored files compare against empty data, have 0 size...
r22597 """Check if a file revision is censored."""
Mike Edgar
filelog: use censored revlog flag bit to quickly check if a node is censored
r23858 return self.flags(rev) & revlog.REVIDX_ISCENSORED
Mike Edgar
revlog: addgroup checks if incoming deltas add censored revs, sets flag bit...
r24255
def _peek_iscensored(self, baserev, delta, flush):
"""Quickly check if a delta produces a censored revision."""
# Fragile heuristic: unless new file meta keys are added alphabetically
# preceding "censored", all censored revisions are prefixed by
# "\1\ncensored:". A delta producing such a censored revision must be a
# full-replacement delta, so we inspect the first and only patch in the
# delta for this prefix.
hlen = struct.calcsize(">lll")
if len(delta) <= hlen:
return False
oldlen = self.rawsize(baserev)
newlen = len(delta) - hlen
if delta[:hlen] != mdiff.replacediffheader(oldlen, newlen):
return False
add = "\1\ncensored:"
addlen = len(add)
return newlen >= addlen and delta[hlen:hlen + addlen] == add