mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 06:47:41 +03:00
manifest: use Rust Tree Manifest by default
Summary: The Rust Manifest is deployed practically everywhere. Removing the C++ code from being compiled in Mercurial along with all of the cstore extension. Reviewed By: quark-zju Differential Revision: D19543248 fbshipit-source-id: d632e171175e6866563c1aa0808a099b67bd937d
This commit is contained in:
parent
f5280b75e9
commit
2dc14cf9a6
@ -1117,9 +1117,9 @@ def _getmanifest(op, rev):
|
||||
else:
|
||||
store = repo.manifestlog.datastore
|
||||
# pyre-fixme[21]: Could not find `edenscmnative`.
|
||||
from edenscmnative import cstore
|
||||
from bindings import manifest
|
||||
|
||||
m = cstore.treemanifest(store, rev.manifestnode())
|
||||
m = manifest.treemanifest(store, rev.manifestnode())
|
||||
if store.getmissing([("", rev.manifestnode())]):
|
||||
raise error.Abort(
|
||||
_(
|
||||
|
@ -135,14 +135,6 @@ trees for new draft roots added to the repository.
|
||||
[treemanifest]
|
||||
prefetchdraftparents = True
|
||||
|
||||
`treemanifest.rustmanifest` causes treemanifest to use the Rust
|
||||
implementation rather than the C++ one.
|
||||
|
||||
::
|
||||
|
||||
[treemanifest]
|
||||
rustmanifest = True
|
||||
|
||||
`treemanifest.bfsprefetch` causes the client to perform a BFS over the
|
||||
tree to be prefetched and manually request all missing nodes from the
|
||||
server, rather than relying on the server to perform this computation.
|
||||
@ -201,9 +193,6 @@ from edenscm.mercurial.i18n import _, _n
|
||||
from edenscm.mercurial.node import bin, hex, nullid, short
|
||||
from edenscm.mercurial.pycompat import range
|
||||
|
||||
# pyre-fixme[21]: Could not find `edenscmnative`.
|
||||
from edenscmnative import cstore
|
||||
|
||||
from ..extutil import flock
|
||||
from ..remotefilelog import (
|
||||
cmdtable as remotefilelogcmdtable,
|
||||
@ -242,9 +231,6 @@ configitem("treemanifest", "stickypushpath", default=True)
|
||||
configitem("treemanifest", "treeonly", default=True)
|
||||
configitem("treemanifest", "usehttp", default=False)
|
||||
configitem("treemanifest", "prefetchdraftparents", default=True)
|
||||
configitem("treemanifest", "rustmanifest", default=False)
|
||||
|
||||
nativemanifesttype = (cstore.treemanifest, rustmanifest.treemanifest)
|
||||
|
||||
PACK_CATEGORY = "manifests"
|
||||
|
||||
@ -1079,18 +1065,11 @@ def _usehttp(ui):
|
||||
return edenapi.enabled(ui) and ui.configbool("treemanifest", "usehttp")
|
||||
|
||||
|
||||
def _userustmanifest(manifestlog):
|
||||
return manifestlog.ui.configbool("treemanifest", "rustmanifest")
|
||||
|
||||
|
||||
def _buildtree(manifestlog, node=None):
|
||||
# this code seems to belong in manifestlog but I have no idea how
|
||||
# manifestlog objects work
|
||||
store = manifestlog.datastore
|
||||
if _userustmanifest(manifestlog):
|
||||
initfn = rustmanifest.treemanifest
|
||||
else:
|
||||
initfn = cstore.treemanifest
|
||||
initfn = rustmanifest.treemanifest
|
||||
if node is not None and node != nullid:
|
||||
return initfn(store, node)
|
||||
else:
|
||||
@ -1504,10 +1483,7 @@ def _converttotree(tr, mfl, tmfl, mfctx, linkrev=None, torevlog=False):
|
||||
_("unable to find tree parent nodes %s %s") % (hex(p1node), hex(p2node))
|
||||
)
|
||||
else:
|
||||
if _userustmanifest(mfl):
|
||||
parenttree = rustmanifest.treemanifest(tmfl.datastore)
|
||||
else:
|
||||
parenttree = cstore.treemanifest(tmfl.datastore)
|
||||
parenttree = rustmanifest.treemanifest(tmfl.datastore)
|
||||
|
||||
added, removed = _getflatdiff(mfl, mfctx)
|
||||
newtree = _getnewtree(parenttree, added, removed)
|
||||
@ -2054,11 +2030,7 @@ def _registerbundle2parts():
|
||||
|
||||
for node in rootnodes:
|
||||
p1, p2, linknode, copyfrom = wirepackstore.getnodeinfo("", node)
|
||||
userustmanifest = mfl.ui.configbool("treemanifest", "rustmanifest")
|
||||
if userustmanifest:
|
||||
newtree = rustmanifest.treemanifest(datastore, node)
|
||||
else:
|
||||
newtree = cstore.treemanifest(datastore, node)
|
||||
newtree = rustmanifest.treemanifest(datastore, node)
|
||||
|
||||
mfl.add(mfl.ui, newtree, p1, p2, linknode, tr=tr)
|
||||
return
|
||||
@ -2483,16 +2455,8 @@ def _generatepackstream(
|
||||
|
||||
# Only use the first two base trees, since the current tree
|
||||
# implementation cannot handle more yet.
|
||||
userustmanifest = repo.ui.configbool("treemanifest", "rustmanifest")
|
||||
if userustmanifest:
|
||||
basenodes = [mybasenode for (_path, mybasenode) in basetrees]
|
||||
subtrees = rustmanifest.subdirdiff(
|
||||
datastore, rootdir, node, basenodes, depth
|
||||
)
|
||||
else:
|
||||
subtrees = cstore.treemanifest.walksubdirtrees(
|
||||
(rootdir, node), datastore, comparetrees=basetrees[:2], depth=depth
|
||||
)
|
||||
basenodes = [mybasenode for (_path, mybasenode) in basetrees]
|
||||
subtrees = rustmanifest.subdirdiff(datastore, rootdir, node, basenodes, depth)
|
||||
rootlinknode = None
|
||||
if linknodefixup is not None:
|
||||
validlinknodes, linknodemap = linknodefixup
|
||||
@ -2663,7 +2627,7 @@ class ondemandtreedatastore(generatingdatastore):
|
||||
def _debugcmdfindtreemanifest(orig, ctx):
|
||||
manifest = ctx.manifest()
|
||||
# Check if the manifest we have is a treemanifest.
|
||||
if isinstance(manifest, nativemanifesttype):
|
||||
if isinstance(manifest, rustmanifest.treemanifest):
|
||||
return manifest
|
||||
try:
|
||||
# Look up the treemanifest in the treemanifestlog. There might not be
|
||||
|
@ -1606,42 +1606,6 @@ extmodules = [
|
||||
sources=["edenscm/hgext/extlib/pywatchman/bser.c"],
|
||||
include_dirs=include_dirs,
|
||||
),
|
||||
Extension(
|
||||
"edenscmnative.cstore",
|
||||
sources=[
|
||||
"edenscm/hgext/extlib/cstore/datapackstore.cpp",
|
||||
"edenscm/hgext/extlib/cstore/deltachain.cpp",
|
||||
"edenscm/hgext/extlib/cstore/py-cstore.cpp",
|
||||
"edenscm/hgext/extlib/cstore/pythonutil.cpp",
|
||||
"edenscm/hgext/extlib/cstore/pythondatastore.cpp",
|
||||
"edenscm/hgext/extlib/cstore/uniondatapackstore.cpp",
|
||||
"edenscm/hgext/extlib/ctreemanifest/manifest.cpp",
|
||||
"edenscm/hgext/extlib/ctreemanifest/manifest_entry.cpp",
|
||||
"edenscm/hgext/extlib/ctreemanifest/manifest_fetcher.cpp",
|
||||
"edenscm/hgext/extlib/ctreemanifest/manifest_ptr.cpp",
|
||||
"edenscm/hgext/extlib/ctreemanifest/treemanifest.cpp",
|
||||
],
|
||||
depends=[
|
||||
"edenscm/hgext/extlib/cstore/datapackstore.h",
|
||||
"edenscm/hgext/extlib/cstore/datastore.h",
|
||||
"edenscm/hgext/extlib/cstore/deltachain.h",
|
||||
"edenscm/hgext/extlib/cstore/key.h",
|
||||
"edenscm/hgext/extlib/cstore/match.h",
|
||||
"edenscm/hgext/extlib/cstore/py-datapackstore.h",
|
||||
"edenscm/hgext/extlib/cstore/py-structs.h",
|
||||
"edenscm/hgext/extlib/cstore/py-treemanifest.h",
|
||||
"edenscm/hgext/extlib/cstore/pythondatastore.h",
|
||||
"edenscm/hgext/extlib/cstore/pythonkeyiterator.h",
|
||||
"edenscm/hgext/extlib/cstore/pythonutil.h",
|
||||
"edenscm/hgext/extlib/cstore/store.h",
|
||||
"edenscm/hgext/extlib/cstore/uniondatapackstore.h",
|
||||
"edenscm/hgext/extlib/cstore/util.h",
|
||||
],
|
||||
include_dirs=include_dirs,
|
||||
library_dirs=["build/" + distutils_dir_name("lib")] + library_dirs,
|
||||
libraries=["datapack", "lz4", "mpatch", SHA1_LIBRARY],
|
||||
extra_compile_args=filter(None, [STDCPP0X, WALL] + cflags),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
|
@ -32,5 +32,3 @@
|
||||
> EOF
|
||||
tests/infinitepush/library.sh is not an executable but does have #!
|
||||
tests/stresstest-atomicreplace.py is not an executable but does have #!
|
||||
tests/test-fb-hgext-cstore-treemanifest.py is a Python script but does not have Python interpreter specified
|
||||
tests/test-fb-hgext-cstore-uniondatapackstore.py is a Python script but does not have Python interpreter specified
|
||||
|
@ -1,775 +0,0 @@
|
||||
#!/usr/bin/env python2.7
|
||||
from __future__ import absolute_import
|
||||
|
||||
import random
|
||||
import unittest
|
||||
|
||||
import silenttestrunner
|
||||
from edenscm.mercurial import manifest, match as matchmod
|
||||
from edenscm.mercurial.node import hex, nullid
|
||||
from edenscmnative import cstore
|
||||
|
||||
|
||||
class FakeDataStore(object):
|
||||
def __init__(self):
|
||||
self._data = {}
|
||||
|
||||
def get(self, path, node):
|
||||
return self._data[(path, node)]
|
||||
|
||||
def add(self, path, node, deltabase, value):
|
||||
self._data[(path, node)] = value
|
||||
|
||||
|
||||
class FakeHistoryStore(object):
|
||||
def __init__(self):
|
||||
self._data = {}
|
||||
|
||||
def getancestors(self, queryname, querynode):
|
||||
results = {}
|
||||
queue = [(queryname, querynode)]
|
||||
while queue:
|
||||
name, node = queue.pop()
|
||||
p1, p2, linknode, copyfrom = self._data[(name, node)]
|
||||
results[node] = (p1, p2, linknode, copyfrom)
|
||||
if p1 != nullid:
|
||||
queue.append((copyfrom or name, p1))
|
||||
if p2 != nullid:
|
||||
queue.append((name, p2))
|
||||
|
||||
return results
|
||||
|
||||
def add(self, path, node, p1, p2, linknode, copyfrom):
|
||||
self._data[(path, node)] = (p1, p2, linknode, copyfrom)
|
||||
|
||||
|
||||
def getvalidflag():
|
||||
# t is reserved as a directory entry, so don't go around setting that as the
|
||||
# flag.
|
||||
while True:
|
||||
r = random.randint(0, 255)
|
||||
if r != ord("t"):
|
||||
return chr(r)
|
||||
|
||||
|
||||
def hashflags(requireflag=False):
|
||||
h = "".join([chr(random.randint(0, 255)) for x in range(20)])
|
||||
if random.randint(0, 1) == 0 and requireflag is False:
|
||||
f = ""
|
||||
else:
|
||||
f = getvalidflag()
|
||||
return h, f
|
||||
|
||||
|
||||
class ctreemanifesttests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
random.seed(0)
|
||||
|
||||
def testInitialization(self):
|
||||
cstore.treemanifest(FakeDataStore())
|
||||
|
||||
def testEmptyFlag(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
h, f = hashflags()[0], ""
|
||||
a.set("abc", h, f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
def testNullFlag(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
h, f = hashflags()[0], "\0"
|
||||
a.set("abc", h, f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
def testSetGet(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
h, f = hashflags()
|
||||
a.set("abc", h, f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
def testUpdate(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
h, f = hashflags()
|
||||
a.set("abc", h, f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
h, f = hashflags()
|
||||
a.set("abc", h, f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
def testDirAfterFile(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
file_h, file_f = hashflags()
|
||||
a.set("abc", file_h, file_f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals((file_h, file_f), out)
|
||||
|
||||
dir_h, dir_f = hashflags()
|
||||
a.set("abc/def", dir_h, dir_f)
|
||||
out = a.find("abc/def")
|
||||
self.assertEquals((dir_h, dir_f), out)
|
||||
|
||||
out = a.find("abc")
|
||||
self.assertEquals((file_h, file_f), out)
|
||||
|
||||
def testFileAfterDir(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
dir_h, dir_f = hashflags()
|
||||
a.set("abc/def", dir_h, dir_f)
|
||||
out = a.find("abc/def")
|
||||
self.assertEquals((dir_h, dir_f), out)
|
||||
|
||||
file_h, file_f = hashflags()
|
||||
a.set("abc", file_h, file_f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals((file_h, file_f), out)
|
||||
|
||||
out = a.find("abc/def")
|
||||
self.assertEquals((dir_h, dir_f), out)
|
||||
|
||||
def testDeeplyNested(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
h, f = hashflags()
|
||||
a.set("abc/def/ghi/jkl", h, f)
|
||||
out = a.find("abc/def/ghi/jkl")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
h, f = hashflags()
|
||||
a.set("abc/def/ghi/jkl2", h, f)
|
||||
out = a.find("abc/def/ghi/jkl2")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
def testBushyTrees(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
nodes = {}
|
||||
for ix in range(111):
|
||||
h, f = hashflags()
|
||||
nodes["abc/def/ghi/jkl%d" % ix] = (h, f)
|
||||
|
||||
for fp, (h, f) in nodes.items():
|
||||
a.set(fp, h, f)
|
||||
|
||||
for fp, (h, f) in nodes.items():
|
||||
out = a.find(fp)
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
def testFlagChanges(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
|
||||
# go from no flags to with flags, back to no flags.
|
||||
h, f = hashflags(requireflag=True)
|
||||
self.assertEquals(len(f), 1)
|
||||
|
||||
a.set("abc", h, "")
|
||||
out = a.find("abc")
|
||||
self.assertEquals(h, out[0])
|
||||
self.assertEquals("", out[1])
|
||||
|
||||
a.set("abc", h, f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals(h, out[0])
|
||||
self.assertEquals(f, out[1])
|
||||
|
||||
a.set("abc", h, "")
|
||||
out = a.find("abc")
|
||||
self.assertEquals(h, out[0])
|
||||
self.assertEquals("", out[1])
|
||||
|
||||
def testSetRemove(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
h, f = hashflags()
|
||||
a.set("abc", h, f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
a.set("abc", None, None)
|
||||
try:
|
||||
out = a.find("abc")
|
||||
raise RuntimeError("set should've removed file abc")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def testCleanupAfterRemove(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
h, f = hashflags()
|
||||
a.set("abc/def/ghi", h, f)
|
||||
out = a.find("abc/def/ghi")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
a.set("abc/def/ghi", None, None)
|
||||
|
||||
h, f = hashflags()
|
||||
a.set("abc", h, f)
|
||||
out = a.find("abc")
|
||||
self.assertEquals((h, f), out)
|
||||
|
||||
def testIterOrder(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
h, f = hashflags()
|
||||
a.set("abc/def/ghi", h, f)
|
||||
a.set("abc/def.ghi", h, f)
|
||||
|
||||
results = [fp for fp in a]
|
||||
self.assertEquals(results[0], "abc/def.ghi")
|
||||
self.assertEquals(results[1], "abc/def/ghi")
|
||||
|
||||
def testIterOrderSigned(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
h, f = hashflags()
|
||||
a.set("abc/def/\xe6\xe9", h, f)
|
||||
a.set("abc/def/gh", h, f)
|
||||
|
||||
results = [fp for fp in a]
|
||||
self.assertEquals(results[0], "abc/def/gh")
|
||||
self.assertEquals(results[1], "abc/def/\xe6\xe9")
|
||||
|
||||
def testWrite(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
a.set("abc/def/x", *hashflags())
|
||||
a.set("abc/def/y", *hashflags())
|
||||
a.set("abc/z", *hashflags())
|
||||
alinknode = hashflags()[0]
|
||||
|
||||
dstore = FakeDataStore()
|
||||
hstore = FakeHistoryStore()
|
||||
for name, node, text, p1text, p1, p2 in a.finalize():
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, alinknode, "")
|
||||
if not name:
|
||||
anode = node
|
||||
|
||||
a2 = cstore.treemanifest(dstore, anode)
|
||||
self.assertEquals(list(a.iterentries()), list(a2.iterentries()))
|
||||
self.assertEquals(
|
||||
hstore.getancestors("", anode), {anode: (nullid, nullid, alinknode, "")}
|
||||
)
|
||||
|
||||
b = a2.copy()
|
||||
b.set("lmn/v", *hashflags())
|
||||
b.set("abc/z", *hashflags())
|
||||
blinknode = hashflags()[0]
|
||||
|
||||
for name, node, text, p1text, p1, p2 in b.finalize(a2):
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, blinknode, "")
|
||||
if not name:
|
||||
bnode = node
|
||||
|
||||
b2 = cstore.treemanifest(dstore, bnode)
|
||||
self.assertEquals(list(b.iterentries()), list(b2.iterentries()))
|
||||
self.assertEquals(
|
||||
hstore.getancestors("", bnode),
|
||||
{
|
||||
bnode: (anode, nullid, blinknode, ""),
|
||||
anode: (nullid, nullid, alinknode, ""),
|
||||
},
|
||||
)
|
||||
|
||||
def testWriteNoChange(self):
|
||||
"""Tests that making a change to a tree, then making a second change
|
||||
such that the result is a no-op, doesn't serialize that subtree. It
|
||||
should only serialize the root node, because we're giving the root node
|
||||
a new parent.
|
||||
"""
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
xhashflags = hashflags()
|
||||
a.set("abc/def/x", *xhashflags)
|
||||
a.set("abc/z", *hashflags())
|
||||
alinknode = hashflags()[0]
|
||||
|
||||
dstore = FakeDataStore()
|
||||
hstore = FakeHistoryStore()
|
||||
for name, node, text, p1text, p1, p2 in a.finalize():
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, alinknode, "")
|
||||
if not name:
|
||||
anode = node
|
||||
|
||||
a2 = cstore.treemanifest(dstore, anode)
|
||||
|
||||
b = a2.copy()
|
||||
b.set("abc/def/x", *hashflags())
|
||||
b.set("abc/def/x", *xhashflags)
|
||||
blinknode = hashflags()[0]
|
||||
|
||||
newtrees = set()
|
||||
for name, node, text, p1text, p1, p2 in b.finalize(a2):
|
||||
newtrees.add((name, node))
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, blinknode, "")
|
||||
|
||||
self.assertEquals(newtrees, set([("", node)]))
|
||||
|
||||
def testWriteReplaceFile(self):
|
||||
"""Tests writing a manifest which replaces a file with a directory."""
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
a.set("abc/a", *hashflags())
|
||||
a.set("abc/z", *hashflags())
|
||||
alinknode = hashflags()[0]
|
||||
|
||||
dstore = FakeDataStore()
|
||||
hstore = FakeHistoryStore()
|
||||
for name, node, text, p1text, p1, p2 in a.finalize():
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, alinknode, "")
|
||||
if not name:
|
||||
anode = node
|
||||
|
||||
b = a.copy()
|
||||
b.set("abc/a", None, None)
|
||||
b.set("abc/a/foo", *hashflags())
|
||||
blinknode = hashflags()[0]
|
||||
|
||||
for name, node, text, p1text, p1, p2 in b.finalize(a):
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, blinknode, "")
|
||||
if not name:
|
||||
bnode = node
|
||||
|
||||
b2 = cstore.treemanifest(dstore, bnode)
|
||||
self.assertEquals(list(b.iterentries()), list(b2.iterentries()))
|
||||
self.assertEquals(
|
||||
hstore.getancestors("", bnode),
|
||||
{
|
||||
bnode: (anode, nullid, blinknode, ""),
|
||||
anode: (nullid, nullid, alinknode, ""),
|
||||
},
|
||||
)
|
||||
|
||||
def testGet(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
|
||||
self.assertEquals(a.get("abc/z"), zflags[0])
|
||||
self.assertEquals(a.get("abc/x"), None)
|
||||
self.assertEquals(a.get("abc"), None)
|
||||
|
||||
def testFind(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
|
||||
self.assertEquals(a.find("abc/z"), zflags)
|
||||
try:
|
||||
a.find("abc/x")
|
||||
raise RuntimeError("find for non-existent file should throw")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def testSetFlag(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
a.setflag("abc/z", "")
|
||||
self.assertEquals(a.flags("abc/z"), "")
|
||||
|
||||
a.setflag("abc/z", "d")
|
||||
self.assertEquals(a.flags("abc/z"), "d")
|
||||
|
||||
try:
|
||||
a.setflag("foo", "d")
|
||||
raise RuntimeError("setflag should throw")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def testSetItem(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags(requireflag=True)
|
||||
a.set("abc/z", *zflags)
|
||||
|
||||
fooflags = hashflags()
|
||||
a["foo"] = fooflags[0]
|
||||
self.assertEquals(a.find("foo"), (fooflags[0], ""))
|
||||
|
||||
newnode = hashflags()[0]
|
||||
a["abc/z"] = newnode
|
||||
self.assertEquals(a.find("abc/z"), (newnode, zflags[1]))
|
||||
|
||||
def testText(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags(requireflag=True)
|
||||
a.set("abc/z", *zflags)
|
||||
|
||||
treetext = a.text()
|
||||
treetextv2 = a.text()
|
||||
|
||||
b = manifest.manifestdict()
|
||||
b["abc/z"] = zflags[0]
|
||||
b.setflag("abc/z", zflags[1])
|
||||
fulltext = b.text()
|
||||
fulltextv2 = b.text()
|
||||
|
||||
self.assertEquals(treetext, fulltext)
|
||||
self.assertEquals(treetextv2, fulltextv2)
|
||||
|
||||
def testDiff(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags()
|
||||
mflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
a.set("xyz/m", *mflags)
|
||||
alinknode = hashflags()[0]
|
||||
|
||||
b = cstore.treemanifest(FakeDataStore())
|
||||
b.set("abc/z", *zflags)
|
||||
b.set("xyz/m", *mflags)
|
||||
blinknode = hashflags()[0]
|
||||
|
||||
# Diff matching trees
|
||||
# - uncommitted trees
|
||||
diff = a.diff(b)
|
||||
self.assertEquals(diff, {})
|
||||
|
||||
# - committed trees
|
||||
dstore = FakeDataStore()
|
||||
hstore = FakeHistoryStore()
|
||||
for name, node, text, p1text, p1, p2 in a.finalize():
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, alinknode, "")
|
||||
for name, node, text, p1text, p1, p2 in b.finalize():
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, blinknode, "")
|
||||
diff = a.diff(b)
|
||||
self.assertEquals(diff, {})
|
||||
|
||||
b2 = b.copy()
|
||||
|
||||
# Diff with modifications
|
||||
newfileflags = hashflags()
|
||||
newzflags = hashflags()
|
||||
b2.set("newfile", *newfileflags)
|
||||
b2.set("abc/z", *newzflags)
|
||||
|
||||
# - uncommitted trees
|
||||
diff = a.diff(b2)
|
||||
self.assertEquals(
|
||||
diff, {"newfile": ((None, ""), newfileflags), "abc/z": (zflags, newzflags)}
|
||||
)
|
||||
|
||||
# - uncommitted trees with matcher
|
||||
matcher = matchmod.match("/", "/", ["abc/*"])
|
||||
diff = a.diff(b2, matcher=matcher)
|
||||
self.assertEquals(diff, {"abc/z": (zflags, newzflags)})
|
||||
|
||||
matcher = matchmod.match("/", "/", ["newfile"])
|
||||
diff = a.diff(b2, matcher=matcher)
|
||||
self.assertEquals(diff, {"newfile": ((None, ""), newfileflags)})
|
||||
|
||||
# - committed trees
|
||||
for name, node, text, p1text, p1, p2 in b2.finalize(a):
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, blinknode, "")
|
||||
|
||||
diff = a.diff(b2)
|
||||
self.assertEquals(
|
||||
diff, {"newfile": ((None, ""), newfileflags), "abc/z": (zflags, newzflags)}
|
||||
)
|
||||
|
||||
# Diff with clean
|
||||
diff = a.diff(b2, clean=True)
|
||||
self.assertEquals(
|
||||
diff,
|
||||
{
|
||||
"newfile": ((None, ""), newfileflags),
|
||||
"abc/z": (zflags, newzflags),
|
||||
"xyz/m": None,
|
||||
},
|
||||
)
|
||||
|
||||
def testFilesNotIn(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags()
|
||||
mflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
a.set("xyz/m", *mflags)
|
||||
alinknode = hashflags()[0]
|
||||
|
||||
b = cstore.treemanifest(FakeDataStore())
|
||||
b.set("abc/z", *zflags)
|
||||
b.set("xyz/m", *mflags)
|
||||
blinknode = hashflags()[0]
|
||||
|
||||
# filesnotin matching trees
|
||||
# - uncommitted trees
|
||||
diff = a.filesnotin(b)
|
||||
self.assertEquals(diff, set())
|
||||
|
||||
# - committed trees
|
||||
dstore = FakeDataStore()
|
||||
hstore = FakeHistoryStore()
|
||||
for name, node, text, p1text, p1, p2 in a.finalize():
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, alinknode, "")
|
||||
for name, node, text, p1text, p1, p2 in b.finalize():
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, blinknode, "")
|
||||
diff = a.filesnotin(b)
|
||||
self.assertEquals(diff, set())
|
||||
|
||||
# filesnotin with modifications
|
||||
newfileflags = hashflags()
|
||||
newzflags = hashflags()
|
||||
b.set("newfile", *newfileflags)
|
||||
b.set("abc/z", *newzflags)
|
||||
|
||||
# In 'a' and not in 'b'
|
||||
files = a.filesnotin(b)
|
||||
self.assertEquals(files, set())
|
||||
|
||||
# In 'b' and not in 'a'
|
||||
files = b.filesnotin(a)
|
||||
self.assertEquals(files, set(["newfile"]))
|
||||
|
||||
# With dir matcher
|
||||
match = matchmod.match("/", "/", ["abc/*"])
|
||||
files = b.filesnotin(a, matcher=match)
|
||||
self.assertEquals(files, set())
|
||||
|
||||
# With file matcher
|
||||
match = matchmod.match("/", "/", ["newfile"])
|
||||
files = b.filesnotin(a, matcher=match)
|
||||
self.assertEquals(files, set(["newfile"]))
|
||||
|
||||
# With no matches
|
||||
match = matchmod.match("/", "/", ["xxx"])
|
||||
files = b.filesnotin(a, matcher=match)
|
||||
self.assertEquals(files, set([]))
|
||||
|
||||
def testHasDir(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
|
||||
self.assertFalse(a.hasdir("abc/z"))
|
||||
self.assertTrue(a.hasdir("abc"))
|
||||
self.assertFalse(a.hasdir("xyz"))
|
||||
|
||||
def testListDir(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags()
|
||||
a.set("a/b/x", *zflags)
|
||||
a.set("a/b/y/_", *zflags)
|
||||
a.set("a/c/z", *zflags)
|
||||
a.set("1", *zflags)
|
||||
self.assertEquals(a.listdir(""), ["1", "a"])
|
||||
self.assertEquals(a.listdir("a"), ["b", "c"])
|
||||
self.assertEquals(a.listdir("a/b"), ["x", "y"])
|
||||
self.assertEquals(a.listdir("a/b/"), ["x", "y"])
|
||||
self.assertEquals(a.listdir("a/b/y"), ["_"])
|
||||
self.assertEquals(a.listdir("a/c"), ["z"])
|
||||
self.assertEquals(a.listdir("foo"), None)
|
||||
self.assertEquals(a.listdir("1"), None)
|
||||
self.assertEquals(a.listdir("1/"), None)
|
||||
self.assertEquals(a.listdir("a/b/y/_"), None)
|
||||
|
||||
def testContains(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
|
||||
self.assertTrue("abc/z" in a)
|
||||
self.assertFalse("abc" in a)
|
||||
self.assertFalse(None in a)
|
||||
|
||||
def testNonZero(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
self.assertFalse(bool(a))
|
||||
zflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
self.assertTrue(bool(a))
|
||||
|
||||
def testFlags(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags(requireflag=True)
|
||||
a.set("abc/z", *zflags)
|
||||
|
||||
self.assertEquals(a.flags("x"), "")
|
||||
self.assertEquals(a.flags("x", default="z"), "z")
|
||||
self.assertEquals(a.flags("abc/z"), zflags[1])
|
||||
|
||||
def testMatches(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
zflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
a.set("foo", *hashflags())
|
||||
|
||||
match = matchmod.match("/", "/", ["abc/z"])
|
||||
|
||||
result = a.matches(match)
|
||||
self.assertEquals(list(result.iterentries()), [("abc/z", zflags[0], zflags[1])])
|
||||
|
||||
match = matchmod.match("/", "/", ["x"])
|
||||
result = a.matches(match)
|
||||
self.assertEquals(list(result.iterentries()), [])
|
||||
|
||||
def testKeys(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
self.assertEquals(a.keys(), [])
|
||||
|
||||
zflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
a.set("foo", *hashflags())
|
||||
|
||||
self.assertEquals(a.keys(), ["abc/z", "foo"])
|
||||
|
||||
def testIterItems(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
self.assertEquals(list(a.iteritems()), [])
|
||||
|
||||
zflags = hashflags()
|
||||
fooflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
a.set("foo", *fooflags)
|
||||
|
||||
self.assertEquals(
|
||||
list(a.iteritems()), [("abc/z", zflags[0]), ("foo", fooflags[0])]
|
||||
)
|
||||
|
||||
def testWalkSubtrees(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
|
||||
zflags = hashflags()
|
||||
fooflags = hashflags()
|
||||
a.set("abc/z", *zflags)
|
||||
a.set("foo", *fooflags)
|
||||
|
||||
# Walk over inmemory tree
|
||||
subtrees = list(a.walksubtrees())
|
||||
self.assertEquals(
|
||||
subtrees,
|
||||
[
|
||||
(
|
||||
"abc",
|
||||
nullid,
|
||||
"z\0%s%s\n" % (hex(zflags[0]), zflags[1]),
|
||||
"",
|
||||
nullid,
|
||||
nullid,
|
||||
),
|
||||
(
|
||||
"",
|
||||
nullid,
|
||||
"abc\0%st\nfoo\0%s%s\n"
|
||||
% (hex(nullid), hex(fooflags[0]), fooflags[1]),
|
||||
"",
|
||||
nullid,
|
||||
nullid,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
# Walk over finalized tree
|
||||
dstore = FakeDataStore()
|
||||
hstore = FakeHistoryStore()
|
||||
for name, node, text, p1text, p1, p2 in a.finalize():
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, nullid, "")
|
||||
if name == "":
|
||||
rootnode = node
|
||||
if name == "abc":
|
||||
abcnode = node
|
||||
|
||||
subtrees = list(a.walksubtrees())
|
||||
self.assertEquals(
|
||||
subtrees,
|
||||
[
|
||||
(
|
||||
"abc",
|
||||
abcnode,
|
||||
"z\0%s%s\n" % (hex(zflags[0]), zflags[1]),
|
||||
"",
|
||||
nullid,
|
||||
nullid,
|
||||
),
|
||||
(
|
||||
"",
|
||||
rootnode,
|
||||
"abc\0%st\nfoo\0%s%s\n"
|
||||
% (hex(abcnode), hex(fooflags[0]), fooflags[1]),
|
||||
"",
|
||||
nullid,
|
||||
nullid,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
def testWalkSubdirtrees(self):
|
||||
a = cstore.treemanifest(FakeDataStore())
|
||||
|
||||
zflags = hashflags()
|
||||
qflags = hashflags()
|
||||
fooflags = hashflags()
|
||||
a.set("abc/def/z", *zflags)
|
||||
a.set("abc/xyz/q", *qflags)
|
||||
a.set("mno/foo", *fooflags)
|
||||
|
||||
# Walk over finalized tree
|
||||
dstore = FakeDataStore()
|
||||
hstore = FakeHistoryStore()
|
||||
for name, node, text, p1text, p1, p2 in a.finalize():
|
||||
dstore.add(name, node, nullid, text)
|
||||
hstore.add(name, node, p1, p2, nullid, "")
|
||||
if name == "abc":
|
||||
abcnode = node
|
||||
if name == "abc/xyz":
|
||||
abcxyznode = node
|
||||
if name == "abc/def":
|
||||
abcdefnode = node
|
||||
|
||||
subtrees = list(
|
||||
cstore.treemanifest.walksubdirtrees(("abc/def", abcdefnode), dstore)
|
||||
)
|
||||
self.assertEquals(
|
||||
subtrees,
|
||||
[
|
||||
(
|
||||
"abc/def",
|
||||
abcdefnode,
|
||||
"z\0%s%s\n" % (hex(zflags[0]), zflags[1]),
|
||||
"",
|
||||
nullid,
|
||||
nullid,
|
||||
)
|
||||
],
|
||||
)
|
||||
|
||||
subtrees = list(cstore.treemanifest.walksubdirtrees(("abc", abcnode), dstore))
|
||||
self.assertEquals(
|
||||
subtrees,
|
||||
[
|
||||
(
|
||||
"abc/def",
|
||||
abcdefnode,
|
||||
"z\0%s%s\n" % (hex(zflags[0]), zflags[1]),
|
||||
"",
|
||||
nullid,
|
||||
nullid,
|
||||
),
|
||||
(
|
||||
"abc/xyz",
|
||||
abcxyznode,
|
||||
"q\0%s%s\n" % (hex(qflags[0]), qflags[1]),
|
||||
"",
|
||||
nullid,
|
||||
nullid,
|
||||
),
|
||||
(
|
||||
"abc",
|
||||
abcnode,
|
||||
"def\0%st\n" % (hex(abcdefnode),)
|
||||
+ "xyz\0%st\n" % (hex(abcxyznode),),
|
||||
"",
|
||||
nullid,
|
||||
nullid,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
silenttestrunner.main(__name__)
|
@ -1,231 +0,0 @@
|
||||
#!/usr/bin/env python2.7
|
||||
from __future__ import absolute_import
|
||||
|
||||
import hashlib
|
||||
import random
|
||||
import shutil
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
import edenscm.mercurial.ui as uimod
|
||||
import silenttestrunner
|
||||
from bindings import revisionstore
|
||||
from edenscm.mercurial import mdiff
|
||||
from edenscm.mercurial.node import nullid
|
||||
from edenscmnative.cstore import datapackstore, uniondatapackstore
|
||||
|
||||
|
||||
class uniondatapackstoretests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
random.seed(0)
|
||||
self.tempdirs = []
|
||||
|
||||
def tearDown(self):
|
||||
for d in self.tempdirs:
|
||||
shutil.rmtree(d)
|
||||
|
||||
def makeTempDir(self):
|
||||
tempdir = tempfile.mkdtemp()
|
||||
self.tempdirs.append(tempdir)
|
||||
return tempdir
|
||||
|
||||
def getHash(self, content):
|
||||
return hashlib.sha1(content).digest()
|
||||
|
||||
def getFakeHash(self):
|
||||
return "".join(chr(random.randint(0, 255)) for _ in range(20))
|
||||
|
||||
def createPackStore(self, packdir, revisions=None):
|
||||
if revisions is None:
|
||||
revisions = [("filename", self.getFakeHash(), nullid, "content")]
|
||||
|
||||
packer = revisionstore.mutabledeltastore(packfilepath=packdir)
|
||||
|
||||
for filename, node, base, content in revisions:
|
||||
packer.add(filename, node, base, content)
|
||||
|
||||
packer.flush()
|
||||
return datapackstore(packdir)
|
||||
|
||||
def testGetFromSingleDelta(self):
|
||||
packdir = self.makeTempDir()
|
||||
|
||||
revisions = [("foo", self.getFakeHash(), nullid, "content")]
|
||||
store = self.createPackStore(packdir, revisions=revisions)
|
||||
|
||||
unionstore = uniondatapackstore([store])
|
||||
|
||||
text = unionstore.get(revisions[0][0], revisions[0][1])
|
||||
self.assertEquals("content", text)
|
||||
|
||||
def testGetFromChainDeltas(self):
|
||||
packdir = self.makeTempDir()
|
||||
|
||||
rev1 = "content"
|
||||
rev2 = "content2"
|
||||
firsthash = self.getFakeHash()
|
||||
revisions = [
|
||||
("foo", firsthash, nullid, rev1),
|
||||
("foo", self.getFakeHash(), firsthash, mdiff.textdiff(rev1, rev2)),
|
||||
]
|
||||
store = self.createPackStore(packdir, revisions=revisions)
|
||||
|
||||
unionstore = uniondatapackstore([store])
|
||||
|
||||
text = unionstore.get(revisions[1][0], revisions[1][1])
|
||||
self.assertEquals(rev2, text)
|
||||
|
||||
def testGetDeltaChainSingleRev(self):
|
||||
"""Test getting a 1-length delta chain."""
|
||||
packdir = self.makeTempDir()
|
||||
|
||||
revisions = [("foo", self.getFakeHash(), nullid, "content")]
|
||||
store = self.createPackStore(packdir, revisions=revisions)
|
||||
|
||||
unionstore = uniondatapackstore([store])
|
||||
|
||||
chain = unionstore.getdeltachain(revisions[0][0], revisions[0][1])
|
||||
self.assertEquals(1, len(chain))
|
||||
self.assertEquals("content", chain[0][4])
|
||||
|
||||
def testGetDeltaChainMultiRev(self):
|
||||
"""Test getting a 2-length delta chain."""
|
||||
packdir = self.makeTempDir()
|
||||
|
||||
firsthash = self.getFakeHash()
|
||||
revisions = [
|
||||
("foo", firsthash, nullid, "content"),
|
||||
("foo", self.getFakeHash(), firsthash, "content2"),
|
||||
]
|
||||
store = self.createPackStore(packdir, revisions=revisions)
|
||||
|
||||
unionstore = uniondatapackstore([store])
|
||||
|
||||
chain = unionstore.getdeltachain(revisions[1][0], revisions[1][1])
|
||||
self.assertEquals(2, len(chain))
|
||||
self.assertEquals("content2", chain[0][4])
|
||||
self.assertEquals("content", chain[1][4])
|
||||
|
||||
def testGetDeltaChainMultiPack(self):
|
||||
"""Test getting chains from multiple packs."""
|
||||
packdir = self.makeTempDir()
|
||||
|
||||
revisions1 = [("foo", self.getFakeHash(), nullid, "content")]
|
||||
store = self.createPackStore(packdir, revisions=revisions1)
|
||||
|
||||
revisions2 = [("foo", self.getFakeHash(), revisions1[0][1], "content2")]
|
||||
store = self.createPackStore(packdir, revisions=revisions2)
|
||||
|
||||
unionstore = uniondatapackstore([store])
|
||||
|
||||
chain = unionstore.getdeltachain(revisions2[0][0], revisions2[0][1])
|
||||
self.assertEquals(2, len(chain))
|
||||
self.assertEquals("content2", chain[0][4])
|
||||
self.assertEquals("content", chain[1][4])
|
||||
|
||||
def testGetMissing(self):
|
||||
packdir = self.makeTempDir()
|
||||
|
||||
revisions = [("foo", self.getFakeHash(), nullid, "content")]
|
||||
store = self.createPackStore(packdir, revisions=revisions)
|
||||
|
||||
unionstore = uniondatapackstore([store])
|
||||
|
||||
missinghash1 = self.getFakeHash()
|
||||
missinghash2 = self.getFakeHash()
|
||||
missing = unionstore.getmissing(
|
||||
[
|
||||
(revisions[0][0], revisions[0][1]),
|
||||
("foo", missinghash1),
|
||||
("foo2", missinghash2),
|
||||
]
|
||||
)
|
||||
self.assertEquals(2, len(missing))
|
||||
self.assertEquals(
|
||||
set([("foo", missinghash1), ("foo2", missinghash2)]), set(missing)
|
||||
)
|
||||
|
||||
def testAddRemoveStore(self):
|
||||
packdir = self.makeTempDir()
|
||||
revisions = [("foo", self.getFakeHash(), nullid, "content")]
|
||||
store = self.createPackStore(packdir, revisions=revisions)
|
||||
|
||||
packdir2 = self.makeTempDir()
|
||||
revisions2 = [("foo2", self.getFakeHash(), nullid, "content2")]
|
||||
store2 = self.createPackStore(packdir2, revisions=revisions2)
|
||||
|
||||
unionstore = uniondatapackstore([store])
|
||||
unionstore.addstore(store2)
|
||||
|
||||
# Fetch from store2
|
||||
result = unionstore.get("foo2", revisions2[0][1])
|
||||
self.assertEquals(result, revisions2[0][3])
|
||||
|
||||
# Drop the store
|
||||
unionstore.removestore(store2)
|
||||
|
||||
# Fetch from store1
|
||||
result = unionstore.get("foo", revisions[0][1])
|
||||
self.assertEquals(result, revisions[0][3])
|
||||
|
||||
# Fetch from missing store2
|
||||
try:
|
||||
unionstore.get("foo2", revisions2[0][1])
|
||||
self.asserFalse(True, "get should've thrown")
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
|
||||
class uniondatastorepythontests(uniondatapackstoretests):
|
||||
def createPackStore(self, packdir, revisions=None):
|
||||
if revisions is None:
|
||||
revisions = [("filename", self.getFakeHash(), nullid, "content")]
|
||||
|
||||
packer = revisionstore.mutabledeltastore(packfilepath=packdir)
|
||||
|
||||
for filename, node, base, content in revisions:
|
||||
packer.add(filename, node, base, content)
|
||||
|
||||
path = packer.flush()
|
||||
return revisionstore.datapack(path)
|
||||
|
||||
def testGetDeltaChainMultiPack(self):
|
||||
"""Test getting chains from multiple packs."""
|
||||
packdir = self.makeTempDir()
|
||||
|
||||
revisions1 = [("foo", self.getFakeHash(), nullid, "content")]
|
||||
pack1 = self.createPackStore(packdir, revisions=revisions1)
|
||||
|
||||
revisions2 = [("foo", self.getFakeHash(), revisions1[0][1], "content2")]
|
||||
pack2 = self.createPackStore(packdir, revisions=revisions2)
|
||||
|
||||
unionstore = uniondatapackstore([pack1, pack2])
|
||||
|
||||
chain = unionstore.getdeltachain(revisions2[0][0], revisions2[0][1])
|
||||
self.assertEquals(2, len(chain))
|
||||
self.assertEquals("content2", chain[0][4])
|
||||
self.assertEquals("content", chain[1][4])
|
||||
|
||||
def testGetDeltaChainMultiPackPyAndC(self):
|
||||
"""Test getting chains from multiple packs."""
|
||||
packdir1 = self.makeTempDir()
|
||||
packdir2 = self.makeTempDir()
|
||||
|
||||
revisions1 = [("foo", self.getFakeHash(), nullid, "content")]
|
||||
store = super(uniondatastorepythontests, self).createPackStore(
|
||||
packdir1, revisions=revisions1
|
||||
)
|
||||
|
||||
revisions2 = [("foo", self.getFakeHash(), revisions1[0][1], "content2")]
|
||||
pack = self.createPackStore(packdir2, revisions=revisions2)
|
||||
|
||||
unionstore = uniondatapackstore([pack, store])
|
||||
|
||||
chain = unionstore.getdeltachain(revisions2[0][0], revisions2[0][1])
|
||||
self.assertEquals(2, len(chain))
|
||||
self.assertEquals("content2", chain[0][4])
|
||||
self.assertEquals("content", chain[1][4])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
silenttestrunner.main(__name__)
|
@ -17,60 +17,47 @@ sh % "setconfig 'rebase.experimental.inmemory=1'"
|
||||
sh % "setconfig 'rebase.experimental.inmemory.nomergedriver=False'"
|
||||
sh % "setconfig 'rebase.experimental.inmemorywarning=rebasing in-memory!'"
|
||||
|
||||
sh.cd(testtmp.TESTTMP)
|
||||
|
||||
for userustmanifest in [True, False]:
|
||||
sh.cd(testtmp.TESTTMP)
|
||||
sh.setconfig("treemanifest.rustmanifest=%s" % int(userustmanifest))
|
||||
# Create a commit with a move + content change:
|
||||
sh % "newrepo"
|
||||
sh % "echo 'original content'" > "file"
|
||||
sh % "hg add -q"
|
||||
sh % "hg commit -q -m base"
|
||||
sh % "echo 'new content'" > "file"
|
||||
sh % "hg mv file file_new"
|
||||
sh % "hg commit -m a"
|
||||
sh % "hg book -r . a"
|
||||
|
||||
# Create a commit with a move + content change:
|
||||
sh % "newrepo"
|
||||
sh % "echo 'original content'" > "file"
|
||||
sh % "hg add -q"
|
||||
sh % "hg commit -q -m base"
|
||||
sh % "echo 'new content'" > "file"
|
||||
sh % "hg mv file file_new"
|
||||
sh % "hg commit -m a"
|
||||
sh % "hg book -r . a"
|
||||
# Recreate the same commit:
|
||||
sh % "hg up -q '.~1'"
|
||||
sh % "echo 'new content'" > "file"
|
||||
sh % "hg mv file file_new"
|
||||
sh % "hg commit -m b"
|
||||
sh % "hg book -r . b"
|
||||
|
||||
# Recreate the same commit:
|
||||
sh % "hg up -q '.~1'"
|
||||
sh % "echo 'new content'" > "file"
|
||||
sh % "hg mv file file_new"
|
||||
sh % "hg commit -m b"
|
||||
sh % "hg book -r . b"
|
||||
reponame = "../without-imm"
|
||||
sh.cp("-R", ".", reponame)
|
||||
|
||||
reponame = "../without-imm-%s" % userustmanifest
|
||||
sh.cp("-R", ".", reponame)
|
||||
# Rebase one version onto the other, confirm it gets rebased out:
|
||||
sh % "hg rebase -r b -d a" == r"""
|
||||
rebasing in-memory!
|
||||
rebasing 811ec875201f "b" (b)
|
||||
note: rebase of 2:811ec875201f created no changes to commit"""
|
||||
|
||||
# Rebase one version onto the other, confirm it gets rebased out:
|
||||
sh % "hg rebase -r b -d a" == r"""
|
||||
rebasing in-memory!
|
||||
rebasing 811ec875201f "b" (b)
|
||||
note: rebase of 2:811ec875201f created no changes to commit"""
|
||||
# Without IMM, this behavior is semi-broken: the commit is not rebased out and the
|
||||
# created commit is empty. (D8676355)
|
||||
sh.cd(reponame)
|
||||
sh % "setconfig 'rebase.experimental.inmemory=0'"
|
||||
sh % "hg rebase -r b -d a" == r"""
|
||||
rebasing 811ec875201f "b" (b)
|
||||
warning: can't find ancestor for 'file_new' copied from 'file'!"""
|
||||
|
||||
# Without IMM, this behavior is semi-broken: the commit is not rebased out and the
|
||||
# created commit is empty. (D8676355)
|
||||
sh.cd(reponame)
|
||||
sh % "setconfig 'rebase.experimental.inmemory=0'"
|
||||
sh % "hg rebase -r b -d a" == r"""
|
||||
rebasing 811ec875201f "b" (b)
|
||||
warning: can't find ancestor for 'file_new' copied from 'file'!"""
|
||||
|
||||
if userustmanifest:
|
||||
sh % "hg export tip" == r"""
|
||||
# HG changeset patch
|
||||
# User test
|
||||
# Date 0 0
|
||||
# Thu Jan 01 00:00:00 1970 +0000
|
||||
# Node ID 0fe513c05d7fe2819c3ceccb072e74940604af36
|
||||
# Parent 24483d5afe6cb1a13b3642b4d8622e91f4d1bec1
|
||||
b"""
|
||||
else:
|
||||
sh % "hg export tip" == r"""
|
||||
# HG changeset patch
|
||||
# User test
|
||||
# Date 0 0
|
||||
# Thu Jan 01 00:00:00 1970 +0000
|
||||
# Node ID 7552e6b0bc4ab4ac16175ced4f08a54c31faf706
|
||||
# Parent 24483d5afe6cb1a13b3642b4d8622e91f4d1bec1
|
||||
b"""
|
||||
sh % "hg export tip" == r"""
|
||||
# HG changeset patch
|
||||
# User test
|
||||
# Date 0 0
|
||||
# Thu Jan 01 00:00:00 1970 +0000
|
||||
# Node ID 0fe513c05d7fe2819c3ceccb072e74940604af36
|
||||
# Parent 24483d5afe6cb1a13b3642b4d8622e91f4d1bec1
|
||||
b"""
|
||||
|
Loading…
Reference in New Issue
Block a user