@lage-run/hasher 1.0.7 → 1.1.1
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/CHANGELOG.json +46 -1
- package/CHANGELOG.md +18 -2
- package/README.md +2 -1
- package/lib/FileHasher.js +12 -12
- package/lib/PackageTree.d.ts +5 -9
- package/lib/PackageTree.js +54 -75
- package/lib/TargetHasher.d.ts +1 -1
- package/lib/TargetHasher.js +24 -27
- package/package.json +3 -5
package/CHANGELOG.json
CHANGED
|
@@ -2,7 +2,52 @@
|
|
|
2
2
|
"name": "@lage-run/hasher",
|
|
3
3
|
"entries": [
|
|
4
4
|
{
|
|
5
|
-
"date": "
|
|
5
|
+
"date": "Sun, 05 May 2024 22:55:31 GMT",
|
|
6
|
+
"version": "1.1.1",
|
|
7
|
+
"tag": "@lage-run/hasher_v1.1.1",
|
|
8
|
+
"comments": {
|
|
9
|
+
"patch": [
|
|
10
|
+
{
|
|
11
|
+
"author": "kchau@microsoft.com",
|
|
12
|
+
"package": "@lage-run/hasher",
|
|
13
|
+
"commit": "1e36de04ab83fc0cde38062fc1543e4b12902166",
|
|
14
|
+
"comment": "fixing hashing issues related to rust panic"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"date": "Wed, 17 Apr 2024 23:20:47 GMT",
|
|
21
|
+
"version": "1.1.0",
|
|
22
|
+
"tag": "@lage-run/hasher_v1.1.0",
|
|
23
|
+
"comments": {
|
|
24
|
+
"none": [
|
|
25
|
+
{
|
|
26
|
+
"author": "elcraig@microsoft.com",
|
|
27
|
+
"package": "@lage-run/hasher",
|
|
28
|
+
"commit": "fb4fcb8419cc778210104d7d04102fc95df13d5b",
|
|
29
|
+
"comment": "Update formatting"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"date": "Fri, 15 Mar 2024 04:35:11 GMT",
|
|
36
|
+
"version": "1.1.0",
|
|
37
|
+
"tag": "@lage-run/hasher_v1.1.0",
|
|
38
|
+
"comments": {
|
|
39
|
+
"minor": [
|
|
40
|
+
{
|
|
41
|
+
"author": "kchau@microsoft.com",
|
|
42
|
+
"package": "@lage-run/hasher",
|
|
43
|
+
"commit": "71283d4af8888454c953e5228c97bfbb471c15ba",
|
|
44
|
+
"comment": "perf optimizations"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"date": "Thu, 21 Dec 2023 09:49:09 GMT",
|
|
6
51
|
"version": "1.0.7",
|
|
7
52
|
"tag": "@lage-run/hasher_v1.0.7",
|
|
8
53
|
"comments": {
|
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
# Change Log - @lage-run/hasher
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Sun, 05 May 2024 22:55:31 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 1.1.1
|
|
8
|
+
|
|
9
|
+
Sun, 05 May 2024 22:55:31 GMT
|
|
10
|
+
|
|
11
|
+
### Patches
|
|
12
|
+
|
|
13
|
+
- fixing hashing issues related to rust panic (kchau@microsoft.com)
|
|
14
|
+
|
|
15
|
+
## 1.1.0
|
|
16
|
+
|
|
17
|
+
Fri, 15 Mar 2024 04:35:11 GMT
|
|
18
|
+
|
|
19
|
+
### Minor changes
|
|
20
|
+
|
|
21
|
+
- perf optimizations (kchau@microsoft.com)
|
|
22
|
+
|
|
7
23
|
## 1.0.7
|
|
8
24
|
|
|
9
|
-
Thu, 21 Dec 2023 09:
|
|
25
|
+
Thu, 21 Dec 2023 09:49:09 GMT
|
|
10
26
|
|
|
11
27
|
### Patches
|
|
12
28
|
|
package/README.md
CHANGED
|
@@ -1,2 +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.
|
package/lib/FileHasher.js
CHANGED
|
@@ -106,12 +106,13 @@ class FileHasher {
|
|
|
106
106
|
input: inputStream,
|
|
107
107
|
crlfDelay: Infinity
|
|
108
108
|
});
|
|
109
|
+
let info = [];
|
|
109
110
|
rl.on("line", (line)=>{
|
|
110
|
-
|
|
111
|
-
_class_private_field_get(this, _store)[
|
|
112
|
-
mtime: BigInt(
|
|
113
|
-
size: parseInt(
|
|
114
|
-
hash
|
|
111
|
+
info = line.split("\0");
|
|
112
|
+
_class_private_field_get(this, _store)[info[0]] = {
|
|
113
|
+
mtime: BigInt(info[1]),
|
|
114
|
+
size: parseInt(info[2]),
|
|
115
|
+
hash: info[3]
|
|
115
116
|
};
|
|
116
117
|
});
|
|
117
118
|
inputStream.on("end", ()=>{
|
|
@@ -124,11 +125,10 @@ class FileHasher {
|
|
|
124
125
|
_gracefulfs.default.mkdirSync(_path.default.dirname(_class_private_field_get(this, _manifestFile)), {
|
|
125
126
|
recursive: true
|
|
126
127
|
});
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
outputStream.end();
|
|
128
|
+
const outputLines = Object.entries(_class_private_field_get(this, _store)).map(([relativePath, info])=>{
|
|
129
|
+
return `${relativePath}\0${info.mtime.toString()}\0${info.size.toString()}\0${info.hash}`;
|
|
130
|
+
});
|
|
131
|
+
_gracefulfs.default.writeFileSync(_class_private_field_get(this, _manifestFile), outputLines.join("\n"), "utf-8");
|
|
132
132
|
}
|
|
133
133
|
hash(files) {
|
|
134
134
|
const hashes = {};
|
|
@@ -156,9 +156,9 @@ class FileHasher {
|
|
|
156
156
|
_class_private_field_get(this, _store)[file] = {
|
|
157
157
|
mtime: stat.mtimeMs,
|
|
158
158
|
size: Number(stat.size),
|
|
159
|
-
hash
|
|
159
|
+
hash: hash ?? ""
|
|
160
160
|
};
|
|
161
|
-
hashes[file] = hash;
|
|
161
|
+
hashes[file] = hash ?? "";
|
|
162
162
|
}
|
|
163
163
|
return hashes;
|
|
164
164
|
}
|
package/lib/PackageTree.d.ts
CHANGED
|
@@ -1,20 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
export interface PackageTreeOptions {
|
|
1
|
+
export interface LocalPackageTreeOptions {
|
|
3
2
|
root: string;
|
|
4
|
-
packageInfos: PackageInfos;
|
|
5
3
|
includeUntracked: boolean;
|
|
6
4
|
}
|
|
7
5
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* TODO: add a watcher to make sure the tree is up to date during a "watched" run.
|
|
6
|
+
* Keeps a data structure to quickly find all files in a package.
|
|
11
7
|
*/
|
|
12
8
|
export declare class PackageTree {
|
|
13
9
|
#private;
|
|
14
10
|
private options;
|
|
15
|
-
constructor(options:
|
|
11
|
+
constructor(options: LocalPackageTreeOptions);
|
|
16
12
|
reset(): void;
|
|
17
13
|
initialize(): Promise<void>;
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
findFilesInPath(packagePath: string, patterns: string[]): Promise<string[]>;
|
|
15
|
+
cleanup(): void;
|
|
20
16
|
}
|
package/lib/PackageTree.js
CHANGED
|
@@ -11,7 +11,6 @@ Object.defineProperty(exports, "PackageTree", {
|
|
|
11
11
|
const _execa = /*#__PURE__*/ _interop_require_default(require("execa"));
|
|
12
12
|
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
|
13
13
|
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
|
|
14
|
-
const _micromatch = /*#__PURE__*/ _interop_require_default(require("micromatch"));
|
|
15
14
|
function _check_private_redeclaration(obj, privateCollection) {
|
|
16
15
|
if (privateCollection.has(obj)) {
|
|
17
16
|
throw new TypeError("Cannot initialize the same private elements twice on an object");
|
|
@@ -52,6 +51,16 @@ function _class_private_field_set(receiver, privateMap, value) {
|
|
|
52
51
|
_class_apply_descriptor_set(receiver, descriptor, value);
|
|
53
52
|
return value;
|
|
54
53
|
}
|
|
54
|
+
function _class_private_method_get(receiver, privateSet, fn) {
|
|
55
|
+
if (!privateSet.has(receiver)) {
|
|
56
|
+
throw new TypeError("attempted to get private field on non-instance");
|
|
57
|
+
}
|
|
58
|
+
return fn;
|
|
59
|
+
}
|
|
60
|
+
function _class_private_method_init(obj, privateSet) {
|
|
61
|
+
_check_private_redeclaration(obj, privateSet);
|
|
62
|
+
privateSet.add(obj);
|
|
63
|
+
}
|
|
55
64
|
function _define_property(obj, key, value) {
|
|
56
65
|
if (key in obj) {
|
|
57
66
|
Object.defineProperty(obj, key, {
|
|
@@ -70,7 +79,7 @@ function _interop_require_default(obj) {
|
|
|
70
79
|
default: obj
|
|
71
80
|
};
|
|
72
81
|
}
|
|
73
|
-
var _tree = /*#__PURE__*/ new WeakMap(), _packageFiles = /*#__PURE__*/ new WeakMap(), _memoizedPackageFiles = /*#__PURE__*/ new WeakMap();
|
|
82
|
+
var _tree = /*#__PURE__*/ new WeakMap(), _packageFiles = /*#__PURE__*/ new WeakMap(), _memoizedPackageFiles = /*#__PURE__*/ new WeakMap(), _findFilesFromGitTree = /*#__PURE__*/ new WeakSet();
|
|
74
83
|
class PackageTree {
|
|
75
84
|
reset() {
|
|
76
85
|
_class_private_field_set(this, _tree, {});
|
|
@@ -78,86 +87,19 @@ class PackageTree {
|
|
|
78
87
|
_class_private_field_set(this, _memoizedPackageFiles, {});
|
|
79
88
|
}
|
|
80
89
|
async initialize() {
|
|
81
|
-
const { root , includeUntracked , packageInfos } = this.options;
|
|
82
90
|
this.reset();
|
|
83
|
-
// Generate path tree of all packages in workspace (scale: ~2000 * ~3)
|
|
84
|
-
for (const info of Object.values(packageInfos)){
|
|
85
|
-
const packagePath = _path.default.dirname(info.packageJsonPath);
|
|
86
|
-
const pathParts = _path.default.relative(root, packagePath).split(/[\\/]/);
|
|
87
|
-
let currentNode = _class_private_field_get(this, _tree);
|
|
88
|
-
for (const part of pathParts){
|
|
89
|
-
currentNode[part] = currentNode[part] || {};
|
|
90
|
-
currentNode = currentNode[part];
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// Get all files in the workspace (scale: ~2000) according to git
|
|
94
|
-
const lsFilesResults = await (0, _execa.default)("git", [
|
|
95
|
-
"ls-files",
|
|
96
|
-
"-z"
|
|
97
|
-
], {
|
|
98
|
-
cwd: root
|
|
99
|
-
});
|
|
100
|
-
if (lsFilesResults.exitCode === 0) {
|
|
101
|
-
const files = lsFilesResults.stdout.split("\0").filter((f)=>Boolean(f) && _fs.default.existsSync(_path.default.join(root, f)));
|
|
102
|
-
this.addToPackageTree(files);
|
|
103
|
-
}
|
|
104
|
-
if (includeUntracked) {
|
|
105
|
-
// Also get all untracked files in the workspace according to git
|
|
106
|
-
const lsOtherResults = await (0, _execa.default)("git", [
|
|
107
|
-
"ls-files",
|
|
108
|
-
"-o",
|
|
109
|
-
"--exclude-standard"
|
|
110
|
-
], {
|
|
111
|
-
cwd: root
|
|
112
|
-
});
|
|
113
|
-
if (lsOtherResults.exitCode === 0) {
|
|
114
|
-
const files = lsOtherResults.stdout.split("\0").filter(Boolean);
|
|
115
|
-
this.addToPackageTree(files);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
91
|
}
|
|
119
|
-
async
|
|
120
|
-
|
|
121
|
-
const packageFiles = _class_private_field_get(this, _packageFiles);
|
|
122
|
-
for (const entry of filePaths){
|
|
123
|
-
const pathParts = entry.split(/[\\/]/);
|
|
124
|
-
let node = _class_private_field_get(this, _tree);
|
|
125
|
-
const packagePathParts = [];
|
|
126
|
-
for (const part of pathParts){
|
|
127
|
-
if (node[part]) {
|
|
128
|
-
node = node[part];
|
|
129
|
-
packagePathParts.push(part);
|
|
130
|
-
} else {
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
const packageRoot = packagePathParts.join("/");
|
|
135
|
-
packageFiles[packageRoot] = packageFiles[packageRoot] || [];
|
|
136
|
-
packageFiles[packageRoot].push(entry);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
getPackageFiles(packageName, patterns) {
|
|
140
|
-
const { root , packageInfos } = this.options;
|
|
141
|
-
const packagePath = _path.default.relative(root, _path.default.dirname(packageInfos[packageName].packageJsonPath)).replace(/\\/g, "/");
|
|
142
|
-
const packageFiles = _class_private_field_get(this, _packageFiles)[packagePath];
|
|
143
|
-
if (!packageFiles) {
|
|
144
|
-
return [];
|
|
145
|
-
}
|
|
146
|
-
const key = `${packageName}\0${patterns.join("\0")}`;
|
|
92
|
+
async findFilesInPath(packagePath, patterns) {
|
|
93
|
+
const key = `${packagePath}\0${patterns.join("\0")}`;
|
|
147
94
|
if (!_class_private_field_get(this, _memoizedPackageFiles)[key]) {
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
return `!${_path.default.join(packagePath, pattern.slice(1)).replace(/\\/g, "/")}`;
|
|
151
|
-
}
|
|
152
|
-
return _path.default.join(packagePath, pattern).replace(/\\/g, "/");
|
|
153
|
-
});
|
|
154
|
-
_class_private_field_get(this, _memoizedPackageFiles)[key] = (0, _micromatch.default)(packageFiles, packagePatterns, {
|
|
155
|
-
dot: true
|
|
156
|
-
});
|
|
95
|
+
const files = (await _class_private_method_get(this, _findFilesFromGitTree, findFilesFromGitTree).call(this, packagePath, patterns)).map((f)=>_path.default.join(packagePath, f));
|
|
96
|
+
_class_private_field_get(this, _memoizedPackageFiles)[key] = files;
|
|
157
97
|
}
|
|
158
98
|
return _class_private_field_get(this, _memoizedPackageFiles)[key];
|
|
159
99
|
}
|
|
100
|
+
cleanup() {}
|
|
160
101
|
constructor(options){
|
|
102
|
+
_class_private_method_init(this, _findFilesFromGitTree);
|
|
161
103
|
_define_property(this, "options", void 0);
|
|
162
104
|
_class_private_field_init(this, _tree, {
|
|
163
105
|
writable: true,
|
|
@@ -177,3 +119,40 @@ class PackageTree {
|
|
|
177
119
|
_class_private_field_set(this, _memoizedPackageFiles, {});
|
|
178
120
|
}
|
|
179
121
|
}
|
|
122
|
+
async function findFilesFromGitTree(packagePath, patterns) {
|
|
123
|
+
const { includeUntracked } = this.options;
|
|
124
|
+
const cwd = _path.default.isAbsolute(packagePath) ? packagePath : _path.default.join(this.options.root, packagePath);
|
|
125
|
+
const trackedPromise = (0, _execa.default)("git", [
|
|
126
|
+
"ls-files",
|
|
127
|
+
"-z",
|
|
128
|
+
...patterns.filter((p)=>!p.startsWith("!")),
|
|
129
|
+
...patterns.filter((p)=>p.startsWith("!")).map((p)=>`:!:${p.slice(1)}`)
|
|
130
|
+
], {
|
|
131
|
+
cwd
|
|
132
|
+
}).then((lsFilesResults)=>{
|
|
133
|
+
if (lsFilesResults.exitCode === 0) {
|
|
134
|
+
return lsFilesResults.stdout.split("\0").filter((f)=>Boolean(f) && _fs.default.existsSync(_path.default.join(cwd, f)));
|
|
135
|
+
}
|
|
136
|
+
return [];
|
|
137
|
+
});
|
|
138
|
+
const untrackedPromise = includeUntracked ? (0, _execa.default)("git", [
|
|
139
|
+
"ls-files",
|
|
140
|
+
"-z",
|
|
141
|
+
"-o",
|
|
142
|
+
"--exclude-standard",
|
|
143
|
+
...patterns.filter((p)=>!p.startsWith("!")),
|
|
144
|
+
...patterns.filter((p)=>p.startsWith("!")).map((p)=>`:!:${p.slice(1)}`)
|
|
145
|
+
], {
|
|
146
|
+
cwd
|
|
147
|
+
}).then((lsOtherResults)=>{
|
|
148
|
+
if (lsOtherResults.exitCode === 0) {
|
|
149
|
+
return lsOtherResults.stdout.split("\0").filter((f)=>Boolean(f));
|
|
150
|
+
}
|
|
151
|
+
return [];
|
|
152
|
+
}) : Promise.resolve([]);
|
|
153
|
+
const [trackedFiles, untrackedFiles] = await Promise.all([
|
|
154
|
+
trackedPromise,
|
|
155
|
+
untrackedPromise
|
|
156
|
+
]);
|
|
157
|
+
return trackedFiles.concat(untrackedFiles);
|
|
158
|
+
}
|
package/lib/TargetHasher.d.ts
CHANGED
|
@@ -32,7 +32,7 @@ export declare class TargetHasher {
|
|
|
32
32
|
private options;
|
|
33
33
|
logger: Logger | undefined;
|
|
34
34
|
fileHasher: FileHasher;
|
|
35
|
-
packageTree: PackageTree
|
|
35
|
+
packageTree: PackageTree;
|
|
36
36
|
initializedPromise: Promise<unknown> | undefined;
|
|
37
37
|
packageInfos: PackageInfos;
|
|
38
38
|
workspaceInfo: WorkspaceInfo | undefined;
|
package/lib/TargetHasher.js
CHANGED
|
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "TargetHasher", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _globhasher = require("glob-hasher");
|
|
12
|
-
const _fastglob = /*#__PURE__*/ _interop_require_default(require("fast-glob"));
|
|
13
12
|
const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
|
|
14
13
|
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
|
|
15
14
|
const _workspacetools = require("workspace-tools");
|
|
@@ -109,26 +108,19 @@ class TargetHasher {
|
|
|
109
108
|
await this.initializedPromise;
|
|
110
109
|
return;
|
|
111
110
|
}
|
|
112
|
-
this.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
this.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// TODO: (optimization) false if process.env.TF_BUILD || process.env.CI
|
|
126
|
-
includeUntracked: true
|
|
127
|
-
});
|
|
128
|
-
return this.packageTree.initialize();
|
|
129
|
-
}),
|
|
130
|
-
(0, _workspacetools.parseLockFile)(root).then((lockInfo)=>this.lockInfo = lockInfo)
|
|
131
|
-
]);
|
|
111
|
+
this.workspaceInfo = (0, _workspacetools.getWorkspaces)(root);
|
|
112
|
+
this.packageInfos = this.getPackageInfos(this.workspaceInfo);
|
|
113
|
+
this.dependencyMap = (0, _workspacetools.createDependencyMap)(this.packageInfos, {
|
|
114
|
+
withDevDependencies: true,
|
|
115
|
+
withPeerDependencies: false
|
|
116
|
+
});
|
|
117
|
+
const finderInitPromise = this.packageTree.initialize();
|
|
118
|
+
this.initializedPromise = finderInitPromise.then(()=>{
|
|
119
|
+
return Promise.all([
|
|
120
|
+
this.fileHasher.readManifest().then(()=>environmentGlob.length > 0 ? this.packageTree.findFilesInPath(root, environmentGlob) : []).then((files)=>this.fileHasher.hash(files)).then((hash)=>this.globalInputsHash = hash),
|
|
121
|
+
(0, _workspacetools.parseLockFile)(root).then((lockInfo)=>this.lockInfo = lockInfo)
|
|
122
|
+
]);
|
|
123
|
+
});
|
|
132
124
|
await this.initializedPromise;
|
|
133
125
|
if (this.logger !== undefined) {
|
|
134
126
|
const globalInputsHash = (0, _hashStrings.hashStrings)(Object.values(this.globalInputsHash ?? {}));
|
|
@@ -145,13 +137,11 @@ class TargetHasher {
|
|
|
145
137
|
if (!target.inputs) {
|
|
146
138
|
throw new Error("Root-level targets must have `inputs` defined if it has cache enabled.");
|
|
147
139
|
}
|
|
148
|
-
const files = await (
|
|
149
|
-
cwd: root
|
|
150
|
-
});
|
|
140
|
+
const files = await this.packageTree.findFilesInPath(root, target.inputs);
|
|
151
141
|
const fileFashes = (0, _globhasher.hash)(files, {
|
|
152
142
|
cwd: root
|
|
153
143
|
}) ?? {};
|
|
154
|
-
const hashes = Object.values(fileFashes);
|
|
144
|
+
const hashes = Object.values(fileFashes).filter((hash)=>hash !== undefined && hash !== null);
|
|
155
145
|
return (0, _hashStrings.hashStrings)(hashes);
|
|
156
146
|
}
|
|
157
147
|
// 1. add hash of target's inputs
|
|
@@ -175,7 +165,9 @@ class TargetHasher {
|
|
|
175
165
|
const packagePatterns = this.expandInputPatterns(inputs, target);
|
|
176
166
|
const files = [];
|
|
177
167
|
for (const [pkg, patterns] of Object.entries(packagePatterns)){
|
|
178
|
-
const
|
|
168
|
+
const { root } = this.options;
|
|
169
|
+
const packagePath = _path.default.relative(root, _path.default.dirname(this.packageInfos[pkg].packageJsonPath)).replace(/\\/g, "/");
|
|
170
|
+
const packageFiles = await this.packageTree.findFilesInPath(packagePath, patterns);
|
|
179
171
|
files.push(...packageFiles);
|
|
180
172
|
}
|
|
181
173
|
const fileHashes = this.fileHasher.hash(files) ?? {}; // this list is sorted by file name
|
|
@@ -197,7 +189,8 @@ class TargetHasher {
|
|
|
197
189
|
return hashString;
|
|
198
190
|
}
|
|
199
191
|
async cleanup() {
|
|
200
|
-
|
|
192
|
+
this.packageTree.cleanup();
|
|
193
|
+
this.fileHasher.writeManifest();
|
|
201
194
|
}
|
|
202
195
|
constructor(options){
|
|
203
196
|
_define_property(this, "options", void 0);
|
|
@@ -223,5 +216,9 @@ class TargetHasher {
|
|
|
223
216
|
this.fileHasher = new _FileHasher.FileHasher({
|
|
224
217
|
root
|
|
225
218
|
});
|
|
219
|
+
this.packageTree = new _PackageTree.PackageTree({
|
|
220
|
+
root,
|
|
221
|
+
includeUntracked: true
|
|
222
|
+
});
|
|
226
223
|
}
|
|
227
224
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lage-run/hasher",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Hasher for Lage Targets",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/microsoft/lage"
|
|
@@ -19,10 +19,8 @@
|
|
|
19
19
|
"@lage-run/logger": "^1.3.0",
|
|
20
20
|
"execa": "5.1.1",
|
|
21
21
|
"workspace-tools": "0.36.4",
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"graceful-fs": "4.2.11",
|
|
25
|
-
"micromatch": "4.0.5"
|
|
22
|
+
"glob-hasher": "^1.4.2",
|
|
23
|
+
"graceful-fs": "4.2.11"
|
|
26
24
|
},
|
|
27
25
|
"devDependencies": {
|
|
28
26
|
"@lage-run/monorepo-fixture": "*",
|