From 64652e99f6db444e2bbb464c7e69905c5afbd70e Mon Sep 17 00:00:00 2001 From: David Terry Date: Wed, 4 Aug 2021 00:31:17 +0200 Subject: [PATCH] dapp: remappings: deduplicate identical packages --- src/dapp-tests/integration/tests.sh | 3 +- src/dapp/libexec/dapp/dapp-remappings | 62 +++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/dapp-tests/integration/tests.sh b/src/dapp-tests/integration/tests.sh index c63346740..82987bab3 100755 --- a/src/dapp-tests/integration/tests.sh +++ b/src/dapp-tests/integration/tests.sh @@ -52,9 +52,10 @@ dapp_testnet # tests the behaviour of the package local dapp remappings dapp_remappings() { + REV="fde82bd3319f7a1407a21553d120927d99a95f26" TMPDIR=$(mktemp -d) git clone https://github.com/dapphub/remappings-test "$TMPDIR" - (cd "$TMPDIR" && dapp update && dapp test) + (cd "$TMPDIR" && git checkout "$REV" && dapp update && dapp test) } dapp_remappings diff --git a/src/dapp/libexec/dapp/dapp-remappings b/src/dapp/libexec/dapp/dapp-remappings index 07d31e94d..2f0a688e4 100755 --- a/src/dapp/libexec/dapp/dapp-remappings +++ b/src/dapp/libexec/dapp/dapp-remappings @@ -1,18 +1,59 @@ #!/usr/bin/env node +const PROGRAM_NAME = process.argv[1].replace(/.*\//, "") -console.log(buildRemappings(".").join("\n")) +const tree = buildDependencyTree(".") +console.log(buildRemappings(deduplicate(mapHashes(tree), tree)).join("\n")) + +// builds a in memory representation of the projects dependency tree +// +// A node in the tree looks like this: +// +// { +// name: "", +// path: "", +// hash: "", +// deps: [] +// } +function buildDependencyTree(prefix) { + if (ls(prefix).includes(".git") != true) { + console.error(`${PROGRAM_NAME}: error: ${prefix} is not a Git repository`) + console.error(`${PROGRAM_NAME}: error: try "dapp update" to initialize submodules`) + process.exit(1) + } -function buildRemappings(prefix) { const lib = `${prefix}/${process.env.DAPP_LIB}` - const ctx = `${prefix}/${process.env.DAPP_SRC}` + return { + name: prefix.split("/").pop(), + path: normalize(`${prefix}/${process.env.DAPP_SRC}`), + hash: run("git", ["-C", prefix, "rev-parse", "HEAD"]), + deps: ls(lib).map(p => buildDependencyTree(`${lib}/${p}`)) + } +} - const remappings = ls(lib).map(name => { - return `${normalize(ctx)}:${name}/=${normalize(lib)}/${name}/${process.env.DAPP_SRC}/` +// walk tree and build remappings +function buildRemappings(pkg) { + const remappings = pkg.deps.map(dep => { + return `${pkg.path}/:${dep.name}/=${dep.path}/` }) + return pkg.deps.map(buildRemappings).concat(remappings).flat() +} - return ls(lib).map(name => { - return buildRemappings(`${lib}/${name}`) - }).concat(remappings).flat() +// walk tree and build a mapping from hash => path +function mapHashes(pkg) { + const go = (mapping, dep) => { + mapping[dep.hash] = dep.path + return dep.deps.reduce(go, mapping) + } + return tree.deps.reduce(go, { [pkg.hash]: pkg.path }) +} + +// walk tree and rewrite paths so that all packages with the same hash have the same path +function deduplicate(mapping, pkg) { + return { + ...pkg, + path: mapping[pkg.hash], + deps: pkg.deps.map(dep => deduplicate(mapping, dep)) + } } // strip the leading `.` or `./` from a path @@ -28,3 +69,8 @@ function ls(dir) { } } +function run(cmd, args) { + return require("child_process").execFileSync(cmd, args, { + encoding: "utf-8" + }) +}