@ontrails/regrade 1.0.0-beta.46 → 1.0.0-beta.48
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.md +10 -0
- package/package.json +6 -6
- package/src/downstream/collect.ts +17 -96
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# @ontrails/regrade
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.48
|
|
4
|
+
|
|
5
|
+
## 1.0.0-beta.47
|
|
6
|
+
|
|
7
|
+
### Patch Changes
|
|
8
|
+
|
|
9
|
+
- [`90d394c`](https://github.com/outfitter-dev/trails/commit/90d394c005fdf6b898ba7052d0b56755af0f4954): Derive nested worktree, repository, and submodule collection boundaries in the
|
|
10
|
+
shared Source walker. Regrade and Warden now observe one directly targeted
|
|
11
|
+
working tree per run, and Regrade audit summaries expose boundary skip counts.
|
|
12
|
+
|
|
3
13
|
## 1.0.0-beta.46
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/regrade",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.48",
|
|
4
4
|
"description": "Downstream migration reporting and safe rewrite helpers for Trails.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@ontrails/core": "^1.0.0-beta.
|
|
31
|
-
"@ontrails/source": "^1.0.0-beta.
|
|
32
|
-
"@ontrails/warden": "^1.0.0-beta.
|
|
30
|
+
"@ontrails/core": "^1.0.0-beta.48",
|
|
31
|
+
"@ontrails/source": "^1.0.0-beta.48",
|
|
32
|
+
"@ontrails/warden": "^1.0.0-beta.48",
|
|
33
33
|
"zod": "^4.3.5"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@ontrails/testing": "^1.0.0-beta.
|
|
37
|
-
"@ontrails/topography": "^1.0.0-beta.
|
|
36
|
+
"@ontrails/testing": "^1.0.0-beta.48",
|
|
37
|
+
"@ontrails/topography": "^1.0.0-beta.48"
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -4,8 +4,7 @@ import {
|
|
|
4
4
|
matchesAnyPathGlob,
|
|
5
5
|
trail,
|
|
6
6
|
} from '@ontrails/core';
|
|
7
|
-
import {
|
|
8
|
-
import { join, posix, relative, resolve, sep } from 'node:path';
|
|
7
|
+
import { collectSourceTree } from '@ontrails/source';
|
|
9
8
|
import { z } from 'zod';
|
|
10
9
|
|
|
11
10
|
/**
|
|
@@ -124,46 +123,10 @@ export const classifyDownstreamEntry = (
|
|
|
124
123
|
: { action: 'skip', reason: 'unsupported-extension' };
|
|
125
124
|
};
|
|
126
125
|
|
|
127
|
-
const toPosixRelative = (root: string, absolutePath: string): string => {
|
|
128
|
-
const rel = relative(root, absolutePath);
|
|
129
|
-
return sep === posix.sep ? rel : rel.split(sep).join(posix.sep);
|
|
130
|
-
};
|
|
131
|
-
|
|
132
126
|
const isImmutableRegradeHistoryDirectory = (path: string): boolean =>
|
|
133
127
|
path === '.trails/regrade/history' ||
|
|
134
128
|
path.endsWith('/.trails/regrade/history');
|
|
135
129
|
|
|
136
|
-
const direntKind = (dirent: {
|
|
137
|
-
isDirectory(): boolean;
|
|
138
|
-
isFile(): boolean;
|
|
139
|
-
}): DownstreamEntryKind => {
|
|
140
|
-
if (dirent.isDirectory()) {
|
|
141
|
-
return 'directory';
|
|
142
|
-
}
|
|
143
|
-
return dirent.isFile() ? 'file' : 'other';
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
type DirectoryRead =
|
|
147
|
-
| {
|
|
148
|
-
readonly ok: true;
|
|
149
|
-
readonly entries: readonly {
|
|
150
|
-
readonly name: string;
|
|
151
|
-
readonly kind: DownstreamEntryKind;
|
|
152
|
-
}[];
|
|
153
|
-
}
|
|
154
|
-
| { readonly ok: false };
|
|
155
|
-
|
|
156
|
-
const readDirectory = (absoluteDir: string): DirectoryRead => {
|
|
157
|
-
try {
|
|
158
|
-
const entries = readdirSync(absoluteDir, { withFileTypes: true }).map(
|
|
159
|
-
(dirent) => ({ kind: direntKind(dirent), name: dirent.name })
|
|
160
|
-
);
|
|
161
|
-
return { entries, ok: true };
|
|
162
|
-
} catch {
|
|
163
|
-
return { ok: false };
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
|
|
167
130
|
/**
|
|
168
131
|
* Walk an explicit downstream root and collect candidate source files.
|
|
169
132
|
*
|
|
@@ -175,69 +138,27 @@ const readDirectory = (absoluteDir: string): DirectoryRead => {
|
|
|
175
138
|
export const collectDownstreamSources = (
|
|
176
139
|
root: string,
|
|
177
140
|
options: DownstreamCollectionOptions = {}
|
|
178
|
-
): DownstreamSourceCollection | null =>
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (!rootRead.ok) {
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const files: CollectedSource[] = [];
|
|
186
|
-
const skipped: SkippedSource[] = [];
|
|
187
|
-
const queue: string[] = [absoluteRoot];
|
|
188
|
-
|
|
189
|
-
while (queue.length > 0) {
|
|
190
|
-
const current = queue.shift() as string;
|
|
191
|
-
const read = current === absoluteRoot ? rootRead : readDirectory(current);
|
|
192
|
-
if (!read.ok) {
|
|
193
|
-
skipped.push({
|
|
194
|
-
path: toPosixRelative(absoluteRoot, current),
|
|
195
|
-
reason: 'unreadable-directory',
|
|
196
|
-
});
|
|
197
|
-
continue;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
for (const entry of read.entries) {
|
|
201
|
-
const absolutePath = join(current, entry.name);
|
|
202
|
-
const path = toPosixRelative(absoluteRoot, absolutePath);
|
|
141
|
+
): DownstreamSourceCollection | null =>
|
|
142
|
+
collectSourceTree(root, {
|
|
143
|
+
classify: ({ kind, name, path }) => {
|
|
203
144
|
if (matchesAnyPathGlob(path, options.exclude)) {
|
|
204
|
-
|
|
205
|
-
|
|
145
|
+
return { action: 'skip', reason: 'ignored-glob' };
|
|
146
|
+
}
|
|
147
|
+
if (kind === 'directory' && isImmutableRegradeHistoryDirectory(path)) {
|
|
148
|
+
return { action: 'skip', reason: 'immutable-regrade-history' };
|
|
206
149
|
}
|
|
150
|
+
const classification = classifyDownstreamEntry(name, kind, options);
|
|
207
151
|
if (
|
|
208
|
-
|
|
209
|
-
|
|
152
|
+
classification.action === 'collect' &&
|
|
153
|
+
options.include !== undefined &&
|
|
154
|
+
options.include.length > 0 &&
|
|
155
|
+
!matchesAnyPathGlob(path, options.include)
|
|
210
156
|
) {
|
|
211
|
-
|
|
212
|
-
continue;
|
|
157
|
+
return { action: 'skip', reason: 'not-included-glob' };
|
|
213
158
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
options
|
|
218
|
-
);
|
|
219
|
-
if (classification.action === 'collect') {
|
|
220
|
-
if (
|
|
221
|
-
options.include !== undefined &&
|
|
222
|
-
options.include.length > 0 &&
|
|
223
|
-
!matchesAnyPathGlob(path, options.include)
|
|
224
|
-
) {
|
|
225
|
-
skipped.push({ path, reason: 'not-included-glob' });
|
|
226
|
-
} else {
|
|
227
|
-
files.push({ absolutePath, path });
|
|
228
|
-
}
|
|
229
|
-
} else if (classification.action === 'recurse') {
|
|
230
|
-
queue.push(absolutePath);
|
|
231
|
-
} else {
|
|
232
|
-
skipped.push({ path, reason: classification.reason });
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
238
|
-
skipped.sort((a, b) => a.path.localeCompare(b.path));
|
|
239
|
-
return { files, root: absoluteRoot, skipped };
|
|
240
|
-
};
|
|
159
|
+
return classification;
|
|
160
|
+
},
|
|
161
|
+
});
|
|
241
162
|
|
|
242
163
|
export const collectDownstreamSourcesInput = z.object({
|
|
243
164
|
exclude: z
|