@appland/scanner 1.71.1 → 1.71.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
# [@appland/scanner-v1.71.3](https://github.com/getappmap/appmap-js/compare/@appland/scanner-v1.71.2...@appland/scanner-v1.71.3) (2022-10-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Handle appmap paths in an OS-agnostic manner in scan --watch ([cc473a8](https://github.com/getappmap/appmap-js/commit/cc473a89c60130b4b518a56b7e50f8617d88dd59))
|
|
7
|
+
* scan --watch works even if the appmap dir doesn't initially exist ([938bb76](https://github.com/getappmap/appmap-js/commit/938bb76d8fd827874731f4cd3258c4b9e0988a35))
|
|
8
|
+
|
|
9
|
+
# [@appland/scanner-v1.71.2](https://github.com/getappmap/appmap-js/compare/@appland/scanner-v1.71.1...@appland/scanner-v1.71.2) (2022-10-04)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* Use default configuration timestamp in scan --watch if none provided ([3d246f2](https://github.com/getappmap/appmap-js/commit/3d246f2b350af2dd14a097519ea9af6fe410e543))
|
|
15
|
+
|
|
1
16
|
# [@appland/scanner-v1.71.1](https://github.com/getappmap/appmap-js/compare/@appland/scanner-v1.71.0...@appland/scanner-v1.71.1) (2022-10-04)
|
|
2
17
|
|
|
3
18
|
|
|
@@ -69,11 +69,11 @@ exports.default = {
|
|
|
69
69
|
if (reportAllFindings && watch) {
|
|
70
70
|
throw new errors_1.ValidationError(`Don't use --all with --watch, because in watch mode all findings are reported`);
|
|
71
71
|
}
|
|
72
|
+
if (appmapDir)
|
|
73
|
+
yield (0, validateFile_1.default)('directory', appmapDir);
|
|
72
74
|
if (!appmapFile && !appmapDir) {
|
|
73
75
|
appmapDir = (yield (0, appmapDirFromConfig_1.appmapDirFromConfig)()) || '.';
|
|
74
76
|
}
|
|
75
|
-
if (appmapDir)
|
|
76
|
-
yield (0, validateFile_1.default)('directory', appmapDir);
|
|
77
77
|
let appId = appIdArg;
|
|
78
78
|
if (!watch && !reportAllFindings)
|
|
79
79
|
appId = yield (0, resolveAppId_1.default)(appIdArg, appmapDir);
|
|
@@ -44,6 +44,29 @@ const configurationProvider_1 = require("../../configuration/configurationProvid
|
|
|
44
44
|
const assert_1 = __importDefault(require("assert"));
|
|
45
45
|
const path_1 = __importDefault(require("path"));
|
|
46
46
|
const async_1 = require("async");
|
|
47
|
+
function isDir(targetPath) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
try {
|
|
50
|
+
return (yield (0, promises_1.stat)(targetPath)).isDirectory();
|
|
51
|
+
}
|
|
52
|
+
catch (_a) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function existingParent(targetPath) {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
while (targetPath.length > 1) {
|
|
60
|
+
if (yield isDir(targetPath))
|
|
61
|
+
break;
|
|
62
|
+
targetPath = path_1.default.dirname(targetPath);
|
|
63
|
+
}
|
|
64
|
+
return targetPath;
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function isAncestorPath(ancestor, descendant) {
|
|
68
|
+
return !path_1.default.relative(ancestor, descendant).startsWith('..');
|
|
69
|
+
}
|
|
47
70
|
class Watcher {
|
|
48
71
|
constructor(options) {
|
|
49
72
|
this.options = options;
|
|
@@ -58,20 +81,34 @@ class Watcher {
|
|
|
58
81
|
this.configWatcher
|
|
59
82
|
.on('add', this.reloadConfig.bind(this))
|
|
60
83
|
.on('change', this.reloadConfig.bind(this));
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
84
|
+
const appmapDir = path_1.default.resolve(this.options.appmapDir);
|
|
85
|
+
// If the appmap directory is a descendant of cwd, watch cwd (presumably project directory).
|
|
86
|
+
// This ensures the watch will survive even if the appmap dir is removed and recreated.
|
|
87
|
+
// Otherwise, make sure to use an existing directory. Chokidar struggles with missing directories.
|
|
88
|
+
const watchDir = isAncestorPath(process.cwd(), appmapDir)
|
|
89
|
+
? process.cwd()
|
|
90
|
+
: yield existingParent(appmapDir);
|
|
91
|
+
// Custom ignore function needed to cut down the watch tree to just what we need.
|
|
92
|
+
const ignored = (targetPath) => {
|
|
93
|
+
// Ignore anything that isn't an ancestor or descendant of the appmap dir.
|
|
94
|
+
if (!(isAncestorPath(targetPath, appmapDir) || isAncestorPath(appmapDir, targetPath)))
|
|
95
|
+
return true;
|
|
96
|
+
// Also make sure to not try to recurse down node_modules or .git
|
|
97
|
+
const basename = path_1.default.basename(targetPath);
|
|
98
|
+
return basename === 'node_modules' || basename === '.git';
|
|
99
|
+
};
|
|
100
|
+
this.appmapWatcher = chokidar.watch(watchDir, {
|
|
64
101
|
ignoreInitial: true,
|
|
65
|
-
ignored
|
|
102
|
+
ignored,
|
|
66
103
|
});
|
|
67
|
-
this.appmapPoller = chokidar.watch(
|
|
104
|
+
this.appmapPoller = chokidar.watch(watchDir, {
|
|
68
105
|
ignoreInitial: false,
|
|
69
|
-
ignored
|
|
106
|
+
ignored,
|
|
70
107
|
usePolling: true,
|
|
71
108
|
interval: 1000,
|
|
72
109
|
persistent: false,
|
|
73
110
|
});
|
|
74
|
-
const enqueue = this.enqueue
|
|
111
|
+
const enqueue = (filePath) => path_1.default.basename(filePath) === 'mtime' && this.enqueue(filePath);
|
|
75
112
|
for (const ch of [this.appmapWatcher, this.appmapPoller])
|
|
76
113
|
ch.on('add', enqueue).on('change', enqueue);
|
|
77
114
|
});
|
|
@@ -94,15 +131,14 @@ class Watcher {
|
|
|
94
131
|
scan(mtimePath) {
|
|
95
132
|
return __awaiter(this, void 0, void 0, function* () {
|
|
96
133
|
(0, assert_1.default)(this.config, `config should always be loaded before appmapWatcher triggers a scan`);
|
|
97
|
-
(
|
|
98
|
-
const appmapFile = mtimePath.replace(/\/mtime$/, '.appmap.json');
|
|
134
|
+
const appmapFile = [path_1.default.dirname(mtimePath), 'appmap.json'].join('.');
|
|
99
135
|
const reportFile = mtimePath.replace(/mtime$/, 'appmap-findings.json');
|
|
100
136
|
const [appmapStats, reportStats] = yield Promise.all([appmapFile, reportFile].map((f) => (0, promises_1.stat)(f).catch(() => null)));
|
|
101
137
|
if (!appmapStats)
|
|
102
138
|
return;
|
|
103
139
|
if (reportStats &&
|
|
104
140
|
reportStats.mtimeMs > appmapStats.mtimeMs &&
|
|
105
|
-
reportStats.mtimeMs > this.
|
|
141
|
+
reportStats.mtimeMs > this.config.timestampMs)
|
|
106
142
|
return; // report is up to date
|
|
107
143
|
const scanner = yield (0, scanner_1.default)(true, this.config, [appmapFile]);
|
|
108
144
|
const rawScanResults = yield scanner.scan();
|
|
@@ -113,7 +149,6 @@ class Watcher {
|
|
|
113
149
|
reloadConfig() {
|
|
114
150
|
return __awaiter(this, void 0, void 0, function* () {
|
|
115
151
|
this.config = yield (0, configurationProvider_1.parseConfigFile)(this.options.configFile);
|
|
116
|
-
this.configTime = (yield (0, promises_1.stat)(this.options.configFile)).mtimeMs;
|
|
117
152
|
});
|
|
118
153
|
}
|
|
119
154
|
}
|
|
@@ -211,10 +211,12 @@ function parseConfigFile(configPath) {
|
|
|
211
211
|
configPath = (0, path_1.join)(__dirname, '../sampleConfig/default.yml');
|
|
212
212
|
}
|
|
213
213
|
console.log(`Using scanner configuration file ${configPath}`);
|
|
214
|
+
const timestampMs = (yield fs_1.promises.stat(configPath)).mtimeMs;
|
|
214
215
|
const yamlConfig = yield fs_1.promises.readFile(configPath, 'utf-8');
|
|
215
|
-
|
|
216
|
+
const config = js_yaml_1.default.load(yamlConfig, {
|
|
216
217
|
filename: configPath,
|
|
217
218
|
});
|
|
219
|
+
return Object.assign(Object.assign({}, config), { timestampMs });
|
|
218
220
|
});
|
|
219
221
|
}
|
|
220
222
|
exports.parseConfigFile = parseConfigFile;
|