@lage-run/hasher 1.9.3 → 1.9.5

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/README.md CHANGED
@@ -1,3 +1,3 @@
1
1
  # @lage-run/hasher
2
2
 
3
- This package takes code from both backfill-hasher & package-dep-hash and strips out the extraneous dependencies: backfill-logger and @rushstack/node-core-lib. This is done so that `lage` can become a pure ES Module package. It also allows us to control how the hashing works should lage gains the ability to customize the `inputs` in the future.
3
+ This package builds on top of some helpers from `backfill-hasher` but adds customization for hashing targets with custom inputs and other logic.
package/lib/FileHasher.js CHANGED
@@ -8,11 +8,11 @@ Object.defineProperty(exports, "FileHasher", {
8
8
  return FileHasher;
9
9
  }
10
10
  });
11
- const _gracefulfs = /*#__PURE__*/ _interop_require_default(require("graceful-fs"));
12
- const _path = /*#__PURE__*/ _interop_require_default(require("path"));
11
+ const _backfillhasher = require("backfill-hasher");
13
12
  const _globhasher = require("glob-hasher");
13
+ const _gracefulfs = /*#__PURE__*/ _interop_require_default(require("graceful-fs"));
14
14
  const _nodereadline = require("node:readline");
15
- const _getPackageDeps = require("./getPackageDeps.js");
15
+ const _path = /*#__PURE__*/ _interop_require_default(require("path"));
16
16
  function _check_private_redeclaration(obj, privateCollection) {
17
17
  if (privateCollection.has(obj)) {
18
18
  throw new TypeError("Cannot initialize the same private elements twice on an object");
@@ -75,15 +75,13 @@ var _store = /*#__PURE__*/ new WeakMap(), _manifestFile = /*#__PURE__*/ new Weak
75
75
  class FileHasher {
76
76
  getHashesFromGit() {
77
77
  const { root } = this.options;
78
- const fileHashes = (0, _getPackageDeps.getPackageDeps)(root);
79
- const files = [
80
- ...fileHashes.keys()
81
- ];
78
+ const fileHashes = (0, _backfillhasher.getFileHashes)(root);
79
+ const files = Object.keys(fileHashes);
82
80
  const fileStats = (0, _globhasher.stat)(files, {
83
81
  cwd: root
84
82
  }) ?? {};
85
83
  for (const [relativePath, fileStat] of Object.entries(fileStats)){
86
- const hash = fileHashes.get(relativePath);
84
+ const hash = fileHashes[relativePath];
87
85
  if (hash) {
88
86
  const { size, mtime } = fileStat;
89
87
  _class_private_field_get(this, _store)[relativePath] = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/FileHasher.ts"],"sourcesContent":["import fs from \"graceful-fs\";\nimport path from \"path\";\nimport { hash as fastHash, stat } from \"glob-hasher\";\nimport { createInterface } from \"node:readline\";\nimport { getPackageDeps } from \"./getPackageDeps.js\";\n\ninterface FileHashStoreOptions {\n root: string;\n}\n\ntype FileHashManifestStore = Record<\n string,\n {\n mtime: bigint;\n size: number;\n hash: string;\n }\n>;\n\nexport class FileHasher {\n #store: FileHashManifestStore = {};\n #manifestFile: string;\n\n constructor(private options: FileHashStoreOptions) {\n const { root } = options;\n const cacheDirectory = path.join(root, \"node_modules\", \".cache\", \"lage\");\n this.#manifestFile = path.join(cacheDirectory, \"file_hashes.manifest\");\n }\n\n private getHashesFromGit(): void {\n const { root } = this.options;\n const fileHashes = getPackageDeps(root);\n const files = [...fileHashes.keys()];\n const fileStats = stat(files, { cwd: root }) ?? {};\n\n for (const [relativePath, fileStat] of Object.entries(fileStats)) {\n const hash = fileHashes.get(relativePath);\n if (hash) {\n const { size, mtime } = fileStat;\n\n this.#store[relativePath] = { hash, size, mtime };\n }\n }\n\n this.writeManifest();\n }\n\n public async readManifest(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (!fs.existsSync(this.#manifestFile)) {\n try {\n this.getHashesFromGit();\n resolve();\n } catch (err) {\n reject(err);\n }\n return;\n }\n\n const inputStream = fs.createReadStream(this.#manifestFile, \"utf-8\");\n const rl = createInterface({\n input: inputStream,\n crlfDelay: Infinity,\n });\n\n let info: string[] = [];\n\n rl.on(\"line\", (line) => {\n info = line.split(\"\\0\");\n\n this.#store[info[0]] = {\n mtime: BigInt(info[1]),\n size: parseInt(info[2]),\n hash: info[3],\n };\n });\n\n inputStream.on(\"end\", () => {\n rl.close();\n resolve();\n });\n });\n }\n\n public writeManifest(): void {\n fs.mkdirSync(path.dirname(this.#manifestFile), { recursive: true });\n const outputLines = Object.entries(this.#store).map(([relativePath, info]) => {\n return `${relativePath}\\0${info.mtime.toString()}\\0${info.size.toString()}\\0${info.hash}`;\n });\n\n fs.writeFileSync(this.#manifestFile, outputLines.join(\"\\n\"), \"utf-8\");\n }\n\n public hash(files: string[]): Record<string, string> {\n const hashes: Record<string, string> = {};\n\n const updatedFiles: string[] = [];\n\n const stats = stat(files, { cwd: this.options.root }) ?? {};\n\n for (const file of files) {\n const stat = stats[file];\n\n const info = this.#store[file];\n if (info && stat.mtime === info.mtime && stat.size == info.size) {\n hashes[file] = info.hash;\n } else {\n updatedFiles.push(file);\n }\n }\n\n const updatedHashes = fastHash(updatedFiles, { cwd: this.options.root, concurrency: 4 }) ?? {};\n\n for (const [file, hash] of Object.entries(updatedHashes)) {\n const stat = fs.statSync(path.join(this.options.root, file), { bigint: true });\n this.#store[file] = {\n mtime: stat.mtimeMs,\n size: Number(stat.size),\n hash: hash ?? \"\",\n };\n hashes[file] = hash ?? \"\";\n }\n\n return hashes;\n }\n}\n"],"names":["FileHasher","getHashesFromGit","root","options","fileHashes","getPackageDeps","files","keys","fileStats","stat","cwd","relativePath","fileStat","Object","entries","hash","get","size","mtime","writeManifest","readManifest","Promise","resolve","reject","fs","existsSync","err","inputStream","createReadStream","rl","createInterface","input","crlfDelay","Infinity","info","on","line","split","BigInt","parseInt","close","mkdirSync","path","dirname","recursive","outputLines","map","toString","writeFileSync","join","hashes","updatedFiles","stats","file","push","updatedHashes","fastHash","concurrency","statSync","bigint","mtimeMs","Number","cacheDirectory"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/FileHasher.ts"],"sourcesContent":["import { getFileHashes } from \"backfill-hasher\";\nimport { hash as fastHash, stat as globStat } from \"glob-hasher\";\nimport fs from \"graceful-fs\";\nimport { createInterface } from \"node:readline\";\nimport path from \"path\";\n\ninterface FileHashStoreOptions {\n root: string;\n}\n\ntype FileHashManifestStore = Record<\n string,\n {\n mtime: bigint;\n size: number;\n hash: string;\n }\n>;\n\nexport class FileHasher {\n #store: FileHashManifestStore = {};\n #manifestFile: string;\n\n constructor(private options: FileHashStoreOptions) {\n const { root } = options;\n const cacheDirectory = path.join(root, \"node_modules\", \".cache\", \"lage\");\n this.#manifestFile = path.join(cacheDirectory, \"file_hashes.manifest\");\n }\n\n private getHashesFromGit(): void {\n const { root } = this.options;\n const fileHashes = getFileHashes(root);\n const files = Object.keys(fileHashes);\n const fileStats = globStat(files, { cwd: root }) ?? {};\n\n for (const [relativePath, fileStat] of Object.entries(fileStats)) {\n const hash = fileHashes[relativePath];\n if (hash) {\n const { size, mtime } = fileStat;\n\n this.#store[relativePath] = { hash, size, mtime };\n }\n }\n\n this.writeManifest();\n }\n\n public async readManifest(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n if (!fs.existsSync(this.#manifestFile)) {\n try {\n this.getHashesFromGit();\n resolve();\n } catch (err) {\n reject(err);\n }\n return;\n }\n\n const inputStream = fs.createReadStream(this.#manifestFile, \"utf-8\");\n const rl = createInterface({\n input: inputStream,\n crlfDelay: Infinity,\n });\n\n let info: string[] = [];\n\n rl.on(\"line\", (line) => {\n info = line.split(\"\\0\");\n\n this.#store[info[0]] = {\n mtime: BigInt(info[1]),\n size: parseInt(info[2]),\n hash: info[3],\n };\n });\n\n inputStream.on(\"end\", () => {\n rl.close();\n resolve();\n });\n });\n }\n\n public writeManifest(): void {\n fs.mkdirSync(path.dirname(this.#manifestFile), { recursive: true });\n const outputLines = Object.entries(this.#store).map(([relativePath, info]) => {\n return `${relativePath}\\0${info.mtime.toString()}\\0${info.size.toString()}\\0${info.hash}`;\n });\n\n fs.writeFileSync(this.#manifestFile, outputLines.join(\"\\n\"), \"utf-8\");\n }\n\n public hash(files: string[]): Record<string, string> {\n const hashes: Record<string, string> = {};\n\n const updatedFiles: string[] = [];\n\n const stats = globStat(files, { cwd: this.options.root }) ?? {};\n\n for (const file of files) {\n const stat = stats[file];\n\n const info = this.#store[file];\n if (info && stat.mtime === info.mtime && stat.size == info.size) {\n hashes[file] = info.hash;\n } else {\n updatedFiles.push(file);\n }\n }\n\n const updatedHashes = fastHash(updatedFiles, { cwd: this.options.root, concurrency: 4 }) ?? {};\n\n for (const [file, hash] of Object.entries(updatedHashes)) {\n const stat = fs.statSync(path.join(this.options.root, file), { bigint: true });\n this.#store[file] = {\n mtime: stat.mtimeMs,\n size: Number(stat.size),\n hash: hash ?? \"\",\n };\n hashes[file] = hash ?? \"\";\n }\n\n return hashes;\n }\n}\n"],"names":["FileHasher","getHashesFromGit","root","options","fileHashes","getFileHashes","files","Object","keys","fileStats","globStat","cwd","relativePath","fileStat","entries","hash","size","mtime","writeManifest","readManifest","Promise","resolve","reject","fs","existsSync","err","inputStream","createReadStream","rl","createInterface","input","crlfDelay","Infinity","info","on","line","split","BigInt","parseInt","close","mkdirSync","path","dirname","recursive","outputLines","map","toString","writeFileSync","join","hashes","updatedFiles","stats","file","stat","push","updatedHashes","fastHash","concurrency","statSync","bigint","mtimeMs","Number","cacheDirectory"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
+ import type { Logger } from "@lage-run/logger";
1
2
  import type { Target } from "@lage-run/target-graph";
2
3
  import { type DependencyMap } from "workspace-tools";
3
4
  import { FileHasher } from "./FileHasher.js";
4
- import type { Logger } from "@lage-run/logger";
5
5
  import { PackageTree } from "./PackageTree.js";
6
6
  export interface TargetHasherOptions {
7
7
  root: string;
@@ -8,16 +8,16 @@ Object.defineProperty(exports, "TargetHasher", {
8
8
  return TargetHasher;
9
9
  }
10
10
  });
11
- const _globhasher = require("glob-hasher");
12
11
  const _globby = require("@lage-run/globby");
12
+ const _backfillhasher = require("backfill-hasher");
13
13
  const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
14
+ const _globhasher = require("glob-hasher");
14
15
  const _path = /*#__PURE__*/ _interop_require_default(require("path"));
15
16
  const _workspacetools = require("workspace-tools");
16
- const _hashStrings = require("./hashStrings.js");
17
- const _resolveExternalDependencies = require("./resolveExternalDependencies.js");
18
17
  const _FileHasher = require("./FileHasher.js");
19
18
  const _PackageTree = require("./PackageTree.js");
20
19
  const _getInputFiles = require("./getInputFiles.js");
20
+ const _hashStrings = require("./hashStrings.js");
21
21
  function _define_property(obj, key, value) {
22
22
  if (key in obj) {
23
23
  Object.defineProperty(obj, key, {
@@ -51,7 +51,7 @@ class TargetHasher {
51
51
  this.initializedPromise = Promise.all([
52
52
  this.fileHasher.readManifest().then(()=>(0, _globby.globAsync)(environmentGlob, {
53
53
  cwd: root
54
- })).then((files)=>this.fileHasher.hash(files)).then((hash)=>this.globalInputsHash = hash),
54
+ })).then((files)=>this.fileHasher.hash(files)).then((h)=>this.globalInputsHash = h),
55
55
  (0, _workspacetools.getPackageInfosAsync)(root).then((packageInfos)=>{
56
56
  if (Object.keys(packageInfos).length) {
57
57
  this.packageInfos = packageInfos;
@@ -108,7 +108,7 @@ class TargetHasher {
108
108
  ...devDependencies
109
109
  };
110
110
  const internalDeps = Object.keys(allDependencies).filter((dep)=>this.packageInfos[dep]);
111
- const externalDeps = (0, _resolveExternalDependencies.resolveExternalDependencies)(allDependencies, this.packageInfos, parsedLock);
111
+ const externalDeps = (0, _backfillhasher.resolveExternalDependencies)(allDependencies, this.packageInfos, parsedLock);
112
112
  const resolvedDependencies = [
113
113
  ...internalDeps,
114
114
  ...externalDeps
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/TargetHasher.ts"],"sourcesContent":["import type { Target } from \"@lage-run/target-graph\";\nimport { hash } from \"glob-hasher\";\nimport { globAsync } from \"@lage-run/globby\";\n\nimport fs from \"fs\";\nimport path from \"path\";\nimport {\n type DependencyMap,\n type ParsedLock,\n type PackageInfos,\n parseLockFile,\n createDependencyMap,\n getPackageInfo,\n getPackageInfosAsync,\n} from \"workspace-tools\";\n\nimport { hashStrings } from \"./hashStrings.js\";\nimport { resolveExternalDependencies } from \"./resolveExternalDependencies.js\";\nimport { FileHasher } from \"./FileHasher.js\";\nimport type { Logger } from \"@lage-run/logger\";\nimport { PackageTree } from \"./PackageTree.js\";\nimport { getInputFiles } from \"./getInputFiles.js\";\n\nexport interface TargetHasherOptions {\n root: string;\n environmentGlob: string[];\n cacheKey?: string;\n cliArgs?: string[];\n logger?: Logger;\n}\n\nexport interface TargetManifest {\n id: string;\n hash: string;\n globalInputsHash: string;\n dependency: Record<string, string>;\n fileHasher: FileHasher;\n files: Record<\n string,\n {\n mtimeMs: number;\n size: number;\n hash: string;\n }\n >;\n}\n\n/**\n * TargetHasher is a class that can be used to generate a hash of a target.\n * It uses `glob-hasher` internally.\n */\nexport class TargetHasher {\n private targetHashesLog: Record<string, { fileHashes: Record<string, string>; globalFileHashes: Record<string, string> }> = {};\n private targetHashesDirectory: string;\n\n private logger: Logger | undefined;\n private fileHasher: FileHasher;\n public packageTree: PackageTree | undefined;\n\n private initializedPromise: Promise<unknown> | undefined;\n\n private packageInfos: PackageInfos = {};\n private globalInputsHash: Record<string, string> | undefined;\n private lockInfo: ParsedLock | undefined;\n private targetHashes: Record<string, string> = {};\n\n public dependencyMap: DependencyMap = {\n dependencies: new Map(),\n dependents: new Map(),\n };\n\n constructor(private options: TargetHasherOptions) {\n const { root, logger } = options;\n this.logger = logger;\n\n this.fileHasher = new FileHasher({\n root,\n });\n\n this.targetHashesDirectory = path.join(root, \"node_modules\", \".cache\", \"lage\", \"hashes\");\n\n if (!fs.existsSync(this.targetHashesDirectory)) {\n fs.mkdirSync(this.targetHashesDirectory, { recursive: true });\n }\n }\n\n private ensureInitialized(): void {\n if (!this.initializedPromise) {\n throw new Error(\"TargetHasher is not initialized\");\n }\n }\n\n public async initialize(): Promise<void> {\n const { environmentGlob, root } = this.options;\n\n if (this.initializedPromise) {\n await this.initializedPromise;\n return;\n }\n\n this.initializedPromise = Promise.all([\n this.fileHasher\n .readManifest()\n .then(() => globAsync(environmentGlob, { cwd: root }))\n .then((files) => this.fileHasher.hash(files))\n .then((hash) => (this.globalInputsHash = hash)),\n\n getPackageInfosAsync(root).then((packageInfos) => {\n if (Object.keys(packageInfos).length) {\n this.packageInfos = packageInfos;\n } else {\n const rootInfo = getPackageInfo(root);\n if (rootInfo) {\n this.packageInfos = { [rootInfo.name]: rootInfo };\n }\n }\n\n this.dependencyMap = createDependencyMap(this.packageInfos, { withDevDependencies: true, withPeerDependencies: false });\n this.packageTree = new PackageTree({\n root,\n packageInfos: this.packageInfos,\n\n // TODO: (optimization) false if process.env.TF_BUILD || process.env.CI\n includeUntracked: true,\n });\n\n return this.packageTree.initialize();\n }),\n\n parseLockFile(root).then((lockInfo) => (this.lockInfo = lockInfo)),\n ]);\n\n await this.initializedPromise;\n\n if (this.logger !== undefined) {\n const globalInputsHash = hashStrings(Object.values(this.globalInputsHash ?? {}));\n this.logger.verbose(`Global inputs hash: ${globalInputsHash}`);\n }\n }\n\n public async hash(target: Target): Promise<string> {\n this.ensureInitialized();\n\n const { root } = this.options;\n\n if (target.cwd === root && target.cache) {\n if (!target.inputs) {\n throw new Error(`No \"inputs\" specified for target \"${target.id}\"; cannot cache.`);\n }\n\n const files = await globAsync(target.inputs, { cwd: root });\n const fileFashes = hash(files, { cwd: root }) ?? {};\n\n const hashes = Object.values(fileFashes) as string[];\n\n return hashStrings(hashes);\n }\n\n // 1. add hash of target's inputs\n // 2. add hash of target packages' internal and external deps\n const { dependencies, devDependencies } = this.packageInfos[target.packageName!];\n\n const parsedLock = this.lockInfo!;\n\n const allDependencies: Record<string, string> = {\n ...dependencies,\n ...devDependencies,\n };\n\n const internalDeps = Object.keys(allDependencies).filter((dep) => this.packageInfos[dep]);\n const externalDeps = resolveExternalDependencies(allDependencies, this.packageInfos, parsedLock);\n const resolvedDependencies = [...internalDeps, ...externalDeps].sort();\n\n const files = getInputFiles(target, this.dependencyMap, this.packageTree!);\n const fileHashes = this.fileHasher.hash(files) ?? {}; // this list is sorted by file name\n\n // get target hashes\n const targetDepHashes = target.dependencies?.sort().map((targetDep) => this.targetHashes[targetDep]);\n\n const globalFileHashes = await this.getEnvironmentGlobHashes(root, target);\n\n const combinedHashes = [\n // Environmental hashes\n ...Object.values(globalFileHashes),\n `${target.id}|${JSON.stringify(this.options.cliArgs)}`,\n this.options.cacheKey || \"\",\n\n // File content hashes based on target.inputs\n ...Object.values(fileHashes),\n\n // Dependency hashes\n ...resolvedDependencies,\n ...targetDepHashes,\n ].filter(Boolean);\n\n const hashString = hashStrings(combinedHashes);\n\n this.targetHashes[target.id] = hashString;\n\n this.targetHashesLog[target.id] = { fileHashes, globalFileHashes };\n\n return hashString;\n }\n\n private writeTargetHashesManifest(): void {\n for (const [id, { fileHashes, globalFileHashes }] of Object.entries(this.targetHashesLog)) {\n const targetHashesManifestPath = path.join(this.targetHashesDirectory, `${id}.json`);\n if (!fs.existsSync(path.dirname(targetHashesManifestPath))) {\n fs.mkdirSync(path.dirname(targetHashesManifestPath), { recursive: true });\n }\n fs.writeFileSync(targetHashesManifestPath, JSON.stringify({ fileHashes, globalFileHashes }), \"utf-8\");\n }\n }\n\n private async getEnvironmentGlobHashes(root: string, target: Target): Promise<Record<string, string>> {\n const globalFileHashes = target.environmentGlob\n ? this.fileHasher.hash(await globAsync(target.environmentGlob ?? [], { cwd: root }))\n : (this.globalInputsHash ?? {});\n\n return globalFileHashes;\n }\n\n public async cleanup(): Promise<void> {\n this.writeTargetHashesManifest();\n this.fileHasher.writeManifest();\n }\n}\n"],"names":["TargetHasher","ensureInitialized","initializedPromise","Error","initialize","environmentGlob","root","options","Promise","all","fileHasher","readManifest","then","globAsync","cwd","files","hash","globalInputsHash","getPackageInfosAsync","packageInfos","Object","keys","length","rootInfo","getPackageInfo","name","dependencyMap","createDependencyMap","withDevDependencies","withPeerDependencies","packageTree","PackageTree","includeUntracked","parseLockFile","lockInfo","logger","undefined","hashStrings","values","verbose","target","cache","inputs","id","fileFashes","hashes","dependencies","devDependencies","packageName","parsedLock","allDependencies","internalDeps","filter","dep","externalDeps","resolveExternalDependencies","resolvedDependencies","sort","getInputFiles","fileHashes","targetDepHashes","map","targetDep","targetHashes","globalFileHashes","getEnvironmentGlobHashes","combinedHashes","JSON","stringify","cliArgs","cacheKey","Boolean","hashString","targetHashesLog","writeTargetHashesManifest","entries","targetHashesManifestPath","path","join","targetHashesDirectory","fs","existsSync","dirname","mkdirSync","recursive","writeFileSync","cleanup","writeManifest","Map","dependents","FileHasher"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/TargetHasher.ts"],"sourcesContent":["import { globAsync } from \"@lage-run/globby\";\nimport type { Logger } from \"@lage-run/logger\";\nimport type { Target } from \"@lage-run/target-graph\";\nimport { resolveExternalDependencies } from \"backfill-hasher\";\nimport fs from \"fs\";\nimport { hash } from \"glob-hasher\";\nimport path from \"path\";\nimport {\n createDependencyMap,\n type DependencyMap,\n getPackageInfo,\n getPackageInfosAsync,\n type PackageInfos,\n type ParsedLock,\n parseLockFile,\n} from \"workspace-tools\";\nimport { FileHasher } from \"./FileHasher.js\";\nimport { PackageTree } from \"./PackageTree.js\";\nimport { getInputFiles } from \"./getInputFiles.js\";\nimport { hashStrings } from \"./hashStrings.js\";\n\nexport interface TargetHasherOptions {\n root: string;\n environmentGlob: string[];\n cacheKey?: string;\n cliArgs?: string[];\n logger?: Logger;\n}\n\nexport interface TargetManifest {\n id: string;\n hash: string;\n globalInputsHash: string;\n dependency: Record<string, string>;\n fileHasher: FileHasher;\n files: Record<\n string,\n {\n mtimeMs: number;\n size: number;\n hash: string;\n }\n >;\n}\n\n/**\n * TargetHasher is a class that can be used to generate a hash of a target.\n * It uses `glob-hasher` internally.\n */\nexport class TargetHasher {\n private targetHashesLog: Record<string, { fileHashes: Record<string, string>; globalFileHashes: Record<string, string> }> = {};\n private targetHashesDirectory: string;\n\n private logger: Logger | undefined;\n private fileHasher: FileHasher;\n public packageTree: PackageTree | undefined;\n\n private initializedPromise: Promise<unknown> | undefined;\n\n private packageInfos: PackageInfos = {};\n private globalInputsHash: Record<string, string> | undefined;\n private lockInfo: ParsedLock | undefined;\n private targetHashes: Record<string, string> = {};\n\n public dependencyMap: DependencyMap = {\n dependencies: new Map(),\n dependents: new Map(),\n };\n\n constructor(private options: TargetHasherOptions) {\n const { root, logger } = options;\n this.logger = logger;\n\n this.fileHasher = new FileHasher({\n root,\n });\n\n this.targetHashesDirectory = path.join(root, \"node_modules\", \".cache\", \"lage\", \"hashes\");\n\n if (!fs.existsSync(this.targetHashesDirectory)) {\n fs.mkdirSync(this.targetHashesDirectory, { recursive: true });\n }\n }\n\n private ensureInitialized(): void {\n if (!this.initializedPromise) {\n throw new Error(\"TargetHasher is not initialized\");\n }\n }\n\n public async initialize(): Promise<void> {\n const { environmentGlob, root } = this.options;\n\n if (this.initializedPromise) {\n await this.initializedPromise;\n return;\n }\n\n this.initializedPromise = Promise.all([\n this.fileHasher\n .readManifest()\n .then(() => globAsync(environmentGlob, { cwd: root }))\n .then((files) => this.fileHasher.hash(files))\n .then((h) => (this.globalInputsHash = h)),\n\n getPackageInfosAsync(root).then((packageInfos) => {\n if (Object.keys(packageInfos).length) {\n this.packageInfos = packageInfos;\n } else {\n const rootInfo = getPackageInfo(root);\n if (rootInfo) {\n this.packageInfos = { [rootInfo.name]: rootInfo };\n }\n }\n\n this.dependencyMap = createDependencyMap(this.packageInfos, { withDevDependencies: true, withPeerDependencies: false });\n this.packageTree = new PackageTree({\n root,\n packageInfos: this.packageInfos,\n\n // TODO: (optimization) false if process.env.TF_BUILD || process.env.CI\n includeUntracked: true,\n });\n\n return this.packageTree.initialize();\n }),\n\n parseLockFile(root).then((lockInfo) => (this.lockInfo = lockInfo)),\n ]);\n\n await this.initializedPromise;\n\n if (this.logger !== undefined) {\n const globalInputsHash = hashStrings(Object.values(this.globalInputsHash ?? {}));\n this.logger.verbose(`Global inputs hash: ${globalInputsHash}`);\n }\n }\n\n public async hash(target: Target): Promise<string> {\n this.ensureInitialized();\n\n const { root } = this.options;\n\n if (target.cwd === root && target.cache) {\n if (!target.inputs) {\n throw new Error(`No \"inputs\" specified for target \"${target.id}\"; cannot cache.`);\n }\n\n const files = await globAsync(target.inputs, { cwd: root });\n const fileFashes = hash(files, { cwd: root }) ?? {};\n\n const hashes = Object.values(fileFashes) as string[];\n\n return hashStrings(hashes);\n }\n\n // 1. add hash of target's inputs\n // 2. add hash of target packages' internal and external deps\n const { dependencies, devDependencies } = this.packageInfos[target.packageName!];\n\n const parsedLock = this.lockInfo!;\n\n const allDependencies: Record<string, string> = {\n ...dependencies,\n ...devDependencies,\n };\n\n const internalDeps = Object.keys(allDependencies).filter((dep) => this.packageInfos[dep]);\n const externalDeps = resolveExternalDependencies(allDependencies, this.packageInfos, parsedLock);\n const resolvedDependencies = [...internalDeps, ...externalDeps].sort();\n\n const files = getInputFiles(target, this.dependencyMap, this.packageTree!);\n const fileHashes = this.fileHasher.hash(files) ?? {}; // this list is sorted by file name\n\n // get target hashes\n const targetDepHashes = target.dependencies?.sort().map((targetDep) => this.targetHashes[targetDep]);\n\n const globalFileHashes = await this.getEnvironmentGlobHashes(root, target);\n\n const combinedHashes = [\n // Environmental hashes\n ...Object.values(globalFileHashes),\n `${target.id}|${JSON.stringify(this.options.cliArgs)}`,\n this.options.cacheKey || \"\",\n\n // File content hashes based on target.inputs\n ...Object.values(fileHashes),\n\n // Dependency hashes\n ...resolvedDependencies,\n ...targetDepHashes,\n ].filter(Boolean);\n\n const hashString = hashStrings(combinedHashes);\n\n this.targetHashes[target.id] = hashString;\n\n this.targetHashesLog[target.id] = { fileHashes, globalFileHashes };\n\n return hashString;\n }\n\n private writeTargetHashesManifest(): void {\n for (const [id, { fileHashes, globalFileHashes }] of Object.entries(this.targetHashesLog)) {\n const targetHashesManifestPath = path.join(this.targetHashesDirectory, `${id}.json`);\n if (!fs.existsSync(path.dirname(targetHashesManifestPath))) {\n fs.mkdirSync(path.dirname(targetHashesManifestPath), { recursive: true });\n }\n fs.writeFileSync(targetHashesManifestPath, JSON.stringify({ fileHashes, globalFileHashes }), \"utf-8\");\n }\n }\n\n private async getEnvironmentGlobHashes(root: string, target: Target): Promise<Record<string, string>> {\n const globalFileHashes = target.environmentGlob\n ? this.fileHasher.hash(await globAsync(target.environmentGlob ?? [], { cwd: root }))\n : (this.globalInputsHash ?? {});\n\n return globalFileHashes;\n }\n\n public async cleanup(): Promise<void> {\n this.writeTargetHashesManifest();\n this.fileHasher.writeManifest();\n }\n}\n"],"names":["TargetHasher","ensureInitialized","initializedPromise","Error","initialize","environmentGlob","root","options","Promise","all","fileHasher","readManifest","then","globAsync","cwd","files","hash","h","globalInputsHash","getPackageInfosAsync","packageInfos","Object","keys","length","rootInfo","getPackageInfo","name","dependencyMap","createDependencyMap","withDevDependencies","withPeerDependencies","packageTree","PackageTree","includeUntracked","parseLockFile","lockInfo","logger","undefined","hashStrings","values","verbose","target","cache","inputs","id","fileFashes","hashes","dependencies","devDependencies","packageName","parsedLock","allDependencies","internalDeps","filter","dep","externalDeps","resolveExternalDependencies","resolvedDependencies","sort","getInputFiles","fileHashes","targetDepHashes","map","targetDep","targetHashes","globalFileHashes","getEnvironmentGlobHashes","combinedHashes","JSON","stringify","cliArgs","cacheKey","Boolean","hashString","targetHashesLog","writeTargetHashesManifest","entries","targetHashesManifestPath","path","join","targetHashesDirectory","fs","existsSync","dirname","mkdirSync","recursive","writeFileSync","cleanup","writeManifest","Map","dependents","FileHasher"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lage-run/hasher",
3
- "version": "1.9.3",
3
+ "version": "1.9.5",
4
4
  "description": "Hasher for Lage Targets",
5
5
  "repository": {
6
6
  "url": "https://github.com/microsoft/lage"
@@ -18,7 +18,8 @@
18
18
  "dependencies": {
19
19
  "@lage-run/globby": "^13.0.1",
20
20
  "@lage-run/logger": "^1.3.3",
21
- "@lage-run/target-graph": "^0.12.3",
21
+ "@lage-run/target-graph": "^0.14.0",
22
+ "backfill-hasher": "^6.7.1",
22
23
  "execa": "^5.1.1",
23
24
  "glob-hasher": "^1.4.2",
24
25
  "graceful-fs": "^4.2.11",
@@ -1,45 +0,0 @@
1
- /**
2
- * Parses a quoted filename sourced from the output of the "git status" command.
3
- *
4
- * Paths with non-standard characters will be enclosed with double-quotes, and non-standard
5
- * characters will be backslash escaped (ex. double-quotes, non-ASCII characters). The
6
- * escaped chars can be included in one of two ways:
7
- * - backslash-escaped chars (ex. \")
8
- * - octal encoded chars (ex. \347)
9
- *
10
- * See documentation: https://git-scm.com/docs/git-status
11
- */
12
- export declare function parseGitFilename(filename: string): string;
13
- /**
14
- * Parses the output of the "git ls-tree" command
15
- */
16
- export declare function parseGitLsTree(output: string): Map<string, string>;
17
- /**
18
- * Parses the output of the "git status" command
19
- */
20
- export declare function parseGitStatus(output: string): Map<string, string>;
21
- /**
22
- * Takes a list of files and returns the current git hashes for them
23
- *
24
- * @public
25
- */
26
- export declare function getGitHashForFiles(filesToHash: string[], packagePath: string, gitPath?: string): Map<string, string>;
27
- /**
28
- * Executes "git ls-tree" in a folder
29
- */
30
- export declare function gitLsTree(path: string, gitPath?: string): string;
31
- /**
32
- * Executes "git status" in a folder
33
- */
34
- export declare function gitStatus(path: string, gitPath?: string): string;
35
- /**
36
- * Builds an object containing hashes for the files under the specified `packagePath` folder.
37
- * @param packagePath - The folder path to derive the package dependencies from. This is typically the folder
38
- * containing package.json. If omitted, the default value is the current working directory.
39
- * @param excludedPaths - An optional array of file path exclusions. If a file should be omitted from the list
40
- * of dependencies, use this to exclude it.
41
- * @returns the package-deps.json file content
42
- *
43
- * @public
44
- */
45
- export declare function getPackageDeps(packagePath?: string, excludedPaths?: string[], gitPath?: string): Map<string, string>;
@@ -1,259 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- function _export(target, all) {
6
- for(var name in all)Object.defineProperty(target, name, {
7
- enumerable: true,
8
- get: Object.getOwnPropertyDescriptor(all, name).get
9
- });
10
- }
11
- _export(exports, {
12
- get getGitHashForFiles () {
13
- return getGitHashForFiles;
14
- },
15
- get getPackageDeps () {
16
- return getPackageDeps;
17
- },
18
- get gitLsTree () {
19
- return gitLsTree;
20
- },
21
- get gitStatus () {
22
- return gitStatus;
23
- },
24
- get parseGitFilename () {
25
- return parseGitFilename;
26
- },
27
- get parseGitLsTree () {
28
- return parseGitLsTree;
29
- },
30
- get parseGitStatus () {
31
- return parseGitStatus;
32
- }
33
- });
34
- const _path = /*#__PURE__*/ _interop_require_wildcard(require("path"));
35
- const _execa = /*#__PURE__*/ _interop_require_default(require("execa"));
36
- function _interop_require_default(obj) {
37
- return obj && obj.__esModule ? obj : {
38
- default: obj
39
- };
40
- }
41
- function _getRequireWildcardCache(nodeInterop) {
42
- if (typeof WeakMap !== "function") return null;
43
- var cacheBabelInterop = new WeakMap();
44
- var cacheNodeInterop = new WeakMap();
45
- return (_getRequireWildcardCache = function(nodeInterop) {
46
- return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
47
- })(nodeInterop);
48
- }
49
- function _interop_require_wildcard(obj, nodeInterop) {
50
- if (!nodeInterop && obj && obj.__esModule) {
51
- return obj;
52
- }
53
- if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
54
- return {
55
- default: obj
56
- };
57
- }
58
- var cache = _getRequireWildcardCache(nodeInterop);
59
- if (cache && cache.has(obj)) {
60
- return cache.get(obj);
61
- }
62
- var newObj = {
63
- __proto__: null
64
- };
65
- var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
66
- for(var key in obj){
67
- if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
68
- var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
69
- if (desc && (desc.get || desc.set)) {
70
- Object.defineProperty(newObj, key, desc);
71
- } else {
72
- newObj[key] = obj[key];
73
- }
74
- }
75
- }
76
- newObj.default = obj;
77
- if (cache) {
78
- cache.set(obj, newObj);
79
- }
80
- return newObj;
81
- }
82
- function parseGitFilename(filename) {
83
- // If there are no double-quotes around the string, then there are no escaped characters
84
- // to decode, so just return
85
- if (!filename.match(/^".+"$/)) {
86
- return filename;
87
- }
88
- // Need to hex encode '%' since we will be decoding the converted octal values from hex
89
- filename = filename.replace(/%/g, "%25");
90
- // Replace all instances of octal literals with percent-encoded hex (ex. '\347\275\221' -> '%E7%BD%91').
91
- // This is done because the octal literals represent UTF-8 bytes, and by converting them to percent-encoded
92
- // hex, we can use decodeURIComponent to get the Unicode chars.
93
- filename = filename.replace(/(?:\\(\d{1,3}))/g, (match, ...[octalValue, index, source])=>{
94
- // We need to make sure that the backslash is intended to escape the octal value. To do this, walk
95
- // backwards from the match to ensure that it's already escaped.
96
- const trailingBackslashes = source.slice(0, index).match(/\\*$/);
97
- return trailingBackslashes && trailingBackslashes.length > 0 && trailingBackslashes[0].length % 2 === 0 ? `%${parseInt(octalValue, 8).toString(16)}` : match;
98
- });
99
- // Finally, decode the filename and unescape the escaped UTF-8 chars
100
- return JSON.parse(decodeURIComponent(filename));
101
- }
102
- function parseGitLsTree(output) {
103
- const changes = new Map();
104
- if (output) {
105
- // A line is expected to look like:
106
- // 100644 blob 3451bccdc831cb43d7a70ed8e628dcf9c7f888c8 src/typings/tsd.d.ts
107
- // 160000 commit c5880bf5b0c6c1f2e2c43c95beeb8f0a808e8bac rushstack
108
- const gitRegex = /([0-9]{6})\s(blob|commit)\s([a-f0-9]{40})\s*(.*)/;
109
- // Note: The output of git ls-tree uses \n newlines regardless of OS.
110
- const outputLines = output.trim().split("\n");
111
- for (const line of outputLines){
112
- if (line) {
113
- // Take everything after the "100644 blob", which is just the hash and filename
114
- const matches = line.match(gitRegex);
115
- if (matches && matches[3] && matches[4]) {
116
- const hash = matches[3];
117
- const filename = parseGitFilename(matches[4]);
118
- changes.set(filename, hash);
119
- } else {
120
- throw new Error(`Cannot parse git ls-tree input: "${line}"`);
121
- }
122
- }
123
- }
124
- }
125
- return changes;
126
- }
127
- function parseGitStatus(output) {
128
- const changes = new Map();
129
- /*
130
- * Typically, output will look something like:
131
- * M temp_modules/rush-package-deps-hash/package.json
132
- * D package-deps-hash/src/index.ts
133
- */ // If there was an issue with `git ls-tree`, or there are no current changes, processOutputBlocks[1]
134
- // will be empty or undefined
135
- if (!output) {
136
- return changes;
137
- }
138
- // Note: The output of git hash-object uses \n newlines regardless of OS.
139
- const outputLines = output.trim().split("\n");
140
- for (const line of outputLines){
141
- /*
142
- * changeType is in the format of "XY" where "X" is the status of the file in the index and "Y" is the status of
143
- * the file in the working tree. Some example statuses:
144
- * - 'D' == deletion
145
- * - 'M' == modification
146
- * - 'A' == addition
147
- * - '??' == untracked
148
- * - 'R' == rename
149
- * - 'RM' == rename with modifications
150
- * - '[MARC]D' == deleted in work tree
151
- * Full list of examples: https://git-scm.com/docs/git-status#_short_format
152
- */ const match = line.match(/("(\\"|[^"])+")|(\S+\s*)/g);
153
- if (match && match.length > 1) {
154
- const [changeType, ...filenameMatches] = match;
155
- // We always care about the last filename in the filenames array. In the case of non-rename changes,
156
- // the filenames array only contains one file, so we can join all segments that were split on spaces.
157
- // In the case of rename changes, the last item in the array is the path to the file in the working tree,
158
- // which is the only one that we care about. It is also surrounded by double-quotes if spaces are
159
- // included, so no need to worry about joining different segments
160
- let lastFilename = changeType.startsWith("R") ? filenameMatches[filenameMatches.length - 1] : filenameMatches.join("");
161
- lastFilename = parseGitFilename(lastFilename);
162
- changes.set(lastFilename, changeType.trimRight());
163
- }
164
- }
165
- return changes;
166
- }
167
- function getGitHashForFiles(filesToHash, packagePath, gitPath) {
168
- const changes = new Map();
169
- if (filesToHash.length) {
170
- // Use --stdin-paths arg to pass the list of files to git in order to avoid issues with
171
- // command length
172
- const result = _execa.default.sync(gitPath || "git", [
173
- "hash-object",
174
- "--stdin-paths"
175
- ], {
176
- input: filesToHash.map((x)=>_path.resolve(packagePath, x)).join("\n")
177
- });
178
- if (result.exitCode !== 0) {
179
- throw new Error(`git hash-object exited with status ${result.exitCode}: ${result.stderr}`);
180
- }
181
- const hashStdout = result.stdout.trim();
182
- // The result of "git hash-object" will be a list of file hashes delimited by newlines
183
- const hashes = hashStdout.split("\n");
184
- if (hashes.length !== filesToHash.length) {
185
- throw new Error(`Passed ${filesToHash.length} file paths to Git to hash, but received ${hashes.length} hashes.`);
186
- }
187
- for(let i = 0; i < hashes.length; i++){
188
- const hash = hashes[i];
189
- const filePath = filesToHash[i];
190
- changes.set(filePath, hash);
191
- }
192
- }
193
- return changes;
194
- }
195
- function gitLsTree(path, gitPath) {
196
- const result = _execa.default.sync(gitPath || "git", [
197
- "ls-tree",
198
- "HEAD",
199
- "-r"
200
- ], {
201
- cwd: path
202
- });
203
- if (result.exitCode !== 0) {
204
- throw new Error(`git ls-tree exited with status ${result.exitCode}: ${result.stderr}`);
205
- }
206
- return result.stdout;
207
- }
208
- function gitStatus(path, gitPath) {
209
- /**
210
- * -s - Short format. Will be printed as 'XY PATH' or 'XY ORIG_PATH -> PATH'. Paths with non-standard
211
- * characters will be escaped using double-quotes, and non-standard characters will be backslash
212
- * escaped (ex. spaces, tabs, double-quotes)
213
- * -u - Untracked files are included
214
- *
215
- * See documentation here: https://git-scm.com/docs/git-status
216
- */ const result = _execa.default.sync(gitPath || "git", [
217
- "status",
218
- "-s",
219
- "-u",
220
- "."
221
- ], {
222
- cwd: path
223
- });
224
- if (result.exitCode !== 0) {
225
- throw new Error(`git status exited with status ${result.exitCode}: ${result.stderr}`);
226
- }
227
- return result.stdout;
228
- }
229
- function getPackageDeps(packagePath = process.cwd(), excludedPaths, gitPath) {
230
- const gitLsOutput = gitLsTree(packagePath, gitPath);
231
- // Add all the checked in hashes
232
- const result = parseGitLsTree(gitLsOutput);
233
- // Remove excluded paths
234
- if (excludedPaths) {
235
- for (const excludedPath of excludedPaths){
236
- result.delete(excludedPath);
237
- }
238
- }
239
- // Update the checked in hashes with the current repo status
240
- const gitStatusOutput = gitStatus(packagePath, gitPath);
241
- const currentlyChangedFiles = parseGitStatus(gitStatusOutput);
242
- const filesToHash = [];
243
- const excludedPathSet = new Set(excludedPaths);
244
- for (const [filename, changeType] of currentlyChangedFiles){
245
- // See comments inside parseGitStatus() for more information
246
- if (changeType === "D" || changeType.length === 2 && changeType.charAt(1) === "D") {
247
- result.delete(filename);
248
- } else {
249
- if (!excludedPathSet.has(filename)) {
250
- filesToHash.push(filename);
251
- }
252
- }
253
- }
254
- const currentlyChangedFileHashes = getGitHashForFiles(filesToHash, packagePath, gitPath);
255
- for (const [filename, hash] of currentlyChangedFileHashes){
256
- result.set(filename, hash);
257
- }
258
- return result;
259
- }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/getPackageDeps.ts"],"sourcesContent":["import * as path from \"path\";\nimport execa from \"execa\";\n\n/**\n * Parses a quoted filename sourced from the output of the \"git status\" command.\n *\n * Paths with non-standard characters will be enclosed with double-quotes, and non-standard\n * characters will be backslash escaped (ex. double-quotes, non-ASCII characters). The\n * escaped chars can be included in one of two ways:\n * - backslash-escaped chars (ex. \\\")\n * - octal encoded chars (ex. \\347)\n *\n * See documentation: https://git-scm.com/docs/git-status\n */\nexport function parseGitFilename(filename: string): string {\n // If there are no double-quotes around the string, then there are no escaped characters\n // to decode, so just return\n if (!filename.match(/^\".+\"$/)) {\n return filename;\n }\n\n // Need to hex encode '%' since we will be decoding the converted octal values from hex\n filename = filename.replace(/%/g, \"%25\");\n // Replace all instances of octal literals with percent-encoded hex (ex. '\\347\\275\\221' -> '%E7%BD%91').\n // This is done because the octal literals represent UTF-8 bytes, and by converting them to percent-encoded\n // hex, we can use decodeURIComponent to get the Unicode chars.\n filename = filename.replace(/(?:\\\\(\\d{1,3}))/g, (match, ...[octalValue, index, source]) => {\n // We need to make sure that the backslash is intended to escape the octal value. To do this, walk\n // backwards from the match to ensure that it's already escaped.\n const trailingBackslashes: RegExpMatchArray | null = (source as string).slice(0, index as number).match(/\\\\*$/);\n return trailingBackslashes && trailingBackslashes.length > 0 && trailingBackslashes[0].length % 2 === 0\n ? `%${parseInt(octalValue, 8).toString(16)}`\n : match;\n });\n\n // Finally, decode the filename and unescape the escaped UTF-8 chars\n return JSON.parse(decodeURIComponent(filename));\n}\n\n/**\n * Parses the output of the \"git ls-tree\" command\n */\nexport function parseGitLsTree(output: string): Map<string, string> {\n const changes: Map<string, string> = new Map<string, string>();\n\n if (output) {\n // A line is expected to look like:\n // 100644 blob 3451bccdc831cb43d7a70ed8e628dcf9c7f888c8 src/typings/tsd.d.ts\n // 160000 commit c5880bf5b0c6c1f2e2c43c95beeb8f0a808e8bac rushstack\n const gitRegex = /([0-9]{6})\\s(blob|commit)\\s([a-f0-9]{40})\\s*(.*)/;\n\n // Note: The output of git ls-tree uses \\n newlines regardless of OS.\n const outputLines: string[] = output.trim().split(\"\\n\");\n for (const line of outputLines) {\n if (line) {\n // Take everything after the \"100644 blob\", which is just the hash and filename\n const matches: RegExpMatchArray | null = line.match(gitRegex);\n if (matches && matches[3] && matches[4]) {\n const hash: string = matches[3];\n const filename: string = parseGitFilename(matches[4]);\n\n changes.set(filename, hash);\n } else {\n throw new Error(`Cannot parse git ls-tree input: \"${line}\"`);\n }\n }\n }\n }\n\n return changes;\n}\n\n/**\n * Parses the output of the \"git status\" command\n */\nexport function parseGitStatus(output: string): Map<string, string> {\n const changes: Map<string, string> = new Map<string, string>();\n\n /*\n * Typically, output will look something like:\n * M temp_modules/rush-package-deps-hash/package.json\n * D package-deps-hash/src/index.ts\n */\n\n // If there was an issue with `git ls-tree`, or there are no current changes, processOutputBlocks[1]\n // will be empty or undefined\n if (!output) {\n return changes;\n }\n\n // Note: The output of git hash-object uses \\n newlines regardless of OS.\n const outputLines: string[] = output.trim().split(\"\\n\");\n for (const line of outputLines) {\n /*\n * changeType is in the format of \"XY\" where \"X\" is the status of the file in the index and \"Y\" is the status of\n * the file in the working tree. Some example statuses:\n * - 'D' == deletion\n * - 'M' == modification\n * - 'A' == addition\n * - '??' == untracked\n * - 'R' == rename\n * - 'RM' == rename with modifications\n * - '[MARC]D' == deleted in work tree\n * Full list of examples: https://git-scm.com/docs/git-status#_short_format\n */\n const match: RegExpMatchArray | null = line.match(/(\"(\\\\\"|[^\"])+\")|(\\S+\\s*)/g);\n\n if (match && match.length > 1) {\n const [changeType, ...filenameMatches] = match;\n\n // We always care about the last filename in the filenames array. In the case of non-rename changes,\n // the filenames array only contains one file, so we can join all segments that were split on spaces.\n // In the case of rename changes, the last item in the array is the path to the file in the working tree,\n // which is the only one that we care about. It is also surrounded by double-quotes if spaces are\n // included, so no need to worry about joining different segments\n let lastFilename: string = changeType.startsWith(\"R\") ? filenameMatches[filenameMatches.length - 1] : filenameMatches.join(\"\");\n lastFilename = parseGitFilename(lastFilename);\n\n changes.set(lastFilename, changeType.trimRight());\n }\n }\n\n return changes;\n}\n\n/**\n * Takes a list of files and returns the current git hashes for them\n *\n * @public\n */\nexport function getGitHashForFiles(filesToHash: string[], packagePath: string, gitPath?: string): Map<string, string> {\n const changes: Map<string, string> = new Map<string, string>();\n\n if (filesToHash.length) {\n // Use --stdin-paths arg to pass the list of files to git in order to avoid issues with\n // command length\n const result = execa.sync(gitPath || \"git\", [\"hash-object\", \"--stdin-paths\"], {\n input: filesToHash.map((x) => path.resolve(packagePath, x)).join(\"\\n\"),\n });\n\n if (result.exitCode !== 0) {\n throw new Error(`git hash-object exited with status ${result.exitCode}: ${result.stderr}`);\n }\n\n const hashStdout: string = result.stdout.trim();\n\n // The result of \"git hash-object\" will be a list of file hashes delimited by newlines\n const hashes: string[] = hashStdout.split(\"\\n\");\n\n if (hashes.length !== filesToHash.length) {\n throw new Error(`Passed ${filesToHash.length} file paths to Git to hash, but received ${hashes.length} hashes.`);\n }\n\n for (let i = 0; i < hashes.length; i++) {\n const hash: string = hashes[i];\n const filePath: string = filesToHash[i];\n changes.set(filePath, hash);\n }\n }\n\n return changes;\n}\n\n/**\n * Executes \"git ls-tree\" in a folder\n */\nexport function gitLsTree(path: string, gitPath?: string): string {\n const result = execa.sync(gitPath || \"git\", [\"ls-tree\", \"HEAD\", \"-r\"], {\n cwd: path,\n });\n\n if (result.exitCode !== 0) {\n throw new Error(`git ls-tree exited with status ${result.exitCode}: ${result.stderr}`);\n }\n\n return result.stdout;\n}\n\n/**\n * Executes \"git status\" in a folder\n */\nexport function gitStatus(path: string, gitPath?: string): string {\n /**\n * -s - Short format. Will be printed as 'XY PATH' or 'XY ORIG_PATH -> PATH'. Paths with non-standard\n * characters will be escaped using double-quotes, and non-standard characters will be backslash\n * escaped (ex. spaces, tabs, double-quotes)\n * -u - Untracked files are included\n *\n * See documentation here: https://git-scm.com/docs/git-status\n */\n const result = execa.sync(gitPath || \"git\", [\"status\", \"-s\", \"-u\", \".\"], {\n cwd: path,\n });\n\n if (result.exitCode !== 0) {\n throw new Error(`git status exited with status ${result.exitCode}: ${result.stderr}`);\n }\n\n return result.stdout;\n}\n\n/**\n * Builds an object containing hashes for the files under the specified `packagePath` folder.\n * @param packagePath - The folder path to derive the package dependencies from. This is typically the folder\n * containing package.json. If omitted, the default value is the current working directory.\n * @param excludedPaths - An optional array of file path exclusions. If a file should be omitted from the list\n * of dependencies, use this to exclude it.\n * @returns the package-deps.json file content\n *\n * @public\n */\nexport function getPackageDeps(packagePath: string = process.cwd(), excludedPaths?: string[], gitPath?: string): Map<string, string> {\n const gitLsOutput: string = gitLsTree(packagePath, gitPath);\n\n // Add all the checked in hashes\n const result: Map<string, string> = parseGitLsTree(gitLsOutput);\n\n // Remove excluded paths\n if (excludedPaths) {\n for (const excludedPath of excludedPaths) {\n result.delete(excludedPath);\n }\n }\n\n // Update the checked in hashes with the current repo status\n const gitStatusOutput: string = gitStatus(packagePath, gitPath);\n const currentlyChangedFiles: Map<string, string> = parseGitStatus(gitStatusOutput);\n const filesToHash: string[] = [];\n const excludedPathSet: Set<string> = new Set<string>(excludedPaths);\n for (const [filename, changeType] of currentlyChangedFiles) {\n // See comments inside parseGitStatus() for more information\n if (changeType === \"D\" || (changeType.length === 2 && changeType.charAt(1) === \"D\")) {\n result.delete(filename);\n } else {\n if (!excludedPathSet.has(filename)) {\n filesToHash.push(filename);\n }\n }\n }\n\n const currentlyChangedFileHashes: Map<string, string> = getGitHashForFiles(filesToHash, packagePath, gitPath);\n for (const [filename, hash] of currentlyChangedFileHashes) {\n result.set(filename, hash);\n }\n\n return result;\n}\n"],"names":["getGitHashForFiles","getPackageDeps","gitLsTree","gitStatus","parseGitFilename","parseGitLsTree","parseGitStatus","filename","match","replace","octalValue","index","source","trailingBackslashes","slice","length","parseInt","toString","JSON","parse","decodeURIComponent","output","changes","Map","gitRegex","outputLines","trim","split","line","matches","hash","set","Error","changeType","filenameMatches","lastFilename","startsWith","join","trimRight","filesToHash","packagePath","gitPath","result","execa","sync","input","map","x","path","resolve","exitCode","stderr","hashStdout","stdout","hashes","i","filePath","cwd","process","excludedPaths","gitLsOutput","excludedPath","delete","gitStatusOutput","currentlyChangedFiles","excludedPathSet","Set","charAt","has","push","currentlyChangedFileHashes"],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- import { type PackageInfos, type ParsedLock } from "workspace-tools";
2
- type Dependencies = Record<string, string>;
3
- export type DependencyQueue = [name: string, versionRange: string][];
4
- export type DependencySpec = `${string}@${string}`;
5
- /** Filter the `dependencies` object to only contain deps from outside the repo. */
6
- export declare function _filterExternalDependencies(dependencies: Dependencies, packageInfos: PackageInfos): Dependencies;
7
- export declare function _addToQueue(dependencies: Dependencies | undefined, done: Set<DependencySpec>, queue: DependencyQueue): void;
8
- /**
9
- * Resolve versions for external (outside repo) dependencies and their transitive dependencies
10
- * using the lock file.
11
- * @returns Array of strings in the format `name@version`
12
- */
13
- export declare function resolveExternalDependencies(allDependencies: Dependencies, packageInfos: PackageInfos, lockInfo: ParsedLock): DependencySpec[];
14
- export {};
@@ -1,72 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", {
3
- value: true
4
- });
5
- function _export(target, all) {
6
- for(var name in all)Object.defineProperty(target, name, {
7
- enumerable: true,
8
- get: Object.getOwnPropertyDescriptor(all, name).get
9
- });
10
- }
11
- _export(exports, {
12
- get _addToQueue () {
13
- return _addToQueue;
14
- },
15
- get _filterExternalDependencies () {
16
- return _filterExternalDependencies;
17
- },
18
- get resolveExternalDependencies () {
19
- return resolveExternalDependencies;
20
- }
21
- });
22
- const _workspacetools = require("workspace-tools");
23
- function _filterExternalDependencies(dependencies, packageInfos) {
24
- const externalDependencies = {};
25
- for (const [name, versionRange] of Object.entries(dependencies)){
26
- if (!packageInfos[name]) {
27
- externalDependencies[name] = versionRange;
28
- }
29
- }
30
- return externalDependencies;
31
- }
32
- function isInQueue(queue, key) {
33
- return queue.some(([name, versionRange])=>`${name}@${versionRange}` === key);
34
- }
35
- function _addToQueue(dependencies, done, queue) {
36
- if (dependencies) {
37
- for (const [name, versionRange] of Object.entries(dependencies)){
38
- const versionRangeSignature = `${name}@${versionRange}`;
39
- if (!done.has(versionRangeSignature) && !isInQueue(queue, versionRangeSignature)) {
40
- queue.push([
41
- name,
42
- versionRange
43
- ]);
44
- }
45
- }
46
- }
47
- }
48
- function resolveExternalDependencies(allDependencies, packageInfos, lockInfo) {
49
- const externalDependencies = _filterExternalDependencies(allDependencies, packageInfos);
50
- const done = new Set();
51
- const doneRange = new Set();
52
- const queue = Object.entries(externalDependencies);
53
- while(queue.length > 0){
54
- const next = queue.shift();
55
- if (!next) {
56
- continue;
57
- }
58
- const [name, versionRange] = next;
59
- doneRange.add(`${name}@${versionRange}`);
60
- const lockFileResult = (0, _workspacetools.queryLockFile)(name, versionRange, lockInfo);
61
- if (lockFileResult) {
62
- const { version, dependencies } = lockFileResult;
63
- _addToQueue(dependencies, doneRange, queue);
64
- done.add(`${name}@${version}`);
65
- } else {
66
- done.add(`${name}@${versionRange}`);
67
- }
68
- }
69
- return [
70
- ...done
71
- ];
72
- }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/resolveExternalDependencies.ts"],"sourcesContent":["import { queryLockFile, type PackageInfos, type ParsedLock } from \"workspace-tools\";\n\ntype Dependencies = Record<string, string>;\n\nexport type DependencyQueue = [name: string, versionRange: string][];\n\nexport type DependencySpec = `${string}@${string}`;\n\n/** Filter the `dependencies` object to only contain deps from outside the repo. */\nexport function _filterExternalDependencies(dependencies: Dependencies, packageInfos: PackageInfos): Dependencies {\n const externalDependencies: Dependencies = {};\n\n for (const [name, versionRange] of Object.entries(dependencies)) {\n if (!packageInfos[name]) {\n externalDependencies[name] = versionRange;\n }\n }\n\n return externalDependencies;\n}\n\nfunction isInQueue(queue: DependencyQueue, key: string): boolean {\n return queue.some(([name, versionRange]) => `${name}@${versionRange}` === key);\n}\n\nexport function _addToQueue(dependencies: Dependencies | undefined, done: Set<DependencySpec>, queue: DependencyQueue): void {\n if (dependencies) {\n for (const [name, versionRange] of Object.entries(dependencies)) {\n const versionRangeSignature = `${name}@${versionRange}` as const;\n\n if (!done.has(versionRangeSignature) && !isInQueue(queue, versionRangeSignature)) {\n queue.push([name, versionRange]);\n }\n }\n }\n}\n\n/**\n * Resolve versions for external (outside repo) dependencies and their transitive dependencies\n * using the lock file.\n * @returns Array of strings in the format `name@version`\n */\nexport function resolveExternalDependencies(\n allDependencies: Dependencies,\n packageInfos: PackageInfos,\n lockInfo: ParsedLock\n): DependencySpec[] {\n const externalDependencies = _filterExternalDependencies(allDependencies, packageInfos);\n\n const done = new Set<DependencySpec>();\n const doneRange = new Set<DependencySpec>();\n const queue: DependencyQueue = Object.entries(externalDependencies);\n\n while (queue.length > 0) {\n const next = queue.shift();\n\n if (!next) {\n continue;\n }\n\n const [name, versionRange] = next;\n doneRange.add(`${name}@${versionRange}`);\n\n const lockFileResult = queryLockFile(name, versionRange, lockInfo);\n\n if (lockFileResult) {\n const { version, dependencies } = lockFileResult;\n\n _addToQueue(dependencies, doneRange, queue);\n done.add(`${name}@${version}`);\n } else {\n done.add(`${name}@${versionRange}`);\n }\n }\n\n return [...done];\n}\n"],"names":["_addToQueue","_filterExternalDependencies","resolveExternalDependencies","dependencies","packageInfos","externalDependencies","name","versionRange","Object","entries","isInQueue","queue","key","some","done","versionRangeSignature","has","push","allDependencies","lockInfo","Set","doneRange","length","next","shift","add","lockFileResult","queryLockFile","version"],"mappings":";;;;;;;;;;;QAyBgBA;eAAAA;;QAhBAC;eAAAA;;QAiCAC;eAAAA;;;gCA1CkD;AAS3D,SAASD,4BAA4BE,YAA0B,EAAEC,YAA0B;IAChG,MAAMC,uBAAqC,CAAC;IAE5C,KAAK,MAAM,CAACC,MAAMC,aAAa,IAAIC,OAAOC,OAAO,CAACN,cAAe;QAC/D,IAAI,CAACC,YAAY,CAACE,KAAK,EAAE;YACvBD,oBAAoB,CAACC,KAAK,GAAGC;QAC/B;IACF;IAEA,OAAOF;AACT;AAEA,SAASK,UAAUC,KAAsB,EAAEC,GAAW;IACpD,OAAOD,MAAME,IAAI,CAAC,CAAC,CAACP,MAAMC,aAAa,GAAK,GAAGD,KAAK,CAAC,EAAEC,cAAc,KAAKK;AAC5E;AAEO,SAASZ,YAAYG,YAAsC,EAAEW,IAAyB,EAAEH,KAAsB;IACnH,IAAIR,cAAc;QAChB,KAAK,MAAM,CAACG,MAAMC,aAAa,IAAIC,OAAOC,OAAO,CAACN,cAAe;YAC/D,MAAMY,wBAAwB,GAAGT,KAAK,CAAC,EAAEC,cAAc;YAEvD,IAAI,CAACO,KAAKE,GAAG,CAACD,0BAA0B,CAACL,UAAUC,OAAOI,wBAAwB;gBAChFJ,MAAMM,IAAI,CAAC;oBAACX;oBAAMC;iBAAa;YACjC;QACF;IACF;AACF;AAOO,SAASL,4BACdgB,eAA6B,EAC7Bd,YAA0B,EAC1Be,QAAoB;IAEpB,MAAMd,uBAAuBJ,4BAA4BiB,iBAAiBd;IAE1E,MAAMU,OAAO,IAAIM;IACjB,MAAMC,YAAY,IAAID;IACtB,MAAMT,QAAyBH,OAAOC,OAAO,CAACJ;IAE9C,MAAOM,MAAMW,MAAM,GAAG,EAAG;QACvB,MAAMC,OAAOZ,MAAMa,KAAK;QAExB,IAAI,CAACD,MAAM;YACT;QACF;QAEA,MAAM,CAACjB,MAAMC,aAAa,GAAGgB;QAC7BF,UAAUI,GAAG,CAAC,GAAGnB,KAAK,CAAC,EAAEC,cAAc;QAEvC,MAAMmB,iBAAiBC,IAAAA,6BAAa,EAACrB,MAAMC,cAAcY;QAEzD,IAAIO,gBAAgB;YAClB,MAAM,EAAEE,OAAO,EAAEzB,YAAY,EAAE,GAAGuB;YAElC1B,YAAYG,cAAckB,WAAWV;YACrCG,KAAKW,GAAG,CAAC,GAAGnB,KAAK,CAAC,EAAEsB,SAAS;QAC/B,OAAO;YACLd,KAAKW,GAAG,CAAC,GAAGnB,KAAK,CAAC,EAAEC,cAAc;QACpC;IACF;IAEA,OAAO;WAAIO;KAAK;AAClB"}