dependency-cruiser 12.3.0 → 12.5.0-beta-1
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/LICENSE +1 -1
- package/package.json +14 -13
- package/src/cache/cache.js +75 -44
- package/src/cache/content-strategy.js +265 -0
- package/src/cache/{revision-data.js → metadata-strategy.js} +34 -34
- package/src/cache/options-compatible.js +22 -10
- package/src/cache/utl.js +18 -10
- package/src/cli/index.js +7 -3
- package/src/cli/init-config/find-extensions.js +8 -70
- package/src/cli/init-config/normalize-init-options.js +4 -1
- package/src/cli/listeners/{cli-feedback/index.js → cli-feedback.js} +1 -1
- package/src/cli/normalize-cli-options.js +0 -15
- package/src/main/index.js +14 -21
- package/src/main/options/normalize.js +33 -0
- package/src/meta.js +1 -1
- package/src/schema/configuration.schema.js +1 -1
- package/src/schema/cruise-result.schema.js +1 -1
- package/src/utl/find-all-files.js +79 -0
- package/types/cache-options.d.ts +22 -0
- package/types/cruise-result.d.ts +1 -1
- package/types/options.d.ts +23 -10
- package/types/strict-options.d.ts +2 -0
package/LICENSE
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dependency-cruiser",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.5.0-beta-1",
|
|
4
4
|
"description": "Validate and visualize dependencies. With your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"static analysis",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"test:i": "LANG=en_US.UTF-8 mocha --grep \"^\\[[I]\\]\"",
|
|
123
123
|
"test:u": "LANG=en_US.UTF-8 mocha --grep \"^\\[[U]\\]\"",
|
|
124
124
|
"test:e": "LANG=en_US.UTF-8 mocha --grep \"^\\[[E]\\]\"",
|
|
125
|
-
"test:cover": "LANG=en_US.UTF-8 c8 --check-coverage --statements 99.9 --branches 99.7 --functions 100 --lines 99.9 --exclude \"{bin,configs/*.js,configs/rules,configs/plugins/3d-*.js,configs/plugins/stats-*.js,doc,docs,coverage,test,tools,webpack.conf.js,tmp*,src/**/*.template.js,src/cli/tools/svg-in-html-snippets/script.snippet.js,src/cli/init-config/get-user-input.js,src/cli/listeners/*/index.js}\" --reporter text-summary --reporter html --reporter json-summary mocha",
|
|
125
|
+
"test:cover": "LANG=en_US.UTF-8 c8 --check-coverage --statements 99.9 --branches 99.7 --functions 100 --lines 99.9 --exclude \"{bin,configs/*.js,configs/rules,configs/plugins/3d-*.js,configs/plugins/stats-*.js,doc,docs,coverage,test,tools,webpack.conf.js,tmp*,src/**/*.template.js,src/cli/tools/svg-in-html-snippets/script.snippet.js,src/cli/init-config/get-user-input.js,src/cli/listeners/*/index.js,src/cli/listeners/cli-feedback.js}\" --reporter text-summary --reporter html --reporter json-summary mocha",
|
|
126
126
|
"test:glob": "set -f && test \"`bin/dependency-cruise.js test/extract/__mocks__/gather-globbing/packages/**/src/**/*.js | grep \"no dependency violations found\"`\" = \"✔ no dependency violations found (6 modules, 0 dependencies cruised)\"",
|
|
127
127
|
"test:yarn-pnp": "npm-run-all test:yarn-pnp:cleanup test:yarn-pnp:pack test:yarn-pnp:copy test:yarn-pnp:install test:yarn-pnp:version test:yarn-pnp:run test:yarn-pnp:test test:yarn-pnp:cleanup",
|
|
128
128
|
"test:yarn-pnp:pack": "npm pack",
|
|
@@ -147,18 +147,19 @@
|
|
|
147
147
|
"acorn-jsx-walk": "2.0.0",
|
|
148
148
|
"acorn-loose": "8.3.0",
|
|
149
149
|
"acorn-walk": "8.2.0",
|
|
150
|
-
"ajv": "8.
|
|
150
|
+
"ajv": "8.12.0",
|
|
151
151
|
"chalk": "^4.1.2",
|
|
152
|
-
"commander": "9.
|
|
152
|
+
"commander": "9.5.0",
|
|
153
153
|
"enhanced-resolve": "5.12.0",
|
|
154
154
|
"figures": "^3.2.0",
|
|
155
155
|
"get-stream": "^6.0.1",
|
|
156
156
|
"glob": "7.2.0",
|
|
157
157
|
"handlebars": "4.7.7",
|
|
158
|
+
"ignore": "5.2.4",
|
|
158
159
|
"indent-string": "^4.0.0",
|
|
159
160
|
"interpret": "^3.1.0",
|
|
160
161
|
"is-installed-globally": "0.4.0",
|
|
161
|
-
"json5": "2.2.
|
|
162
|
+
"json5": "2.2.3",
|
|
162
163
|
"lodash": "4.17.21",
|
|
163
164
|
"prompts": "2.4.2",
|
|
164
165
|
"rechoir": "^0.8.0",
|
|
@@ -171,23 +172,23 @@
|
|
|
171
172
|
"wrap-ansi": "^7.0.0"
|
|
172
173
|
},
|
|
173
174
|
"devDependencies": {
|
|
174
|
-
"@babel/core": "7.20.
|
|
175
|
+
"@babel/core": "7.20.12",
|
|
175
176
|
"@babel/plugin-transform-modules-commonjs": "7.20.11",
|
|
176
177
|
"@babel/preset-typescript": "7.18.6",
|
|
177
|
-
"@swc/core": "1.3.
|
|
178
|
+
"@swc/core": "1.3.25",
|
|
178
179
|
"@types/lodash": "4.14.191",
|
|
179
180
|
"@types/node": "18.11.18",
|
|
180
181
|
"@types/prompts": "2.4.2",
|
|
181
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
182
|
-
"@typescript-eslint/parser": "5.
|
|
182
|
+
"@typescript-eslint/eslint-plugin": "5.48.0",
|
|
183
|
+
"@typescript-eslint/parser": "5.48.0",
|
|
183
184
|
"@vue/compiler-sfc": "3.2.45",
|
|
184
185
|
"c8": "7.12.0",
|
|
185
186
|
"chai": "4.3.7",
|
|
186
187
|
"chai-json-schema": "1.5.1",
|
|
187
188
|
"coffeescript": "2.7.0",
|
|
188
|
-
"eslint": "8.
|
|
189
|
+
"eslint": "8.31.0",
|
|
189
190
|
"eslint-config-moving-meadow": "4.0.2",
|
|
190
|
-
"eslint-config-prettier": "8.
|
|
191
|
+
"eslint-config-prettier": "8.6.0",
|
|
191
192
|
"eslint-plugin-budapestian": "5.0.1",
|
|
192
193
|
"eslint-plugin-eslint-comments": "3.2.0",
|
|
193
194
|
"eslint-plugin-import": "2.26.0",
|
|
@@ -195,13 +196,13 @@
|
|
|
195
196
|
"eslint-plugin-node": "11.1.0",
|
|
196
197
|
"eslint-plugin-security": "1.5.0",
|
|
197
198
|
"eslint-plugin-unicorn": "^45.0.0",
|
|
198
|
-
"husky": "8.0.
|
|
199
|
+
"husky": "8.0.3",
|
|
199
200
|
"intercept-stdout": "0.1.2",
|
|
200
201
|
"lint-staged": "13.1.0",
|
|
201
202
|
"mocha": "10.2.0",
|
|
202
203
|
"normalize-newline": "^3.0.0",
|
|
203
204
|
"npm-run-all": "4.1.5",
|
|
204
|
-
"prettier": "2.8.
|
|
205
|
+
"prettier": "2.8.2",
|
|
205
206
|
"proxyquire": "2.1.3",
|
|
206
207
|
"shx": "0.3.4",
|
|
207
208
|
"svelte": "3.55.0",
|
package/src/cache/cache.js
CHANGED
|
@@ -1,56 +1,87 @@
|
|
|
1
1
|
const { readFileSync, mkdirSync, writeFileSync } = require("fs");
|
|
2
2
|
const { join } = require("path");
|
|
3
|
+
const meta = require("../extract/transpile/meta");
|
|
3
4
|
const { optionsAreCompatible } = require("./options-compatible");
|
|
4
|
-
const
|
|
5
|
+
const metadataStrategy = require("./metadata-strategy");
|
|
6
|
+
const contentStrategy = require("./content-strategy");
|
|
5
7
|
|
|
6
8
|
const CACHE_FILE_NAME = "cache.json";
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
* @param {string} pCacheFolder
|
|
10
|
-
* @param {import("../../types/cruise-result").ICruiseResult} pCruiseResult
|
|
11
|
-
*/
|
|
12
|
-
function writeCache(pCacheFolder, pCruiseResult) {
|
|
13
|
-
mkdirSync(pCacheFolder, { recursive: true });
|
|
14
|
-
writeFileSync(
|
|
15
|
-
join(pCacheFolder, CACHE_FILE_NAME),
|
|
16
|
-
JSON.stringify(pCruiseResult),
|
|
17
|
-
"utf8"
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
9
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
10
|
+
module.exports = class Cache {
|
|
11
|
+
/**
|
|
12
|
+
* @param {import("../../types/cache-options").cacheStrategyType=} pCacheStrategy
|
|
13
|
+
*/
|
|
14
|
+
constructor(pCacheStrategy) {
|
|
15
|
+
this.revisionData = null;
|
|
16
|
+
this.cacheStrategy =
|
|
17
|
+
pCacheStrategy === "content" ? contentStrategy : metadataStrategy;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @param {import("../../types/strict-options").IStrictCruiseOptions} pCruiseOptions
|
|
22
|
+
* @param {import("../..").ICruiseResult} pCachedCruiseResult
|
|
23
|
+
* @param {import("../..").IRevisionData=} pRevisionData
|
|
24
|
+
* @returns {boolean}
|
|
25
|
+
*/
|
|
26
|
+
canServeFromCache(pCruiseOptions, pCachedCruiseResult, pRevisionData) {
|
|
27
|
+
this.revisionData =
|
|
28
|
+
pRevisionData ??
|
|
29
|
+
this.cacheStrategy.getRevisionData(
|
|
30
|
+
".",
|
|
31
|
+
pCachedCruiseResult,
|
|
32
|
+
pCruiseOptions,
|
|
33
|
+
{
|
|
34
|
+
extensions: new Set(
|
|
35
|
+
meta.scannableExtensions.concat(
|
|
36
|
+
pCruiseOptions.extraExtensionsToScan
|
|
37
|
+
)
|
|
38
|
+
),
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
return (
|
|
42
|
+
this.cacheStrategy.revisionDataEqual(
|
|
43
|
+
pCachedCruiseResult.revisionData,
|
|
44
|
+
this.revisionData
|
|
45
|
+
) &&
|
|
46
|
+
optionsAreCompatible(
|
|
47
|
+
pCachedCruiseResult.summary.optionsUsed,
|
|
48
|
+
pCruiseOptions
|
|
49
|
+
)
|
|
30
50
|
);
|
|
31
|
-
} catch (pError) {
|
|
32
|
-
return { modules: [], summary: {} };
|
|
33
51
|
}
|
|
34
|
-
}
|
|
35
52
|
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
/**
|
|
54
|
+
* @param {string} pCacheFolder
|
|
55
|
+
* @returns {import("../..").ICruiseResult}
|
|
56
|
+
*/
|
|
57
|
+
read(pCacheFolder) {
|
|
58
|
+
try {
|
|
59
|
+
return JSON.parse(
|
|
60
|
+
readFileSync(join(pCacheFolder, CACHE_FILE_NAME), "utf8")
|
|
61
|
+
);
|
|
62
|
+
} catch (pError) {
|
|
63
|
+
return { modules: [], summary: {} };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
45
66
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
67
|
+
/**
|
|
68
|
+
* @param {string} pCacheFolder
|
|
69
|
+
* @param {import("../..").ICruiseResult} pCruiseResult
|
|
70
|
+
* @param {import("../..").IRevisionData=} pRevisionData
|
|
71
|
+
*/
|
|
72
|
+
write(pCacheFolder, pCruiseResult, pRevisionData) {
|
|
73
|
+
const lRevisionData = pRevisionData ?? this.revisionData;
|
|
51
74
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
75
|
+
mkdirSync(pCacheFolder, { recursive: true });
|
|
76
|
+
writeFileSync(
|
|
77
|
+
join(pCacheFolder, CACHE_FILE_NAME),
|
|
78
|
+
JSON.stringify(
|
|
79
|
+
this.cacheStrategy.prepareRevisionDataForSaving(
|
|
80
|
+
pCruiseResult,
|
|
81
|
+
lRevisionData
|
|
82
|
+
)
|
|
83
|
+
),
|
|
84
|
+
"utf8"
|
|
85
|
+
);
|
|
86
|
+
}
|
|
56
87
|
};
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const { isDeepStrictEqual } = require("util");
|
|
3
|
+
const { filenameMatchesPattern } = require("../graph-utl/match-facade");
|
|
4
|
+
const bus = require("../utl/bus");
|
|
5
|
+
const { DEBUG } = require("../utl/bus-log-levels");
|
|
6
|
+
const findAllFiles = require("../utl/find-all-files");
|
|
7
|
+
const { getFileHash } = require("./utl");
|
|
8
|
+
|
|
9
|
+
// skipping: "pairing broken", "unmodified", "unmerged", "type changed"
|
|
10
|
+
const DEFAULT_INTERESTING_CHANGE_TYPES = new Set([
|
|
11
|
+
"added",
|
|
12
|
+
"copied",
|
|
13
|
+
"deleted",
|
|
14
|
+
"ignored",
|
|
15
|
+
"modified",
|
|
16
|
+
"renamed",
|
|
17
|
+
"unmerged",
|
|
18
|
+
"untracked",
|
|
19
|
+
]);
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {Set<string>} pExtensions
|
|
23
|
+
* @returns {(pChange: import("watskeburt").IChange) => boolean}
|
|
24
|
+
*/
|
|
25
|
+
function hasInterestingExtension(pExtensions) {
|
|
26
|
+
return (pChange) => pExtensions.has(path.extname(pChange.name));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {Set<import("watskeburt").changeTypeType>} pInterestingChangeTypes
|
|
31
|
+
* @returns {(pChange: import("watskeburt").IChange) => boolean}
|
|
32
|
+
*/
|
|
33
|
+
function isInterestingChangeType(pInterestingChangeTypes) {
|
|
34
|
+
return (pChange) => pInterestingChangeTypes.has(pChange.changeType);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {import("watskeburt").IChange} pChange
|
|
39
|
+
* @param {import("../..").IRevisionChange}
|
|
40
|
+
*/
|
|
41
|
+
function addCheckSumToChange(pChange) {
|
|
42
|
+
return {
|
|
43
|
+
...pChange,
|
|
44
|
+
checkSum: getFileHash(pChange.name),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* @param {import("../../types/strict-filter-types").IStrictExcludeType} pExcludeOption
|
|
50
|
+
* @returns {(pFileName: string) => boolean}
|
|
51
|
+
*/
|
|
52
|
+
function excludeFilter(pExcludeOption) {
|
|
53
|
+
return (pFileName) => {
|
|
54
|
+
if (pExcludeOption.path) {
|
|
55
|
+
return !filenameMatchesPattern(pFileName, pExcludeOption.path);
|
|
56
|
+
}
|
|
57
|
+
return true;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param {import("../../types/strict-filter-types").IStrictIncludeOnlyType} pIncludeOnlyFilter
|
|
63
|
+
* @returns {(pFileName: string) => boolean}
|
|
64
|
+
*/
|
|
65
|
+
function includeOnlyFilter(pIncludeOnlyFilter) {
|
|
66
|
+
return (pFileName) => {
|
|
67
|
+
if (pIncludeOnlyFilter) {
|
|
68
|
+
return filenameMatchesPattern(pFileName, pIncludeOnlyFilter.path);
|
|
69
|
+
}
|
|
70
|
+
return true;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function diffCachedModuleAgainstFileSet(
|
|
75
|
+
pFileSet,
|
|
76
|
+
pFileHashFunction = getFileHash
|
|
77
|
+
) {
|
|
78
|
+
// eslint-disable-next-line complexity
|
|
79
|
+
return (pModule) => {
|
|
80
|
+
if (
|
|
81
|
+
!pModule.consolidated &&
|
|
82
|
+
!pModule.coreModule &&
|
|
83
|
+
!pModule.couldNotResolve &&
|
|
84
|
+
!pModule.matchesDoNotFollow
|
|
85
|
+
) {
|
|
86
|
+
if (!pFileSet.has(pModule.source)) {
|
|
87
|
+
return { name: pModule.source, changeType: "deleted" };
|
|
88
|
+
}
|
|
89
|
+
const lNewCheckSum = pFileHashFunction(pModule.source);
|
|
90
|
+
if (lNewCheckSum !== pModule.checkSum) {
|
|
91
|
+
return {
|
|
92
|
+
name: pModule.source,
|
|
93
|
+
changeType: "modified",
|
|
94
|
+
checkSum: lNewCheckSum,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
name: pModule.source,
|
|
100
|
+
changeType: "unmodified",
|
|
101
|
+
checkSum: pModule.checkSum,
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
- there is no cache yet:
|
|
108
|
+
modules will === []; all files will be marked as 'added'
|
|
109
|
+
- there is a cache and it contains checksums:
|
|
110
|
+
- existing files that are not in the cache => added
|
|
111
|
+
- modules that are in the cache:
|
|
112
|
+
- don't exist anymore => deleted TODO:
|
|
113
|
+
we might wrongly bump into this for files that are gitignored and that don't have an interesting extension
|
|
114
|
+
- cached checksum === current checksum => not a change; left out
|
|
115
|
+
- cached checksum !== current checksum => modified
|
|
116
|
+
- there is a cache, but it doesn't contain checksums => same as before, except
|
|
117
|
+
all files will be marked as 'modified'
|
|
118
|
+
* @param {string} pDirectory
|
|
119
|
+
* @param {import("../..").ICruiseResult} pCachedCruiseResult
|
|
120
|
+
* @param {Object} pOptions
|
|
121
|
+
* @param {Set<string>} pOptions.extensions
|
|
122
|
+
* @param {string} pOptions.baseDir
|
|
123
|
+
* @returns {{source: string; changeType: import("watskeburt").changeTypeType; checkSum: string}[]}
|
|
124
|
+
*/
|
|
125
|
+
function findChanges(pDirectory, pCachedCruiseResult, pOptions) {
|
|
126
|
+
bus.emit("progress", "cache: - hauling revision data", { level: DEBUG });
|
|
127
|
+
const lFileSet = new Set(
|
|
128
|
+
findAllFiles(pDirectory, {
|
|
129
|
+
baseDir: pOptions.baseDir,
|
|
130
|
+
})
|
|
131
|
+
.filter(excludeFilter(pOptions.exclude))
|
|
132
|
+
.filter(includeOnlyFilter(pOptions.includeOnly))
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
bus.emit("progress", "cache: - determining cached vs new", { level: DEBUG });
|
|
136
|
+
const lDiffCachedVsNew = pCachedCruiseResult.modules.map(
|
|
137
|
+
diffCachedModuleAgainstFileSet(lFileSet)
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
bus.emit("progress", "cache: - determining new vs cached", { level: DEBUG });
|
|
141
|
+
lDiffCachedVsNew.forEach(({ name }) => lFileSet.delete(name));
|
|
142
|
+
|
|
143
|
+
const lDiffNewVsCached = [];
|
|
144
|
+
for (let lFileName of lFileSet) {
|
|
145
|
+
lDiffNewVsCached.push({
|
|
146
|
+
name: lFileName,
|
|
147
|
+
changeType: "added",
|
|
148
|
+
checkSum: getFileHash(lFileName),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
bus.emit("progress", "cache: - returning revision data", { level: DEBUG });
|
|
153
|
+
return lDiffCachedVsNew
|
|
154
|
+
.concat(lDiffNewVsCached)
|
|
155
|
+
.filter(hasInterestingExtension(pOptions.extensions));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
*
|
|
160
|
+
* @param {string} pDirectory
|
|
161
|
+
* @param {import("../..").ICruiseResult} pCachedCruiseResult
|
|
162
|
+
* @param {import("../../types/strict-options").IStrictCruiseOptions} pCruiseOptions
|
|
163
|
+
* @param {Object} pOptions
|
|
164
|
+
* @param {Set<string>} pOptions.extensions
|
|
165
|
+
* @param {Set<import("watskeburt").changeTypeType>} pOptions.interestingChangeTypes
|
|
166
|
+
* @param {string} pOptions.baseDir
|
|
167
|
+
* @param {(pString:string) => Array<import("watskeburt").IChange>} pOptions.diffListFn
|
|
168
|
+
* @param {(import("watskeburt").IChange) => import("../..").IRevisionChange} pOptions.checkSumFn
|
|
169
|
+
* @returns {import("../..").IRevisionData}
|
|
170
|
+
*/
|
|
171
|
+
function getRevisionData(
|
|
172
|
+
pDirectory,
|
|
173
|
+
pCachedCruiseResult,
|
|
174
|
+
pCruiseOptions,
|
|
175
|
+
pOptions
|
|
176
|
+
) {
|
|
177
|
+
const lOptions = {
|
|
178
|
+
diffListFn: findChanges,
|
|
179
|
+
checkSumFn: addCheckSumToChange,
|
|
180
|
+
interestingChangeTypes: DEFAULT_INTERESTING_CHANGE_TYPES,
|
|
181
|
+
baseDir: process.cwd(),
|
|
182
|
+
...pOptions,
|
|
183
|
+
};
|
|
184
|
+
return {
|
|
185
|
+
SHA1: "unknown-in-content-cache-strategy",
|
|
186
|
+
changes: lOptions
|
|
187
|
+
.diffListFn(pDirectory, pCachedCruiseResult, {
|
|
188
|
+
baseDir: lOptions.baseDir,
|
|
189
|
+
extensions: lOptions.extensions,
|
|
190
|
+
includeOnly: pCruiseOptions.includeOnly,
|
|
191
|
+
exclude: pCruiseOptions.exclude,
|
|
192
|
+
})
|
|
193
|
+
.filter(isInterestingChangeType(lOptions.interestingChangeTypes)),
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* @param {import("../..").IRevisionData} pExistingRevisionData
|
|
199
|
+
* @param {import("../..").IRevisionData} pNewRevisionData
|
|
200
|
+
* @returns {boolean}
|
|
201
|
+
*/
|
|
202
|
+
function revisionDataEqual(pExistingRevisionData, pNewRevisionData) {
|
|
203
|
+
return (
|
|
204
|
+
Boolean(pExistingRevisionData) &&
|
|
205
|
+
Boolean(pNewRevisionData) &&
|
|
206
|
+
isDeepStrictEqual(pExistingRevisionData.changes, pNewRevisionData.changes)
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @param {import("../..").IModule} pModule
|
|
212
|
+
* @param {import("../..").IRevisionChange}
|
|
213
|
+
*/
|
|
214
|
+
function addCheckSumToModule(pModule) {
|
|
215
|
+
if (
|
|
216
|
+
!pModule.consolidated &&
|
|
217
|
+
!pModule.coreModule &&
|
|
218
|
+
!pModule.couldNotResolve &&
|
|
219
|
+
!pModule.matchesDoNotFollow
|
|
220
|
+
) {
|
|
221
|
+
return {
|
|
222
|
+
...pModule,
|
|
223
|
+
checkSum: getFileHash(pModule.source),
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
return pModule;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @param {import("../..").IRevisionChange[]} pChanges
|
|
231
|
+
* @param {import("../..").IModule[]} pModules
|
|
232
|
+
* @returns {import("../..").IRevisionChange[]}
|
|
233
|
+
*/
|
|
234
|
+
function refreshChanges(pChanges, pModules) {
|
|
235
|
+
return pChanges.filter(
|
|
236
|
+
(pChange) =>
|
|
237
|
+
!pModules.some(
|
|
238
|
+
(pModule) =>
|
|
239
|
+
pModule.source === pChange.name &&
|
|
240
|
+
pModule.checkSum === pChange.checkSum
|
|
241
|
+
)
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function prepareRevisionDataForSaving(pCruiseResult, pRevisionData) {
|
|
246
|
+
const lModules = pCruiseResult.modules.map(addCheckSumToModule);
|
|
247
|
+
const lRevisionData = {
|
|
248
|
+
...pRevisionData,
|
|
249
|
+
changes: refreshChanges(pRevisionData.changes, lModules),
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
return pRevisionData
|
|
253
|
+
? {
|
|
254
|
+
...pCruiseResult,
|
|
255
|
+
modules: lModules,
|
|
256
|
+
revisionData: lRevisionData,
|
|
257
|
+
}
|
|
258
|
+
: pCruiseResult;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
module.exports = {
|
|
262
|
+
getRevisionData,
|
|
263
|
+
revisionDataEqual,
|
|
264
|
+
prepareRevisionDataForSaving,
|
|
265
|
+
};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
const { createHash } = require("crypto");
|
|
2
|
-
const { readFileSync } = require("fs");
|
|
3
1
|
const { extname } = require("path");
|
|
2
|
+
const { isDeepStrictEqual } = require("util");
|
|
4
3
|
const { getSHASync, listSync } = require("watskeburt");
|
|
5
|
-
const {
|
|
4
|
+
const { getFileHash } = require("./utl");
|
|
6
5
|
|
|
7
6
|
// skipping: "pairing broken", "unmodified", "unmerged", "type changed"
|
|
8
7
|
const DEFAULT_INTERESTING_CHANGE_TYPES = new Set([
|
|
@@ -17,7 +16,6 @@ const DEFAULT_INTERESTING_CHANGE_TYPES = new Set([
|
|
|
17
16
|
]);
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
|
-
*
|
|
21
19
|
* @param {Set<string>} pExtensions
|
|
22
20
|
* @returns {(pChange: import("watskeburt").IChange) => boolean}
|
|
23
21
|
*/
|
|
@@ -36,34 +34,14 @@ function isInterestingChangeType(pInterestingChangeTypes) {
|
|
|
36
34
|
return (pChange) => pInterestingChangeTypes.has(pChange.changeType);
|
|
37
35
|
}
|
|
38
36
|
|
|
39
|
-
/**
|
|
40
|
-
* @param {string} pString
|
|
41
|
-
* @returns {string}
|
|
42
|
-
*/
|
|
43
|
-
function hash(pString) {
|
|
44
|
-
return createHash("sha1").update(pString).digest("base64");
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* @param {import("fs").PathOrFileDescriptor} pFileName
|
|
49
|
-
* @returns {string}
|
|
50
|
-
*/
|
|
51
|
-
function getFileHash(pFileName) {
|
|
52
|
-
try {
|
|
53
|
-
return hash(readFileSync(pFileName, "utf8"));
|
|
54
|
-
} catch (pError) {
|
|
55
|
-
return "file not found";
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
37
|
/**
|
|
60
38
|
* @param {import("watskeburt").IChange} pChange
|
|
61
|
-
* @param {import("
|
|
39
|
+
* @param {import("../../types/dependency-cruiser").IRevisionChange}
|
|
62
40
|
*/
|
|
63
41
|
function addChecksum(pChange) {
|
|
64
42
|
return {
|
|
65
43
|
...pChange,
|
|
66
|
-
|
|
44
|
+
checkSum: getFileHash(pChange.name),
|
|
67
45
|
};
|
|
68
46
|
}
|
|
69
47
|
|
|
@@ -71,21 +49,26 @@ function addChecksum(pChange) {
|
|
|
71
49
|
*
|
|
72
50
|
* @param {Set<string>} pExtensions
|
|
73
51
|
* @param {Set<import("watskeburt").changeTypeType>} pInterestingChangeTypes
|
|
52
|
+
* @param {import("../../types/strict-options").IStrictCruiseOptions} pCruiseOptions
|
|
74
53
|
* @param {Object} pOptions
|
|
54
|
+
* @param {Set<string>} pOptions.extensions
|
|
55
|
+
* @param {Set<import("watskeburt").changeTypeType>} pOptions.interestingChangeTypes
|
|
75
56
|
* @param {() => string} pOptions.shaRetrievalFn
|
|
76
57
|
* @param {(pString:string) => Array<import("watskeburt").IChange>} pOptions.diffListFn
|
|
77
58
|
* @param {(import("watskeburt").IChange) => import("../..").IRevisionChange} pOptions.checkSumFn
|
|
78
|
-
* @returns {import("
|
|
59
|
+
* @returns {import("../../types/dependency-cruiser").IRevisionData}
|
|
79
60
|
*/
|
|
80
61
|
function getRevisionData(
|
|
81
|
-
|
|
82
|
-
|
|
62
|
+
pDirectory,
|
|
63
|
+
pCachedCruiseResult,
|
|
64
|
+
pCruiseOptions,
|
|
83
65
|
pOptions
|
|
84
66
|
) {
|
|
85
67
|
const lOptions = {
|
|
86
68
|
shaRetrievalFn: getSHASync,
|
|
87
69
|
diffListFn: listSync,
|
|
88
70
|
checkSumFn: addChecksum,
|
|
71
|
+
interestingChangeTypes: DEFAULT_INTERESTING_CHANGE_TYPES,
|
|
89
72
|
...pOptions,
|
|
90
73
|
};
|
|
91
74
|
try {
|
|
@@ -94,8 +77,9 @@ function getRevisionData(
|
|
|
94
77
|
SHA1: lSHA,
|
|
95
78
|
changes: lOptions
|
|
96
79
|
.diffListFn(lSHA)
|
|
97
|
-
|
|
98
|
-
.filter(
|
|
80
|
+
// TODO: optimize - also apply filters for exclude and includeOnly (see content strategy)
|
|
81
|
+
.filter(hasInterestingExtension(lOptions.extensions))
|
|
82
|
+
.filter(isInterestingChangeType(lOptions.interestingChangeTypes))
|
|
99
83
|
.map(lOptions.checkSumFn),
|
|
100
84
|
};
|
|
101
85
|
} catch (pError) {
|
|
@@ -108,8 +92,8 @@ function getRevisionData(
|
|
|
108
92
|
}
|
|
109
93
|
|
|
110
94
|
/**
|
|
111
|
-
* @param {import("
|
|
112
|
-
* @param {import("
|
|
95
|
+
* @param {import("../../types/dependency-cruiser").IRevisionData} pExistingRevisionData
|
|
96
|
+
* @param {import("../../types/dependency-cruiser").IRevisionData} pNewRevisionData
|
|
113
97
|
* @returns {boolean}
|
|
114
98
|
*/
|
|
115
99
|
function revisionDataEqual(pExistingRevisionData, pNewRevisionData) {
|
|
@@ -117,11 +101,27 @@ function revisionDataEqual(pExistingRevisionData, pNewRevisionData) {
|
|
|
117
101
|
Boolean(pExistingRevisionData) &&
|
|
118
102
|
Boolean(pNewRevisionData) &&
|
|
119
103
|
pExistingRevisionData.SHA1 === pNewRevisionData.SHA1 &&
|
|
120
|
-
|
|
104
|
+
isDeepStrictEqual(pExistingRevisionData.changes, pNewRevisionData.changes)
|
|
121
105
|
);
|
|
122
106
|
}
|
|
123
107
|
|
|
108
|
+
/**
|
|
109
|
+
*
|
|
110
|
+
* @param {import("../..").ICruiseResult} pCruiseResult
|
|
111
|
+
* @param {*} pRevisionData
|
|
112
|
+
* @returns {import("../..").ICruiseResult}
|
|
113
|
+
*/
|
|
114
|
+
function prepareRevisionDataForSaving(pCruiseResult, pRevisionData) {
|
|
115
|
+
return pRevisionData
|
|
116
|
+
? {
|
|
117
|
+
...pCruiseResult,
|
|
118
|
+
revisionData: pRevisionData,
|
|
119
|
+
}
|
|
120
|
+
: pCruiseResult;
|
|
121
|
+
}
|
|
122
|
+
|
|
124
123
|
module.exports = {
|
|
125
124
|
getRevisionData,
|
|
126
125
|
revisionDataEqual,
|
|
126
|
+
prepareRevisionDataForSaving,
|
|
127
127
|
};
|