@syke1/mcp-server 1.5.6 → 1.6.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 +13 -57
- package/README.md +18 -21
- package/dist/ai/analyzer.js +1 -112
- package/dist/ai/context-extractor.js +1 -224
- package/dist/ai/provider.js +1 -186
- package/dist/ai/realtime-analyzer.js +1 -253
- package/dist/config.js +1 -121
- package/dist/git/change-coupling.js +1 -250
- package/dist/graph/incremental.js +1 -319
- package/dist/graph/memo-cache.js +1 -176
- package/dist/graph/scc.js +1 -206
- package/dist/graph.js +1 -137
- package/dist/index.js +1 -852
- package/dist/license/validator.d.ts +3 -0
- package/dist/license/validator.js +1 -328
- package/dist/scoring/pagerank.js +1 -221
- package/dist/scoring/risk-scorer.js +1 -623
- package/dist/tools/analyze-impact.js +1 -378
- package/dist/tools/gate-build.js +1 -409
- package/dist/watcher/file-cache.js +1 -281
- package/dist/web/server.js +1 -925
- package/package.json +53 -68
|
@@ -1,250 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.invalidateCouplingCache = invalidateCouplingCache;
|
|
4
|
-
exports.mineGitHistory = mineGitHistory;
|
|
5
|
-
exports.getCoupledFiles = getCoupledFiles;
|
|
6
|
-
const child_process_1 = require("child_process");
|
|
7
|
-
// ── Defaults ──
|
|
8
|
-
const DEFAULT_MAX_COMMITS = 500;
|
|
9
|
-
const DEFAULT_MIN_SUPPORT = 3;
|
|
10
|
-
const DEFAULT_MIN_CONFIDENCE = 0.3;
|
|
11
|
-
const DEFAULT_MAX_FILES_PER_COMMIT = 20;
|
|
12
|
-
const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
13
|
-
// ── Cache ──
|
|
14
|
-
let cachedResult = null;
|
|
15
|
-
let cachedProjectRoot = null;
|
|
16
|
-
/**
|
|
17
|
-
* Invalidate the coupling cache. Call this when the graph is refreshed
|
|
18
|
-
* or when git history may have changed.
|
|
19
|
-
*/
|
|
20
|
-
function invalidateCouplingCache() {
|
|
21
|
-
cachedResult = null;
|
|
22
|
-
cachedProjectRoot = null;
|
|
23
|
-
}
|
|
24
|
-
// ── Git History Mining ──
|
|
25
|
-
/**
|
|
26
|
-
* Check whether the given directory is inside a git repository.
|
|
27
|
-
*/
|
|
28
|
-
function isGitRepo(projectRoot) {
|
|
29
|
-
try {
|
|
30
|
-
(0, child_process_1.execSync)("git rev-parse --is-inside-work-tree", {
|
|
31
|
-
cwd: projectRoot,
|
|
32
|
-
encoding: "utf-8",
|
|
33
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
34
|
-
});
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Parse git log output into a list of commits, each containing
|
|
43
|
-
* the list of files changed in that commit.
|
|
44
|
-
*/
|
|
45
|
-
function parseGitLog(raw) {
|
|
46
|
-
const commits = [];
|
|
47
|
-
const segments = raw.split("COMMIT:");
|
|
48
|
-
for (const segment of segments) {
|
|
49
|
-
const trimmed = segment.trim();
|
|
50
|
-
if (!trimmed)
|
|
51
|
-
continue;
|
|
52
|
-
// First line is the commit hash, remaining lines are file paths
|
|
53
|
-
const lines = trimmed.split("\n");
|
|
54
|
-
const files = [];
|
|
55
|
-
for (let i = 1; i < lines.length; i++) {
|
|
56
|
-
const fileLine = lines[i].trim();
|
|
57
|
-
if (fileLine) {
|
|
58
|
-
files.push(fileLine);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (files.length > 0) {
|
|
62
|
-
commits.push(files);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return commits;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Normalize a git-output path (forward slashes) to be consistent
|
|
69
|
-
* with how the dependency graph stores paths.
|
|
70
|
-
*/
|
|
71
|
-
function normalizePath(filePath) {
|
|
72
|
-
// Git always outputs forward slashes; normalize for consistency
|
|
73
|
-
return filePath.replace(/\\/g, "/");
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Check if a file path looks like a source file (not binary, not config noise).
|
|
77
|
-
* We keep this broad — the dependency graph comparison will handle the real filtering.
|
|
78
|
-
*/
|
|
79
|
-
function isSourceFile(filePath) {
|
|
80
|
-
// Skip obviously non-source files
|
|
81
|
-
const skipPatterns = [
|
|
82
|
-
/\.lock$/,
|
|
83
|
-
/package-lock\.json$/,
|
|
84
|
-
/yarn\.lock$/,
|
|
85
|
-
/\.min\.(js|css)$/,
|
|
86
|
-
/\.map$/,
|
|
87
|
-
/\.d\.ts$/,
|
|
88
|
-
/\.png$/,
|
|
89
|
-
/\.jpg$/,
|
|
90
|
-
/\.jpeg$/,
|
|
91
|
-
/\.gif$/,
|
|
92
|
-
/\.svg$/,
|
|
93
|
-
/\.ico$/,
|
|
94
|
-
/\.woff2?$/,
|
|
95
|
-
/\.ttf$/,
|
|
96
|
-
/\.eot$/,
|
|
97
|
-
/\.pdf$/,
|
|
98
|
-
/\.zip$/,
|
|
99
|
-
/\.tar$/,
|
|
100
|
-
/\.gz$/,
|
|
101
|
-
];
|
|
102
|
-
const normalized = filePath.toLowerCase();
|
|
103
|
-
return !skipPatterns.some((p) => p.test(normalized));
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Create a canonical pair key for two files (order-independent).
|
|
107
|
-
*/
|
|
108
|
-
function pairKey(a, b) {
|
|
109
|
-
return a < b ? `${a}\0${b}` : `${b}\0${a}`;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Mine git history to find files that frequently co-change.
|
|
113
|
-
*
|
|
114
|
-
* Runs `git log --name-only` and analyzes pairwise file combinations
|
|
115
|
-
* within each commit to identify hidden logical dependencies.
|
|
116
|
-
*/
|
|
117
|
-
async function mineGitHistory(projectRoot, options) {
|
|
118
|
-
// Return cached result if still valid
|
|
119
|
-
if (cachedResult &&
|
|
120
|
-
cachedProjectRoot === projectRoot &&
|
|
121
|
-
Date.now() - cachedResult.analyzedAt < CACHE_TTL_MS) {
|
|
122
|
-
return cachedResult;
|
|
123
|
-
}
|
|
124
|
-
const maxCommits = options?.maxCommits ?? DEFAULT_MAX_COMMITS;
|
|
125
|
-
const minSupport = options?.minSupport ?? DEFAULT_MIN_SUPPORT;
|
|
126
|
-
const minConfidence = options?.minConfidence ?? DEFAULT_MIN_CONFIDENCE;
|
|
127
|
-
const maxFilesPerCommit = options?.maxFilesPerCommit ?? DEFAULT_MAX_FILES_PER_COMMIT;
|
|
128
|
-
// Empty result for non-git projects
|
|
129
|
-
const emptyResult = {
|
|
130
|
-
couplings: [],
|
|
131
|
-
fileCouplings: new Map(),
|
|
132
|
-
totalCommitsAnalyzed: 0,
|
|
133
|
-
analyzedAt: Date.now(),
|
|
134
|
-
};
|
|
135
|
-
if (!isGitRepo(projectRoot)) {
|
|
136
|
-
cachedResult = emptyResult;
|
|
137
|
-
cachedProjectRoot = projectRoot;
|
|
138
|
-
return emptyResult;
|
|
139
|
-
}
|
|
140
|
-
// Run git log
|
|
141
|
-
let raw;
|
|
142
|
-
try {
|
|
143
|
-
raw = (0, child_process_1.execSync)(`git log --name-only --format="COMMIT:%H" --max-count=${maxCommits}`, {
|
|
144
|
-
cwd: projectRoot,
|
|
145
|
-
encoding: "utf-8",
|
|
146
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
147
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
cachedResult = emptyResult;
|
|
152
|
-
cachedProjectRoot = projectRoot;
|
|
153
|
-
return emptyResult;
|
|
154
|
-
}
|
|
155
|
-
const commits = parseGitLog(raw);
|
|
156
|
-
// Track per-file change counts and per-pair co-change counts
|
|
157
|
-
const fileChangeCount = new Map();
|
|
158
|
-
const pairCoChangeCount = new Map();
|
|
159
|
-
let totalCommitsAnalyzed = 0;
|
|
160
|
-
for (const commitFiles of commits) {
|
|
161
|
-
// Filter to source files and normalize paths
|
|
162
|
-
const filtered = commitFiles
|
|
163
|
-
.map(normalizePath)
|
|
164
|
-
.filter(isSourceFile);
|
|
165
|
-
// Skip mega-commits (merge commits, large refactors)
|
|
166
|
-
if (filtered.length > maxFilesPerCommit || filtered.length < 2) {
|
|
167
|
-
if (filtered.length === 1) {
|
|
168
|
-
// Still count single-file commits for per-file totals
|
|
169
|
-
const file = filtered[0];
|
|
170
|
-
fileChangeCount.set(file, (fileChangeCount.get(file) || 0) + 1);
|
|
171
|
-
}
|
|
172
|
-
totalCommitsAnalyzed++;
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
totalCommitsAnalyzed++;
|
|
176
|
-
// Count per-file changes
|
|
177
|
-
for (const file of filtered) {
|
|
178
|
-
fileChangeCount.set(file, (fileChangeCount.get(file) || 0) + 1);
|
|
179
|
-
}
|
|
180
|
-
// Count pairwise co-changes
|
|
181
|
-
for (let i = 0; i < filtered.length; i++) {
|
|
182
|
-
for (let j = i + 1; j < filtered.length; j++) {
|
|
183
|
-
const key = pairKey(filtered[i], filtered[j]);
|
|
184
|
-
pairCoChangeCount.set(key, (pairCoChangeCount.get(key) || 0) + 1);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
// Build coupling results, filtering by thresholds
|
|
189
|
-
const couplings = [];
|
|
190
|
-
for (const [key, coCount] of pairCoChangeCount) {
|
|
191
|
-
if (coCount < minSupport)
|
|
192
|
-
continue;
|
|
193
|
-
const [file1, file2] = key.split("\0");
|
|
194
|
-
const file1Changes = fileChangeCount.get(file1) || 0;
|
|
195
|
-
const file2Changes = fileChangeCount.get(file2) || 0;
|
|
196
|
-
const maxChanges = Math.max(file1Changes, file2Changes);
|
|
197
|
-
const confidence = maxChanges > 0 ? coCount / maxChanges : 0;
|
|
198
|
-
if (confidence < minConfidence)
|
|
199
|
-
continue;
|
|
200
|
-
couplings.push({
|
|
201
|
-
file1,
|
|
202
|
-
file2,
|
|
203
|
-
coChangeCount: coCount,
|
|
204
|
-
file1Changes,
|
|
205
|
-
file2Changes,
|
|
206
|
-
confidence,
|
|
207
|
-
support: coCount,
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
// Sort by confidence descending
|
|
211
|
-
couplings.sort((a, b) => b.confidence - a.confidence);
|
|
212
|
-
// Build the per-file lookup map
|
|
213
|
-
const fileCouplings = new Map();
|
|
214
|
-
for (const coupling of couplings) {
|
|
215
|
-
// Add to file1's list
|
|
216
|
-
if (!fileCouplings.has(coupling.file1)) {
|
|
217
|
-
fileCouplings.set(coupling.file1, []);
|
|
218
|
-
}
|
|
219
|
-
fileCouplings.get(coupling.file1).push(coupling);
|
|
220
|
-
// Add to file2's list
|
|
221
|
-
if (!fileCouplings.has(coupling.file2)) {
|
|
222
|
-
fileCouplings.set(coupling.file2, []);
|
|
223
|
-
}
|
|
224
|
-
fileCouplings.get(coupling.file2).push(coupling);
|
|
225
|
-
}
|
|
226
|
-
// Sort each file's couplings by confidence descending
|
|
227
|
-
for (const [, list] of fileCouplings) {
|
|
228
|
-
list.sort((a, b) => b.confidence - a.confidence);
|
|
229
|
-
}
|
|
230
|
-
const result = {
|
|
231
|
-
couplings,
|
|
232
|
-
fileCouplings,
|
|
233
|
-
totalCommitsAnalyzed,
|
|
234
|
-
analyzedAt: Date.now(),
|
|
235
|
-
};
|
|
236
|
-
cachedResult = result;
|
|
237
|
-
cachedProjectRoot = projectRoot;
|
|
238
|
-
return result;
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Get all significant couplings for a given file path.
|
|
242
|
-
* Returns an empty array if no couplings are found.
|
|
243
|
-
*
|
|
244
|
-
* The filePath should be a relative path matching git log output format
|
|
245
|
-
* (forward slashes, relative to project root).
|
|
246
|
-
*/
|
|
247
|
-
function getCoupledFiles(filePath, result) {
|
|
248
|
-
const normalized = normalizePath(filePath);
|
|
249
|
-
return result.fileCouplings.get(normalized) || [];
|
|
250
|
-
}
|
|
1
|
+
'use strict';const _0x2efc11=_0x3683;(function(_0x119b61,_0x4c2975){const _0x495457={_0x3138c9:0x1fe,_0x2e95d4:0x217,_0x101039:0x1f8,_0x413ca1:0x1fd},_0x2c1957=_0x3683,_0x16467d=_0x119b61();while(!![]){try{const _0x4cf828=parseInt(_0x2c1957(0x1fc))/0x1+parseInt(_0x2c1957(_0x495457._0x3138c9))/0x2+-parseInt(_0x2c1957(0x1f9))/0x3*(-parseInt(_0x2c1957(0x213))/0x4)+parseInt(_0x2c1957(_0x495457._0x2e95d4))/0x5+-parseInt(_0x2c1957(_0x495457._0x101039))/0x6+-parseInt(_0x2c1957(0x1ef))/0x7+parseInt(_0x2c1957(_0x495457._0x413ca1))/0x8;if(_0x4cf828===_0x4c2975)break;else _0x16467d['push'](_0x16467d['shift']());}catch(_0x343329){_0x16467d['push'](_0x16467d['shift']());}}}(_0x2df0,0x9a41f));const _0x221e64={};_0x221e64[_0x2efc11(0x1f2)]=!![],Object[_0x2efc11(0x209)](exports,_0x2efc11(0x206),_0x221e64),exports['invalidateCouplingCache']=invalidateCouplingCache,exports['mineGitHistory']=mineGitHistory,exports['getCoupledFiles']=getCoupledFiles;const child_process_1=require(_0x2efc11(0x20d)),DEFAULT_MAX_COMMITS=0x1f4,DEFAULT_MIN_SUPPORT=0x3,DEFAULT_MIN_CONFIDENCE=0.3,DEFAULT_MAX_FILES_PER_COMMIT=0x14,CACHE_TTL_MS=0x5*0x3c*0x3e8;function _0x3683(_0x24fb9a,_0x2f3185){_0x24fb9a=_0x24fb9a-0x1ed;const _0x2df0c1=_0x2df0();let _0x368312=_0x2df0c1[_0x24fb9a];if(_0x3683['cIyQuW']===undefined){var _0xe8001a=function(_0x563981){const _0x3e0b9f='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x37bc7d='',_0x1b3b14='';for(let _0x276deb=0x0,_0x295774,_0x53362b,_0x2c68b4=0x0;_0x53362b=_0x563981['charAt'](_0x2c68b4++);~_0x53362b&&(_0x295774=_0x276deb%0x4?_0x295774*0x40+_0x53362b:_0x53362b,_0x276deb++%0x4)?_0x37bc7d+=String['fromCharCode'](0xff&_0x295774>>(-0x2*_0x276deb&0x6)):0x0){_0x53362b=_0x3e0b9f['indexOf'](_0x53362b);}for(let _0x1fca32=0x0,_0x1c6d72=_0x37bc7d['length'];_0x1fca32<_0x1c6d72;_0x1fca32++){_0x1b3b14+='%'+('00'+_0x37bc7d['charCodeAt'](_0x1fca32)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x1b3b14);};_0x3683['tVSIcB']=_0xe8001a,_0x3683['lnvgNV']={},_0x3683['cIyQuW']=!![];}const _0x12dfab=_0x2df0c1[0x0],_0x5d16bf=_0x24fb9a+_0x12dfab,_0x8c200a=_0x3683['lnvgNV'][_0x5d16bf];return!_0x8c200a?(_0x368312=_0x3683['tVSIcB'](_0x368312),_0x3683['lnvgNV'][_0x5d16bf]=_0x368312):_0x368312=_0x8c200a,_0x368312;}let cachedResult=null,cachedProjectRoot=null;function invalidateCouplingCache(){cachedResult=null,cachedProjectRoot=null;}function isGitRepo(_0x10927f){const _0x20f649={_0x53b320:0x1f3,_0x2d276b:0x1f5,_0x130284:0x216,_0x1edcd6:0x218},_0x3cfb18=_0x2efc11,_0x1f5c78={};_0x1f5c78['KxQTz']=_0x3cfb18(_0x20f649._0x53b320);const _0x429198=_0x1f5c78;try{const _0x348756={};return _0x348756[_0x3cfb18(_0x20f649._0x2d276b)]=_0x10927f,_0x348756['encoding']=_0x3cfb18(_0x20f649._0x130284),_0x348756['stdio']=[_0x429198[_0x3cfb18(_0x20f649._0x1edcd6)],'pipe',_0x429198[_0x3cfb18(0x218)]],(0x0,child_process_1['execSync'])('git\x20rev-parse\x20--is-inside-work-tree',_0x348756),!![];}catch{return![];}}function parseGitLog(_0x289172){const _0x3e3ce3={_0x3197d5:0x204,_0x5779a7:0x215,_0x15db6d:0x201,_0x1b6da7:0x1ff},_0x3f6eec=_0x2efc11,_0xe05e7b={};_0xe05e7b['AbcZm']=_0x3f6eec(_0x3e3ce3._0x3197d5),_0xe05e7b[_0x3f6eec(_0x3e3ce3._0x5779a7)]=function(_0x2483ff,_0x1386b2){return _0x2483ff<_0x1386b2;};const _0x32c63a=_0xe05e7b,_0x12566b=[],_0x25ae9a=_0x289172[_0x3f6eec(_0x3e3ce3._0x15db6d)](_0x32c63a[_0x3f6eec(0x1f6)]);for(const _0x4586d7 of _0x25ae9a){const _0x434ba2=_0x4586d7[_0x3f6eec(_0x3e3ce3._0x1b6da7)]();if(!_0x434ba2)continue;const _0x47f60b=_0x434ba2[_0x3f6eec(0x201)]('\x0a'),_0x33c6df=[];for(let _0x3b9e00=0x1;_0x32c63a['kvLNj'](_0x3b9e00,_0x47f60b[_0x3f6eec(0x210)]);_0x3b9e00++){const _0xa9d4aa=_0x47f60b[_0x3b9e00]['trim']();_0xa9d4aa&&_0x33c6df['push'](_0xa9d4aa);}_0x33c6df['length']>0x0&&_0x12566b[_0x3f6eec(0x205)](_0x33c6df);}return _0x12566b;}function normalizePath(_0x538839){return _0x538839['replace'](/\\/g,'/');}function isSourceFile(_0x1a7292){const _0x68bc64=_0x2efc11,_0x1d123c=[/\.lock$/,/package-lock\.json$/,/yarn\.lock$/,/\.min\.(js|css)$/,/\.map$/,/\.d\.ts$/,/\.png$/,/\.jpg$/,/\.jpeg$/,/\.gif$/,/\.svg$/,/\.ico$/,/\.woff2?$/,/\.ttf$/,/\.eot$/,/\.pdf$/,/\.zip$/,/\.tar$/,/\.gz$/],_0x34498d=_0x1a7292['toLowerCase']();return!_0x1d123c[_0x68bc64(0x211)](_0x1c7088=>_0x1c7088['test'](_0x34498d));}function pairKey(_0x532d4d,_0x3e529d){return _0x532d4d<_0x3e529d?_0x532d4d+'\x00'+_0x3e529d:_0x3e529d+'\x00'+_0x532d4d;}function _0x2df0(){const _0x470894=['A3zmtMO','DxrMltG','ntmWnJaWzM96yK5M','s3HrvhO','C2v0','zMLSztjdAgfUz2vZ','nZC0nZi1mfvksfLNAW','EvDfA2O','CMfiBMK','DMfSDwu','CgLWzq','C29YDa','y3DK','qwjJwM0','wwrQDwO','mZi2otiXnhHyz2jPrW','mZn4zw90DhK','zMLSzunVDxbSAw5NCW','zMLSzti','mtC3nZKYweXkAgLb','ode2odKXmNPezLLXvq','ody5nJi0ueDgEuzL','DhjPBq','C1b1EMi','C3bSAxq','zxHLy1n5BMm','uMXOB0e','q09ntuLuoG','ChvZAa','x19LC01VzhvSzq','BM93','AgfZ','zgvMAw5LuhjVCgvYDhK','y29UzMLKzw5Jzq','z2v0','DLPIwNe','y2HPBgrFChjVy2vZCW','zMLSztfdAgfUz2vZ','C3vWCg9YDa','BgvUz3rO','C29Tzq','zMLSzte','mtK3nJGWELzVCMfu','zw5JB2rPBMC'];_0x2df0=function(){return _0x470894;};return _0x2df0();}async function mineGitHistory(_0x468d33,_0x36fa54){const _0x2bea76={_0x5cf63c:0x216,_0x48e757:0x1f3,_0x3772f6:0x207,_0x3e4aef:0x214,_0x253c0a:0x1f7,_0x1b5dff:0x202,_0x2d61a1:0x210,_0x448ddf:0x203,_0xb980ff:0x20b,_0x4590d7:0x1ed,_0x364db4:0x210,_0x380ece:0x200,_0x37a50f:0x20b,_0x4df886:0x212,_0x3159ea:0x1ee,_0x4a0ea1:0x208,_0x33c0a9:0x212,_0x99ef59:0x1ed,_0x3d0bfb:0x208,_0x3d5fa8:0x1fb,_0x1b8517:0x20b,_0x18e90b:0x1f4},_0x501ab4=_0x2efc11,_0x4bf42b={'XiVLi':function(_0x5a482e,_0x37552d){return _0x5a482e-_0x37552d;},'yVnit':function(_0x3595e5,_0x49e763){return _0x3595e5(_0x49e763);},'nuMGX':_0x501ab4(_0x2bea76._0x5cf63c),'Ydjuj':_0x501ab4(_0x2bea76._0x48e757),'raHni':function(_0x351f1c,_0x1f7f7d){return _0x351f1c(_0x1f7f7d);},'vZbZq':function(_0x30bc60,_0x1f9b67){return _0x30bc60<_0x1f9b67;},'RlhoA':function(_0x12d244,_0x291004){return _0x12d244===_0x291004;},'gKKlS':function(_0x46c236,_0x18353f){return _0x46c236+_0x18353f;},'sPuzb':function(_0x5e839c,_0x795357){return _0x5e839c<_0x795357;}};if(cachedResult&&cachedProjectRoot===_0x468d33&&_0x4bf42b['XiVLi'](Date[_0x501ab4(_0x2bea76._0x3772f6)](),cachedResult['analyzedAt'])<CACHE_TTL_MS)return cachedResult;const _0x41c47c=_0x36fa54?.['maxCommits']??DEFAULT_MAX_COMMITS,_0x5d45b2=_0x36fa54?.['minSupport']??DEFAULT_MIN_SUPPORT,_0x3feeb8=_0x36fa54?.['minConfidence']??DEFAULT_MIN_CONFIDENCE,_0x4ce9b5=_0x36fa54?.['maxFilesPerCommit']??DEFAULT_MAX_FILES_PER_COMMIT,_0x127146={'couplings':[],'fileCouplings':new Map(),'totalCommitsAnalyzed':0x0,'analyzedAt':Date['now']()};if(!_0x4bf42b['yVnit'](isGitRepo,_0x468d33))return cachedResult=_0x127146,cachedProjectRoot=_0x468d33,_0x127146;let _0x182fd1;try{const _0x126bb4={};_0x126bb4[_0x501ab4(0x1f5)]=_0x468d33,_0x126bb4[_0x501ab4(_0x2bea76._0x3e4aef)]=_0x4bf42b['nuMGX'],_0x126bb4['maxBuffer']=0xa*0x400*0x400,_0x126bb4['stdio']=[_0x4bf42b['Ydjuj'],_0x4bf42b[_0x501ab4(_0x2bea76._0x253c0a)],_0x501ab4(0x1f3)],_0x182fd1=(0x0,child_process_1[_0x501ab4(_0x2bea76._0x1b5dff)])('git\x20log\x20--name-only\x20--format=\x22COMMIT:%H\x22\x20--max-count='+_0x41c47c,_0x126bb4);}catch{return cachedResult=_0x127146,cachedProjectRoot=_0x468d33,_0x127146;}const _0x490c16=_0x4bf42b[_0x501ab4(0x1f1)](parseGitLog,_0x182fd1),_0x5dd92e=new Map(),_0xc540dc=new Map();let _0xbe35bd=0x0;for(const _0x2936cc of _0x490c16){const _0x3f2343=_0x2936cc['map'](normalizePath)['filter'](isSourceFile);if(_0x3f2343[_0x501ab4(0x210)]>_0x4ce9b5||_0x4bf42b['vZbZq'](_0x3f2343[_0x501ab4(_0x2bea76._0x2d61a1)],0x2)){if(_0x4bf42b[_0x501ab4(_0x2bea76._0x448ddf)](_0x3f2343[_0x501ab4(0x210)],0x1)){const _0x20498f=_0x3f2343[0x0];_0x5dd92e['set'](_0x20498f,(_0x5dd92e[_0x501ab4(_0x2bea76._0xb980ff)](_0x20498f)||0x0)+0x1);}_0xbe35bd++;continue;}_0xbe35bd++;for(const _0x3bf161 of _0x3f2343){_0x5dd92e[_0x501ab4(_0x2bea76._0x4590d7)](_0x3bf161,_0x4bf42b['gKKlS'](_0x5dd92e[_0x501ab4(0x20b)](_0x3bf161)||0x0,0x1));}for(let _0x319614=0x0;_0x4bf42b[_0x501ab4(0x20c)](_0x319614,_0x3f2343[_0x501ab4(_0x2bea76._0x2d61a1)]);_0x319614++){for(let _0x325daf=_0x319614+0x1;_0x325daf<_0x3f2343[_0x501ab4(_0x2bea76._0x364db4)];_0x325daf++){const _0x4c1f01=pairKey(_0x3f2343[_0x319614],_0x3f2343[_0x325daf]);_0xc540dc[_0x501ab4(0x1ed)](_0x4c1f01,(_0xc540dc[_0x501ab4(_0x2bea76._0xb980ff)](_0x4c1f01)||0x0)+0x1);}}}const _0x2d83e8=[];for(const [_0x1c8e38,_0x3d0099]of _0xc540dc){if(_0x4bf42b[_0x501ab4(_0x2bea76._0x380ece)](_0x3d0099,_0x5d45b2))continue;const [_0x52f935,_0x48c1dc]=_0x1c8e38[_0x501ab4(0x201)]('\x00'),_0x20a7b6=_0x5dd92e[_0x501ab4(_0x2bea76._0x37a50f)](_0x52f935)||0x0,_0x1e2132=_0x5dd92e['get'](_0x48c1dc)||0x0,_0x451c46=Math['max'](_0x20a7b6,_0x1e2132),_0x32254c=_0x451c46>0x0?_0x3d0099/_0x451c46:0x0;if(_0x32254c<_0x3feeb8)continue;const _0x3d20c2={};_0x3d20c2[_0x501ab4(_0x2bea76._0x4df886)]=_0x52f935,_0x3d20c2['file2']=_0x48c1dc,_0x3d20c2['coChangeCount']=_0x3d0099,_0x3d20c2[_0x501ab4(0x20e)]=_0x20a7b6,_0x3d20c2[_0x501ab4(_0x2bea76._0x3159ea)]=_0x1e2132,_0x3d20c2['confidence']=_0x32254c,_0x3d20c2[_0x501ab4(0x20f)]=_0x3d0099,_0x2d83e8['push'](_0x3d20c2);}_0x2d83e8['sort']((_0x5e8150,_0x2ae1cd)=>_0x2ae1cd[_0x501ab4(0x20a)]-_0x5e8150['confidence']);const _0xd8952e=new Map();for(const _0xc98b80 of _0x2d83e8){!_0xd8952e[_0x501ab4(_0x2bea76._0x4a0ea1)](_0xc98b80[_0x501ab4(_0x2bea76._0x33c0a9)])&&_0xd8952e[_0x501ab4(_0x2bea76._0x99ef59)](_0xc98b80['file1'],[]),_0xd8952e['get'](_0xc98b80['file1'])['push'](_0xc98b80),!_0xd8952e[_0x501ab4(_0x2bea76._0x3d0bfb)](_0xc98b80[_0x501ab4(0x1fb)])&&_0xd8952e['set'](_0xc98b80[_0x501ab4(_0x2bea76._0x3d5fa8)],[]),_0xd8952e[_0x501ab4(_0x2bea76._0x1b8517)](_0xc98b80['file2'])['push'](_0xc98b80);}for(const [,_0x230515]of _0xd8952e){_0x230515[_0x501ab4(_0x2bea76._0x18e90b)]((_0x2da1f7,_0x2e5881)=>_0x2e5881[_0x501ab4(0x20a)]-_0x2da1f7['confidence']);}const _0xaa6a16={'couplings':_0x2d83e8,'fileCouplings':_0xd8952e,'totalCommitsAnalyzed':_0xbe35bd,'analyzedAt':Date[_0x501ab4(0x207)]()};return cachedResult=_0xaa6a16,cachedProjectRoot=_0x468d33,_0xaa6a16;}function getCoupledFiles(_0x37e7ee,_0x291b99){const _0x10b25c={_0x4ddcd:0x1f0,_0x4c2d23:0x1fa},_0x4973c5=_0x2efc11,_0x4c025b={'yWEkj':function(_0x107085,_0x2ad943){return _0x107085(_0x2ad943);}},_0x4ba330=_0x4c025b[_0x4973c5(_0x10b25c._0x4ddcd)](normalizePath,_0x37e7ee);return _0x291b99[_0x4973c5(_0x10b25c._0x4c2d23)][_0x4973c5(0x20b)](_0x4ba330)||[];}
|
|
@@ -1,319 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Incremental Graph Updates for SYKE.
|
|
4
|
-
*
|
|
5
|
-
* Instead of rebuilding the entire dependency graph when a single file changes,
|
|
6
|
-
* this module re-parses only the changed file's imports and updates the
|
|
7
|
-
* forward/reverse maps in place. SCC and PageRank are recomputed fully
|
|
8
|
-
* (both are O(V+E) and fast enough) only when edges actually change.
|
|
9
|
-
*
|
|
10
|
-
* This brings update latency from O(N * parse) down to O(1 * parse + V+E)
|
|
11
|
-
* for large codebases (10K+ files).
|
|
12
|
-
*/
|
|
13
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
16
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
17
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
18
|
-
}
|
|
19
|
-
Object.defineProperty(o, k2, desc);
|
|
20
|
-
}) : (function(o, m, k, k2) {
|
|
21
|
-
if (k2 === undefined) k2 = k;
|
|
22
|
-
o[k2] = m[k];
|
|
23
|
-
}));
|
|
24
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
25
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
26
|
-
}) : function(o, v) {
|
|
27
|
-
o["default"] = v;
|
|
28
|
-
});
|
|
29
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
30
|
-
var ownKeys = function(o) {
|
|
31
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
32
|
-
var ar = [];
|
|
33
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
34
|
-
return ar;
|
|
35
|
-
};
|
|
36
|
-
return ownKeys(o);
|
|
37
|
-
};
|
|
38
|
-
return function (mod) {
|
|
39
|
-
if (mod && mod.__esModule) return mod;
|
|
40
|
-
var result = {};
|
|
41
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
42
|
-
__setModuleDefault(result, mod);
|
|
43
|
-
return result;
|
|
44
|
-
};
|
|
45
|
-
})();
|
|
46
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
47
|
-
exports.updateGraphForFile = updateGraphForFile;
|
|
48
|
-
exports.addFileToGraph = addFileToGraph;
|
|
49
|
-
exports.removeFileFromGraph = removeFileFromGraph;
|
|
50
|
-
const path = __importStar(require("path"));
|
|
51
|
-
const plugin_1 = require("../languages/plugin");
|
|
52
|
-
const scc_1 = require("./scc");
|
|
53
|
-
const pagerank_1 = require("../scoring/pagerank");
|
|
54
|
-
const risk_scorer_1 = require("../scoring/risk-scorer");
|
|
55
|
-
// ── Core Functions ──
|
|
56
|
-
/**
|
|
57
|
-
* Update the graph for a single changed file.
|
|
58
|
-
* Re-parses only that file's imports and updates forward/reverse maps.
|
|
59
|
-
* Returns info about what changed for cache invalidation.
|
|
60
|
-
*/
|
|
61
|
-
function updateGraphForFile(graph, filePath, projectRoot) {
|
|
62
|
-
const normalized = path.normalize(filePath);
|
|
63
|
-
// If file is not in the graph, treat as a new file addition
|
|
64
|
-
if (!graph.files.has(normalized)) {
|
|
65
|
-
return addFileToGraph(graph, filePath, projectRoot);
|
|
66
|
-
}
|
|
67
|
-
// 1. Get old forward edges for this file
|
|
68
|
-
const oldDeps = graph.forward.get(normalized) || [];
|
|
69
|
-
const oldDepsSet = new Set(oldDeps);
|
|
70
|
-
// 2. Determine which language plugin handles this file
|
|
71
|
-
const plugin = (0, plugin_1.getPluginForFile)(normalized);
|
|
72
|
-
if (!plugin) {
|
|
73
|
-
// No plugin can handle this file extension - nothing to update
|
|
74
|
-
return {
|
|
75
|
-
updatedFile: normalized,
|
|
76
|
-
addedEdges: [],
|
|
77
|
-
removedEdges: [],
|
|
78
|
-
edgesChanged: false,
|
|
79
|
-
affectedFiles: [],
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
// 3. Find the appropriate source directory for this file
|
|
83
|
-
const sourceDir = findSourceDirForFile(normalized, graph);
|
|
84
|
-
// 4. Re-parse imports for this file
|
|
85
|
-
const rawImports = plugin.parseImports(normalized, projectRoot, sourceDir);
|
|
86
|
-
// 5. Filter to only include files that exist in the graph (internal deps)
|
|
87
|
-
const newDeps = rawImports.filter(imp => graph.files.has(imp));
|
|
88
|
-
const newDepsSet = new Set(newDeps);
|
|
89
|
-
// 6. Compute diff
|
|
90
|
-
const addedEdges = [];
|
|
91
|
-
const removedEdges = [];
|
|
92
|
-
for (const dep of newDeps) {
|
|
93
|
-
if (!oldDepsSet.has(dep)) {
|
|
94
|
-
addedEdges.push([normalized, dep]);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
for (const dep of oldDeps) {
|
|
98
|
-
if (!newDepsSet.has(dep)) {
|
|
99
|
-
removedEdges.push([normalized, dep]);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
const edgesChanged = addedEdges.length > 0 || removedEdges.length > 0;
|
|
103
|
-
// 7. Update forward map
|
|
104
|
-
graph.forward.set(normalized, newDeps);
|
|
105
|
-
// 8. Update reverse map for removed edges
|
|
106
|
-
for (const [, dep] of removedEdges) {
|
|
107
|
-
const revList = graph.reverse.get(dep);
|
|
108
|
-
if (revList) {
|
|
109
|
-
const idx = revList.indexOf(normalized);
|
|
110
|
-
if (idx !== -1) {
|
|
111
|
-
revList.splice(idx, 1);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
// 9. Update reverse map for added edges
|
|
116
|
-
for (const [, dep] of addedEdges) {
|
|
117
|
-
const revList = graph.reverse.get(dep);
|
|
118
|
-
if (revList) {
|
|
119
|
-
if (!revList.includes(normalized)) {
|
|
120
|
-
revList.push(normalized);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
else {
|
|
124
|
-
graph.reverse.set(dep, [normalized]);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// 10. Compute affected files (reverse transitive closure of the changed file)
|
|
128
|
-
const affectedFiles = computeAffectedFiles(normalized, graph);
|
|
129
|
-
// 11. If edges changed, recompute SCC and PageRank
|
|
130
|
-
if (edgesChanged) {
|
|
131
|
-
recomputeGraphMetrics(graph);
|
|
132
|
-
}
|
|
133
|
-
return {
|
|
134
|
-
updatedFile: normalized,
|
|
135
|
-
addedEdges,
|
|
136
|
-
removedEdges,
|
|
137
|
-
edgesChanged,
|
|
138
|
-
affectedFiles,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Add a new file to the graph.
|
|
143
|
-
* Initializes forward/reverse entries, parses imports, and adds edges.
|
|
144
|
-
*/
|
|
145
|
-
function addFileToGraph(graph, filePath, projectRoot) {
|
|
146
|
-
const normalized = path.normalize(filePath);
|
|
147
|
-
// Already in graph? Treat as an update instead
|
|
148
|
-
if (graph.files.has(normalized)) {
|
|
149
|
-
return updateGraphForFile(graph, filePath, projectRoot);
|
|
150
|
-
}
|
|
151
|
-
// 1. Add to the files set
|
|
152
|
-
graph.files.add(normalized);
|
|
153
|
-
// 2. Initialize forward entry
|
|
154
|
-
graph.forward.set(normalized, []);
|
|
155
|
-
// 3. Initialize reverse entry if not exists
|
|
156
|
-
if (!graph.reverse.has(normalized)) {
|
|
157
|
-
graph.reverse.set(normalized, []);
|
|
158
|
-
}
|
|
159
|
-
// 4. Determine which plugin handles this file
|
|
160
|
-
const plugin = (0, plugin_1.getPluginForFile)(normalized);
|
|
161
|
-
if (!plugin) {
|
|
162
|
-
return {
|
|
163
|
-
updatedFile: normalized,
|
|
164
|
-
addedEdges: [],
|
|
165
|
-
removedEdges: [],
|
|
166
|
-
edgesChanged: false,
|
|
167
|
-
affectedFiles: [],
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
// 5. Find source directory
|
|
171
|
-
const sourceDir = findSourceDirForFile(normalized, graph);
|
|
172
|
-
// 6. Parse imports
|
|
173
|
-
const rawImports = plugin.parseImports(normalized, projectRoot, sourceDir);
|
|
174
|
-
const newDeps = rawImports.filter(imp => graph.files.has(imp));
|
|
175
|
-
const addedEdges = [];
|
|
176
|
-
// 7. Set forward edges
|
|
177
|
-
graph.forward.set(normalized, newDeps);
|
|
178
|
-
// 8. Update reverse maps for new edges
|
|
179
|
-
for (const dep of newDeps) {
|
|
180
|
-
addedEdges.push([normalized, dep]);
|
|
181
|
-
const revList = graph.reverse.get(dep);
|
|
182
|
-
if (revList) {
|
|
183
|
-
if (!revList.includes(normalized)) {
|
|
184
|
-
revList.push(normalized);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
graph.reverse.set(dep, [normalized]);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
// 9. Check if any existing file imports this new file
|
|
192
|
-
// (their forward edges might now resolve to this file)
|
|
193
|
-
// This is hard to detect without re-parsing all files,
|
|
194
|
-
// so we skip it — the next full refresh will catch it.
|
|
195
|
-
// The conservative approach is to just note that edges changed.
|
|
196
|
-
const edgesChanged = addedEdges.length > 0;
|
|
197
|
-
const affectedFiles = computeAffectedFiles(normalized, graph);
|
|
198
|
-
if (edgesChanged) {
|
|
199
|
-
recomputeGraphMetrics(graph);
|
|
200
|
-
}
|
|
201
|
-
return {
|
|
202
|
-
updatedFile: normalized,
|
|
203
|
-
addedEdges,
|
|
204
|
-
removedEdges: [],
|
|
205
|
-
edgesChanged,
|
|
206
|
-
affectedFiles,
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Remove a file from the graph.
|
|
211
|
-
* Cleans up all forward edges, reverse edges, and the files set.
|
|
212
|
-
*/
|
|
213
|
-
function removeFileFromGraph(graph, filePath) {
|
|
214
|
-
const normalized = path.normalize(filePath);
|
|
215
|
-
if (!graph.files.has(normalized)) {
|
|
216
|
-
// File wasn't in graph, nothing to do
|
|
217
|
-
return {
|
|
218
|
-
updatedFile: normalized,
|
|
219
|
-
addedEdges: [],
|
|
220
|
-
removedEdges: [],
|
|
221
|
-
edgesChanged: false,
|
|
222
|
-
affectedFiles: [],
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
// Compute affected files BEFORE removing (need the reverse graph intact)
|
|
226
|
-
const affectedFiles = computeAffectedFiles(normalized, graph);
|
|
227
|
-
const removedEdges = [];
|
|
228
|
-
// 1. Remove all forward edges (this file imports X)
|
|
229
|
-
const forwardDeps = graph.forward.get(normalized) || [];
|
|
230
|
-
for (const dep of forwardDeps) {
|
|
231
|
-
removedEdges.push([normalized, dep]);
|
|
232
|
-
// Remove this file from dep's reverse list
|
|
233
|
-
const revList = graph.reverse.get(dep);
|
|
234
|
-
if (revList) {
|
|
235
|
-
const idx = revList.indexOf(normalized);
|
|
236
|
-
if (idx !== -1) {
|
|
237
|
-
revList.splice(idx, 1);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// 2. Remove all reverse edges (X imports this file)
|
|
242
|
-
const reverseDeps = graph.reverse.get(normalized) || [];
|
|
243
|
-
for (const src of reverseDeps) {
|
|
244
|
-
removedEdges.push([src, normalized]);
|
|
245
|
-
// Remove this file from src's forward list
|
|
246
|
-
const fwdList = graph.forward.get(src);
|
|
247
|
-
if (fwdList) {
|
|
248
|
-
const idx = fwdList.indexOf(normalized);
|
|
249
|
-
if (idx !== -1) {
|
|
250
|
-
fwdList.splice(idx, 1);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
// 3. Clean up maps
|
|
255
|
-
graph.forward.delete(normalized);
|
|
256
|
-
graph.reverse.delete(normalized);
|
|
257
|
-
graph.files.delete(normalized);
|
|
258
|
-
const edgesChanged = removedEdges.length > 0;
|
|
259
|
-
if (edgesChanged) {
|
|
260
|
-
recomputeGraphMetrics(graph);
|
|
261
|
-
}
|
|
262
|
-
return {
|
|
263
|
-
updatedFile: normalized,
|
|
264
|
-
addedEdges: [],
|
|
265
|
-
removedEdges,
|
|
266
|
-
edgesChanged,
|
|
267
|
-
affectedFiles,
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
// ── Internal Helpers ──
|
|
271
|
-
/**
|
|
272
|
-
* Find the source directory that contains the given file.
|
|
273
|
-
* Falls back to graph.sourceDir if no match found.
|
|
274
|
-
*/
|
|
275
|
-
function findSourceDirForFile(filePath, graph) {
|
|
276
|
-
for (const dir of graph.sourceDirs) {
|
|
277
|
-
if (filePath.startsWith(dir)) {
|
|
278
|
-
return dir;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return graph.sourceDir;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Compute the set of files whose cached BFS/impact results might be stale.
|
|
285
|
-
* This is the reverse transitive closure: all files that transitively depend
|
|
286
|
-
* on the changed file (including the changed file itself).
|
|
287
|
-
*/
|
|
288
|
-
function computeAffectedFiles(filePath, graph) {
|
|
289
|
-
const affected = new Set();
|
|
290
|
-
affected.add(filePath);
|
|
291
|
-
const queue = [filePath];
|
|
292
|
-
while (queue.length > 0) {
|
|
293
|
-
const current = queue.shift();
|
|
294
|
-
const dependents = graph.reverse.get(current) || [];
|
|
295
|
-
for (const dep of dependents) {
|
|
296
|
-
if (!affected.has(dep)) {
|
|
297
|
-
affected.add(dep);
|
|
298
|
-
queue.push(dep);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
return [...affected];
|
|
303
|
-
}
|
|
304
|
-
/**
|
|
305
|
-
* Recompute SCC and PageRank after edge changes.
|
|
306
|
-
* Both are O(V+E) and fast (<100ms for 10K files).
|
|
307
|
-
*/
|
|
308
|
-
function recomputeGraphMetrics(graph) {
|
|
309
|
-
// Recompute SCC
|
|
310
|
-
graph.scc = (0, scc_1.computeSCC)(graph);
|
|
311
|
-
// Recompute PageRank
|
|
312
|
-
(0, pagerank_1.invalidatePageRank)();
|
|
313
|
-
graph.pageRank = (0, pagerank_1.computePageRank)(graph);
|
|
314
|
-
// Invalidate project metrics (will be recomputed lazily)
|
|
315
|
-
(0, risk_scorer_1.invalidateProjectMetrics)();
|
|
316
|
-
const cyclicCount = graph.scc.condensed.nodes.filter(n => n.isCyclic).length;
|
|
317
|
-
console.error(`[syke:incremental] Graph metrics recomputed: ${graph.files.size} files, ` +
|
|
318
|
-
`${graph.scc.components.length} SCCs (${cyclicCount} cyclic)`);
|
|
319
|
-
}
|
|
1
|
+
'use strict';const _0x560d7e=_0x64c7;(function(_0x508e71,_0x3dcd62){const _0x512bb1={_0x357dcf:0x159,_0x3cfe76:0x14c,_0x5d3205:0x15a,_0x599c9d:0x15d,_0x3818b6:0x152,_0x3139f0:0x145},_0x57bb62=_0x64c7,_0x17d65b=_0x508e71();while(!![]){try{const _0x3faa05=-parseInt(_0x57bb62(_0x512bb1._0x357dcf))/0x1+parseInt(_0x57bb62(_0x512bb1._0x3cfe76))/0x2+-parseInt(_0x57bb62(0x13b))/0x3*(parseInt(_0x57bb62(0x16c))/0x4)+-parseInt(_0x57bb62(_0x512bb1._0x5d3205))/0x5+parseInt(_0x57bb62(0x139))/0x6+parseInt(_0x57bb62(_0x512bb1._0x599c9d))/0x7*(parseInt(_0x57bb62(0x162))/0x8)+-parseInt(_0x57bb62(_0x512bb1._0x3818b6))/0x9*(-parseInt(_0x57bb62(_0x512bb1._0x3139f0))/0xa);if(_0x3faa05===_0x3dcd62)break;else _0x17d65b['push'](_0x17d65b['shift']());}catch(_0x47d839){_0x17d65b['push'](_0x17d65b['shift']());}}}(_0x2ead,0xd2d94));var __createBinding=this&&this['__createBinding']||(Object['create']?function(_0x351f4b,_0x4549b6,_0x164c7f,_0x181bfe){const _0x45f092={_0x1a3cd7:0x138,_0x8248c5:0x14d,_0x25e4b4:0x15b},_0xbeca20=_0x64c7,_0x195a98={};_0x195a98[_0xbeca20(_0x45f092._0x1a3cd7)]=function(_0x49317e,_0x11c46b){return _0x49317e===_0x11c46b;},_0x195a98[_0xbeca20(0x160)]=function(_0x19dfe6,_0x134c21){return _0x19dfe6 in _0x134c21;},_0x195a98[_0xbeca20(_0x45f092._0x8248c5)]='get';const _0x116c03=_0x195a98;if(_0x116c03['PVuOX'](_0x181bfe,undefined))_0x181bfe=_0x164c7f;var _0x1d1aff=Object[_0xbeca20(0x158)](_0x4549b6,_0x164c7f);if(!_0x1d1aff||(_0x116c03['sXpqr'](_0x116c03['iMpEB'],_0x1d1aff)?!_0x4549b6['__esModule']:_0x1d1aff[_0xbeca20(_0x45f092._0x25e4b4)]||_0x1d1aff[_0xbeca20(0x140)])){const _0x4befa2={};_0x4befa2['enumerable']=!![],_0x4befa2['get']=function(){return _0x4549b6[_0x164c7f];},_0x1d1aff=_0x4befa2;}Object[_0xbeca20(0x144)](_0x351f4b,_0x181bfe,_0x1d1aff);}:function(_0x4634db,_0x44f7de,_0x50a5e0,_0x52f470){if(_0x52f470===undefined)_0x52f470=_0x50a5e0;_0x4634db[_0x52f470]=_0x44f7de[_0x50a5e0];}),__setModuleDefault=this&&this[_0x560d7e(0x13a)]||(Object[_0x560d7e(0x12e)]?function(_0x440adf,_0x424194){const _0x3b7c21=_0x560d7e,_0x4268e5={};_0x4268e5[_0x3b7c21(0x141)]=!![],_0x4268e5['value']=_0x424194,Object['defineProperty'](_0x440adf,'default',_0x4268e5);}:function(_0x595313,_0x248262){const _0x50a2ba=_0x560d7e,_0x31eea6={};_0x31eea6['uqCYg']='default';const _0x4a263c=_0x31eea6;_0x595313[_0x4a263c[_0x50a2ba(0x169)]]=_0x248262;}),__importStar=this&&this['__importStar']||(function(){const _0x2025a9={'NrAzF':'0|3|4|1|2','Qxshv':function(_0x179f61,_0x349102,_0x509401){return _0x179f61(_0x349102,_0x509401);},'JCaXW':function(_0x159472,_0x332631){return _0x159472(_0x332631);}};var _0x56ec64=function(_0x3b92cc){const _0x228f22={_0x2b7671:0x168},_0x2f46f5=_0x64c7;return _0x56ec64=Object[_0x2f46f5(0x13e)]||function(_0x482062){const _0xa9fc1d=_0x2f46f5;var _0xdd873c=[];for(var _0x1f0f5b in _0x482062)if(Object['prototype']['hasOwnProperty'][_0xa9fc1d(0x148)](_0x482062,_0x1f0f5b))_0xdd873c[_0xdd873c[_0xa9fc1d(_0x228f22._0x2b7671)]]=_0x1f0f5b;return _0xdd873c;},_0x56ec64(_0x3b92cc);};return function(_0x193fbb){const _0x471e63=_0x64c7,_0x28a1d8=_0x2025a9['NrAzF'][_0x471e63(0x136)]('|');let _0x36ae03=0x0;while(!![]){switch(_0x28a1d8[_0x36ae03++]){case'0':if(_0x193fbb&&_0x193fbb['__esModule'])return _0x193fbb;continue;case'1':_0x2025a9['Qxshv'](__setModuleDefault,_0x1fc38d,_0x193fbb);continue;case'2':return _0x1fc38d;case'3':var _0x1fc38d={};continue;case'4':if(_0x193fbb!=null){for(var _0x2a4442=_0x2025a9[_0x471e63(0x14b)](_0x56ec64,_0x193fbb),_0x49c98e=0x0;_0x49c98e<_0x2a4442['length'];_0x49c98e++)if(_0x2a4442[_0x49c98e]!==_0x471e63(0x142))__createBinding(_0x1fc38d,_0x193fbb,_0x2a4442[_0x49c98e]);}continue;}break;}};}());const _0x205c91={};function _0x2ead(){const _0x2d9e4f=['ufz1t1G','nZeWmti3mgPtzg9qDG','x19ZzxrnB2r1BgvezwzHDwX0','m0rcq2LKtq','EvP5BNe','ChvZAa','z2v0t3DUuhjVCgvYDhLoyw1LCW','y29UzgvUC2vK','y29UzMLNDxjHyMXL','zw51BwvYywjSzq','zgvMyxvSDa','zMLSDgvY','zgvMAw5LuhjVCgvYDhK','mZiZmJmWDgfKqNDs','zwrNzxndAgfUz2vK','zMLSzxm','y2fSBa','C3rHCNrZv2L0Aa','DxbKyxrLzezPBgu','sKnHwfC','mtC1ndC5nNjNBeL4ta','Au1Wrui','CMv2zxjZzq','lI4VC2nVCMLUzY9WywDLCMfUAW','C2L6zq','ywrKrMLSzvrVr3jHCgG','mtCXuxf1suvj','z2v0ugX1z2LUrM9YrMLSzq','ywrK','y29TChv0zvbHz2vsyw5R','CgfYC2vjBxbVCNrZ','AxndEwnSAwm','z2v0t3DUuhjVCgvYDhLezxnJCMLWDg9Y','mtaYotiYnu5IzNvwDG','mZy5ntCYmhHcz3bjqW','D3jPDgfIBgu','BM9YBwfSAxPL','ndyYAunws0fI','C2v0','Cvj1EKG','C1HWCxi','C3bSAwnL','nZm2ndbHENHVvMm','CMvTB3zLzevKz2vZ','ywrKzwrfzgDLCW','CMvTB3zLrMLSzuzYB21hCMfWAa','ywzMzwn0zwrgAwXLCW','Aw52ywXPzgf0zvbHz2vsyw5R','BgvUz3rO','DxfdwwC','y29TCg9Uzw50CW','lI9Zy2m','mJyWmJqYmfbUy0vJyW','Aw5JBhvKzxm','AgfZ','zM9YD2fYza','y3jLyxrL','x19LC01VzhvSzq','ign5y2XPyYK','A1LJr1K','lI4VC2nVCMLUzY9YAxnRlxnJB3jLCG','t09jvwu','C2nJ','z2v0','C3bSAxq','DxbKyxrLr3jHCgHgB3jgAwXL'];_0x2ead=function(){return _0x2d9e4f;};return _0x2ead();}_0x205c91['value']=!![],Object[_0x560d7e(0x144)](exports,_0x560d7e(0x12f),_0x205c91),exports[_0x560d7e(0x137)]=updateGraphForFile,exports[_0x560d7e(0x151)]=addFileToGraph,exports[_0x560d7e(0x165)]=removeFileFromGraph;function _0x64c7(_0x2c38e9,_0x11b81a){_0x2c38e9=_0x2c38e9-0x12c;const _0x2ead19=_0x2ead();let _0x64c714=_0x2ead19[_0x2c38e9];if(_0x64c7['yGRqvV']===undefined){var _0x4369de=function(_0x30cce2){const _0xa1a965='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x34aa9a='',_0x3a63fd='';for(let _0x5d9565=0x0,_0xe4e712,_0x3cc41b,_0x525c67=0x0;_0x3cc41b=_0x30cce2['charAt'](_0x525c67++);~_0x3cc41b&&(_0xe4e712=_0x5d9565%0x4?_0xe4e712*0x40+_0x3cc41b:_0x3cc41b,_0x5d9565++%0x4)?_0x34aa9a+=String['fromCharCode'](0xff&_0xe4e712>>(-0x2*_0x5d9565&0x6)):0x0){_0x3cc41b=_0xa1a965['indexOf'](_0x3cc41b);}for(let _0x33c326=0x0,_0x136832=_0x34aa9a['length'];_0x33c326<_0x136832;_0x33c326++){_0x3a63fd+='%'+('00'+_0x34aa9a['charCodeAt'](_0x33c326)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(_0x3a63fd);};_0x64c7['EEUuVf']=_0x4369de,_0x64c7['tFwlVb']={},_0x64c7['yGRqvV']=!![];}const _0x43797e=_0x2ead19[0x0],_0x3fcfee=_0x2c38e9+_0x43797e,_0x1893ef=_0x64c7['tFwlVb'][_0x3fcfee];return!_0x1893ef?(_0x64c714=_0x64c7['EEUuVf'](_0x64c714),_0x64c7['tFwlVb'][_0x3fcfee]=_0x64c714):_0x64c714=_0x1893ef,_0x64c714;}const path=__importStar(require('path')),plugin_1=require('../languages/plugin'),scc_1=require(_0x560d7e(0x16b)),pagerank_1=require(_0x560d7e(0x14f)),risk_scorer_1=require(_0x560d7e(0x132));function updateGraphForFile(_0x1793c9,_0x18825a,_0x47e8ad){const _0xce7411={_0x2f9619:0x14a,_0xaa7fa3:0x143,_0x150f5f:0x13d,_0x405a88:0x14e,_0x47b527:0x135,_0x100162:0x16d,_0x35c62d:0x146},_0x25b8cc=_0x560d7e,_0x5cc995={'yZynq':function(_0x25e7d1,_0x2ba970,_0xc3046,_0x2ae1b7){return _0x25e7d1(_0x2ba970,_0xc3046,_0x2ae1b7);},'EJIoo':function(_0x2af4b9,_0x5de403,_0x5328b9){return _0x2af4b9(_0x5de403,_0x5328b9);},'gSMYw':function(_0x3e6cb7,_0x55c0dc){return _0x3e6cb7(_0x55c0dc);}},_0x4306c2=path['normalize'](_0x18825a);if(!_0x1793c9['files']['has'](_0x4306c2))return _0x5cc995[_0x25b8cc(0x13c)](addFileToGraph,_0x1793c9,_0x18825a,_0x47e8ad);const _0x3ac206=_0x1793c9['forward']['get'](_0x4306c2)||[],_0x2602c3=new Set(_0x3ac206),_0x537290=(0x0,plugin_1[_0x25b8cc(0x153)])(_0x4306c2);if(!_0x537290){const _0x2850e8={};return _0x2850e8[_0x25b8cc(_0xce7411._0x2f9619)]=_0x4306c2,_0x2850e8['addedEdges']=[],_0x2850e8['removedEdges']=[],_0x2850e8['edgesChanged']=![],_0x2850e8[_0x25b8cc(0x166)]=[],_0x2850e8;}const _0x701a1f=_0x5cc995['EJIoo'](findSourceDirForFile,_0x4306c2,_0x1793c9),_0x1f41ab=_0x537290['parseImports'](_0x4306c2,_0x47e8ad,_0x701a1f),_0x41cda9=_0x1f41ab[_0x25b8cc(_0xce7411._0xaa7fa3)](_0x4249e5=>_0x1793c9['files']['has'](_0x4249e5)),_0x14d73d=new Set(_0x41cda9),_0x3761bc=[],_0x1a8ba3=[];for(const _0xc4d3c6 of _0x41cda9){!_0x2602c3['has'](_0xc4d3c6)&&_0x3761bc[_0x25b8cc(_0xce7411._0x150f5f)]([_0x4306c2,_0xc4d3c6]);}for(const _0x1f228a of _0x3ac206){!_0x14d73d[_0x25b8cc(0x12c)](_0x1f228a)&&_0x1a8ba3[_0x25b8cc(0x13d)]([_0x4306c2,_0x1f228a]);}const _0x119098=_0x3761bc['length']>0x0||_0x1a8ba3[_0x25b8cc(0x168)]>0x0;_0x1793c9['forward']['set'](_0x4306c2,_0x41cda9);for(const [,_0x54b6d3]of _0x1a8ba3){const _0x40fa92=_0x1793c9[_0x25b8cc(_0xce7411._0x405a88)][_0x25b8cc(_0xce7411._0x47b527)](_0x54b6d3);if(_0x40fa92){const _0x51bbc7=_0x40fa92['indexOf'](_0x4306c2);_0x51bbc7!==-0x1&&_0x40fa92['splice'](_0x51bbc7,0x1);}}for(const [,_0x430ca3]of _0x3761bc){const _0x44d0c5=_0x1793c9['reverse'][_0x25b8cc(0x135)](_0x430ca3);_0x44d0c5?!_0x44d0c5[_0x25b8cc(_0xce7411._0x100162)](_0x4306c2)&&_0x44d0c5[_0x25b8cc(_0xce7411._0x150f5f)](_0x4306c2):_0x1793c9['reverse']['set'](_0x430ca3,[_0x4306c2]);}const _0x5de73b=computeAffectedFiles(_0x4306c2,_0x1793c9);_0x119098&&_0x5cc995['gSMYw'](recomputeGraphMetrics,_0x1793c9);const _0x3d29f5={};return _0x3d29f5['updatedFile']=_0x4306c2,_0x3d29f5['addedEdges']=_0x3761bc,_0x3d29f5[_0x25b8cc(0x163)]=_0x1a8ba3,_0x3d29f5[_0x25b8cc(_0xce7411._0x35c62d)]=_0x119098,_0x3d29f5['affectedFiles']=_0x5de73b,_0x3d29f5;}function addFileToGraph(_0x4445e1,_0x4880c2,_0x33d014){const _0x140698={_0x585633:0x12c,_0x4149c0:0x153,_0x222503:0x164,_0x2c85bb:0x163,_0x3b6261:0x166,_0x5bd52e:0x156,_0x42454d:0x13d,_0x3befd4:0x15e,_0x443fb7:0x131},_0x43356c=_0x560d7e,_0x584642={'HWGSp':function(_0x585540,_0x5e70d9,_0x9ebcd1,_0x37d646){return _0x585540(_0x5e70d9,_0x9ebcd1,_0x37d646);},'kYcGY':function(_0x76c5c1,_0x7ff585,_0x42539b){return _0x76c5c1(_0x7ff585,_0x42539b);},'yRapA':function(_0x40f415,_0x53abbe){return _0x40f415(_0x53abbe);}},_0x2e5420=path['normalize'](_0x4880c2);if(_0x4445e1['files'][_0x43356c(0x12c)](_0x2e5420))return _0x584642['HWGSp'](updateGraphForFile,_0x4445e1,_0x4880c2,_0x33d014);_0x4445e1[_0x43356c(0x147)][_0x43356c(0x154)](_0x2e5420),_0x4445e1['forward']['set'](_0x2e5420,[]);!_0x4445e1[_0x43356c(0x14e)][_0x43356c(_0x140698._0x585633)](_0x2e5420)&&_0x4445e1['reverse']['set'](_0x2e5420,[]);const _0x584ba4=(0x0,plugin_1[_0x43356c(_0x140698._0x4149c0)])(_0x2e5420);if(!_0x584ba4){const _0x418673={};return _0x418673['updatedFile']=_0x2e5420,_0x418673[_0x43356c(_0x140698._0x222503)]=[],_0x418673[_0x43356c(_0x140698._0x2c85bb)]=[],_0x418673['edgesChanged']=![],_0x418673[_0x43356c(_0x140698._0x3b6261)]=[],_0x418673;}const _0x3c8fd5=_0x584642['kYcGY'](findSourceDirForFile,_0x2e5420,_0x4445e1),_0x492852=_0x584ba4[_0x43356c(_0x140698._0x5bd52e)](_0x2e5420,_0x33d014,_0x3c8fd5),_0x270c7e=_0x492852['filter'](_0x3c278f=>_0x4445e1['files'][_0x43356c(0x12c)](_0x3c278f)),_0x1b1563=[];_0x4445e1[_0x43356c(0x12d)]['set'](_0x2e5420,_0x270c7e);for(const _0x35d491 of _0x270c7e){_0x1b1563['push']([_0x2e5420,_0x35d491]);const _0x1f9521=_0x4445e1[_0x43356c(0x14e)][_0x43356c(0x135)](_0x35d491);_0x1f9521?!_0x1f9521['includes'](_0x2e5420)&&_0x1f9521[_0x43356c(_0x140698._0x42454d)](_0x2e5420):_0x4445e1[_0x43356c(0x14e)][_0x43356c(_0x140698._0x3befd4)](_0x35d491,[_0x2e5420]);}const _0x94ba0b=_0x1b1563['length']>0x0,_0x39ebaa=_0x584642[_0x43356c(_0x140698._0x443fb7)](computeAffectedFiles,_0x2e5420,_0x4445e1);_0x94ba0b&&_0x584642['yRapA'](recomputeGraphMetrics,_0x4445e1);const _0x226600={};return _0x226600[_0x43356c(0x14a)]=_0x2e5420,_0x226600['addedEdges']=_0x1b1563,_0x226600['removedEdges']=[],_0x226600['edgesChanged']=_0x94ba0b,_0x226600['affectedFiles']=_0x39ebaa,_0x226600;}function removeFileFromGraph(_0x14bb79,_0x17ab37){const _0x828e46={_0x4ba918:0x147,_0x1ab8b8:0x14a,_0x479014:0x163,_0x15bfdd:0x166,_0x3d07b3:0x161,_0x5392b7:0x14e,_0x47046:0x13d,_0x532ca5:0x135,_0x53b228:0x15f,_0x14d490:0x133,_0x18f7cb:0x163},_0x4bf85b=_0x560d7e,_0x551f69={'VmYCT':function(_0x3ca252,_0x2bd4ad){return _0x3ca252!==_0x2bd4ad;},'qRuzH':function(_0x401325,_0x34374c){return _0x401325>_0x34374c;},'OOIUe':function(_0x104f4f,_0x4f0710){return _0x104f4f(_0x4f0710);}},_0x31c488=path[_0x4bf85b(0x15c)](_0x17ab37);if(!_0x14bb79[_0x4bf85b(_0x828e46._0x4ba918)][_0x4bf85b(0x12c)](_0x31c488)){const _0x550f94={};return _0x550f94[_0x4bf85b(_0x828e46._0x1ab8b8)]=_0x31c488,_0x550f94['addedEdges']=[],_0x550f94[_0x4bf85b(_0x828e46._0x479014)]=[],_0x550f94[_0x4bf85b(0x146)]=![],_0x550f94[_0x4bf85b(_0x828e46._0x15bfdd)]=[],_0x550f94;}const _0x35028c=computeAffectedFiles(_0x31c488,_0x14bb79),_0x5a6edb=[],_0x5bb5bd=_0x14bb79['forward'][_0x4bf85b(0x135)](_0x31c488)||[];for(const _0x2b10b6 of _0x5bb5bd){_0x5a6edb[_0x4bf85b(0x13d)]([_0x31c488,_0x2b10b6]);const _0x28cc27=_0x14bb79[_0x4bf85b(0x14e)]['get'](_0x2b10b6);if(_0x28cc27){const _0x53f1a0=_0x28cc27['indexOf'](_0x31c488);_0x53f1a0!==-0x1&&_0x28cc27[_0x4bf85b(_0x828e46._0x3d07b3)](_0x53f1a0,0x1);}}const _0xaae28d=_0x14bb79[_0x4bf85b(_0x828e46._0x5392b7)][_0x4bf85b(0x135)](_0x31c488)||[];for(const _0x26005c of _0xaae28d){_0x5a6edb[_0x4bf85b(_0x828e46._0x47046)]([_0x26005c,_0x31c488]);const _0x3f0d9d=_0x14bb79['forward'][_0x4bf85b(_0x828e46._0x532ca5)](_0x26005c);if(_0x3f0d9d){const _0x50c0a=_0x3f0d9d['indexOf'](_0x31c488);_0x551f69['VmYCT'](_0x50c0a,-0x1)&&_0x3f0d9d['splice'](_0x50c0a,0x1);}}_0x14bb79['forward']['delete'](_0x31c488),_0x14bb79['reverse']['delete'](_0x31c488),_0x14bb79[_0x4bf85b(0x147)]['delete'](_0x31c488);const _0x5bcd24=_0x551f69[_0x4bf85b(_0x828e46._0x53b228)](_0x5a6edb[_0x4bf85b(0x168)],0x0);_0x5bcd24&&_0x551f69[_0x4bf85b(_0x828e46._0x14d490)](recomputeGraphMetrics,_0x14bb79);const _0x146a92={};return _0x146a92['updatedFile']=_0x31c488,_0x146a92[_0x4bf85b(0x164)]=[],_0x146a92[_0x4bf85b(_0x828e46._0x18f7cb)]=_0x5a6edb,_0x146a92['edgesChanged']=_0x5bcd24,_0x146a92[_0x4bf85b(0x166)]=_0x35028c,_0x146a92;}function findSourceDirForFile(_0x521cae,_0x3665a0){const _0x5e9ac9={_0x2e2c70:0x149},_0xba674=_0x560d7e;for(const _0x341733 of _0x3665a0['sourceDirs']){if(_0x521cae[_0xba674(_0x5e9ac9._0x2e2c70)](_0x341733))return _0x341733;}return _0x3665a0['sourceDir'];}function computeAffectedFiles(_0x357a9c,_0x425dd6){const _0x3c9d8e={_0x50b212:0x12c,_0x37d7c8:0x154},_0x43684c=_0x560d7e,_0x3e27e2=new Set();_0x3e27e2['add'](_0x357a9c);const _0x132955=[_0x357a9c];while(_0x132955[_0x43684c(0x168)]>0x0){const _0x560c7d=_0x132955['shift'](),_0x4feda8=_0x425dd6['reverse']['get'](_0x560c7d)||[];for(const _0x14ea5e of _0x4feda8){!_0x3e27e2[_0x43684c(_0x3c9d8e._0x50b212)](_0x14ea5e)&&(_0x3e27e2[_0x43684c(_0x3c9d8e._0x37d7c8)](_0x14ea5e),_0x132955[_0x43684c(0x13d)](_0x14ea5e));}}return[..._0x3e27e2];}function recomputeGraphMetrics(_0x4e6252){const _0x328295={_0x3f2b06:0x155,_0x520b1b:0x134,_0x1849b4:0x13f,_0x5bd44c:0x168,_0x4bd48b:0x147,_0x316a5f:0x150,_0x20ff2e:0x16a},_0x379c6b=_0x560d7e;_0x4e6252[_0x379c6b(0x134)]=(0x0,scc_1['computeSCC'])(_0x4e6252),(0x0,pagerank_1[_0x379c6b(0x167)])(),_0x4e6252['pageRank']=(0x0,pagerank_1[_0x379c6b(_0x328295._0x3f2b06)])(_0x4e6252),(0x0,risk_scorer_1['invalidateProjectMetrics'])();const _0x5f1978=_0x4e6252[_0x379c6b(_0x328295._0x520b1b)][_0x379c6b(_0x328295._0x1849b4)]['nodes']['filter'](_0x97878b=>_0x97878b[_0x379c6b(0x157)])[_0x379c6b(_0x328295._0x5bd44c)];console['error']('[syke:incremental]\x20Graph\x20metrics\x20recomputed:\x20'+_0x4e6252[_0x379c6b(_0x328295._0x4bd48b)][_0x379c6b(_0x328295._0x316a5f)]+'\x20files,\x20'+(_0x4e6252[_0x379c6b(0x134)][_0x379c6b(_0x328295._0x20ff2e)]['length']+'\x20SCCs\x20('+_0x5f1978+_0x379c6b(0x130)));}
|