@antora/content-aggregator 3.2.0-alpha.5 → 3.2.0-alpha.8
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 +43 -45
- package/lib/compute-origin.js +4 -3
- package/lib/filter-refs.js +3 -4
- package/lib/resolve-path-globs.js +24 -23
- package/package.json +9 -5
package/lib/aggregate-content.js
CHANGED
|
@@ -100,12 +100,12 @@ 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
105
|
const fetchConfig = { always: fetch, depth: Math.max(0, gitConfig.fetchDepth ?? 1) }
|
|
106
106
|
const loadOpts = { cacheDir, fetch: fetchConfig, gitPlugins, progress, startDir, refPatternCache }
|
|
107
107
|
return collectFiles(sourcesByUrl, loadOpts, concurrency).then(buildAggregate, (err) => {
|
|
108
|
-
progress
|
|
108
|
+
progress?.terminate()
|
|
109
109
|
throw err
|
|
110
110
|
})
|
|
111
111
|
})
|
|
@@ -125,7 +125,7 @@ async function collectFiles (sourcesByUrl, loadOpts, concurrency, fetchedUrls =
|
|
|
125
125
|
const msg0 = 'An unexpected error occurred while fetching content sources concurrently.'
|
|
126
126
|
const msg1 = 'Retrying with git.fetch_concurrency value of 1.'
|
|
127
127
|
logger.warn(rejections[0], msg0 + ' ' + msg1)
|
|
128
|
-
const fulfilledUrls = results.
|
|
128
|
+
const fulfilledUrls = results.filter((it) => it?.repo.url).map((it) => it.url)
|
|
129
129
|
return collectFiles(sourcesByUrl, loadOpts, Object.assign(concurrency, { fetch: 1 }), fulfilledUrls)
|
|
130
130
|
}
|
|
131
131
|
throw rejections[0]
|
|
@@ -182,12 +182,12 @@ async function loadRepository (url, opts, result = {}) {
|
|
|
182
182
|
return git.setConfig(Object.assign({ path: 'remote.origin.private', value: authStatus }, repo))
|
|
183
183
|
})
|
|
184
184
|
.catch((fetchErr) => {
|
|
185
|
-
|
|
185
|
+
fetchOpts.onProgress?.finish(fetchErr)
|
|
186
186
|
if (HTTP_ERROR_CODE_RX.test(fetchErr.code) && fetchErr.data.statusCode === 401) fetchErr.rethrow = true
|
|
187
187
|
throw fetchErr
|
|
188
188
|
})
|
|
189
189
|
.then(() => fsp.writeFile(validStateFile, '').catch(invariably.void))
|
|
190
|
-
.then(() => fetchOpts.onProgress
|
|
190
|
+
.then(() => fetchOpts.onProgress?.finish())
|
|
191
191
|
} else {
|
|
192
192
|
authStatus = await git.getConfig(Object.assign({ path: 'remote.origin.private' }, repo))
|
|
193
193
|
}
|
|
@@ -203,12 +203,12 @@ async function loadRepository (url, opts, result = {}) {
|
|
|
203
203
|
return git.setConfig(Object.assign({ path: 'remote.origin.private', value: authStatus }, repo))
|
|
204
204
|
})
|
|
205
205
|
.catch((cloneErr) => {
|
|
206
|
-
|
|
206
|
+
fetchOpts.onProgress?.finish(cloneErr)
|
|
207
207
|
const authRequested = credentialManager.status({ url }) === 'requested'
|
|
208
208
|
throw transformGitCloneError(cloneErr, displayUrl, authRequested)
|
|
209
209
|
})
|
|
210
210
|
.then(() => fsp.writeFile(validStateFile, '').catch(invariably.void))
|
|
211
|
-
.then(() => fetchOpts.onProgress
|
|
211
|
+
.then(() => fetchOpts.onProgress?.finish())
|
|
212
212
|
}
|
|
213
213
|
} else if (await isDirectory((dir = expandPath(url, { dot: opts.startDir })))) {
|
|
214
214
|
const dotgit = ospath.join(dir, '.git')
|
|
@@ -244,11 +244,9 @@ function extractCredentials (url) {
|
|
|
244
244
|
// NOTE if only username is present, assume it's an oauth token and set password to empty string
|
|
245
245
|
const credentials = username ? { username, password: password || '' } : {}
|
|
246
246
|
return { displayUrl, url, credentials }
|
|
247
|
-
} else if (url.startsWith('git@')) {
|
|
248
|
-
return { displayUrl: url, url: 'https://' + url.substr(4).replace(':', '/') }
|
|
249
|
-
} else {
|
|
250
|
-
return { displayUrl: url, url }
|
|
251
247
|
}
|
|
248
|
+
if (url.startsWith('git@')) return { displayUrl: url, url: 'https://' + url.substr(4).replace(':', '/') }
|
|
249
|
+
return { displayUrl: url, url }
|
|
252
250
|
}
|
|
253
251
|
|
|
254
252
|
async function selectStartPathsForRepository (repo, authStatus, sources) {
|
|
@@ -415,8 +413,8 @@ function getCurrentBranchName (repo, remote) {
|
|
|
415
413
|
return (
|
|
416
414
|
remote && repo.noCheckout
|
|
417
415
|
? git
|
|
418
|
-
|
|
419
|
-
|
|
416
|
+
.resolveRef(Object.assign({ ref: 'refs/remotes/' + remote + '/HEAD', depth: 2 }, repo))
|
|
417
|
+
.catch(() => git.resolveRef(Object.assign({ ref: 'HEAD', depth: 2 }, repo)))
|
|
420
418
|
: git.resolveRef(Object.assign({ ref: 'HEAD', depth: 2 }, repo))
|
|
421
419
|
).then((ref) => (ref.startsWith('refs/') ? ref.replace(SHORTEN_REF_RX, '') : undefined))
|
|
422
420
|
}
|
|
@@ -463,7 +461,7 @@ function collectFilesFromStartPath (startPath, repo, authStatus, ref, originUrl,
|
|
|
463
461
|
return (worktreePath ? readFilesFromWorktree(origin) : readFilesFromGitTree(repo, ref.oid, startPath))
|
|
464
462
|
.then((files) => {
|
|
465
463
|
const batch = deepClone((origin.descriptor = loadComponentDescriptor(files, ref, version)))
|
|
466
|
-
if ('nav' in batch) batch.nav.origin = origin
|
|
464
|
+
if ('nav' in batch && Array.isArray(batch.nav)) batch.nav.origin = origin
|
|
467
465
|
batch.files = files.map((file) => assignFileProperties(file, origin))
|
|
468
466
|
batch.origins = [origin]
|
|
469
467
|
return batch
|
|
@@ -548,9 +546,9 @@ function readFilesFromGitTree (repo, oid, startPath) {
|
|
|
548
546
|
Object.assign(root, { dirname: '' })
|
|
549
547
|
return startPath
|
|
550
548
|
? getGitTreeAtStartPath(repo, oid, startPath).then((start) => {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
549
|
+
Object.assign(start, { dirname: startPath })
|
|
550
|
+
return srcGitTree(repo, root, start)
|
|
551
|
+
})
|
|
554
552
|
: srcGitTree(repo, root)
|
|
555
553
|
})
|
|
556
554
|
}
|
|
@@ -605,7 +603,8 @@ function visitGitTree (emitter, repo, root, filter, convert, parent, dirname = '
|
|
|
605
603
|
(target) => {
|
|
606
604
|
if (target.type === 'tree') {
|
|
607
605
|
return visitGitTree(emitter, repo, root, filter, convert, target, vfilePath, target.following)
|
|
608
|
-
}
|
|
606
|
+
}
|
|
607
|
+
if (target.type === 'blob' && filterVerdict === true && (mode = FILE_MODES[target.mode])) {
|
|
609
608
|
return convert(Object.assign({ mode, oid: target.oid, path: vfilePath }, repo)).then((result) =>
|
|
610
609
|
emitter.emit('entry', result)
|
|
611
610
|
)
|
|
@@ -677,11 +676,11 @@ function readGitObjectAtPath (repo, root, parent, pathSegments, following) {
|
|
|
677
676
|
if (entry.path === firstPathSegment) {
|
|
678
677
|
return entry.type === 'tree'
|
|
679
678
|
? git.readTree(Object.assign({ oid: entry.oid }, repo)).then((subtree) => {
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
679
|
+
Object.assign(subtree, { dirname: path.join(parent.dirname, entry.path) })
|
|
680
|
+
return (pathSegments = pathSegments.slice(1)).length
|
|
681
|
+
? readGitObjectAtPath(repo, root, subtree, pathSegments, following)
|
|
682
|
+
: Object.assign(subtree, { type: 'tree', following }) // Q: should this create copy?
|
|
683
|
+
})
|
|
685
684
|
: entry.mode === SYMLINK_FILE_MODE
|
|
686
685
|
? readGitSymlink(repo, root, parent, entry, following)
|
|
687
686
|
: Promise.resolve(entry)
|
|
@@ -761,7 +760,7 @@ function loadComponentDescriptor (files, ref, version) {
|
|
|
761
760
|
throw new Error(`version in ${COMPONENT_DESC_FILENAME} cannot have path segments: ${version}`)
|
|
762
761
|
}
|
|
763
762
|
data.version = version
|
|
764
|
-
return camelCaseKeys(data, ['asciidoc'])
|
|
763
|
+
return camelCaseKeys(data, ['asciidoc', 'ext'])
|
|
765
764
|
}
|
|
766
765
|
|
|
767
766
|
function assignFileProperties (file, origin) {
|
|
@@ -889,9 +888,8 @@ function identifyAuthStatus (credentialManager, credentials, url) {
|
|
|
889
888
|
const status = credentialManager.status({ url })
|
|
890
889
|
if (credentials) {
|
|
891
890
|
return typeof status === 'string' && status.startsWith('requested,') ? 'auth-required' : 'auth-embedded'
|
|
892
|
-
} else if (status != null) {
|
|
893
|
-
return 'auth-required'
|
|
894
891
|
}
|
|
892
|
+
if (status != null) return 'auth-required'
|
|
895
893
|
}
|
|
896
894
|
|
|
897
895
|
/**
|
|
@@ -900,7 +898,7 @@ function identifyAuthStatus (credentialManager, credentials, url) {
|
|
|
900
898
|
* The purpose of this function is generate a safe, unique folder name for the cloned
|
|
901
899
|
* repository that gets stored in the cache directory.
|
|
902
900
|
*
|
|
903
|
-
* The generated folder name follows the pattern: <basename>-<sha1
|
|
901
|
+
* The generated folder name follows the pattern: <basename>-<sha1-of-normalized-url>.git
|
|
904
902
|
*
|
|
905
903
|
* @param {String} url - The repository URL to convert.
|
|
906
904
|
* @returns {String} The generated folder name.
|
|
@@ -923,9 +921,9 @@ function resolveRemoteUrl (repo, remoteName) {
|
|
|
923
921
|
if (url) {
|
|
924
922
|
if (url.startsWith('https://') || url.startsWith('http://')) {
|
|
925
923
|
return ~url.indexOf('@') ? url.replace(URL_AUTH_CLEANER_RX, '$1') : url
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
|
|
924
|
+
}
|
|
925
|
+
if (url.startsWith('git@')) return 'https://' + url.substr(4).replace(':', '/')
|
|
926
|
+
if (url.startsWith('ssh://')) {
|
|
929
927
|
return 'https://' + url.substr(url.indexOf('@') + 1 || 6).replace(URL_PORT_CLEANER_RX, '$1')
|
|
930
928
|
}
|
|
931
929
|
}
|
|
@@ -958,7 +956,7 @@ function loadGitPlugins (gitConfig, networkConfig, startDir) {
|
|
|
958
956
|
if (typeof credentialManager.configure === 'function') {
|
|
959
957
|
credentialManager.configure({ config: gitConfig.credentials, startDir })
|
|
960
958
|
}
|
|
961
|
-
if (typeof credentialManager.status !== 'function') Object.assign(credentialManager, { status
|
|
959
|
+
if (typeof credentialManager.status !== 'function') Object.assign(credentialManager, { status: invariably.void })
|
|
962
960
|
} else {
|
|
963
961
|
credentialManager = new GitCredentialManagerStore().configure({ config: gitConfig.credentials, startDir })
|
|
964
962
|
}
|
|
@@ -1075,21 +1073,21 @@ function findWorktrees (repo, patterns) {
|
|
|
1075
1073
|
return (
|
|
1076
1074
|
worktreesDir
|
|
1077
1075
|
? fsp
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1076
|
+
.readdir(worktreesDir)
|
|
1077
|
+
.then((worktreeNames) => filterRefs(worktreeNames, patterns, patternCache), invariably.emptyArray)
|
|
1078
|
+
.then((worktreeNames) =>
|
|
1079
|
+
Promise.all(
|
|
1080
|
+
worktreeNames.map((worktreeName) => {
|
|
1081
|
+
const gitdir = ospath.resolve(worktreesDir, worktreeName)
|
|
1082
|
+
// NOTE branch name defaults to worktree name if HEAD is detached
|
|
1083
|
+
return getCurrentBranchName(Object.assign({}, repo, { gitdir })).then((branch = worktreeName) =>
|
|
1084
|
+
fsp
|
|
1085
|
+
.readFile(ospath.join(gitdir, 'gitdir'), 'utf8')
|
|
1086
|
+
.then((contents) => [branch, { head: ospath.dirname(contents.trimEnd()), name: worktreeName }])
|
|
1087
|
+
)
|
|
1088
|
+
})
|
|
1089
|
+
)
|
|
1091
1090
|
)
|
|
1092
|
-
)
|
|
1093
1091
|
: Promise.resolve()
|
|
1094
1092
|
).then((entries = []) => mainWorktree.then((entry) => new Map(entry ? entries.push(entry) && entries : entries)))
|
|
1095
1093
|
}
|
package/lib/compute-origin.js
CHANGED
|
@@ -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,8 +33,9 @@ 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
|
}
|
package/lib/filter-refs.js
CHANGED
|
@@ -11,10 +11,9 @@ function compileRx (pattern, opts) {
|
|
|
11
11
|
return Object.defineProperty(rx, 'pattern', { value: pattern })
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
function createMatcher (patterns, cache,
|
|
14
|
+
function createMatcher (patterns, cache = Object.assign(new Map(), { braces: new Map() })) {
|
|
15
15
|
const rxs = patterns.map(
|
|
16
|
-
(pattern) =>
|
|
17
|
-
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)
|
|
18
17
|
)
|
|
19
18
|
if (rxs[0].negated) rxs.unshift(MATCH_ALL_RX)
|
|
20
19
|
return (candidate, onMatch) => {
|
|
@@ -39,7 +38,7 @@ function createMatcher (patterns, cache, opts) {
|
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
function filterRefs (candidates, patterns, cache
|
|
41
|
+
function filterRefs (candidates, patterns, cache, onMatch) {
|
|
43
42
|
const match = createMatcher(patterns, cache)
|
|
44
43
|
return candidates.reduce((accum, candidate) => {
|
|
45
44
|
if ((candidate = match(candidate, onMatch))) accum.push(candidate)
|
|
@@ -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.2.0-alpha.
|
|
3
|
+
"version": "3.2.0-alpha.8",
|
|
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.2.0-alpha.
|
|
33
|
-
"@antora/user-require-helper": "~
|
|
35
|
+
"@antora/expand-path-helper": "~3.0",
|
|
36
|
+
"@antora/logger": "3.2.0-alpha.8",
|
|
37
|
+
"@antora/user-require-helper": "~3.0",
|
|
34
38
|
"braces": "~3.0",
|
|
35
39
|
"cache-directory": "~2.0",
|
|
36
40
|
"fast-glob": "~3.3",
|