@antora/content-aggregator 3.1.10 → 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 +150 -98
- package/lib/compute-origin.js +6 -4
- package/lib/decode-uint8-array.js +1 -1
- package/lib/filter-refs.js +17 -9
- 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 +1 -1
- package/package.json +7 -6
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')
|
|
@@ -102,7 +102,8 @@ function aggregateContent (playbook) {
|
|
|
102
102
|
}, new Map())
|
|
103
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
108
|
progress?.terminate()
|
|
108
109
|
throw err
|
|
@@ -110,11 +111,11 @@ function aggregateContent (playbook) {
|
|
|
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]) => {
|
|
@@ -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(() => {
|
|
@@ -193,7 +194,7 @@ async function loadRepository (url, opts, result = {}) {
|
|
|
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)))
|
|
@@ -210,8 +211,15 @@ async function loadRepository (url, opts, result = {}) {
|
|
|
210
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 {
|
|
@@ -246,14 +254,27 @@ async function selectStartPathsForRepository (repo, authStatus, sources) {
|
|
|
246
254
|
const originUrls = {}
|
|
247
255
|
for (const source of sources) {
|
|
248
256
|
const { version, editUrl } = source
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
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
|
+
}
|
|
253
274
|
const refs = await selectReferences(source, repo, remoteName)
|
|
254
275
|
if (refs.length) {
|
|
255
276
|
for (const ref of refs) {
|
|
256
|
-
for (const startPath of await selectStartPaths(source, repo,
|
|
277
|
+
for (const startPath of await selectStartPaths(source, repo, ref)) {
|
|
257
278
|
startPaths.push({ startPath, ref, originUrl, editUrl, version })
|
|
258
279
|
}
|
|
259
280
|
}
|
|
@@ -272,7 +293,7 @@ async function selectStartPathsForRepository (repo, authStatus, sources) {
|
|
|
272
293
|
|
|
273
294
|
// QUESTION should we resolve HEAD to a ref eagerly to avoid having to do a match on it?
|
|
274
295
|
async function selectReferences (source, repo, remote) {
|
|
275
|
-
let { branches: branchPatterns, tags: tagPatterns, worktrees: worktreePatterns
|
|
296
|
+
let { branches: branchPatterns, tags: tagPatterns, worktrees: worktreePatterns } = source
|
|
276
297
|
const managed = 'url' in repo
|
|
277
298
|
const isBare = managed || repo.noCheckout
|
|
278
299
|
const patternCache = repo.cache[REF_PATTERN_CACHE_KEY]
|
|
@@ -292,7 +313,16 @@ async function selectReferences (source, repo, remote) {
|
|
|
292
313
|
}
|
|
293
314
|
}
|
|
294
315
|
}
|
|
295
|
-
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))
|
|
296
326
|
if (worktreePatterns) {
|
|
297
327
|
if (worktreePatterns === '.') {
|
|
298
328
|
worktreePatterns = ['.']
|
|
@@ -302,14 +332,14 @@ async function selectReferences (source, repo, remote) {
|
|
|
302
332
|
worktreePatterns = Array.isArray(worktreePatterns)
|
|
303
333
|
? worktreePatterns.map((pattern) => String(pattern))
|
|
304
334
|
: splitRefPatterns(String(worktreePatterns))
|
|
335
|
+
if (worktreeName) worktreePatterns = worktreePatterns.map((it) => (it === '@' ? worktreeName : it))
|
|
305
336
|
}
|
|
306
337
|
} else {
|
|
307
|
-
worktreePatterns = []
|
|
338
|
+
worktreePatterns = worktreePatterns === undefined ? [worktreeName || '.'] : []
|
|
308
339
|
}
|
|
309
|
-
|
|
310
|
-
if (
|
|
311
|
-
|
|
312
|
-
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))) {
|
|
313
343
|
branchPatterns = [currentBranch]
|
|
314
344
|
} else if (isBare) {
|
|
315
345
|
return [...refs.values()]
|
|
@@ -319,17 +349,11 @@ async function selectReferences (source, repo, remote) {
|
|
|
319
349
|
refs.set('HEAD', { shortname: 'HEAD', fullname: 'HEAD', type: 'branch', detached: true, head })
|
|
320
350
|
return [...refs.values()]
|
|
321
351
|
}
|
|
322
|
-
} else
|
|
323
|
-
(branchPatterns = Array.isArray(branchPatterns)
|
|
324
|
-
? branchPatterns.map((pattern) => String(pattern))
|
|
325
|
-
: splitRefPatterns(branchPatternsString)).length
|
|
326
|
-
) {
|
|
352
|
+
} else {
|
|
327
353
|
let headBranchIdx
|
|
328
354
|
// NOTE we can assume at least two entries if HEAD or . are present
|
|
329
355
|
if (~(headBranchIdx = branchPatterns.indexOf('HEAD')) || ~(headBranchIdx = branchPatterns.indexOf('.'))) {
|
|
330
|
-
|
|
331
|
-
if (currentBranch) {
|
|
332
|
-
// NOTE ignore if current branch is already in list
|
|
356
|
+
if ((currentBranch = await getCurrentBranchName(repo, remote).then((branch) => branch ?? false))) {
|
|
333
357
|
if (~branchPatterns.indexOf(currentBranch)) {
|
|
334
358
|
branchPatterns.splice(headBranchIdx, 1)
|
|
335
359
|
} else {
|
|
@@ -348,11 +372,11 @@ async function selectReferences (source, repo, remote) {
|
|
|
348
372
|
branchPatterns.splice(headBranchIdx, 1)
|
|
349
373
|
}
|
|
350
374
|
}
|
|
351
|
-
} else {
|
|
352
|
-
return [...refs.values()]
|
|
353
375
|
}
|
|
354
376
|
// NOTE isomorphic-git includes HEAD in list of remote branches (see https://isomorphic-git.org/docs/listBranches)
|
|
355
|
-
const remoteBranches =
|
|
377
|
+
const remoteBranches = remote
|
|
378
|
+
? (await git.listBranches(Object.assign({ remote }, repo))).filter((it) => it !== 'HEAD')
|
|
379
|
+
: []
|
|
356
380
|
if (remoteBranches.length) {
|
|
357
381
|
for (const shortname of filterRefs(remoteBranches, branchPatterns, patternCache)) {
|
|
358
382
|
const fullname = 'remotes/' + remote + '/' + shortname
|
|
@@ -361,11 +385,27 @@ async function selectReferences (source, repo, remote) {
|
|
|
361
385
|
}
|
|
362
386
|
// NOTE only consider local branches if repo has a worktree or there are no remote tracking branches
|
|
363
387
|
if (!isBare) {
|
|
364
|
-
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
|
+
})
|
|
365
393
|
if (localBranches.length) {
|
|
366
394
|
const worktrees = await findWorktrees(repo, worktreePatterns)
|
|
367
|
-
|
|
368
|
-
|
|
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
|
|
369
409
|
refs.set(shortname, { shortname, fullname: 'heads/' + shortname, type: 'branch', head })
|
|
370
410
|
}
|
|
371
411
|
}
|
|
@@ -385,18 +425,16 @@ async function selectReferences (source, repo, remote) {
|
|
|
385
425
|
* Returns the current branch name or undefined if the HEAD is detached.
|
|
386
426
|
*/
|
|
387
427
|
function getCurrentBranchName (repo, remote) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
}
|
|
396
|
-
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))
|
|
397
435
|
}
|
|
398
436
|
|
|
399
|
-
async function selectStartPaths (source, repo,
|
|
437
|
+
async function selectStartPaths (source, repo, ref) {
|
|
400
438
|
const url = repo.url
|
|
401
439
|
const displayUrl = url || repo.dir
|
|
402
440
|
const worktreePath = ref.head
|
|
@@ -711,18 +749,18 @@ function loadComponentDescriptor (files, ref, version) {
|
|
|
711
749
|
if (!version) {
|
|
712
750
|
if (version === undefined) throw new Error(`${COMPONENT_DESC_FILENAME} is missing a version`)
|
|
713
751
|
if (version === false) throw new Error(`${COMPONENT_DESC_FILENAME} has an invalid version`)
|
|
714
|
-
version =
|
|
752
|
+
version = typeof version === 'number' ? '' + version : ''
|
|
715
753
|
} else if (version === true) {
|
|
716
754
|
version = ref.shortname.replace(PATH_SEPARATOR_RX, '-')
|
|
717
755
|
} else if (version.constructor === Object) {
|
|
718
756
|
const refname = ref.shortname
|
|
719
757
|
let matched
|
|
720
758
|
if (refname in version) {
|
|
721
|
-
matched = version[refname]
|
|
759
|
+
matched = '' + (version[refname] ?? '')
|
|
722
760
|
} else if (
|
|
723
761
|
!Object.entries(version).some(([pattern, replacement]) => {
|
|
724
|
-
const result = refname.replace(makeMatcherRx(pattern, VERSION_MATCHER_OPTS), '\0' + replacement)
|
|
725
|
-
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
|
|
726
764
|
matched = result.substr(1)
|
|
727
765
|
return true
|
|
728
766
|
})
|
|
@@ -737,7 +775,7 @@ function loadComponentDescriptor (files, ref, version) {
|
|
|
737
775
|
throw new Error(`version in ${COMPONENT_DESC_FILENAME} cannot have path segments: ${version}`)
|
|
738
776
|
}
|
|
739
777
|
data.version = version
|
|
740
|
-
return camelCaseKeys(data, ['asciidoc'])
|
|
778
|
+
return camelCaseKeys(data, ['asciidoc', 'ext'])
|
|
741
779
|
}
|
|
742
780
|
|
|
743
781
|
function assignFileProperties (file, origin) {
|
|
@@ -754,18 +792,20 @@ function assignFileProperties (file, origin) {
|
|
|
754
792
|
return file
|
|
755
793
|
}
|
|
756
794
|
|
|
757
|
-
function buildFetchOptions (repo, progress, displayUrl, credentialsFromUrl, gitPlugins,
|
|
795
|
+
function buildFetchOptions (repo, progress, displayUrl, credentialsFromUrl, gitPlugins, fetch, operation) {
|
|
758
796
|
const { credentialManager, http, urlRouter } = gitPlugins
|
|
797
|
+
const corsProxy = false
|
|
798
|
+
const depth = fetch.depth || undefined
|
|
759
799
|
const onAuth = resolveCredentials.bind(credentialManager, new Map().set(undefined, credentialsFromUrl))
|
|
760
800
|
const onAuthFailure = onAuth
|
|
761
801
|
const onAuthSuccess = (url) => credentialManager.approved({ url })
|
|
762
|
-
const opts = Object.assign({ corsProxy
|
|
802
|
+
const opts = Object.assign({ corsProxy, depth, http, onAuth, onAuthFailure, onAuthSuccess }, repo)
|
|
763
803
|
if (urlRouter) opts.url = urlRouter.ensureGitSuffix(opts.url)
|
|
764
804
|
if (progress) opts.onProgress = createProgressListener(progress, displayUrl, operation)
|
|
765
805
|
if (operation === 'fetch') {
|
|
766
806
|
opts.prune = true
|
|
767
|
-
if (
|
|
768
|
-
} else if (!
|
|
807
|
+
if (fetch.tags) opts.tags = opts.pruneTags = true
|
|
808
|
+
} else if (!fetch.tags) {
|
|
769
809
|
opts.noTags = true
|
|
770
810
|
}
|
|
771
811
|
return opts
|
|
@@ -860,7 +900,11 @@ function resolveCredentials (credentialsFromUrlHolder, url, auth) {
|
|
|
860
900
|
}
|
|
861
901
|
|
|
862
902
|
function identifyAuthStatus (credentialManager, credentials, url) {
|
|
863
|
-
|
|
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'
|
|
864
908
|
}
|
|
865
909
|
|
|
866
910
|
/**
|
|
@@ -885,21 +929,18 @@ function generateCloneFolderName (url) {
|
|
|
885
929
|
*
|
|
886
930
|
* @param {Repository} repo - The repository on which to operate.
|
|
887
931
|
* @param {String} remoteName - The name of the remote to resolve.
|
|
888
|
-
* @returns {String} The URL of the specified remote, if defined
|
|
932
|
+
* @returns {String} The URL of the specified remote, if defined
|
|
889
933
|
*/
|
|
890
934
|
function resolveRemoteUrl (repo, remoteName) {
|
|
891
935
|
return git.getConfig(Object.assign({ path: 'remote.' + remoteName + '.url' }, repo)).then((url) => {
|
|
892
|
-
if (url)
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
}
|
|
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')
|
|
900
943
|
}
|
|
901
|
-
url = posixify ? 'file:///' + posixify(repo.dir) : 'file://' + repo.dir
|
|
902
|
-
return ~url.indexOf(' ') ? url.replace(SPACE_RX, '%20') : url
|
|
903
944
|
})
|
|
904
945
|
}
|
|
905
946
|
|
|
@@ -1017,39 +1058,50 @@ function coerceToString (value) {
|
|
|
1017
1058
|
return value == null ? '' : String(value)
|
|
1018
1059
|
}
|
|
1019
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
|
+
|
|
1020
1077
|
function findWorktrees (repo, patterns) {
|
|
1021
1078
|
if (!patterns.length) return new Map()
|
|
1022
|
-
const
|
|
1023
|
-
|
|
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
|
|
1024
1084
|
const patternCache = repo.cache[REF_PATTERN_CACHE_KEY]
|
|
1025
1085
|
return (
|
|
1026
|
-
|
|
1086
|
+
worktreesDir
|
|
1027
1087
|
? fsp
|
|
1028
|
-
.readdir(
|
|
1088
|
+
.readdir(worktreesDir)
|
|
1029
1089
|
.then((worktreeNames) => filterRefs(worktreeNames, patterns, patternCache), invariably.emptyArray)
|
|
1030
1090
|
.then((worktreeNames) =>
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
)
|
|
1043
|
-
})
|
|
1044
|
-
).then((entries) => entries.reduce((accum, it) => accum.set(it.branch, it.dir), new Map()))
|
|
1045
|
-
: new Map()
|
|
1091
|
+
Promise.all(
|
|
1092
|
+
worktreeNames.map((worktreeName) => {
|
|
1093
|
+
const gitdir = ospath.resolve(worktreesDir, worktreeName)
|
|
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
|
+
)
|
|
1100
|
+
})
|
|
1101
|
+
)
|
|
1046
1102
|
)
|
|
1047
|
-
: Promise.resolve(
|
|
1048
|
-
).then((
|
|
1049
|
-
linkedOnly
|
|
1050
|
-
? worktrees
|
|
1051
|
-
: git.currentBranch(repo).then((branch) => (branch ? worktrees.set(branch, repo.dir) : worktrees))
|
|
1052
|
-
)
|
|
1103
|
+
: Promise.resolve()
|
|
1104
|
+
).then((entries = []) => mainWorktree.then((entry) => new Map(entry ? entries.push(entry) && entries : entries)))
|
|
1053
1105
|
}
|
|
1054
1106
|
|
|
1055
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) {
|
|
@@ -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,9 +4,11 @@ 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
14
|
function createMatcher (patterns, cache = Object.assign(new Map(), { braces: new Map() })) {
|
|
@@ -14,8 +16,8 @@ function createMatcher (patterns, cache = Object.assign(new Map(), { braces: new
|
|
|
14
16
|
(pattern) => cache.get(pattern) || cache.set(pattern, compileRx(pattern, getMatcherOpts(cache))).get(pattern)
|
|
15
17
|
)
|
|
16
18
|
if (rxs[0].negated) rxs.unshift(MATCH_ALL_RX)
|
|
17
|
-
return (candidate) => {
|
|
18
|
-
let matched
|
|
19
|
+
return (candidate, onMatch) => {
|
|
20
|
+
let matched, symbolic
|
|
19
21
|
for (const rx of rxs) {
|
|
20
22
|
let voteIfMatched = true
|
|
21
23
|
if (matched) {
|
|
@@ -24,16 +26,22 @@ function createMatcher (patterns, cache = Object.assign(new Map(), { braces: new
|
|
|
24
26
|
} else if (rx.negated) {
|
|
25
27
|
continue
|
|
26
28
|
}
|
|
27
|
-
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
|
+
}
|
|
28
36
|
}
|
|
29
37
|
return matched
|
|
30
38
|
}
|
|
31
39
|
}
|
|
32
40
|
|
|
33
|
-
function filterRefs (candidates, patterns, cache) {
|
|
34
|
-
const
|
|
41
|
+
function filterRefs (candidates, patterns, cache, onMatch) {
|
|
42
|
+
const match = createMatcher(patterns, cache)
|
|
35
43
|
return candidates.reduce((accum, candidate) => {
|
|
36
|
-
if (
|
|
44
|
+
if ((candidate = match(candidate, onMatch))) accum.push(candidate)
|
|
37
45
|
return accum
|
|
38
46
|
}, [])
|
|
39
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')
|
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)",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"homepage": "https://antora.org",
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
|
-
"url": "git+https://gitlab.com/antora/antora.git"
|
|
16
|
+
"url": "git+https://gitlab.com/antora/antora.git",
|
|
17
|
+
"directory": "packages/content-aggregator"
|
|
17
18
|
},
|
|
18
19
|
"bugs": {
|
|
19
20
|
"url": "https://gitlab.com/antora/antora/issues"
|
|
@@ -32,7 +33,7 @@
|
|
|
32
33
|
},
|
|
33
34
|
"dependencies": {
|
|
34
35
|
"@antora/expand-path-helper": "~3.0",
|
|
35
|
-
"@antora/logger": "3.1.
|
|
36
|
+
"@antora/logger": "3.1.11",
|
|
36
37
|
"@antora/user-require-helper": "~3.0",
|
|
37
38
|
"braces": "~3.0",
|
|
38
39
|
"cache-directory": "~2.0",
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
"vinyl": "~3.0"
|
|
49
50
|
},
|
|
50
51
|
"engines": {
|
|
51
|
-
"node": ">=
|
|
52
|
+
"node": ">=18.0.0"
|
|
52
53
|
},
|
|
53
54
|
"files": [
|
|
54
55
|
"lib/"
|
|
@@ -65,7 +66,7 @@
|
|
|
65
66
|
],
|
|
66
67
|
"scripts": {
|
|
67
68
|
"test": "_mocha",
|
|
68
|
-
"prepublishOnly": "npx -y downdoc --prepublish",
|
|
69
|
-
"postpublish": "npx -y downdoc --postpublish"
|
|
69
|
+
"prepublishOnly": "npx -y downdoc@latest --prepublish",
|
|
70
|
+
"postpublish": "npx -y downdoc@latest --postpublish"
|
|
70
71
|
}
|
|
71
72
|
}
|