@antora/content-aggregator 3.1.6 → 3.1.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.
@@ -15,7 +15,8 @@ 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
- const globStream = require('glob-stream')
18
+ const { globStream } = require('fast-glob')
19
+ const { inspect } = require('util')
19
20
  const invariably = require('./invariably')
20
21
  const logger = require('./logger')
21
22
  const { makeMatcherRx, versionMatcherOpts: VERSION_MATCHER_OPTS } = require('./matcher')
@@ -118,11 +119,11 @@ async function collectFiles (sourcesByUrl, loadOpts, concurrency, fetchedUrls) {
118
119
  })
119
120
  return gracefulPromiseAllWithLimit(loadTasks, concurrency.fetch).then(([results, rejections]) => {
120
121
  if (rejections.length) {
121
- if (concurrency.fetch > 1 && rejections.every(({ recoverable }) => recoverable)) {
122
+ if (concurrency.fetch > 1 && results.length > 1 && rejections.every(({ recoverable }) => recoverable)) {
122
123
  if (loadOpts.progress) loadOpts.progress.terminate() // reset cursor position and allow it be reused
123
- const msg0 = 'An unexpected error occurred while concurrently fetching content sources.'
124
+ const msg0 = 'An unexpected error occurred while fetching content sources concurrently.'
124
125
  const msg1 = 'Retrying with git.fetch_concurrency value of 1.'
125
- logger.warn(msg0 + ' ' + msg1)
126
+ logger.warn(rejections[0], msg0 + ' ' + msg1)
126
127
  const fulfilledUrls = results.map((it) => it && it.repo.url && it.url).filter((it) => it)
127
128
  return collectFiles(sourcesByUrl, loadOpts, Object.assign(concurrency, { fetch: 1 }), fulfilledUrls)
128
129
  }
@@ -383,7 +384,7 @@ async function selectReferences (source, repo, remote) {
383
384
  }
384
385
 
385
386
  /**
386
- * Returns the current branch name unless the HEAD is detached.
387
+ * Returns the current branch name or undefined if the HEAD is detached.
387
388
  */
388
389
  function getCurrentBranchName (repo, remote) {
389
390
  let refPromise
@@ -437,12 +438,13 @@ function collectFilesFromStartPath (startPath, repo, authStatus, ref, originUrl,
437
438
  const worktreePath = ref.head
438
439
  const origin = computeOrigin(originUrl, authStatus, repo.gitdir, ref, startPath, worktreePath, editUrl)
439
440
  return (worktreePath ? readFilesFromWorktree(origin) : readFilesFromGitTree(repo, ref.oid, startPath))
440
- .then((files) =>
441
- Object.assign(deepClone((origin.descriptor = loadComponentDescriptor(files, ref, version))), {
442
- files: files.map((file) => assignFileProperties(file, origin)),
443
- origins: [origin],
444
- })
445
- )
441
+ .then((files) => {
442
+ const batch = deepClone((origin.descriptor = loadComponentDescriptor(files, ref, version)))
443
+ if ('nav' in batch) batch.nav.origin = origin
444
+ batch.files = files.map((file) => assignFileProperties(file, origin))
445
+ batch.origins = [origin]
446
+ return batch
447
+ })
446
448
  .catch((err) => {
447
449
  const where = worktreePath || (worktreePath === false ? repo.gitdir : repo.url || repo.dir)
448
450
  const flag = worktreePath ? ' <worktree>' : ref.remote && worktreePath === false ? ` <remotes/${ref.remote}>` : ''
@@ -467,19 +469,18 @@ function readFilesFromWorktree (origin) {
467
469
  }
468
470
 
469
471
  function srcFs (cwd, origin) {
470
- return new Promise((resolve, reject, cache = Object.create(null), files = [], relpathStart = cwd.length + 1) =>
472
+ return new Promise((resolve, reject, files = []) =>
471
473
  pipeline(
472
- globStream(CONTENT_SRC_GLOB, Object.assign({ cache, cwd }, CONTENT_SRC_OPTS)),
473
- forEach(({ path: abspathPosix }, _, done) => {
474
- if ((cache[abspathPosix] || {}).constructor === Array) return done() // detects some directories
475
- const abspath = posixify ? ospath.normalize(abspathPosix) : abspathPosix
476
- const relpath = abspath.substr(relpathStart)
477
- symlinkAwareStat(abspath).then(
478
- (stat) => {
479
- if (stat.isDirectory()) return done() // detects directories that slipped through cache check
474
+ globStream(CONTENT_SRC_GLOB, Object.assign({ cwd }, CONTENT_SRC_OPTS)),
475
+ forEach(({ path: relpath, dirent }, _, done) => {
476
+ if (dirent.isDirectory()) return done()
477
+ const relpathPosix = relpath
478
+ const abspath = posixify ? ospath.join(cwd, (relpath = ospath.normalize(relpath))) : cwd + '/' + relpath
479
+ fsp.stat(abspath).then(
480
+ (stat) =>
480
481
  fsp.readFile(abspath).then(
481
482
  (contents) => {
482
- files.push(new File({ path: posixify ? posixify(relpath) : relpath, contents, stat, src: { abspath } }))
483
+ files.push(new File({ path: relpathPosix, contents, stat, src: { abspath } }))
483
484
  done()
484
485
  },
485
486
  (readErr) => {
@@ -489,22 +490,28 @@ function srcFs (cwd, origin) {
489
490
  : logger.error(logObject, readErr.message.replace(`'${abspath}'`, relpath))
490
491
  done()
491
492
  }
492
- )
493
- },
493
+ ),
494
494
  (statErr) => {
495
495
  const logObject = { file: { abspath, origin } }
496
- if (statErr.symlink) {
497
- logger.error(
498
- logObject,
499
- (statErr.code === 'ELOOP' ? 'ELOOP: symbolic link cycle, ' : 'ENOENT: broken symbolic link, ') +
500
- `${relpath} -> ${statErr.symlink}`
501
- )
502
- } else if (statErr.code === 'ENOENT') {
503
- logger.warn(logObject, `ENOENT: file or directory disappeared, ${statErr.syscall} ${relpath}`)
496
+ if (dirent.isSymbolicLink()) {
497
+ fsp
498
+ .readlink(abspath)
499
+ .then(
500
+ (symlink) =>
501
+ (statErr.code === 'ELOOP' ? 'ELOOP: symbolic link cycle, ' : 'ENOENT: broken symbolic link, ') +
502
+ `${relpath} -> ${symlink}`,
503
+ () => statErr.message.replace(`'${abspath}'`, relpath)
504
+ )
505
+ .then((message) => {
506
+ logger.error(logObject, message)
507
+ done()
508
+ })
504
509
  } else {
505
- logger.error(logObject, statErr.message.replace(`'${abspath}'`, relpath))
510
+ statErr.code === 'ENOENT'
511
+ ? logger.warn(logObject, `ENOENT: file or directory disappeared, ${statErr.syscall} ${relpath}`)
512
+ : logger.error(logObject, statErr.message.replace(`'${abspath}'`, relpath))
513
+ done()
506
514
  }
507
- done()
508
515
  }
509
516
  )
510
517
  }),
@@ -674,8 +681,13 @@ function filterGitEntry (entry) {
674
681
 
675
682
  function gitEntryToFile (entry) {
676
683
  return git.readBlob(entry).then(({ blob: contents }) => {
677
- contents = Buffer.from(contents.buffer)
678
- const stat = Object.assign(new fs.Stats(), { mode: entry.mode, mtime: undefined, size: contents.byteLength })
684
+ const stat = {
685
+ mode: entry.mode,
686
+ size: (contents = Buffer.from(contents.buffer)).byteLength,
687
+ isDirectory: invariably.false,
688
+ isFile: invariably.true,
689
+ isSymbolicLink: invariably.false,
690
+ }
679
691
  return new File({ path: entry.path, contents, stat })
680
692
  })
681
693
  }
@@ -687,7 +699,7 @@ function loadComponentDescriptor (files, ref, version) {
687
699
  files.splice(descriptorFileIdx, 1)
688
700
  let data
689
701
  try {
690
- data = yaml.load(descriptorFile.contents.toString(), { schema: yaml.CORE_SCHEMA })
702
+ data = Object(yaml.load(descriptorFile.contents.toString(), { schema: yaml.CORE_SCHEMA }))
691
703
  } catch (err) {
692
704
  throw Object.assign(err, { message: `${COMPONENT_DESC_FILENAME} has invalid syntax; ${err.message}` })
693
705
  }
@@ -902,20 +914,6 @@ function isDirectory (url) {
902
914
  return fsp.stat(url).then((stat) => stat.isDirectory(), invariably.false)
903
915
  }
904
916
 
905
- function symlinkAwareStat (path_) {
906
- return fsp.lstat(path_).then((lstat) => {
907
- if (!lstat.isSymbolicLink()) return lstat
908
- return fsp.stat(path_).catch((statErr) =>
909
- fsp
910
- .readlink(path_)
911
- .catch(invariably.void)
912
- .then((symlink) => {
913
- throw Object.assign(statErr, { symlink })
914
- })
915
- )
916
- })
917
- }
918
-
919
917
  function tagsSpecified (sources) {
920
918
  return sources.some(({ tags }) => tags && (Array.isArray(tags) ? tags.length : true))
921
919
  }
@@ -986,15 +984,14 @@ function transformGitCloneError (err, displayUrl, authRequested) {
986
984
  } else if (err.code === 'ENOTFOUND') {
987
985
  wrappedMsg = `Content repository host could not be resolved: ${err.hostname}`
988
986
  } else {
989
- wrappedMsg = `${err.name}: ${err.message}`
987
+ wrappedMsg = err.message || String(err)
990
988
  recoverable = trimMessage = true
991
989
  }
992
- if (trimMessage) {
993
- wrappedMsg = ~(wrappedMsg = wrappedMsg.trimEnd()).indexOf('. ') ? wrappedMsg : wrappedMsg.replace(/\.$/, '')
994
- }
990
+ if (trimMessage && !~(wrappedMsg = wrappedMsg.trimEnd()).indexOf('. ')) wrappedMsg = wrappedMsg.replace(/\.$/, '')
995
991
  const errWrapper = new Error(`${wrappedMsg} (url: ${displayUrl})`)
996
- errWrapper.stack += `\nCaused by: ${err.stack || 'unknown'}`
997
- return recoverable ? Object.assign(errWrapper, { recoverable }) : errWrapper
992
+ errWrapper.stack += `\nCaused by: ${err.stack ? inspect(err).replace(/^Error \[(.+?)\](?=: )/, '$1') : err}`
993
+ if (recoverable) Object.defineProperty(errWrapper, 'recoverable', { value: true })
994
+ return errWrapper
998
995
  }
999
996
 
1000
997
  function splitRefPatterns (str) {
package/lib/constants.js CHANGED
@@ -3,8 +3,8 @@
3
3
  module.exports = Object.freeze({
4
4
  COMPONENT_DESC_FILENAME: 'antora.yml',
5
5
  CONTENT_CACHE_FOLDER: 'content',
6
- CONTENT_SRC_GLOB: '**/*[!~]',
7
- CONTENT_SRC_OPTS: { follow: true, nomount: true, nosort: true, nounique: true, strict: false },
6
+ CONTENT_SRC_GLOB: '**/!(*~)',
7
+ CONTENT_SRC_OPTS: { dot: true, ignore: ['**/.*{,/**}'], objectMode: true, onlyFiles: false, unique: false },
8
8
  FILE_MODES: { 100644: 0o100666 & ~process.umask(), 100755: 0o100777 & ~process.umask() },
9
9
  GIT_CORE: 'antora',
10
10
  GIT_OPERATION_LABEL_LENGTH: 8,
@@ -49,11 +49,12 @@ module.exports = ({ headers: extraHeaders, httpProxy, httpsProxy, noProxy } = {}
49
49
  }
50
50
  return {
51
51
  async request ({ url, method, headers, body }) {
52
- headers = mergeHeaders(headers, extraHeaders)
52
+ headers = Object.assign(mergeHeaders(headers, extraHeaders), { connection: 'close' })
53
53
  body = await mergeBuffers(body)
54
- return new Promise((resolve, reject) =>
55
- get({ url, method, headers, body }, (err, res) => (err ? reject(err) : resolve(distillResponse(res))))
56
- )
54
+ return new Promise((resolve, reject) => {
55
+ const opts = { url, method, headers, body, timeout: 0, keepAlive: false }
56
+ return get(opts, (err, res) => (err ? reject(err) : resolve(distillResponse(res))))
57
+ })
57
58
  },
58
59
  }
59
60
  }
package/lib/matcher.js CHANGED
@@ -16,15 +16,10 @@ const BASE_OPTS = {
16
16
  strictSlashes: true,
17
17
  }
18
18
 
19
- function makeMatcherRx (input, opts) {
20
- if (input && ~input.indexOf('{')) input = input.replace(/^([^({]+)\./, '$1(?:.)')
21
- return makeRe(input, opts)
22
- }
23
-
24
19
  module.exports = {
25
20
  MATCH_ALL_RX: { test: () => true },
26
21
  expandBraces,
27
- makeMatcherRx,
22
+ makeMatcherRx: makeRe,
28
23
  pathMatcherOpts: Object.assign({}, BASE_OPTS, { dot: false }),
29
24
  refMatcherOpts: (cache) =>
30
25
  Object.assign({}, BASE_OPTS, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antora/content-aggregator",
3
- "version": "3.1.6",
3
+ "version": "3.1.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)",
@@ -29,20 +29,20 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@antora/expand-path-helper": "~2.0",
32
- "@antora/logger": "3.1.6",
32
+ "@antora/logger": "3.1.8",
33
33
  "@antora/user-require-helper": "~2.0",
34
34
  "braces": "~3.0",
35
35
  "cache-directory": "~2.0",
36
- "glob-stream": "~7.0",
36
+ "fast-glob": "~3.3",
37
37
  "hpagent": "~1.2",
38
- "isomorphic-git": "~1.21",
38
+ "isomorphic-git": "~1.25",
39
39
  "js-yaml": "~4.1",
40
40
  "multi-progress": "~4.0",
41
- "picomatch": "~2.3",
41
+ "picomatch": "~4.0",
42
42
  "progress": "~2.0",
43
43
  "should-proxy": "~1.0",
44
44
  "simple-get": "~4.0",
45
- "vinyl": "~2.2"
45
+ "vinyl": "~3.0"
46
46
  },
47
47
  "engines": {
48
48
  "node": ">=16.0.0"