@antora/content-aggregator 3.2.0-alpha.10 → 3.2.0-alpha.12

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.
@@ -116,6 +116,8 @@ async function collectFiles (sourcesByUrl, loadOpts, concurrency, fetchedUrls =
116
116
  const loadOptsForUrl = Object.assign({}, loadOpts)
117
117
  if (loadOpts.fetch.always && fetchedUrls.length && ~fetchedUrls.indexOf(url)) loadOptsForUrl.fetch.always = false
118
118
  if (tagsSpecified(sources)) loadOptsForUrl.fetch.tags = true
119
+ const commits = commitsRequested(sources)
120
+ if (commits) loadOptsForUrl.fetch.commits = commits
119
121
  return loadRepository.bind(null, url, loadOptsForUrl, { url, sources })
120
122
  })
121
123
  return gracefulPromiseAllWithLimit(loadTasks, concurrency.fetch).then(([results, rejections]) => {
@@ -177,6 +179,7 @@ async function loadRepository (url, opts, result = {}) {
177
179
  const fetchOpts = buildFetchOptions(repo, progress, displayUrl, credentials, gitPlugins, fetch, 'fetch')
178
180
  await git
179
181
  .fetch(fetchOpts)
182
+ .then(() => ensureOids(fetchOpts))
180
183
  .then(() => {
181
184
  authStatus = identifyAuthStatus(credentialManager, credentials, url)
182
185
  return git.setConfig(Object.assign({ path: 'remote.origin.private', value: authStatus }, repo))
@@ -192,12 +195,13 @@ async function loadRepository (url, opts, result = {}) {
192
195
  authStatus = await git.getConfig(Object.assign({ path: 'remote.origin.private' }, repo))
193
196
  }
194
197
  } catch (gitErr) {
195
- await fsp['rm' in fsp ? 'rm' : 'rmdir'](dir, { recursive: true, force: true })
198
+ await fsp.rm(dir, { recursive: true, force: true })
196
199
  if (gitErr.rethrow) throw transformGitCloneError(gitErr, displayUrl)
197
200
  const fetchOpts = buildFetchOptions(repo, progress, displayUrl, credentials, gitPlugins, fetch, 'clone')
198
201
  await git
199
202
  .clone(fetchOpts)
200
203
  .then(() => git.resolveRef(Object.assign({ ref: 'HEAD', depth: 1 }, repo)))
204
+ .then(() => ensureOids(fetchOpts))
201
205
  .then(() => {
202
206
  authStatus = identifyAuthStatus(credentialManager, credentials, url)
203
207
  return git.setConfig(Object.assign({ path: 'remote.origin.private', value: authStatus }, repo))
@@ -216,6 +220,7 @@ async function loadRepository (url, opts, result = {}) {
216
220
  if (dotgitStat.isDirectory()) {
217
221
  repo = { cache, dir, fs, gitdir: dotgit }
218
222
  } else if (dotgitStat.isFile()) {
223
+ // NOTE isomorphic-git will discover the gitdir, but we must do it eagerly to process worktree patterns correctly
219
224
  repo = await resolveRepositoryFromWorktree({ cache, dir, fs, gitdir: dotgit })
220
225
  } else {
221
226
  repo = { cache, dir, fs, gitdir: dir, noCheckout: true }
@@ -279,12 +284,12 @@ async function selectStartPathsForRepository (repo, sources) {
279
284
  }
280
285
  }
281
286
  } else {
282
- const { url, branches, tags } = source
287
+ const { url, branches, tags, commits } = source
283
288
  const startPathInfo =
284
289
  'startPaths' in source
285
290
  ? { 'start paths': source.startPaths || undefined }
286
291
  : { 'start path': source.startPath || undefined }
287
- const sourceInfo = yaml.dump({ url, branches, tags, ...startPathInfo }, { flowLevel: 1 }).trimRight()
292
+ const sourceInfo = yaml.dump({ url, branches, tags, commits, ...startPathInfo }, { flowLevel: 1 }).trimRight()
288
293
  logger.info(`No matching references found for content source entry (${sourceInfo.replace(NEWLINE_RX, ' | ')})`)
289
294
  }
290
295
  }
@@ -293,7 +298,7 @@ async function selectStartPathsForRepository (repo, sources) {
293
298
 
294
299
  // QUESTION should we resolve HEAD to a ref eagerly to avoid having to do a match on it?
295
300
  async function selectReferences (source, repo, remote) {
296
- let { branches: branchPatterns, tags: tagPatterns, worktrees: worktreePatterns } = source
301
+ let { branches: branchPatterns, tags: tagPatterns, commits, worktrees: worktreePatterns } = source
297
302
  const managed = 'url' in repo
298
303
  const isBare = managed || repo.noCheckout
299
304
  const patternCache = repo.cache[REF_PATTERN_CACHE_KEY]
@@ -309,11 +314,20 @@ async function selectReferences (source, repo, remote) {
309
314
  const tags = await git.listTags(repo)
310
315
  if (tags.length) {
311
316
  for (const shortname of filterRefs(tags, tagPatterns, patternCache)) {
312
- // NOTE tags are stored using symbol keys to distinguish them from branches
313
- refs.set(Symbol(shortname), { shortname, fullname: 'tags/' + shortname, type: 'tag', head: noWorktree })
317
+ // NOTE tags are stored using Buffer keys to distinguish them from commits and branches
318
+ refs.set(Buffer.from(shortname), { shortname, fullname: 'tags/' + shortname, type: 'tag', head: noWorktree })
314
319
  }
315
320
  }
316
321
  }
322
+ if (
323
+ commits &&
324
+ (commits = Array.isArray(commits) ? commits.map((commit) => String(commit)) : commits.split(CSV_RX)).length
325
+ ) {
326
+ for (const oid of commits) {
327
+ // NOTE commits are stored using Symbol keys to distinguish them from tags and branches
328
+ refs.set(Symbol(oid), { oid, shortname: oid, fullname: 'commits/' + oid, type: 'commit' })
329
+ }
330
+ }
317
331
  if (
318
332
  !branchPatterns ||
319
333
  !(branchPatterns = Array.isArray(branchPatterns)
@@ -402,9 +416,11 @@ async function selectReferences (source, repo, remote) {
402
416
  if (currentBranch != null) return [currentBranch]
403
417
  return getCurrentBranchName(repo).then((branch) => (branch ? [branch] : []))
404
418
  })
405
- const worktrees = await findWorktrees(repo, worktreePatterns, useWorktree)
406
- let onMatch
407
- if ((useWorktree || worktreePatterns.length) && worktrees.size) {
419
+ let onMatch, worktrees
420
+ if (
421
+ (useWorktree || worktreePatterns.length) &&
422
+ (worktrees = await findWorktrees(repo, worktreePatterns, useWorktree)).size
423
+ ) {
408
424
  const headNames = new Map()
409
425
  worktrees.forEach(({ name, symbolicNames }, shortname) => {
410
426
  if (name) {
@@ -430,6 +446,7 @@ async function selectReferences (source, repo, remote) {
430
446
  const preferRemote = isBare && remoteBranches.length > 0
431
447
  for (const shortname of filterRefs(localBranches, branchPatterns, patternCache, onMatch)) {
432
448
  if (preferRemote && refs.has(shortname)) continue
449
+ worktrees ??= await findWorktrees(repo, worktreePatterns, useWorktree)
433
450
  const head = (worktrees.get(shortname) || { head: false }).head
434
451
  refs.set(shortname, { shortname, fullname: 'heads/' + shortname, type: 'branch', head })
435
452
  }
@@ -456,9 +473,11 @@ async function selectStartPaths (source, repo, ref) {
456
473
  const displayUrl = url || repo.dir
457
474
  const worktreePath = ref.head
458
475
  if (!worktreePath) {
459
- ref.oid = await git.resolveRef(
460
- Object.assign(ref.detached ? { ref: 'HEAD', depth: 1 } : { ref: 'refs/' + ref.fullname }, repo)
461
- )
476
+ ref.oid = ref.oid
477
+ ? await git.expandOid(Object.assign({ oid: ref.oid }, repo)).catch(() => ref.oid)
478
+ : await git.resolveRef(
479
+ Object.assign(ref.detached ? { ref: 'HEAD', depth: 1 } : { ref: 'refs/' + ref.fullname }, repo)
480
+ )
462
481
  }
463
482
  if ('startPaths' in source) {
464
483
  let startPaths
@@ -493,7 +512,9 @@ function collectFilesFromStartPath (startPath, repo, authStatus, ref, originUrl,
493
512
  return (worktreePath ? readFilesFromWorktree(origin) : readFilesFromGitTree(repo, ref.oid, startPath))
494
513
  .then((files) => {
495
514
  const batch = deepClone((origin.descriptor = loadComponentDescriptor(files, ref, version)))
496
- if ('nav' in batch && Array.isArray(batch.nav)) batch.nav.origin = origin
515
+ if ('nav' in batch && Array.isArray(batch.nav)) {
516
+ Object.defineProperty(batch.nav, 'origin', { configurable: true, value: origin, writable: true })
517
+ }
497
518
  batch.files = files.map((file) => assignFileProperties(file, origin))
498
519
  batch.origins = [origin]
499
520
  return batch
@@ -825,6 +846,7 @@ function buildFetchOptions (repo, progress, displayUrl, credentialsFromUrl, gitP
825
846
  } else if (!fetch.tags) {
826
847
  opts.noTags = true
827
848
  }
849
+ if (fetch.commits) opts.oids = fetch.commits
828
850
  return opts
829
851
  }
830
852
 
@@ -859,7 +881,10 @@ function createProgressListener (progress, progressLabel, operation) {
859
881
  // NOTE leave room for indeterminate progress at end of bar; this isn't strictly needed for a bare clone
860
882
  progressBar.scaleFactor = Math.max(0, (ticks - 1) / ticks)
861
883
  progressBar.tick(0)
862
- return Object.assign(onGitProgress.bind(progressBar), { finish: onGitComplete.bind(progressBar) })
884
+ return Object.assign(onGitProgress.bind(progressBar), {
885
+ finish: onGitComplete.bind(progressBar),
886
+ reset: () => progressBar.update(0),
887
+ })
863
888
  }
864
889
 
865
890
  function formatProgressBar (label, maxLabelWidth, operation) {
@@ -975,6 +1000,16 @@ function tagsSpecified (sources) {
975
1000
  return sources.some(({ tags }) => tags && (Array.isArray(tags) ? tags.length : true))
976
1001
  }
977
1002
 
1003
+ function commitsRequested (sources) {
1004
+ if (!sources.some(({ commits }) => commits && (Array.isArray(commits) ? commits.length : true))) return
1005
+ const result = new Set()
1006
+ for (const { commits } of sources) {
1007
+ if (!commits) continue
1008
+ for (const commit of Array.isArray(commits) ? commits : commits.split(CSV_RX)) result.add(String(commit))
1009
+ }
1010
+ return [...result]
1011
+ }
1012
+
978
1013
  function loadGitPlugins (gitConfig, networkConfig, startDir) {
979
1014
  const plugins = new Map((git.cores || git.default.cores || new Map()).get(GIT_CORE))
980
1015
  for (const [name, request] of Object.entries(gitConfig.plugins || {})) {
@@ -1164,4 +1199,27 @@ async function promiseAllWithLimit (tasks, limit = Infinity) {
1164
1199
  return Promise.all(started)
1165
1200
  }
1166
1201
 
1202
+ async function ensureOids (opts) {
1203
+ if (!opts.oids) return
1204
+ let prevShallowCommits = await getShallowCommits(opts)
1205
+ if (prevShallowCommits == null) return
1206
+ let oids = opts.oids.slice()
1207
+ const deepenOpts = Object.assign({}, opts, { relative: true })
1208
+ const format = 'deflated'
1209
+ while (oids.length) {
1210
+ deepenOpts.onProgress?.reset()
1211
+ await git.fetch(deepenOpts)
1212
+ const shallowCommits = await getShallowCommits(opts)
1213
+ if (shallowCommits == null || shallowCommits === prevShallowCommits) break
1214
+ prevShallowCommits = shallowCommits
1215
+ oids = await Promise.all(
1216
+ oids.map((oid) => git.readObject(Object.assign({ oid, format }, opts)).then(invariably.void, () => oid))
1217
+ ).then((results) => results.filter((it) => it))
1218
+ }
1219
+ }
1220
+
1221
+ function getShallowCommits ({ gitdir }) {
1222
+ return fsp.readFile(ospath.join(gitdir, 'shallow'), 'utf8').catch(invariably.void)
1223
+ }
1224
+
1167
1225
  module.exports = aggregateContent
@@ -42,7 +42,7 @@ function computeOrigin (url, authStatus, gitdir, ref, startPath, worktreePath =
42
42
  } else if (editUrl) {
43
43
  const vars = {
44
44
  path: () => (startPath ? path.join(startPath, '%s') : '%s'),
45
- ref: () => 'refs/' + (reftype === 'branch' ? 'heads' : reftype) + '/' + refname,
45
+ ref: () => 'refs/' + (reftype === 'branch' ? 'head' : reftype) + 's/' + refname,
46
46
  refhash: () => refhash,
47
47
  reftype: () => reftype,
48
48
  refname: () => refname,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antora/content-aggregator",
3
- "version": "3.2.0-alpha.10",
3
+ "version": "3.2.0-alpha.12",
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)",
@@ -33,13 +33,13 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@antora/expand-path-helper": "~3.0",
36
- "@antora/logger": "3.2.0-alpha.10",
36
+ "@antora/logger": "3.2.0-alpha.12",
37
37
  "@antora/user-require-helper": "~3.0",
38
38
  "braces": "~3.0",
39
39
  "cache-directory": "~2.0",
40
40
  "fast-glob": "~3.3",
41
41
  "hpagent": "~1.2",
42
- "isomorphic-git": "~1.25",
42
+ "isomorphic-git": "~1.37",
43
43
  "js-yaml": "~4.1",
44
44
  "multi-progress": "~4.0",
45
45
  "picomatch": "~4.0",
@@ -65,7 +65,7 @@
65
65
  "web publishing"
66
66
  ],
67
67
  "scripts": {
68
- "test": "_mocha",
68
+ "test": "node --test",
69
69
  "prepublishOnly": "npx -y downdoc@latest --prepublish",
70
70
  "postpublish": "npx -y downdoc@latest --postpublish"
71
71
  }