@udondan/avanti 0.24.0 → 0.26.0
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/README.md +488 -64
- package/dist/commands/diff.d.ts.map +1 -1
- package/dist/commands/diff.js +82 -18
- package/dist/commands/diff.js.map +1 -1
- package/dist/commands/lock.d.ts.map +1 -1
- package/dist/commands/lock.js +6 -4
- package/dist/commands/lock.js.map +1 -1
- package/dist/commands/log.d.ts.map +1 -1
- package/dist/commands/log.js +7 -5
- package/dist/commands/log.js.map +1 -1
- package/dist/commands/pull.d.ts.map +1 -1
- package/dist/commands/pull.js +682 -42
- package/dist/commands/pull.js.map +1 -1
- package/dist/commands/reset.d.ts.map +1 -1
- package/dist/commands/reset.js +43 -11
- package/dist/commands/reset.js.map +1 -1
- package/dist/commands/revert.d.ts.map +1 -1
- package/dist/commands/revert.js +68 -14
- package/dist/commands/revert.js.map +1 -1
- package/dist/condition.d.ts.map +1 -1
- package/dist/condition.js +9 -6
- package/dist/condition.js.map +1 -1
- package/dist/config-writeback.d.ts.map +1 -1
- package/dist/config-writeback.js +17 -0
- package/dist/config-writeback.js.map +1 -1
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +346 -3
- package/dist/config.js.map +1 -1
- package/dist/diff.d.ts +19 -0
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +317 -12
- package/dist/diff.js.map +1 -1
- package/dist/extract.d.ts +4 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +142 -0
- package/dist/extract.js.map +1 -0
- package/dist/filter.d.ts +3 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.js +126 -0
- package/dist/filter.js.map +1 -0
- package/dist/history.d.ts +7 -1
- package/dist/history.d.ts.map +1 -1
- package/dist/history.js +89 -9
- package/dist/history.js.map +1 -1
- package/dist/paths.d.ts +4 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +97 -0
- package/dist/paths.js.map +1 -1
- package/dist/processors/ini.d.ts +33 -0
- package/dist/processors/ini.d.ts.map +1 -0
- package/dist/processors/ini.js +500 -0
- package/dist/processors/ini.js.map +1 -0
- package/dist/processors/insert.d.ts.map +1 -1
- package/dist/processors/insert.js +338 -15
- package/dist/processors/insert.js.map +1 -1
- package/dist/processors/on.d.ts +4 -0
- package/dist/processors/on.d.ts.map +1 -0
- package/dist/processors/on.js +54 -0
- package/dist/processors/on.js.map +1 -0
- package/dist/ref.d.ts +21 -0
- package/dist/ref.d.ts.map +1 -0
- package/dist/ref.js +65 -0
- package/dist/ref.js.map +1 -0
- package/dist/sources/bitbucket.d.ts.map +1 -1
- package/dist/sources/bitbucket.js +51 -12
- package/dist/sources/bitbucket.js.map +1 -1
- package/dist/sources/git.d.ts.map +1 -1
- package/dist/sources/git.js +54 -6
- package/dist/sources/git.js.map +1 -1
- package/dist/sources/github.d.ts.map +1 -1
- package/dist/sources/github.js +188 -51
- package/dist/sources/github.js.map +1 -1
- package/dist/sources/gitlab.d.ts.map +1 -1
- package/dist/sources/gitlab.js +242 -44
- package/dist/sources/gitlab.js.map +1 -1
- package/dist/sources/index.d.ts +4 -2
- package/dist/sources/index.d.ts.map +1 -1
- package/dist/sources/index.js +220 -49
- package/dist/sources/index.js.map +1 -1
- package/dist/sources/local.d.ts +3 -0
- package/dist/sources/local.d.ts.map +1 -1
- package/dist/sources/local.js +44 -0
- package/dist/sources/local.js.map +1 -1
- package/dist/types.d.ts +38 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/variables-remote.d.ts +1 -1
- package/dist/variables-remote.d.ts.map +1 -1
- package/dist/variables-remote.js +4 -3
- package/dist/variables-remote.js.map +1 -1
- package/dist/variables.d.ts +1 -0
- package/dist/variables.d.ts.map +1 -1
- package/dist/variables.js +37 -2
- package/dist/variables.js.map +1 -1
- package/dist/writer.d.ts +17 -0
- package/dist/writer.d.ts.map +1 -1
- package/dist/writer.js +848 -20
- package/dist/writer.js.map +1 -1
- package/package.json +14 -10
package/dist/sources/index.js
CHANGED
|
@@ -37,6 +37,8 @@ exports._testable = void 0;
|
|
|
37
37
|
exports.resolveJsonOptions = resolveJsonOptions;
|
|
38
38
|
exports.resolveYamlOptions = resolveYamlOptions;
|
|
39
39
|
exports.resolveTomlOptions = resolveTomlOptions;
|
|
40
|
+
exports.resolveIniOptions = resolveIniOptions;
|
|
41
|
+
exports.formatSourceLabel = formatSourceLabel;
|
|
40
42
|
exports.fetchSource = fetchSource;
|
|
41
43
|
const crypto = __importStar(require("crypto"));
|
|
42
44
|
const os = __importStar(require("os"));
|
|
@@ -60,10 +62,15 @@ const vault_1 = require("./vault");
|
|
|
60
62
|
const json_1 = require("../processors/json");
|
|
61
63
|
const yaml_1 = require("../processors/yaml");
|
|
62
64
|
const toml_1 = require("../processors/toml");
|
|
65
|
+
const ini_1 = require("../processors/ini");
|
|
63
66
|
const binary_1 = require("../binary");
|
|
67
|
+
const filter_1 = require("../filter");
|
|
68
|
+
const extract_1 = require("../extract");
|
|
69
|
+
const config_1 = require("../config");
|
|
64
70
|
const JSON_EXTENSIONS = new Set(['.json', '.jsonc']);
|
|
65
71
|
const YAML_EXTENSIONS = new Set(['.yaml', '.yml']);
|
|
66
72
|
const TOML_EXTENSIONS = new Set(['.toml']);
|
|
73
|
+
const INI_EXTENSIONS = new Set(['.ini', '.cfg']);
|
|
67
74
|
function srcFilename(src) {
|
|
68
75
|
if (typeof src === 'string') {
|
|
69
76
|
if (src.startsWith('http://') || src.startsWith('https://')) {
|
|
@@ -144,6 +151,12 @@ function hasTomlExtension(src) {
|
|
|
144
151
|
return false;
|
|
145
152
|
return TOML_EXTENSIONS.has(path.extname(name).toLowerCase());
|
|
146
153
|
}
|
|
154
|
+
function hasIniExtension(src) {
|
|
155
|
+
const name = srcFilename(src);
|
|
156
|
+
if (!name)
|
|
157
|
+
return false;
|
|
158
|
+
return INI_EXTENSIONS.has(path.extname(name).toLowerCase());
|
|
159
|
+
}
|
|
147
160
|
function resolveJsonOptions(entry, srcs) {
|
|
148
161
|
const { json } = entry;
|
|
149
162
|
if (json === false)
|
|
@@ -183,12 +196,40 @@ function resolveTomlOptions(entry, srcs) {
|
|
|
183
196
|
return {};
|
|
184
197
|
return null;
|
|
185
198
|
}
|
|
199
|
+
function resolveIniOptions(entry, srcs) {
|
|
200
|
+
const { ini } = entry;
|
|
201
|
+
if (ini === false)
|
|
202
|
+
return null;
|
|
203
|
+
if (ini === true)
|
|
204
|
+
return {};
|
|
205
|
+
if (ini !== undefined && typeof ini === 'object')
|
|
206
|
+
return ini;
|
|
207
|
+
// Auto-detect: all sources have an INI file extension
|
|
208
|
+
if (srcs.length > 0 && srcs.every(hasIniExtension))
|
|
209
|
+
return {};
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
186
212
|
// labelForSrc returns the source label used in SourceFetchRecord. Structured
|
|
187
213
|
// sources (github:, gitlab:, etc.) keep variable references unresolved so the
|
|
188
214
|
// label matches the literal YAML values that applyUpdatedShas reads for SHA
|
|
189
215
|
// writeback. Plain-string sources resolve variables since they don't support
|
|
190
|
-
// SHA pinning.
|
|
216
|
+
// SHA pinning. When a filter is present a NUL-byte separator (\x00) is used
|
|
217
|
+
// before "filter:<json>" so the label is unambiguous even if the base contains
|
|
218
|
+
// the display string " | filter:" (e.g. a local path with that literal text).
|
|
219
|
+
// Use formatSourceLabel() to convert to a human-readable form for display.
|
|
191
220
|
function labelForSrc(src, vars) {
|
|
221
|
+
const base = baseLabelForSrc(src, vars);
|
|
222
|
+
const filter = filterForSrc(src);
|
|
223
|
+
if (filter && filter.length > 0)
|
|
224
|
+
return `${base}\x00filter:${JSON.stringify(filter)}`;
|
|
225
|
+
return base;
|
|
226
|
+
}
|
|
227
|
+
// formatSourceLabel converts an internal label (which may contain a NUL-byte
|
|
228
|
+
// filter separator) into a human-readable string for log/error output.
|
|
229
|
+
function formatSourceLabel(label) {
|
|
230
|
+
return label.replace('\x00filter:', ' | filter:');
|
|
231
|
+
}
|
|
232
|
+
function baseLabelForSrc(src, vars) {
|
|
192
233
|
if (typeof src === 'string')
|
|
193
234
|
return (0, variables_1.resolveVars)(src, vars);
|
|
194
235
|
if ('github' in src) {
|
|
@@ -253,6 +294,7 @@ function labelForSrc(src, vars) {
|
|
|
253
294
|
// using variables are correctly distinguished when vars change between
|
|
254
295
|
// stabilization iterations, and raw: sources are keyed by their content.
|
|
255
296
|
function cacheKeyForSrc(src, vars) {
|
|
297
|
+
let base;
|
|
256
298
|
if (typeof src === 'string')
|
|
257
299
|
return (0, variables_1.resolveVars)(src, vars);
|
|
258
300
|
if ('github' in src) {
|
|
@@ -265,12 +307,14 @@ function cacheKeyForSrc(src, vars) {
|
|
|
265
307
|
: (src.github.via ?? 'api,cli');
|
|
266
308
|
const via = viaStr === 'api,cli' ? '' : `(${viaStr})`;
|
|
267
309
|
if ('release' in src.github) {
|
|
268
|
-
|
|
310
|
+
base = `github${host}:${(0, variables_1.resolveVars)(src.github.repo, vars)}:release:${(0, variables_1.resolveVars)(src.github.release, vars)}${via}`;
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
const ref = src.github.ref ? `@${(0, variables_1.resolveVars)(src.github.ref, vars)}` : '';
|
|
314
|
+
base = `github${host}:${(0, variables_1.resolveVars)(src.github.repo, vars)}:${(0, variables_1.resolveVars)(src.github.file, vars)}${ref}${via}`;
|
|
269
315
|
}
|
|
270
|
-
const ref = src.github.ref ? `@${(0, variables_1.resolveVars)(src.github.ref, vars)}` : '';
|
|
271
|
-
return `github${host}:${(0, variables_1.resolveVars)(src.github.repo, vars)}:${(0, variables_1.resolveVars)(src.github.file, vars)}${ref}${via}`;
|
|
272
316
|
}
|
|
273
|
-
if ('gitlab' in src) {
|
|
317
|
+
else if ('gitlab' in src) {
|
|
274
318
|
const resolvedHost = src.gitlab.host
|
|
275
319
|
? (0, variables_1.resolveVars)(src.gitlab.host, vars).trim()
|
|
276
320
|
: '';
|
|
@@ -280,12 +324,14 @@ function cacheKeyForSrc(src, vars) {
|
|
|
280
324
|
: (src.gitlab.via ?? 'api,cli');
|
|
281
325
|
const via = viaStr === 'api,cli' ? '' : `(${viaStr})`;
|
|
282
326
|
if ('release' in src.gitlab) {
|
|
283
|
-
|
|
327
|
+
base = `gitlab${host}:${(0, variables_1.resolveVars)(src.gitlab.project, vars)}:release:${(0, variables_1.resolveVars)(src.gitlab.release, vars)}${via}`;
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
const ref = src.gitlab.ref ? `@${(0, variables_1.resolveVars)(src.gitlab.ref, vars)}` : '';
|
|
331
|
+
base = `gitlab${host}:${(0, variables_1.resolveVars)(src.gitlab.project, vars)}:${(0, variables_1.resolveVars)(src.gitlab.file, vars)}${ref}${via}`;
|
|
284
332
|
}
|
|
285
|
-
const ref = src.gitlab.ref ? `@${(0, variables_1.resolveVars)(src.gitlab.ref, vars)}` : '';
|
|
286
|
-
return `gitlab${host}:${(0, variables_1.resolveVars)(src.gitlab.project, vars)}:${(0, variables_1.resolveVars)(src.gitlab.file, vars)}${ref}${via}`;
|
|
287
333
|
}
|
|
288
|
-
if ('bitbucket' in src) {
|
|
334
|
+
else if ('bitbucket' in src) {
|
|
289
335
|
const ref = src.bitbucket.ref
|
|
290
336
|
? `@${(0, variables_1.resolveVars)(src.bitbucket.ref, vars)}`
|
|
291
337
|
: '';
|
|
@@ -293,17 +339,19 @@ function cacheKeyForSrc(src, vars) {
|
|
|
293
339
|
? (0, variables_1.resolveVars)(src.bitbucket.host, vars).trim()
|
|
294
340
|
: '';
|
|
295
341
|
const host = resolvedHost ? `[${resolvedHost}]` : '';
|
|
296
|
-
|
|
342
|
+
base = `bitbucket${host}:${(0, variables_1.resolveVars)(src.bitbucket.workspace, vars)}/${(0, variables_1.resolveVars)(src.bitbucket.repo, vars)}:${(0, variables_1.resolveVars)(src.bitbucket.file, vars)}${ref}`;
|
|
297
343
|
}
|
|
298
|
-
if ('git' in src) {
|
|
344
|
+
else if ('git' in src) {
|
|
299
345
|
const ref = src.git.ref ? `@${(0, variables_1.resolveVars)(src.git.ref, vars)}` : '';
|
|
300
|
-
|
|
346
|
+
base = `git:${(0, variables_1.resolveVars)(src.git.repo, vars)}:${(0, variables_1.resolveVars)(src.git.file, vars)}${ref}`;
|
|
301
347
|
}
|
|
302
|
-
if ('exec' in src)
|
|
348
|
+
else if ('exec' in src) {
|
|
303
349
|
return `exec:${(0, variables_1.resolveVars)(src.exec, vars)}`;
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
350
|
+
}
|
|
351
|
+
else if ('aws_s3' in src) {
|
|
352
|
+
base = `aws_s3:${(0, variables_1.resolveVars)(src.aws_s3, vars)}`;
|
|
353
|
+
}
|
|
354
|
+
else if ('aws_secrets_manager' in src) {
|
|
307
355
|
const k = src.aws_secrets_manager.key !== undefined
|
|
308
356
|
? `#${(0, variables_1.resolveVars)(src.aws_secrets_manager.key, vars)}`
|
|
309
357
|
: '';
|
|
@@ -312,28 +360,35 @@ function cacheKeyForSrc(src, vars) {
|
|
|
312
360
|
: '';
|
|
313
361
|
return `aws_secrets_manager:${(0, variables_1.resolveVars)(src.aws_secrets_manager.name, vars)}${k}${r}`;
|
|
314
362
|
}
|
|
315
|
-
if ('aws_systems_manager_parameter' in src) {
|
|
363
|
+
else if ('aws_systems_manager_parameter' in src) {
|
|
316
364
|
const r = src.aws_systems_manager_parameter.region !== undefined
|
|
317
365
|
? `@${(0, variables_1.resolveVars)(src.aws_systems_manager_parameter.region, vars)}`
|
|
318
366
|
: '';
|
|
319
367
|
return `aws_systems_manager_parameter:${(0, variables_1.resolveVars)(src.aws_systems_manager_parameter.name, vars)}${r}`;
|
|
320
368
|
}
|
|
321
|
-
if ('vault' in src) {
|
|
369
|
+
else if ('vault' in src) {
|
|
322
370
|
const field = src.vault.field
|
|
323
371
|
? `#${(0, variables_1.resolveVars)(src.vault.field, vars)}`
|
|
324
372
|
: '';
|
|
325
373
|
return `vault:${(0, variables_1.resolveVars)(src.vault.path, vars)}${field}`;
|
|
326
374
|
}
|
|
327
|
-
if ('http' in src)
|
|
375
|
+
else if ('http' in src) {
|
|
328
376
|
return `http:${(0, variables_1.resolveVars)(src.http, vars)}`;
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
377
|
+
}
|
|
378
|
+
else if ('path' in src) {
|
|
379
|
+
base = `path:${(0, variables_1.resolveVars)(src.path, vars)}`;
|
|
380
|
+
}
|
|
381
|
+
else if ('url' in src) {
|
|
332
382
|
return `url:${(0, variables_1.resolveVars)(src.url, vars)}`;
|
|
333
|
-
|
|
334
|
-
if ('raw' in src)
|
|
383
|
+
}
|
|
384
|
+
else if ('raw' in src) {
|
|
385
|
+
// raw: key includes the resolved content so distinct raw values don't collide
|
|
335
386
|
return `raw:${(0, variables_1.resolveVars)(src.raw, vars)}`;
|
|
336
|
-
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
return JSON.stringify(src);
|
|
390
|
+
}
|
|
391
|
+
return base;
|
|
337
392
|
}
|
|
338
393
|
function expectedShaForSrc(src) {
|
|
339
394
|
if (typeof src === 'string')
|
|
@@ -383,6 +438,23 @@ function buildRecord(src, files, vars) {
|
|
|
383
438
|
matched: expectedSha === undefined || expectedSha === observedSha,
|
|
384
439
|
};
|
|
385
440
|
}
|
|
441
|
+
function filterForSrc(src) {
|
|
442
|
+
if (typeof src === 'string')
|
|
443
|
+
return undefined;
|
|
444
|
+
if ('github' in src)
|
|
445
|
+
return src.filter;
|
|
446
|
+
if ('gitlab' in src)
|
|
447
|
+
return src.filter;
|
|
448
|
+
if ('bitbucket' in src)
|
|
449
|
+
return src.filter;
|
|
450
|
+
if ('git' in src)
|
|
451
|
+
return src.filter;
|
|
452
|
+
if ('aws_s3' in src)
|
|
453
|
+
return src.filter;
|
|
454
|
+
if ('path' in src)
|
|
455
|
+
return src.filter;
|
|
456
|
+
return undefined;
|
|
457
|
+
}
|
|
386
458
|
function computeFilesSha(files) {
|
|
387
459
|
// Always include filename in the hash so a rename/path change affects the SHA
|
|
388
460
|
// consistently, whether the source resolves to one file or many.
|
|
@@ -396,21 +468,46 @@ function computeFilesSha(files) {
|
|
|
396
468
|
}
|
|
397
469
|
return hash.digest('hex');
|
|
398
470
|
}
|
|
399
|
-
async function _fetchOneSrcRaw(src, workingDir, vars) {
|
|
471
|
+
async function _fetchOneSrcRaw(src, workingDir, vars, configBase) {
|
|
400
472
|
if ((0, logger_1.isVerbose)())
|
|
401
|
-
(0, logger_1.verbose)(`fetching source: ${(0, fetch_1.redactUrl)(labelForSrc(src, vars))}`);
|
|
473
|
+
(0, logger_1.verbose)(`fetching source: ${(0, fetch_1.redactUrl)(formatSourceLabel(labelForSrc(src, vars)))}`);
|
|
402
474
|
if (typeof src === 'string') {
|
|
403
475
|
const resolved = (0, variables_1.resolveVars)(src, vars);
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
476
|
+
const effective = configBase !== undefined
|
|
477
|
+
? (0, config_1.resolveRelativeSrc)(resolved, configBase)
|
|
478
|
+
: resolved;
|
|
479
|
+
if (effective.startsWith('http://') || effective.startsWith('https://')) {
|
|
480
|
+
const content = await (0, http_1.fetchHttp)(effective);
|
|
481
|
+
const filename = (0, http_1.inferFilenameFromUrl)(effective) ?? 'download';
|
|
407
482
|
return { files: new Map([[filename, content]]) };
|
|
408
483
|
}
|
|
409
|
-
if ((0, git_1.isGitRemoteUrl)(
|
|
410
|
-
const { repo, file, ref } = (0, git_1.parseGitRemoteSpec)(
|
|
484
|
+
if ((0, git_1.isGitRemoteUrl)(effective)) {
|
|
485
|
+
const { repo, file, ref } = (0, git_1.parseGitRemoteSpec)(effective);
|
|
411
486
|
return { files: (0, git_1.fetchGit)(repo, file, ref).files };
|
|
412
487
|
}
|
|
413
|
-
|
|
488
|
+
if (effective.startsWith('github:')) {
|
|
489
|
+
let parsedGh;
|
|
490
|
+
try {
|
|
491
|
+
parsedGh = (0, config_1.parseGitHubSpec)(effective);
|
|
492
|
+
}
|
|
493
|
+
catch {
|
|
494
|
+
throw new Error(`Invalid github source spec "${effective}". Expected: github:owner/repo:path/to/file[@ref]`);
|
|
495
|
+
}
|
|
496
|
+
const result = await (0, github_1.fetchGitHub)(parsedGh.repo, parsedGh.file, parsedGh.ref);
|
|
497
|
+
return { files: result.files };
|
|
498
|
+
}
|
|
499
|
+
if (effective.startsWith('gitlab:')) {
|
|
500
|
+
let parsedGl;
|
|
501
|
+
try {
|
|
502
|
+
parsedGl = (0, config_1.parseGitLabSpec)(effective);
|
|
503
|
+
}
|
|
504
|
+
catch {
|
|
505
|
+
throw new Error(`Invalid gitlab source spec "${effective}". Expected: gitlab:group/project:path/to/file[@ref]`);
|
|
506
|
+
}
|
|
507
|
+
const result = await (0, gitlab_1.fetchGitLab)(parsedGl.project, parsedGl.file, parsedGl.ref);
|
|
508
|
+
return { files: result.files };
|
|
509
|
+
}
|
|
510
|
+
return { files: (0, local_1.fetchLocal)(effective, workingDir).files };
|
|
414
511
|
}
|
|
415
512
|
if ('raw' in src) {
|
|
416
513
|
return {
|
|
@@ -531,7 +628,7 @@ async function _fetchOneSrcRaw(src, workingDir, vars) {
|
|
|
531
628
|
}
|
|
532
629
|
return { files };
|
|
533
630
|
}
|
|
534
|
-
async function fetchOneSrc(src, workingDir, vars, cache, getTargetPath = () => '', pendingWrites) {
|
|
631
|
+
async function fetchOneSrc(src, workingDir, vars, cache, getTargetPath = () => '', pendingWrites, configBase) {
|
|
535
632
|
// Evaluate source-level conditions before the cache so a cached result for
|
|
536
633
|
// the same URL is not returned when conditions gate this source out.
|
|
537
634
|
if (typeof src !== 'string') {
|
|
@@ -547,7 +644,7 @@ async function fetchOneSrc(src, workingDir, vars, cache, getTargetPath = () => '
|
|
|
547
644
|
// write target in this run should resolve to the future content, not whatever
|
|
548
645
|
// is on disk (or in the cache from a previous iteration).
|
|
549
646
|
if (pendingWrites !== undefined) {
|
|
550
|
-
const pending = pendingLocalFiles(src, workingDir, vars, pendingWrites);
|
|
647
|
+
const pending = pendingLocalFiles(src, workingDir, vars, pendingWrites, configBase);
|
|
551
648
|
if (pending !== null) {
|
|
552
649
|
return { files: pending, record: buildRecord(src, pending, vars) };
|
|
553
650
|
}
|
|
@@ -558,11 +655,11 @@ async function fetchOneSrc(src, workingDir, vars, cache, getTargetPath = () => '
|
|
|
558
655
|
let skipped;
|
|
559
656
|
if (cached !== undefined) {
|
|
560
657
|
if ((0, logger_1.isVerbose)())
|
|
561
|
-
(0, logger_1.verbose)(`cache hit: ${(0, fetch_1.redactUrl)(labelForSrc(src, vars))}`);
|
|
658
|
+
(0, logger_1.verbose)(`cache hit: ${(0, fetch_1.redactUrl)(formatSourceLabel(labelForSrc(src, vars)))}`);
|
|
562
659
|
files = cached.files;
|
|
563
660
|
}
|
|
564
661
|
else {
|
|
565
|
-
const raw = await _fetchOneSrcRaw(src, workingDir, vars);
|
|
662
|
+
const raw = await _fetchOneSrcRaw(src, workingDir, vars, configBase);
|
|
566
663
|
files = raw.files;
|
|
567
664
|
skipped = raw.skipped;
|
|
568
665
|
// Don't cache skipped results: if optional changes to required between
|
|
@@ -572,11 +669,16 @@ async function fetchOneSrc(src, workingDir, vars, cache, getTargetPath = () => '
|
|
|
572
669
|
}
|
|
573
670
|
if (skipped)
|
|
574
671
|
return { files: new Map(), record: null, skipped: true };
|
|
672
|
+
const rawFilter = filterForSrc(src);
|
|
673
|
+
const filterPatterns = rawFilter?.map((p) => (0, variables_1.resolveVars)(p, vars));
|
|
674
|
+
if (filterPatterns && filterPatterns.length > 0) {
|
|
675
|
+
files = (0, filter_1.applyFilter)(files, filterPatterns);
|
|
676
|
+
}
|
|
575
677
|
// Recompute record from the current source spec so expectedSha/matched
|
|
576
678
|
// always reflect the caller's config iteration, not the first fetch.
|
|
577
679
|
return { files, record: buildRecord(src, files, vars) };
|
|
578
680
|
}
|
|
579
|
-
function pendingLocalFiles(src, workingDir, vars, pendingWrites) {
|
|
681
|
+
function pendingLocalFiles(src, workingDir, vars, pendingWrites, configBase) {
|
|
580
682
|
let rawPath = null;
|
|
581
683
|
try {
|
|
582
684
|
if (typeof src === 'string') {
|
|
@@ -584,7 +686,16 @@ function pendingLocalFiles(src, workingDir, vars, pendingWrites) {
|
|
|
584
686
|
if (!resolved.startsWith('http://') &&
|
|
585
687
|
!resolved.startsWith('https://') &&
|
|
586
688
|
!(0, git_1.isGitRemoteUrl)(resolved)) {
|
|
587
|
-
|
|
689
|
+
const effective = configBase !== undefined
|
|
690
|
+
? (0, config_1.resolveRelativeSrc)(resolved, configBase)
|
|
691
|
+
: resolved;
|
|
692
|
+
if (!effective.startsWith('http://') &&
|
|
693
|
+
!effective.startsWith('https://') &&
|
|
694
|
+
!(0, git_1.isGitRemoteUrl)(effective) &&
|
|
695
|
+
!effective.startsWith('github:') &&
|
|
696
|
+
!effective.startsWith('gitlab:')) {
|
|
697
|
+
rawPath = effective;
|
|
698
|
+
}
|
|
588
699
|
}
|
|
589
700
|
}
|
|
590
701
|
else if ('path' in src) {
|
|
@@ -634,7 +745,7 @@ function assertTextFiles(files, context) {
|
|
|
634
745
|
}
|
|
635
746
|
}
|
|
636
747
|
}
|
|
637
|
-
async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOverride, pendingWrites) {
|
|
748
|
+
async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOverride, pendingWrites, configBase) {
|
|
638
749
|
const { src } = entry;
|
|
639
750
|
const getTargetPath = getTargetPathOverride ??
|
|
640
751
|
(() => (0, paths_1.resolveTargetPath)(entry, '', workingDir, vars));
|
|
@@ -644,7 +755,7 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
644
755
|
const sourceRecords = [];
|
|
645
756
|
for (let i = 0; i < src.length; i++) {
|
|
646
757
|
try {
|
|
647
|
-
const { files, record, skipped } = await fetchOneSrc(src[i], workingDir, vars, cache, getTargetPath, pendingWrites);
|
|
758
|
+
const { files, record, skipped } = await fetchOneSrc(src[i], workingDir, vars, cache, getTargetPath, pendingWrites, configBase);
|
|
648
759
|
if (skipped)
|
|
649
760
|
continue;
|
|
650
761
|
assertTextFiles(files, `source ${i}`);
|
|
@@ -667,6 +778,9 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
667
778
|
const tomlOpts = jsonOpts === null && yamlOpts === null
|
|
668
779
|
? resolveTomlOptions(entry, src)
|
|
669
780
|
: null;
|
|
781
|
+
const iniOpts = jsonOpts === null && yamlOpts === null && tomlOpts === null
|
|
782
|
+
? resolveIniOptions(entry, src)
|
|
783
|
+
: null;
|
|
670
784
|
let content;
|
|
671
785
|
if (jsonOpts !== null) {
|
|
672
786
|
content = (0, json_1.mergeJson)(parts, jsonOpts);
|
|
@@ -677,6 +791,9 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
677
791
|
else if (tomlOpts !== null) {
|
|
678
792
|
content = (0, toml_1.mergeToml)(parts, tomlOpts);
|
|
679
793
|
}
|
|
794
|
+
else if (iniOpts !== null) {
|
|
795
|
+
content = (0, ini_1.mergeIni)(parts, iniOpts);
|
|
796
|
+
}
|
|
680
797
|
else {
|
|
681
798
|
content = parts.join('\n');
|
|
682
799
|
}
|
|
@@ -686,10 +803,37 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
686
803
|
};
|
|
687
804
|
}
|
|
688
805
|
// Single src — delegate dispatch to fetchOneSrc, then apply post-processing
|
|
689
|
-
const { files: singleFiles, record: singleRecord, skipped, } = await fetchOneSrc(src, workingDir, vars, cache, getTargetPath, pendingWrites);
|
|
806
|
+
const { files: singleFiles, record: singleRecord, skipped, } = await fetchOneSrc(src, workingDir, vars, cache, getTargetPath, pendingWrites, configBase);
|
|
690
807
|
if (skipped)
|
|
691
808
|
return { files: new Map(), sourceRecords: [], allSkipped: true };
|
|
692
|
-
|
|
809
|
+
let resolvedFiles = singleFiles;
|
|
810
|
+
if (entry.extract !== undefined) {
|
|
811
|
+
if (singleFiles.size !== 1) {
|
|
812
|
+
throw new Error(`"extract" requires a single-file source, but source returned ${singleFiles.size} file(s)`);
|
|
813
|
+
}
|
|
814
|
+
const [[archiveFilename, archiveBuffer]] = [...singleFiles.entries()];
|
|
815
|
+
if ((0, extract_1.detectArchiveFormat)(archiveFilename) === null) {
|
|
816
|
+
throw new Error(`"extract" was specified but "${archiveFilename}" is not a recognised archive format`);
|
|
817
|
+
}
|
|
818
|
+
const extracted = await (0, extract_1.extractArchive)(archiveBuffer, archiveFilename);
|
|
819
|
+
if (entry.extract === true) {
|
|
820
|
+
resolvedFiles = extracted;
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
const resolvedPatterns = entry.extract.map((p) => (0, variables_1.resolveVars)(p, vars));
|
|
824
|
+
try {
|
|
825
|
+
resolvedFiles = (0, filter_1.applyFilter)(extracted, resolvedPatterns);
|
|
826
|
+
}
|
|
827
|
+
catch (err) {
|
|
828
|
+
if (err instanceof Error &&
|
|
829
|
+
err.message.startsWith('filter matched no files')) {
|
|
830
|
+
throw new Error(`extract matched no entries (${resolvedPatterns.length} pattern${resolvedPatterns.length === 1 ? '' : 's'}: ${resolvedPatterns.map((p) => JSON.stringify(p)).join(', ')})`, { cause: err });
|
|
831
|
+
}
|
|
832
|
+
throw err;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
const singleResult = { files: resolvedFiles };
|
|
693
837
|
const sourceRecords = singleRecord !== null ? [singleRecord] : [];
|
|
694
838
|
// When a directory source resolves to multiple files but the target is a
|
|
695
839
|
// single file (no trailing slash), merge all files sorted by name instead
|
|
@@ -704,7 +848,13 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
704
848
|
let dirTomlOpts = dirJsonOpts === null && dirYamlOpts === null
|
|
705
849
|
? resolveTomlOptions(entry, [src])
|
|
706
850
|
: null;
|
|
707
|
-
|
|
851
|
+
let dirIniOpts = dirJsonOpts === null && dirYamlOpts === null && dirTomlOpts === null
|
|
852
|
+
? resolveIniOptions(entry, [src])
|
|
853
|
+
: null;
|
|
854
|
+
if (dirJsonOpts === null &&
|
|
855
|
+
dirYamlOpts === null &&
|
|
856
|
+
dirTomlOpts === null &&
|
|
857
|
+
dirIniOpts === null) {
|
|
708
858
|
const keys = Array.from(singleResult.files.keys());
|
|
709
859
|
if (entry.json !== false &&
|
|
710
860
|
keys.every((k) => JSON_EXTENSIONS.has(path.extname(k).toLowerCase()))) {
|
|
@@ -718,8 +868,15 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
718
868
|
keys.every((k) => TOML_EXTENSIONS.has(path.extname(k).toLowerCase()))) {
|
|
719
869
|
dirTomlOpts = {};
|
|
720
870
|
}
|
|
871
|
+
else if (entry.ini !== false &&
|
|
872
|
+
keys.every((k) => INI_EXTENSIONS.has(path.extname(k).toLowerCase()))) {
|
|
873
|
+
dirIniOpts = {};
|
|
874
|
+
}
|
|
721
875
|
}
|
|
722
|
-
if (dirJsonOpts !== null ||
|
|
876
|
+
if (dirJsonOpts !== null ||
|
|
877
|
+
dirYamlOpts !== null ||
|
|
878
|
+
dirTomlOpts !== null ||
|
|
879
|
+
dirIniOpts !== null) {
|
|
723
880
|
assertTextFiles(singleResult.files, 'directory merge');
|
|
724
881
|
const sortedValues = Array.from(singleResult.files.entries())
|
|
725
882
|
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
@@ -732,9 +889,12 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
732
889
|
else if (dirYamlOpts !== null) {
|
|
733
890
|
merged = (0, yaml_1.mergeYaml)(sortedValues, dirYamlOpts);
|
|
734
891
|
}
|
|
735
|
-
else {
|
|
892
|
+
else if (dirTomlOpts !== null) {
|
|
736
893
|
merged = (0, toml_1.mergeToml)(sortedValues, dirTomlOpts);
|
|
737
894
|
}
|
|
895
|
+
else {
|
|
896
|
+
merged = (0, ini_1.mergeIni)(sortedValues, dirIniOpts);
|
|
897
|
+
}
|
|
738
898
|
return {
|
|
739
899
|
files: new Map([[filename, Buffer.from(merged, 'utf8')]]),
|
|
740
900
|
sourceRecords,
|
|
@@ -747,9 +907,15 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
747
907
|
const singleTomlOpts = singleJsonOpts === null && singleYamlOpts === null
|
|
748
908
|
? resolveTomlOptions(entry, [src])
|
|
749
909
|
: null;
|
|
910
|
+
const singleIniOpts = singleJsonOpts === null &&
|
|
911
|
+
singleYamlOpts === null &&
|
|
912
|
+
singleTomlOpts === null
|
|
913
|
+
? resolveIniOptions(entry, [src])
|
|
914
|
+
: null;
|
|
750
915
|
if (singleJsonOpts === null &&
|
|
751
916
|
singleYamlOpts === null &&
|
|
752
|
-
singleTomlOpts === null
|
|
917
|
+
singleTomlOpts === null &&
|
|
918
|
+
singleIniOpts === null)
|
|
753
919
|
return { ...singleResult, sourceRecords };
|
|
754
920
|
const formatted = new Map();
|
|
755
921
|
for (const [k, v] of singleResult.files) {
|
|
@@ -758,7 +924,9 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
758
924
|
? 'json'
|
|
759
925
|
: singleYamlOpts !== null
|
|
760
926
|
? 'yaml'
|
|
761
|
-
:
|
|
927
|
+
: singleTomlOpts !== null
|
|
928
|
+
? 'toml'
|
|
929
|
+
: 'ini';
|
|
762
930
|
throw new Error(`Binary file "${k}" cannot be formatted as ${fmtName}. Remove the format option or use a text source.`);
|
|
763
931
|
}
|
|
764
932
|
const text = v.toString('utf8');
|
|
@@ -768,9 +936,12 @@ async function fetchSource(entry, workingDir, vars = {}, cache, getTargetPathOve
|
|
|
768
936
|
else if (singleYamlOpts !== null) {
|
|
769
937
|
formatted.set(k, Buffer.from((0, yaml_1.formatYaml)(text), 'utf8'));
|
|
770
938
|
}
|
|
771
|
-
else {
|
|
939
|
+
else if (singleTomlOpts !== null) {
|
|
772
940
|
formatted.set(k, Buffer.from((0, toml_1.formatToml)(text), 'utf8'));
|
|
773
941
|
}
|
|
942
|
+
else {
|
|
943
|
+
formatted.set(k, Buffer.from((0, ini_1.formatIni)(text), 'utf8'));
|
|
944
|
+
}
|
|
774
945
|
}
|
|
775
946
|
return { files: formatted, sourceRecords };
|
|
776
947
|
}
|