Skip to content

Commit 8352d01

Browse files
committed
solcjs: Change base path stripping logic to match the new logic in solc
1 parent cfc853c commit 8352d01

File tree

2 files changed

+76
-9
lines changed

2 files changed

+76
-9
lines changed

solcjs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
var originalUncaughtExceptionListeners = process.listeners("uncaughtException");
55

66
var fs = require('fs-extra');
7+
var os = require('os');
78
var path = require('path');
89
var solc = require('./index.js');
910
var smtchecker = require('./smtchecker.js');
@@ -45,11 +46,32 @@ function readFileCallback(sourcePath) {
4546
} else
4647
return { error: 'File not found at ' + sourcePath}
4748
}
49+
50+
function withUnixPathSeparators(filePath) {
51+
if (os.platform !== 'win32')
52+
// On UNIX-like systems forward slashes in paths are just a part of the file name.
53+
return filePath;
54+
55+
return filePath.replace(/\\/g, "/");
56+
}
57+
4858
function stripBasePath(sourcePath) {
49-
if (program.basePath && sourcePath.startsWith(program.basePath))
50-
return sourcePath.slice(program.basePath.length);
51-
else
52-
return sourcePath;
59+
const absoluteBasePath = (program.basePath ? path.resolve(program.basePath) : path.resolve('.'));
60+
61+
// Compared to base path stripping logic in solc this is much simpler because path.resolve()
62+
// handles symlinks correctly (does not resolve them except in work dir) and strips .. segments
63+
// from paths going beyond root (e.g. `/../../a/b/c` -> `/a/b/c/`). It's simpler also because it
64+
// ignores less important corner cases: drive letters are not stripped from absolute paths on
65+
// Windows and UNC paths are not handled in a special way (at least on Linux). Finally, it has
66+
// very little test coverage so there might be more differences that we are just not aware of.
67+
const absoluteSourcePath = path.resolve(sourcePath);
68+
const relativeSourcePath = path.relative(absoluteBasePath, absoluteSourcePath);
69+
70+
if (relativeSourcePath.startsWith('../'))
71+
// Path can't be made relative without stepping outside of base path so return absolute one.
72+
return withUnixPathSeparators(absoluteSourcePath);
73+
74+
return withUnixPathSeparators(relativeSourcePath);
5375
}
5476

5577
var callbacks = undefined

test/cli.js

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const tape = require('tape');
22
const spawn = require('tape-spawn');
3+
const path = require('path');
34
const pkg = require('../package.json');
45

56
tape('CLI', function (t) {
@@ -62,14 +63,58 @@ tape('CLI', function (t) {
6263
spt.end();
6364
});
6465

65-
t.test('no-base-path', function (st) {
66-
var spt = spawn(st, './solcjs --bin test/resources/importA.sol');
67-
spt.stderr.match(/not found: File import callback not supported/);
66+
t.test('no base path', function (st) {
67+
var spt = spawn(
68+
st,
69+
'./solcjs --bin ' +
70+
'test/resources/importA.sol ' +
71+
'./test/resources//importA.sol ' +
72+
path.resolve('test/resources/importA.sol') + ' ' +
73+
// Adding importB explicitly here should make compiler find it despite the lack of callback
74+
'test/resources/importB.sol '
75+
);
76+
spt.stderr.empty();
77+
spt.succeeds();
78+
spt.end();
79+
});
80+
81+
t.test('relative base path', function (st) {
82+
// NOTE: This and other base path tests rely on the relative ./importB.sol import in importA.sol.
83+
// If base path is not stripped correctly from all source paths below, they will not be found
84+
// by the import callback when it appends the base path back.
85+
var spt = spawn(
86+
st,
87+
'./solcjs --bin --base-path test/resources ' +
88+
'test/resources/importA.sol ' +
89+
'./test/resources//importA.sol ' +
90+
path.resolve('test/resources/importA.sol')
91+
);
92+
spt.stderr.empty();
93+
spt.succeeds();
94+
spt.end();
95+
});
96+
97+
t.test('relative non canonical base path', function (st) {
98+
var spt = spawn(
99+
st,
100+
'./solcjs --bin --base-path ./test/resources ' +
101+
'test/resources/importA.sol ' +
102+
'./test/resources//importA.sol ' +
103+
path.resolve('test/resources/importA.sol')
104+
);
105+
spt.stderr.empty();
106+
spt.succeeds();
68107
spt.end();
69108
});
70109

71-
t.test('base-path', function (st) {
72-
var spt = spawn(st, './solcjs --bin --base-path test/resources test/resources/importA.sol');
110+
t.test('absolute base path', function (st) {
111+
var spt = spawn(
112+
st,
113+
'./solcjs --bin --base-path ' + path.resolve('test/resources') + ' ' +
114+
'test/resources/importA.sol ' +
115+
'./test/resources//importA.sol ' +
116+
path.resolve('test/resources/importA.sol')
117+
);
73118
spt.stderr.empty();
74119
spt.succeeds();
75120
spt.end();

0 commit comments

Comments
 (0)