diff --git a/package-lock.json b/package-lock.json index 808405c66..001331b51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2299,6 +2299,11 @@ "minipass": "^2.2.1" } }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==" + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", diff --git a/packages/cli/package.json b/packages/cli/package.json index 1c3d94b35..7f35b2b18 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -70,6 +70,7 @@ "ethereumjs-util": "^6.1.0", "find-up": "^3.0.0", "fs-extra": "^7.0.1", + "fs-readdir-recursive": "^1.1.0", "inquirer": "^6.4.1", "is-url": "^1.2.4", "lockfile": "^1.0.4", diff --git a/packages/cli/src/models/compiler/solidity/SolidityProjectCompiler.ts b/packages/cli/src/models/compiler/solidity/SolidityProjectCompiler.ts index fe7b87f2c..91980c83e 100644 --- a/packages/cli/src/models/compiler/solidity/SolidityProjectCompiler.ts +++ b/packages/cli/src/models/compiler/solidity/SolidityProjectCompiler.ts @@ -5,7 +5,8 @@ import pick from 'lodash.pick'; import omitBy from 'lodash.omitby'; import isUndefined from 'lodash.isundefined'; import { readJsonSync, ensureDirSync, readJSON, writeJson, unlink } from 'fs-extra'; -import { statSync, existsSync, readdirSync, lstatSync } from 'fs'; +import { statSync, existsSync, lstatSync } from 'fs'; +import readdirSync from 'fs-readdir-recursive'; import { Loggy, Contracts } from '@openzeppelin/upgrades'; import { RawContract, @@ -188,7 +189,9 @@ class SolidityProjectCompiler { await Promise.all( this.compilerOutput.map(async data => { const name = data.contractName; - const buildFileName = `${this.outputDir}/${name}.json`; + const buildDirName = `${this.outputDir}/${data.sourcePath.replace(/^contracts\/(.*)$/, `$1`)}`; + ensureDirSync(buildDirName); + const buildFileName = `${buildDirName}/${name}.json`; if (networksInfo[name]) Object.assign(data, { networks: networksInfo[name] }); await writeJson(buildFileName, data, { spaces: 2 }); }), diff --git a/packages/cli/src/models/local/ContractManager.ts b/packages/cli/src/models/local/ContractManager.ts index 4c027df2f..1fb5d1992 100644 --- a/packages/cli/src/models/local/ContractManager.ts +++ b/packages/cli/src/models/local/ContractManager.ts @@ -3,6 +3,7 @@ import Dependency from '../dependency/Dependency'; import ProjectFile from '../files/ProjectFile'; import ConfigManager from '../config/ConfigManager'; import path from 'path'; +import readdirSync from 'fs-readdir-recursive'; export default class ContractManager { public projectFile: ProjectFile; @@ -35,7 +36,7 @@ export default class ContractManager { const buildDir = ConfigManager.getBuildDir(); const contractsDir = Contracts.getLocalContractsDir(); if (FileSystem.exists(buildDir)) { - return FileSystem.readDir(buildDir) + return readdirSync(buildDir) .filter(name => name.match(/\.json$/)) .map(name => FileSystem.parseJsonIfExists(`${buildDir}/${name}`)) .filter(contract => { @@ -45,7 +46,7 @@ export default class ContractManager { !this.isAbstractContract(contract) ); }) - .map(({ contractName }) => contractName); + .map(({ sourcePath, contractName }) => `${sourcePath.replace(/contracts\/(.*)/, `$1`)}/${contractName}`); } else return []; } diff --git a/packages/cli/src/utils/naming.ts b/packages/cli/src/utils/naming.ts index 08d7a43f8..11d7f5a31 100644 --- a/packages/cli/src/utils/naming.ts +++ b/packages/cli/src/utils/naming.ts @@ -8,7 +8,6 @@ export function toContractFullName(packageName: string, contractName: string): s export function fromContractFullName(contractFullName: string): { contract?: string; package?: string } { if (!contractFullName) return {}; const fragments = contractFullName.split('/'); - const contractName = fragments.pop(); - if (fragments.length === 0) return { contract: contractName }; - else return pickBy({ contract: contractName, package: fragments.join('/') }); + if (fragments.length === 2) return { contract: contractFullName }; + else return pickBy({ contract: fragments.slice(1).join('/'), package: fragments[0] }); } diff --git a/packages/cli/test/commands/create.test.js b/packages/cli/test/commands/create.test.js index f5e06ab36..b7d260032 100644 --- a/packages/cli/test/commands/create.test.js +++ b/packages/cli/test/commands/create.test.js @@ -10,7 +10,7 @@ describe('create command', function() { itShouldParse( 'should call create script with options', 'create', - 'zos create Impl --network test --init setup --args 42 --force --from 0x40', + 'zos create Impl.sol/Impl --network test --init setup --args 42 --force --from 0x40', function(create) { create.should.have.been.calledWithExactly({ contractAlias: 'Impl', @@ -26,7 +26,7 @@ describe('create command', function() { itShouldParse( 'should call create script with kind', 'create', - 'zos create Impl --network test --init setup --args 42 --force --from 0x40 --minimal', + 'zos create Impl.sol/Impl --network test --init setup --args 42 --force --from 0x40 --minimal', function(create) { create.should.have.been.calledWithExactly({ contractAlias: 'Impl', @@ -43,7 +43,7 @@ describe('create command', function() { itShouldParse( 'should call create script with options', 'create', - 'zos create Boolean --network test --init initialize --args false --force --from 0x40', + 'zos create Boolean.sol/Boolean --network test --init initialize --args false --force --from 0x40', function(create) { create.should.have.been.calledWithExactly({ contractAlias: 'Boolean', @@ -59,7 +59,7 @@ describe('create command', function() { itShouldParse( 'should call create script with default init method', 'create', - 'zos create Impl --network test --init --args 42 --force --from 0x40', + 'zos create Impl.sol/Impl --network test --init --args 42 --force --from 0x40', function(create) { create.should.have.been.calledWithExactly({ contractAlias: 'Impl', @@ -75,7 +75,7 @@ describe('create command', function() { itShouldParse( 'should call create script with init if only args is provided', 'create', - 'zos create Impl --network test --args 42 --force --from 0x40', + 'zos create Impl.sol/Impl --network test --args 42 --force --from 0x40', function(create) { create.should.have.been.calledWithExactly({ contractAlias: 'Impl', diff --git a/packages/cli/test/commands/create2.test.js b/packages/cli/test/commands/create2.test.js index 3073455c8..371589987 100644 --- a/packages/cli/test/commands/create2.test.js +++ b/packages/cli/test/commands/create2.test.js @@ -9,7 +9,7 @@ contract('create2 command', function() { itShouldParse( 'should call create2 script with options', 'create', - 'zos create2 Impl --network test --init setup --args 42 --force --salt 10 --from 0x40 --signature 0x80', + 'zos create2 Impl.sol/Impl --network test --init setup --args 42 --force --salt 10 --from 0x40 --signature 0x80', function(create) { create.should.have.been.calledWithExactly({ contractAlias: 'Impl', @@ -41,7 +41,7 @@ contract('create2 command', function() { itShouldParse( 'should call create2 script querying signature', 'querySignedDeployment', - 'zos create2 Impl --query --init setup --args 42 --signature 0x80 --network test --salt 10 --from 0x40', + 'zos create2 Impl.sol/Impl --query --init setup --args 42 --signature 0x80 --network test --salt 10 --from 0x40', function(querySignedDeployment) { querySignedDeployment.should.have.been.calledWithExactly({ network: 'test',