@antora/content-aggregator 3.1.9 → 3.1.11
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/lib/aggregate-content.js +172 -121
- package/lib/compute-origin.js +7 -5
- package/lib/decode-uint8-array.js +1 -1
- package/lib/filter-refs.js +19 -12
- package/lib/git-credential-manager-store.js +5 -5
- package/lib/git.js +8 -1
- package/lib/matcher.js +1 -1
- package/lib/posixify.js +1 -1
- package/lib/resolve-path-globs.js +25 -24
- package/package.json +12 -8
package/lib/aggregate-content.js
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const computeOrigin = require('./compute-origin')
|
|
4
|
-
const { createHash } = require('crypto')
|
|
4
|
+
const { createHash } = require('node:crypto')
|
|
5
5
|
const createGitHttpPlugin = require('./git-plugin-http')
|
|
6
6
|
const decodeUint8Array = require('./decode-uint8-array')
|
|
7
7
|
const deepClone = require('./deep-clone')
|
|
8
|
-
const EventEmitter = require('events')
|
|
8
|
+
const EventEmitter = require('node:events')
|
|
9
9
|
const expandPath = require('@antora/expand-path-helper')
|
|
10
10
|
const File = require('./file')
|
|
11
11
|
const filterRefs = require('./filter-refs')
|
|
12
|
-
const fs = require('fs')
|
|
12
|
+
const fs = require('node:fs')
|
|
13
13
|
const { promises: fsp } = fs
|
|
14
14
|
const getCacheDir = require('cache-directory')
|
|
15
15
|
const GitCredentialManagerStore = require('./git-credential-manager-store')
|
|
16
16
|
const git = require('./git')
|
|
17
17
|
const { NotFoundError, ObjectTypeError, UnknownTransportError, UrlParseError } = git.Errors
|
|
18
18
|
const { globStream } = require('fast-glob')
|
|
19
|
-
const { inspect } = require('util')
|
|
19
|
+
const { inspect } = require('node:util')
|
|
20
20
|
const invariably = require('./invariably')
|
|
21
21
|
const logger = require('./logger')
|
|
22
22
|
const { makeMatcherRx, versionMatcherOpts: VERSION_MATCHER_OPTS } = require('./matcher')
|
|
23
23
|
const MultiProgress = require('multi-progress') // calls require('progress') as a peer dependencies
|
|
24
|
-
const ospath = require('path')
|
|
24
|
+
const ospath = require('node:path')
|
|
25
25
|
const { posix: path } = ospath
|
|
26
26
|
const posixify = require('./posixify')
|
|
27
27
|
const removeGitSuffix = require('./remove-git-suffix')
|
|
28
28
|
const { fs: resolvePathGlobsFs, git: resolvePathGlobsGit } = require('./resolve-path-globs')
|
|
29
|
-
const { pipeline, Writable } = require('stream')
|
|
29
|
+
const { pipeline, Writable } = require('node:stream')
|
|
30
30
|
const forEach = (write) => new Writable({ objectMode: true, write })
|
|
31
31
|
const userRequire = require('@antora/user-require-helper')
|
|
32
32
|
const yaml = require('js-yaml')
|
|
@@ -100,21 +100,22 @@ function aggregateContent (playbook) {
|
|
|
100
100
|
const sourcesByUrl = sources.reduce((accum, source) => {
|
|
101
101
|
return accum.set(source.url, [...(accum.get(source.url) || []), Object.assign({}, sourceDefaults, source)])
|
|
102
102
|
}, new Map())
|
|
103
|
-
const progress =
|
|
103
|
+
const progress = quiet ? undefined : createProgress(sourcesByUrl.keys(), process.stdout)
|
|
104
104
|
const refPatternCache = Object.assign(new Map(), { braces: new Map() })
|
|
105
|
-
const
|
|
105
|
+
const fetchConfig = { always: fetch, depth: Math.max(0, gitConfig.fetchDepth ?? 1) }
|
|
106
|
+
const loadOpts = { cacheDir, fetch: fetchConfig, gitPlugins, progress, startDir, refPatternCache }
|
|
106
107
|
return collectFiles(sourcesByUrl, loadOpts, concurrency).then(buildAggregate, (err) => {
|
|
107
|
-
progress
|
|
108
|
+
progress?.terminate()
|
|
108
109
|
throw err
|
|
109
110
|
})
|
|
110
111
|
})
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
async function collectFiles (sourcesByUrl, loadOpts, concurrency, fetchedUrls) {
|
|
114
|
+
async function collectFiles (sourcesByUrl, loadOpts, concurrency, fetchedUrls = []) {
|
|
114
115
|
const loadTasks = [...sourcesByUrl.entries()].map(([url, sources]) => {
|
|
115
116
|
const loadOptsForUrl = Object.assign({}, loadOpts)
|
|
116
|
-
if (loadOpts.fetch && fetchedUrls
|
|
117
|
-
if (tagsSpecified(sources)) loadOptsForUrl.
|
|
117
|
+
if (loadOpts.fetch.always && fetchedUrls.length && fetchedUrls.includes(url)) loadOptsForUrl.fetch.always = false
|
|
118
|
+
if (tagsSpecified(sources)) loadOptsForUrl.fetch.tags = true
|
|
118
119
|
return loadRepository.bind(null, url, loadOptsForUrl, { url, sources })
|
|
119
120
|
})
|
|
120
121
|
return gracefulPromiseAllWithLimit(loadTasks, concurrency.fetch).then(([results, rejections]) => {
|
|
@@ -124,7 +125,7 @@ async function collectFiles (sourcesByUrl, loadOpts, concurrency, fetchedUrls) {
|
|
|
124
125
|
const msg0 = 'An unexpected error occurred while fetching content sources concurrently.'
|
|
125
126
|
const msg1 = 'Retrying with git.fetch_concurrency value of 1.'
|
|
126
127
|
logger.warn(rejections[0], msg0 + ' ' + msg1)
|
|
127
|
-
const fulfilledUrls = results.
|
|
128
|
+
const fulfilledUrls = results.filter((it) => it?.repo.url).map((it) => it.url)
|
|
128
129
|
return collectFiles(sourcesByUrl, loadOpts, Object.assign(concurrency, { fetch: 1 }), fulfilledUrls)
|
|
129
130
|
}
|
|
130
131
|
throw rejections[0]
|
|
@@ -163,7 +164,7 @@ async function loadRepository (url, opts, result = {}) {
|
|
|
163
164
|
if (~url.indexOf(':') && GIT_URI_DETECTOR_RX.test(url)) {
|
|
164
165
|
let credentials, displayUrl
|
|
165
166
|
;({ displayUrl, url, credentials } = extractCredentials(url))
|
|
166
|
-
const { cacheDir, fetch,
|
|
167
|
+
const { cacheDir, fetch, gitPlugins, progress } = opts
|
|
167
168
|
dir = ospath.join(cacheDir, generateCloneFolderName(displayUrl))
|
|
168
169
|
// NOTE the presence of the url property on the repo object implies the repository is remote
|
|
169
170
|
repo = { cache, dir, fs, gitdir: dir, noCheckout: true, url }
|
|
@@ -171,9 +172,9 @@ async function loadRepository (url, opts, result = {}) {
|
|
|
171
172
|
const validStateFile = ospath.join(dir, VALID_STATE_FILENAME)
|
|
172
173
|
try {
|
|
173
174
|
await fsp.access(validStateFile)
|
|
174
|
-
if (fetch) {
|
|
175
|
+
if (fetch.always) {
|
|
175
176
|
await fsp.unlink(validStateFile)
|
|
176
|
-
const fetchOpts = buildFetchOptions(repo, progress, displayUrl, credentials, gitPlugins,
|
|
177
|
+
const fetchOpts = buildFetchOptions(repo, progress, displayUrl, credentials, gitPlugins, fetch, 'fetch')
|
|
177
178
|
await git
|
|
178
179
|
.fetch(fetchOpts)
|
|
179
180
|
.then(() => {
|
|
@@ -181,19 +182,19 @@ async function loadRepository (url, opts, result = {}) {
|
|
|
181
182
|
return git.setConfig(Object.assign({ path: 'remote.origin.private', value: authStatus }, repo))
|
|
182
183
|
})
|
|
183
184
|
.catch((fetchErr) => {
|
|
184
|
-
|
|
185
|
+
fetchOpts.onProgress?.finish(fetchErr)
|
|
185
186
|
if (HTTP_ERROR_CODE_RX.test(fetchErr.code) && fetchErr.data.statusCode === 401) fetchErr.rethrow = true
|
|
186
187
|
throw fetchErr
|
|
187
188
|
})
|
|
188
189
|
.then(() => fsp.writeFile(validStateFile, '').catch(invariably.void))
|
|
189
|
-
.then(() => fetchOpts.onProgress
|
|
190
|
+
.then(() => fetchOpts.onProgress?.finish())
|
|
190
191
|
} else {
|
|
191
192
|
authStatus = await git.getConfig(Object.assign({ path: 'remote.origin.private' }, repo))
|
|
192
193
|
}
|
|
193
194
|
} catch (gitErr) {
|
|
194
195
|
await fsp['rm' in fsp ? 'rm' : 'rmdir'](dir, { recursive: true, force: true })
|
|
195
196
|
if (gitErr.rethrow) throw transformGitCloneError(gitErr, displayUrl)
|
|
196
|
-
const fetchOpts = buildFetchOptions(repo, progress, displayUrl, credentials, gitPlugins,
|
|
197
|
+
const fetchOpts = buildFetchOptions(repo, progress, displayUrl, credentials, gitPlugins, fetch, 'clone')
|
|
197
198
|
await git
|
|
198
199
|
.clone(fetchOpts)
|
|
199
200
|
.then(() => git.resolveRef(Object.assign({ ref: 'HEAD', depth: 1 }, repo)))
|
|
@@ -202,16 +203,23 @@ async function loadRepository (url, opts, result = {}) {
|
|
|
202
203
|
return git.setConfig(Object.assign({ path: 'remote.origin.private', value: authStatus }, repo))
|
|
203
204
|
})
|
|
204
205
|
.catch((cloneErr) => {
|
|
205
|
-
|
|
206
|
+
fetchOpts.onProgress?.finish(cloneErr)
|
|
206
207
|
const authRequested = credentialManager.status({ url }) === 'requested'
|
|
207
208
|
throw transformGitCloneError(cloneErr, displayUrl, authRequested)
|
|
208
209
|
})
|
|
209
210
|
.then(() => fsp.writeFile(validStateFile, '').catch(invariably.void))
|
|
210
|
-
.then(() => fetchOpts.onProgress
|
|
211
|
+
.then(() => fetchOpts.onProgress?.finish())
|
|
211
212
|
}
|
|
212
213
|
} else if (await isDirectory((dir = expandPath(url, { dot: opts.startDir })))) {
|
|
213
|
-
const
|
|
214
|
-
|
|
214
|
+
const dotgit = ospath.join(dir, '.git')
|
|
215
|
+
const dotgitStat = await fsp.stat(dotgit).catch(() => ({ isFile: invariably.false, isDirectory: invariably.false }))
|
|
216
|
+
if (dotgitStat.isDirectory()) {
|
|
217
|
+
repo = { cache, dir, fs, gitdir: dotgit }
|
|
218
|
+
} else if (dotgitStat.isFile()) {
|
|
219
|
+
repo = await resolveRepositoryFromWorktree({ cache, dir, fs, gitdir: dotgit })
|
|
220
|
+
} else {
|
|
221
|
+
repo = { cache, dir, fs, gitdir: dir, noCheckout: true }
|
|
222
|
+
}
|
|
215
223
|
try {
|
|
216
224
|
await git.resolveRef(Object.assign({ ref: 'HEAD', depth: 1 }, repo))
|
|
217
225
|
} catch {
|
|
@@ -236,11 +244,9 @@ function extractCredentials (url) {
|
|
|
236
244
|
// NOTE if only username is present, assume it's an oauth token and set password to empty string
|
|
237
245
|
const credentials = username ? { username, password: password || '' } : {}
|
|
238
246
|
return { displayUrl, url, credentials }
|
|
239
|
-
} else if (url.startsWith('git@')) {
|
|
240
|
-
return { displayUrl: url, url: 'https://' + url.substr(4).replace(':', '/') }
|
|
241
|
-
} else {
|
|
242
|
-
return { displayUrl: url, url }
|
|
243
247
|
}
|
|
248
|
+
if (url.startsWith('git@')) return { displayUrl: url, url: 'https://' + url.substr(4).replace(':', '/') }
|
|
249
|
+
return { displayUrl: url, url }
|
|
244
250
|
}
|
|
245
251
|
|
|
246
252
|
async function selectStartPathsForRepository (repo, authStatus, sources) {
|
|
@@ -248,14 +254,27 @@ async function selectStartPathsForRepository (repo, authStatus, sources) {
|
|
|
248
254
|
const originUrls = {}
|
|
249
255
|
for (const source of sources) {
|
|
250
256
|
const { version, editUrl } = source
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
257
|
+
let remoteName, originUrl
|
|
258
|
+
if (repo.url) {
|
|
259
|
+
remoteName = 'origin' // NOTE if repository is managed (has url property), we can assume remote name is origin
|
|
260
|
+
originUrl = repo.url
|
|
261
|
+
} else {
|
|
262
|
+
remoteName = source.remote || 'origin'
|
|
263
|
+
originUrl =
|
|
264
|
+
remoteName in originUrls
|
|
265
|
+
? originUrls[remoteName]
|
|
266
|
+
: (originUrls[remoteName] = await resolveRemoteUrl(repo, remoteName))
|
|
267
|
+
if (!originUrl) {
|
|
268
|
+
remoteName = undefined
|
|
269
|
+
if ((originUrl = posixify ? 'file:///' + posixify(repo.dir) : 'file://' + repo.dir).indexOf(' ')) {
|
|
270
|
+
originUrl = originUrl.replace(SPACE_RX, '%20')
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
255
274
|
const refs = await selectReferences(source, repo, remoteName)
|
|
256
275
|
if (refs.length) {
|
|
257
276
|
for (const ref of refs) {
|
|
258
|
-
for (const startPath of await selectStartPaths(source, repo,
|
|
277
|
+
for (const startPath of await selectStartPaths(source, repo, ref)) {
|
|
259
278
|
startPaths.push({ startPath, ref, originUrl, editUrl, version })
|
|
260
279
|
}
|
|
261
280
|
}
|
|
@@ -274,7 +293,7 @@ async function selectStartPathsForRepository (repo, authStatus, sources) {
|
|
|
274
293
|
|
|
275
294
|
// QUESTION should we resolve HEAD to a ref eagerly to avoid having to do a match on it?
|
|
276
295
|
async function selectReferences (source, repo, remote) {
|
|
277
|
-
let { branches: branchPatterns, tags: tagPatterns, worktrees: worktreePatterns
|
|
296
|
+
let { branches: branchPatterns, tags: tagPatterns, worktrees: worktreePatterns } = source
|
|
278
297
|
const managed = 'url' in repo
|
|
279
298
|
const isBare = managed || repo.noCheckout
|
|
280
299
|
const patternCache = repo.cache[REF_PATTERN_CACHE_KEY]
|
|
@@ -294,7 +313,16 @@ async function selectReferences (source, repo, remote) {
|
|
|
294
313
|
}
|
|
295
314
|
}
|
|
296
315
|
}
|
|
297
|
-
if (
|
|
316
|
+
if (
|
|
317
|
+
!branchPatterns ||
|
|
318
|
+
!(branchPatterns = Array.isArray(branchPatterns)
|
|
319
|
+
? branchPatterns.map((pattern) => String(pattern))
|
|
320
|
+
: splitRefPatterns(String(branchPatterns))).length
|
|
321
|
+
) {
|
|
322
|
+
return [...refs.values()]
|
|
323
|
+
}
|
|
324
|
+
const worktreeName = repo.worktreeName // possibly switch to worktree property ({ name, dir}) in future
|
|
325
|
+
if (worktreeName) branchPatterns = branchPatterns.map((it) => (it === 'HEAD' ? 'HEAD@' + worktreeName : it))
|
|
298
326
|
if (worktreePatterns) {
|
|
299
327
|
if (worktreePatterns === '.') {
|
|
300
328
|
worktreePatterns = ['.']
|
|
@@ -304,14 +332,14 @@ async function selectReferences (source, repo, remote) {
|
|
|
304
332
|
worktreePatterns = Array.isArray(worktreePatterns)
|
|
305
333
|
? worktreePatterns.map((pattern) => String(pattern))
|
|
306
334
|
: splitRefPatterns(String(worktreePatterns))
|
|
335
|
+
if (worktreeName) worktreePatterns = worktreePatterns.map((it) => (it === '@' ? worktreeName : it))
|
|
307
336
|
}
|
|
308
337
|
} else {
|
|
309
|
-
worktreePatterns = []
|
|
338
|
+
worktreePatterns = worktreePatterns === undefined ? [worktreeName || '.'] : []
|
|
310
339
|
}
|
|
311
|
-
|
|
312
|
-
if (
|
|
313
|
-
|
|
314
|
-
if (currentBranch) {
|
|
340
|
+
let currentBranch
|
|
341
|
+
if (branchPatterns.length === 1 && (branchPatterns[0] === 'HEAD' || branchPatterns[0] === '.')) {
|
|
342
|
+
if ((currentBranch = await getCurrentBranchName(repo, remote).then((branch) => branch ?? false))) {
|
|
315
343
|
branchPatterns = [currentBranch]
|
|
316
344
|
} else if (isBare) {
|
|
317
345
|
return [...refs.values()]
|
|
@@ -321,17 +349,11 @@ async function selectReferences (source, repo, remote) {
|
|
|
321
349
|
refs.set('HEAD', { shortname: 'HEAD', fullname: 'HEAD', type: 'branch', detached: true, head })
|
|
322
350
|
return [...refs.values()]
|
|
323
351
|
}
|
|
324
|
-
} else
|
|
325
|
-
(branchPatterns = Array.isArray(branchPatterns)
|
|
326
|
-
? branchPatterns.map((pattern) => String(pattern))
|
|
327
|
-
: splitRefPatterns(branchPatternsString)).length
|
|
328
|
-
) {
|
|
352
|
+
} else {
|
|
329
353
|
let headBranchIdx
|
|
330
354
|
// NOTE we can assume at least two entries if HEAD or . are present
|
|
331
355
|
if (~(headBranchIdx = branchPatterns.indexOf('HEAD')) || ~(headBranchIdx = branchPatterns.indexOf('.'))) {
|
|
332
|
-
|
|
333
|
-
if (currentBranch) {
|
|
334
|
-
// NOTE ignore if current branch is already in list
|
|
356
|
+
if ((currentBranch = await getCurrentBranchName(repo, remote).then((branch) => branch ?? false))) {
|
|
335
357
|
if (~branchPatterns.indexOf(currentBranch)) {
|
|
336
358
|
branchPatterns.splice(headBranchIdx, 1)
|
|
337
359
|
} else {
|
|
@@ -350,11 +372,11 @@ async function selectReferences (source, repo, remote) {
|
|
|
350
372
|
branchPatterns.splice(headBranchIdx, 1)
|
|
351
373
|
}
|
|
352
374
|
}
|
|
353
|
-
} else {
|
|
354
|
-
return [...refs.values()]
|
|
355
375
|
}
|
|
356
376
|
// NOTE isomorphic-git includes HEAD in list of remote branches (see https://isomorphic-git.org/docs/listBranches)
|
|
357
|
-
const remoteBranches =
|
|
377
|
+
const remoteBranches = remote
|
|
378
|
+
? (await git.listBranches(Object.assign({ remote }, repo))).filter((it) => it !== 'HEAD')
|
|
379
|
+
: []
|
|
358
380
|
if (remoteBranches.length) {
|
|
359
381
|
for (const shortname of filterRefs(remoteBranches, branchPatterns, patternCache)) {
|
|
360
382
|
const fullname = 'remotes/' + remote + '/' + shortname
|
|
@@ -363,11 +385,27 @@ async function selectReferences (source, repo, remote) {
|
|
|
363
385
|
}
|
|
364
386
|
// NOTE only consider local branches if repo has a worktree or there are no remote tracking branches
|
|
365
387
|
if (!isBare) {
|
|
366
|
-
const localBranches = await git.listBranches(repo)
|
|
388
|
+
const localBranches = await git.listBranches(repo).then((branches) => {
|
|
389
|
+
if (branches.length) return branches
|
|
390
|
+
if (currentBranch == null) return getCurrentBranchName(repo).then((branch) => (branch ? [branch] : []))
|
|
391
|
+
return currentBranch ? [currentBranch] : []
|
|
392
|
+
})
|
|
367
393
|
if (localBranches.length) {
|
|
368
394
|
const worktrees = await findWorktrees(repo, worktreePatterns)
|
|
369
|
-
|
|
370
|
-
|
|
395
|
+
let onMatch
|
|
396
|
+
if ((worktreePatterns.join('') || '.') !== '.') {
|
|
397
|
+
const symbolicNames = new Map()
|
|
398
|
+
worktrees.forEach(({ name, symbolicName = 'HEAD@' + name }, shortname) => {
|
|
399
|
+
localBranches.push(symbolicName)
|
|
400
|
+
symbolicNames.set(symbolicName, shortname)
|
|
401
|
+
})
|
|
402
|
+
onMatch = (candidate, { pattern }) => {
|
|
403
|
+
const shortname = symbolicNames.get(candidate)
|
|
404
|
+
return shortname ? (pattern.startsWith('HEAD@') ? shortname : undefined) : candidate
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
for (const shortname of filterRefs(localBranches, branchPatterns, patternCache, onMatch)) {
|
|
408
|
+
const head = (worktrees.get(shortname) || { head: noWorktree }).head
|
|
371
409
|
refs.set(shortname, { shortname, fullname: 'heads/' + shortname, type: 'branch', head })
|
|
372
410
|
}
|
|
373
411
|
}
|
|
@@ -387,18 +425,16 @@ async function selectReferences (source, repo, remote) {
|
|
|
387
425
|
* Returns the current branch name or undefined if the HEAD is detached.
|
|
388
426
|
*/
|
|
389
427
|
function getCurrentBranchName (repo, remote) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
}
|
|
398
|
-
return refPromise.then((ref) => (ref.startsWith('refs/') ? ref.replace(SHORTEN_REF_RX, '') : undefined))
|
|
428
|
+
return (
|
|
429
|
+
remote && repo.noCheckout
|
|
430
|
+
? git
|
|
431
|
+
.resolveRef(Object.assign({ ref: 'refs/remotes/' + remote + '/HEAD', depth: 2 }, repo))
|
|
432
|
+
.catch(() => git.resolveRef(Object.assign({ ref: 'HEAD', depth: 2 }, repo)))
|
|
433
|
+
: git.resolveRef(Object.assign({ ref: 'HEAD', depth: 2 }, repo))
|
|
434
|
+
).then((ref) => (ref.startsWith('refs/') ? ref.replace(SHORTEN_REF_RX, '') : undefined))
|
|
399
435
|
}
|
|
400
436
|
|
|
401
|
-
async function selectStartPaths (source, repo,
|
|
437
|
+
async function selectStartPaths (source, repo, ref) {
|
|
402
438
|
const url = repo.url
|
|
403
439
|
const displayUrl = url || repo.dir
|
|
404
440
|
const worktreePath = ref.head
|
|
@@ -440,7 +476,7 @@ function collectFilesFromStartPath (startPath, repo, authStatus, ref, originUrl,
|
|
|
440
476
|
return (worktreePath ? readFilesFromWorktree(origin) : readFilesFromGitTree(repo, ref.oid, startPath))
|
|
441
477
|
.then((files) => {
|
|
442
478
|
const batch = deepClone((origin.descriptor = loadComponentDescriptor(files, ref, version)))
|
|
443
|
-
if ('nav' in batch) batch.nav.origin = origin
|
|
479
|
+
if ('nav' in batch && Array.isArray(batch.nav)) batch.nav.origin = origin
|
|
444
480
|
batch.files = files.map((file) => assignFileProperties(file, origin))
|
|
445
481
|
batch.origins = [origin]
|
|
446
482
|
return batch
|
|
@@ -525,9 +561,9 @@ function readFilesFromGitTree (repo, oid, startPath) {
|
|
|
525
561
|
Object.assign(root, { dirname: '' })
|
|
526
562
|
return startPath
|
|
527
563
|
? getGitTreeAtStartPath(repo, oid, startPath).then((start) => {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
564
|
+
Object.assign(start, { dirname: startPath })
|
|
565
|
+
return srcGitTree(repo, root, start)
|
|
566
|
+
})
|
|
531
567
|
: srcGitTree(repo, root)
|
|
532
568
|
})
|
|
533
569
|
}
|
|
@@ -582,7 +618,8 @@ function visitGitTree (emitter, repo, root, filter, convert, parent, dirname = '
|
|
|
582
618
|
(target) => {
|
|
583
619
|
if (target.type === 'tree') {
|
|
584
620
|
return visitGitTree(emitter, repo, root, filter, convert, target, vfilePath, target.following)
|
|
585
|
-
}
|
|
621
|
+
}
|
|
622
|
+
if (target.type === 'blob' && filterVerdict === true && (mode = FILE_MODES[target.mode])) {
|
|
586
623
|
return convert(Object.assign({ mode, oid: target.oid, path: vfilePath }, repo)).then((result) =>
|
|
587
624
|
emitter.emit('entry', result)
|
|
588
625
|
)
|
|
@@ -654,11 +691,11 @@ function readGitObjectAtPath (repo, root, parent, pathSegments, following) {
|
|
|
654
691
|
if (entry.path === firstPathSegment) {
|
|
655
692
|
return entry.type === 'tree'
|
|
656
693
|
? git.readTree(Object.assign({ oid: entry.oid }, repo)).then((subtree) => {
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
694
|
+
Object.assign(subtree, { dirname: path.join(parent.dirname, entry.path) })
|
|
695
|
+
return (pathSegments = pathSegments.slice(1)).length
|
|
696
|
+
? readGitObjectAtPath(repo, root, subtree, pathSegments, following)
|
|
697
|
+
: Object.assign(subtree, { type: 'tree', following }) // Q: should this create copy?
|
|
698
|
+
})
|
|
662
699
|
: entry.mode === SYMLINK_FILE_MODE
|
|
663
700
|
? readGitSymlink(repo, root, parent, entry, following)
|
|
664
701
|
: Promise.resolve(entry)
|
|
@@ -712,18 +749,18 @@ function loadComponentDescriptor (files, ref, version) {
|
|
|
712
749
|
if (!version) {
|
|
713
750
|
if (version === undefined) throw new Error(`${COMPONENT_DESC_FILENAME} is missing a version`)
|
|
714
751
|
if (version === false) throw new Error(`${COMPONENT_DESC_FILENAME} has an invalid version`)
|
|
715
|
-
version =
|
|
752
|
+
version = typeof version === 'number' ? '' + version : ''
|
|
716
753
|
} else if (version === true) {
|
|
717
754
|
version = ref.shortname.replace(PATH_SEPARATOR_RX, '-')
|
|
718
755
|
} else if (version.constructor === Object) {
|
|
719
756
|
const refname = ref.shortname
|
|
720
757
|
let matched
|
|
721
758
|
if (refname in version) {
|
|
722
|
-
matched = version[refname]
|
|
759
|
+
matched = '' + (version[refname] ?? '')
|
|
723
760
|
} else if (
|
|
724
761
|
!Object.entries(version).some(([pattern, replacement]) => {
|
|
725
|
-
const result = refname.replace(makeMatcherRx(pattern, VERSION_MATCHER_OPTS), '\0' + replacement)
|
|
726
|
-
if (result === refname) return false
|
|
762
|
+
const result = refname.replace(makeMatcherRx(pattern, VERSION_MATCHER_OPTS), '\0' + (replacement ?? ''))
|
|
763
|
+
if (result === refname) return false // no match
|
|
727
764
|
matched = result.substr(1)
|
|
728
765
|
return true
|
|
729
766
|
})
|
|
@@ -738,7 +775,7 @@ function loadComponentDescriptor (files, ref, version) {
|
|
|
738
775
|
throw new Error(`version in ${COMPONENT_DESC_FILENAME} cannot have path segments: ${version}`)
|
|
739
776
|
}
|
|
740
777
|
data.version = version
|
|
741
|
-
return camelCaseKeys(data, ['asciidoc'])
|
|
778
|
+
return camelCaseKeys(data, ['asciidoc', 'ext'])
|
|
742
779
|
}
|
|
743
780
|
|
|
744
781
|
function assignFileProperties (file, origin) {
|
|
@@ -755,18 +792,20 @@ function assignFileProperties (file, origin) {
|
|
|
755
792
|
return file
|
|
756
793
|
}
|
|
757
794
|
|
|
758
|
-
function buildFetchOptions (repo, progress, displayUrl, credentialsFromUrl, gitPlugins,
|
|
795
|
+
function buildFetchOptions (repo, progress, displayUrl, credentialsFromUrl, gitPlugins, fetch, operation) {
|
|
759
796
|
const { credentialManager, http, urlRouter } = gitPlugins
|
|
797
|
+
const corsProxy = false
|
|
798
|
+
const depth = fetch.depth || undefined
|
|
760
799
|
const onAuth = resolveCredentials.bind(credentialManager, new Map().set(undefined, credentialsFromUrl))
|
|
761
800
|
const onAuthFailure = onAuth
|
|
762
801
|
const onAuthSuccess = (url) => credentialManager.approved({ url })
|
|
763
|
-
const opts = Object.assign({ corsProxy
|
|
802
|
+
const opts = Object.assign({ corsProxy, depth, http, onAuth, onAuthFailure, onAuthSuccess }, repo)
|
|
764
803
|
if (urlRouter) opts.url = urlRouter.ensureGitSuffix(opts.url)
|
|
765
804
|
if (progress) opts.onProgress = createProgressListener(progress, displayUrl, operation)
|
|
766
805
|
if (operation === 'fetch') {
|
|
767
806
|
opts.prune = true
|
|
768
|
-
if (
|
|
769
|
-
} else if (!
|
|
807
|
+
if (fetch.tags) opts.tags = opts.pruneTags = true
|
|
808
|
+
} else if (!fetch.tags) {
|
|
770
809
|
opts.noTags = true
|
|
771
810
|
}
|
|
772
811
|
return opts
|
|
@@ -861,7 +900,11 @@ function resolveCredentials (credentialsFromUrlHolder, url, auth) {
|
|
|
861
900
|
}
|
|
862
901
|
|
|
863
902
|
function identifyAuthStatus (credentialManager, credentials, url) {
|
|
864
|
-
|
|
903
|
+
const status = credentialManager.status({ url })
|
|
904
|
+
if (credentials) {
|
|
905
|
+
return typeof status === 'string' && status.startsWith('requested,') ? 'auth-required' : 'auth-embedded'
|
|
906
|
+
}
|
|
907
|
+
if (status != null) return 'auth-required'
|
|
865
908
|
}
|
|
866
909
|
|
|
867
910
|
/**
|
|
@@ -870,7 +913,7 @@ function identifyAuthStatus (credentialManager, credentials, url) {
|
|
|
870
913
|
* The purpose of this function is generate a safe, unique folder name for the cloned
|
|
871
914
|
* repository that gets stored in the cache directory.
|
|
872
915
|
*
|
|
873
|
-
* The generated folder name follows the pattern: <basename>-<sha1
|
|
916
|
+
* The generated folder name follows the pattern: <basename>-<sha1-of-normalized-url>.git
|
|
874
917
|
*
|
|
875
918
|
* @param {String} url - The repository URL to convert.
|
|
876
919
|
* @returns {String} The generated folder name.
|
|
@@ -886,21 +929,18 @@ function generateCloneFolderName (url) {
|
|
|
886
929
|
*
|
|
887
930
|
* @param {Repository} repo - The repository on which to operate.
|
|
888
931
|
* @param {String} remoteName - The name of the remote to resolve.
|
|
889
|
-
* @returns {String} The URL of the specified remote, if defined
|
|
932
|
+
* @returns {String} The URL of the specified remote, if defined
|
|
890
933
|
*/
|
|
891
934
|
function resolveRemoteUrl (repo, remoteName) {
|
|
892
935
|
return git.getConfig(Object.assign({ path: 'remote.' + remoteName + '.url' }, repo)).then((url) => {
|
|
893
|
-
if (url)
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
}
|
|
936
|
+
if (!url) return
|
|
937
|
+
if (url.startsWith('https://') || url.startsWith('http://')) {
|
|
938
|
+
return ~url.indexOf('@') ? url.replace(URL_AUTH_CLEANER_RX, '$1') : url
|
|
939
|
+
}
|
|
940
|
+
if (url.startsWith('git@')) return 'https://' + url.substr(4).replace(':', '/')
|
|
941
|
+
if (url.startsWith('ssh://')) {
|
|
942
|
+
return 'https://' + url.substr(url.indexOf('@') + 1 || 6).replace(URL_PORT_CLEANER_RX, '$1')
|
|
901
943
|
}
|
|
902
|
-
url = posixify ? 'file:///' + posixify(repo.dir) : 'file://' + repo.dir
|
|
903
|
-
return ~url.indexOf(' ') ? url.replace(SPACE_RX, '%20') : url
|
|
904
944
|
})
|
|
905
945
|
}
|
|
906
946
|
|
|
@@ -928,7 +968,7 @@ function loadGitPlugins (gitConfig, networkConfig, startDir) {
|
|
|
928
968
|
if (typeof credentialManager.configure === 'function') {
|
|
929
969
|
credentialManager.configure({ config: gitConfig.credentials, startDir })
|
|
930
970
|
}
|
|
931
|
-
if (typeof credentialManager.status !== 'function') Object.assign(credentialManager, { status
|
|
971
|
+
if (typeof credentialManager.status !== 'function') Object.assign(credentialManager, { status: invariably.void })
|
|
932
972
|
} else {
|
|
933
973
|
credentialManager = new GitCredentialManagerStore().configure({ config: gitConfig.credentials, startDir })
|
|
934
974
|
}
|
|
@@ -1018,39 +1058,50 @@ function coerceToString (value) {
|
|
|
1018
1058
|
return value == null ? '' : String(value)
|
|
1019
1059
|
}
|
|
1020
1060
|
|
|
1061
|
+
function resolveRepositoryFromWorktree (repo) {
|
|
1062
|
+
return fsp
|
|
1063
|
+
.readFile(repo.gitdir, 'utf8')
|
|
1064
|
+
.then((contents) => contents.substr(8).trimEnd())
|
|
1065
|
+
.then((worktreeGitdir) =>
|
|
1066
|
+
fsp.readFile(ospath.join(worktreeGitdir, 'commondir'), 'utf8').then(
|
|
1067
|
+
(contents) => {
|
|
1068
|
+
const gitdir = ospath.join(worktreeGitdir, contents.trimEnd())
|
|
1069
|
+
const dir = ospath.basename(gitdir) === '.git' ? ospath.dirname(gitdir) : gitdir
|
|
1070
|
+
return Object.assign(repo, { dir, gitdir, worktreeName: ospath.basename(worktreeGitdir) })
|
|
1071
|
+
},
|
|
1072
|
+
() => repo
|
|
1073
|
+
)
|
|
1074
|
+
)
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1021
1077
|
function findWorktrees (repo, patterns) {
|
|
1022
1078
|
if (!patterns.length) return new Map()
|
|
1023
|
-
const
|
|
1024
|
-
|
|
1079
|
+
const mainWorktree =
|
|
1080
|
+
patterns[0] === '.' && (patterns = patterns.slice(1))
|
|
1081
|
+
? getCurrentBranchName(repo).then((branch) => branch && [branch, { head: repo.dir, name: '.' }])
|
|
1082
|
+
: Promise.resolve()
|
|
1083
|
+
const worktreesDir = patterns.length ? ospath.join(repo.dir, '.git', 'worktrees') : undefined
|
|
1025
1084
|
const patternCache = repo.cache[REF_PATTERN_CACHE_KEY]
|
|
1026
1085
|
return (
|
|
1027
|
-
|
|
1086
|
+
worktreesDir
|
|
1028
1087
|
? fsp
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
? Promise.all(
|
|
1088
|
+
.readdir(worktreesDir)
|
|
1089
|
+
.then((worktreeNames) => filterRefs(worktreeNames, patterns, patternCache), invariably.emptyArray)
|
|
1090
|
+
.then((worktreeNames) =>
|
|
1091
|
+
Promise.all(
|
|
1034
1092
|
worktreeNames.map((worktreeName) => {
|
|
1035
1093
|
const gitdir = ospath.resolve(worktreesDir, worktreeName)
|
|
1036
|
-
// NOTE
|
|
1037
|
-
return
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
.then((contents) => ({ branch, dir: ospath.dirname(contents.trimEnd()) }))
|
|
1043
|
-
)
|
|
1094
|
+
// NOTE branch name defaults to worktree name if HEAD is detached
|
|
1095
|
+
return getCurrentBranchName(Object.assign({}, repo, { gitdir })).then((branch = worktreeName) =>
|
|
1096
|
+
fsp
|
|
1097
|
+
.readFile(ospath.join(gitdir, 'gitdir'), 'utf8')
|
|
1098
|
+
.then((contents) => [branch, { head: ospath.dirname(contents.trimEnd()), name: worktreeName }])
|
|
1099
|
+
)
|
|
1044
1100
|
})
|
|
1045
|
-
)
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
).then((worktrees) =>
|
|
1050
|
-
linkedOnly
|
|
1051
|
-
? worktrees
|
|
1052
|
-
: git.currentBranch(repo).then((branch) => (branch ? worktrees.set(branch, repo.dir) : worktrees))
|
|
1053
|
-
)
|
|
1101
|
+
)
|
|
1102
|
+
)
|
|
1103
|
+
: Promise.resolve()
|
|
1104
|
+
).then((entries = []) => mainWorktree.then((entry) => new Map(entry ? entries.push(entry) && entries : entries)))
|
|
1054
1105
|
}
|
|
1055
1106
|
|
|
1056
1107
|
async function gracefulPromiseAllWithLimit (tasks, limit = Infinity) {
|
package/lib/compute-origin.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { posix: path } = require('path')
|
|
3
|
+
const { posix: path } = require('node:path')
|
|
4
4
|
const posixify = require('./posixify')
|
|
5
5
|
const removeGitSuffix = require('./remove-git-suffix')
|
|
6
6
|
|
|
7
|
-
const EDIT_URL_TEMPLATE_VAR_RX = /\{(web_url|ref(?:hash|name|type)
|
|
7
|
+
const EDIT_URL_TEMPLATE_VAR_RX = /\{(web_url|ref(?:hash|name|type)?|path)\}/g
|
|
8
8
|
const HOSTED_GIT_REPO_RX = /^(?:https?:\/\/|.+@)(git(?:hub|lab)\.com|bitbucket\.org|pagure\.io)[/:](.+?)(?:\.git)?$/
|
|
9
9
|
|
|
10
10
|
function computeOrigin (url, authStatus, gitdir, ref, startPath, worktreePath = undefined, editUrl = true) {
|
|
@@ -24,7 +24,7 @@ function computeOrigin (url, authStatus, gitdir, ref, startPath, worktreePath =
|
|
|
24
24
|
if (authStatus) origin.private = authStatus
|
|
25
25
|
if (url) origin.webUrl = removeGitSuffix(url)
|
|
26
26
|
if (editUrl === true) {
|
|
27
|
-
const match = url
|
|
27
|
+
const match = url?.match(HOSTED_GIT_REPO_RX)
|
|
28
28
|
if (match) {
|
|
29
29
|
const host = match[1]
|
|
30
30
|
let action = 'blob'
|
|
@@ -33,14 +33,16 @@ function computeOrigin (url, authStatus, gitdir, ref, startPath, worktreePath =
|
|
|
33
33
|
category = 'f'
|
|
34
34
|
} else if (host === 'bitbucket.org') {
|
|
35
35
|
action = 'src'
|
|
36
|
-
} else
|
|
37
|
-
action = 'edit'
|
|
36
|
+
} else {
|
|
37
|
+
if (reftype === 'branch') action = 'edit'
|
|
38
|
+
if (host.startsWith('gitlab.')) action = '-/' + action
|
|
38
39
|
}
|
|
39
40
|
origin.editUrlPattern = 'https://' + path.join(match[1], match[2], action, refname, category, startPath, '%s')
|
|
40
41
|
}
|
|
41
42
|
} else if (editUrl) {
|
|
42
43
|
const vars = {
|
|
43
44
|
path: () => (startPath ? path.join(startPath, '%s') : '%s'),
|
|
45
|
+
ref: () => 'refs/' + (reftype === 'branch' ? 'heads' : reftype) + '/' + refname,
|
|
44
46
|
refhash: () => refhash,
|
|
45
47
|
reftype: () => reftype,
|
|
46
48
|
refname: () => refname,
|
package/lib/filter-refs.js
CHANGED
|
@@ -4,19 +4,20 @@ const { makeMatcherRx, refMatcherOpts: getMatcherOpts, MATCH_ALL_RX } = require(
|
|
|
4
4
|
|
|
5
5
|
function compileRx (pattern, opts) {
|
|
6
6
|
if (pattern === '*' || pattern === '**') return MATCH_ALL_RX
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const rx =
|
|
8
|
+
pattern.charAt() === '!' // we handle negate ourselves
|
|
9
|
+
? Object.defineProperty(makeMatcherRx((pattern = pattern.substr(1)), opts), 'negated', { value: true })
|
|
10
|
+
: makeMatcherRx(pattern, opts)
|
|
11
|
+
return Object.defineProperty(rx, 'pattern', { value: pattern })
|
|
10
12
|
}
|
|
11
13
|
|
|
12
|
-
function createMatcher (patterns, cache,
|
|
14
|
+
function createMatcher (patterns, cache = Object.assign(new Map(), { braces: new Map() })) {
|
|
13
15
|
const rxs = patterns.map(
|
|
14
|
-
(pattern) =>
|
|
15
|
-
cache.get(pattern) || cache.set(pattern, compileRx(pattern, opts || (opts = getMatcherOpts(cache)))).get(pattern)
|
|
16
|
+
(pattern) => cache.get(pattern) || cache.set(pattern, compileRx(pattern, getMatcherOpts(cache))).get(pattern)
|
|
16
17
|
)
|
|
17
18
|
if (rxs[0].negated) rxs.unshift(MATCH_ALL_RX)
|
|
18
|
-
return (candidate) => {
|
|
19
|
-
let matched
|
|
19
|
+
return (candidate, onMatch) => {
|
|
20
|
+
let matched, symbolic
|
|
20
21
|
for (const rx of rxs) {
|
|
21
22
|
let voteIfMatched = true
|
|
22
23
|
if (matched) {
|
|
@@ -25,16 +26,22 @@ function createMatcher (patterns, cache, opts) {
|
|
|
25
26
|
} else if (rx.negated) {
|
|
26
27
|
continue
|
|
27
28
|
}
|
|
28
|
-
if (rx.test(candidate))
|
|
29
|
+
if (rx.test(candidate) || (symbolic && rx.test(symbolic) && (candidate = symbolic))) {
|
|
30
|
+
if (onMatch) {
|
|
31
|
+
if (!(matched = onMatch(candidate, rx))) continue
|
|
32
|
+
;[symbolic, candidate] = [candidate, matched]
|
|
33
|
+
}
|
|
34
|
+
matched = voteIfMatched && candidate
|
|
35
|
+
}
|
|
29
36
|
}
|
|
30
37
|
return matched
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
function filterRefs (candidates, patterns, cache
|
|
35
|
-
const
|
|
41
|
+
function filterRefs (candidates, patterns, cache, onMatch) {
|
|
42
|
+
const match = createMatcher(patterns, cache)
|
|
36
43
|
return candidates.reduce((accum, candidate) => {
|
|
37
|
-
if (
|
|
44
|
+
if ((candidate = match(candidate, onMatch))) accum.push(candidate)
|
|
38
45
|
return accum
|
|
39
46
|
}, [])
|
|
40
47
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { homedir } = require('os')
|
|
3
|
+
const { homedir } = require('node:os')
|
|
4
4
|
const expandPath = require('@antora/expand-path-helper')
|
|
5
|
-
const { promises: fsp } = require('fs')
|
|
5
|
+
const { promises: fsp } = require('node:fs')
|
|
6
6
|
const invariably = require('./invariably')
|
|
7
|
-
const ospath = require('path')
|
|
7
|
+
const ospath = require('node:path')
|
|
8
8
|
|
|
9
9
|
class GitCredentialManagerStore {
|
|
10
10
|
configure ({ config, startDir }) {
|
|
@@ -86,11 +86,11 @@ class GitCredentialManagerStore {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
async approved ({ url }) {
|
|
89
|
-
this.urls[url] = 'approved'
|
|
89
|
+
this.urls[url] = (url in this.urls ? this.urls[url] + ',' : '') + 'approved'
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
async rejected ({ url, auth }) {
|
|
93
|
-
this.urls[url] = 'rejected'
|
|
93
|
+
this.urls[url] = (url in this.urls ? this.urls[url] + ',' : '') + 'rejected'
|
|
94
94
|
const statusCode = 401
|
|
95
95
|
const statusMessage = 'HTTP Basic: Access Denied'
|
|
96
96
|
const err = new Error(`HTTP Error: ${statusCode} ${statusMessage}`)
|
package/lib/git.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
const zlib = require('node:zlib')
|
|
4
|
+
const { promisify } = require('node:util')
|
|
5
|
+
|
|
6
|
+
module.exports = ((pakoModuleId) => {
|
|
7
|
+
const git = require('isomorphic-git')
|
|
8
|
+
require(pakoModuleId).inflate = promisify(zlib.inflate)
|
|
9
|
+
return git
|
|
10
|
+
})('pako')
|
package/lib/matcher.js
CHANGED
|
@@ -17,7 +17,7 @@ const BASE_OPTS = {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
module.exports = {
|
|
20
|
-
MATCH_ALL_RX: { test: () => true },
|
|
20
|
+
MATCH_ALL_RX: Object.defineProperty({ test: () => true }, 'pattern', { value: '*' }),
|
|
21
21
|
expandBraces,
|
|
22
22
|
makeMatcherRx: makeRe,
|
|
23
23
|
pathMatcherOpts: Object.assign({}, BASE_OPTS, { dot: false }),
|
package/lib/posixify.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const deepFlatten = require('./deep-flatten')
|
|
4
|
-
const { promises: fsp } = require('fs')
|
|
4
|
+
const { promises: fsp } = require('node:fs')
|
|
5
5
|
const git = require('./git')
|
|
6
6
|
const invariably = require('./invariably')
|
|
7
7
|
const { expandBraces, makeMatcherRx, pathMatcherOpts: MATCHER_OPTS } = require('./matcher')
|
|
@@ -16,11 +16,11 @@ function resolvePathGlobs (base, patterns, listDirents, retrievePath, tree = { p
|
|
|
16
16
|
if (resolvedPaths.length) {
|
|
17
17
|
const rx = makeMatcherRx(pattern.substr(1), MATCHER_OPTS)
|
|
18
18
|
return resolvedPaths.filter((it) => !rx.test(it))
|
|
19
|
-
} else {
|
|
20
|
-
return resolvedPaths
|
|
21
19
|
}
|
|
20
|
+
return resolvedPaths
|
|
22
21
|
})
|
|
23
|
-
}
|
|
22
|
+
}
|
|
23
|
+
if (RX_MAGIC_DETECTOR.test(pattern)) {
|
|
24
24
|
return glob(base, pattern.split('/'), listDirents, retrievePath, tree).then((nestedPaths) =>
|
|
25
25
|
paths.then((resolvedPaths) => [...resolvedPaths, ...nestedPaths])
|
|
26
26
|
)
|
|
@@ -62,35 +62,36 @@ async function glob (base, patternSegments, listDirents, retrievePath, { oid, pa
|
|
|
62
62
|
dirent.isDirectory() && isMatch(dirent.name)
|
|
63
63
|
? patternSegments.length
|
|
64
64
|
? glob(base, patternSegments, listDirents, retrievePath, {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
oid: dirent.oid,
|
|
66
|
+
path: joinPath(path, dirent.name),
|
|
67
|
+
globbed: true,
|
|
68
|
+
})
|
|
69
69
|
: joinPath(path, dirent.name)
|
|
70
70
|
: []
|
|
71
71
|
)
|
|
72
72
|
)
|
|
73
73
|
)
|
|
74
74
|
return explicit ? [...[...explicit].map((it) => joinPath(path, it)), ...discovered] : discovered
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return [joinPath(path, patternSegment)]
|
|
89
|
-
} else if (globbed) {
|
|
90
|
-
return (await retrievePath(base, { oid, path }, patternSegment)) ? [joinPath(path, patternSegment)] : []
|
|
75
|
+
}
|
|
76
|
+
const [magicBase, nextSegment] = extractMagicBase(patternSegments, patternSegment)
|
|
77
|
+
patternSegment = magicBase
|
|
78
|
+
if (nextSegment) {
|
|
79
|
+
const obj = await retrievePath(base, { oid, path }, patternSegment)
|
|
80
|
+
if (obj) {
|
|
81
|
+
return glob(base, patternSegments, listDirents, retrievePath, {
|
|
82
|
+
oid: obj.oid,
|
|
83
|
+
path: joinPath(path, patternSegment),
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
if ((patternSegment += '/' + patternSegments.join('/')).indexOf('{')) {
|
|
87
|
+
return expandBraces(patternSegment).map((it) => joinPath(path, it))
|
|
91
88
|
}
|
|
92
89
|
return [joinPath(path, patternSegment)]
|
|
93
90
|
}
|
|
91
|
+
if (globbed) {
|
|
92
|
+
return (await retrievePath(base, { oid, path }, patternSegment)) ? [joinPath(path, patternSegment)] : []
|
|
93
|
+
}
|
|
94
|
+
return [joinPath(path, patternSegment)]
|
|
94
95
|
}
|
|
95
96
|
|
|
96
97
|
function extractMagicBase (patternSegments, base) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antora/content-aggregator",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.11",
|
|
4
4
|
"description": "Fetches and aggregates content from distributed sources for use in an Antora documentation pipeline.",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"author": "OpenDevise Inc. (https://opendevise.com)",
|
|
@@ -11,7 +11,11 @@
|
|
|
11
11
|
"Balachandran Sivakumar <balachandran@balachandran.org>"
|
|
12
12
|
],
|
|
13
13
|
"homepage": "https://antora.org",
|
|
14
|
-
"repository":
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://gitlab.com/antora/antora.git",
|
|
17
|
+
"directory": "packages/content-aggregator"
|
|
18
|
+
},
|
|
15
19
|
"bugs": {
|
|
16
20
|
"url": "https://gitlab.com/antora/antora/issues"
|
|
17
21
|
},
|
|
@@ -28,9 +32,9 @@
|
|
|
28
32
|
"#constants": "./lib/constants.js"
|
|
29
33
|
},
|
|
30
34
|
"dependencies": {
|
|
31
|
-
"@antora/expand-path-helper": "~
|
|
32
|
-
"@antora/logger": "3.1.
|
|
33
|
-
"@antora/user-require-helper": "~
|
|
35
|
+
"@antora/expand-path-helper": "~3.0",
|
|
36
|
+
"@antora/logger": "3.1.11",
|
|
37
|
+
"@antora/user-require-helper": "~3.0",
|
|
34
38
|
"braces": "~3.0",
|
|
35
39
|
"cache-directory": "~2.0",
|
|
36
40
|
"fast-glob": "~3.3",
|
|
@@ -45,7 +49,7 @@
|
|
|
45
49
|
"vinyl": "~3.0"
|
|
46
50
|
},
|
|
47
51
|
"engines": {
|
|
48
|
-
"node": ">=
|
|
52
|
+
"node": ">=18.0.0"
|
|
49
53
|
},
|
|
50
54
|
"files": [
|
|
51
55
|
"lib/"
|
|
@@ -62,7 +66,7 @@
|
|
|
62
66
|
],
|
|
63
67
|
"scripts": {
|
|
64
68
|
"test": "_mocha",
|
|
65
|
-
"prepublishOnly": "npx -y downdoc --prepublish",
|
|
66
|
-
"postpublish": "npx -y downdoc --postpublish"
|
|
69
|
+
"prepublishOnly": "npx -y downdoc@latest --prepublish",
|
|
70
|
+
"postpublish": "npx -y downdoc@latest --postpublish"
|
|
67
71
|
}
|
|
68
72
|
}
|