@fabricorg/cli 0.3.6 → 0.3.7
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/dist/fabric.js +658 -134
- package/dist/fabric.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
package/dist/fabric.js
CHANGED
|
@@ -57,7 +57,7 @@ import { Command as Command21 } from "commander";
|
|
|
57
57
|
// package.json
|
|
58
58
|
var package_default = {
|
|
59
59
|
name: "@fabricorg/cli",
|
|
60
|
-
version: "0.3.
|
|
60
|
+
version: "0.3.7",
|
|
61
61
|
description: "CLI for the Fabric AI platform",
|
|
62
62
|
keywords: [
|
|
63
63
|
"fabric",
|
|
@@ -2048,15 +2048,61 @@ function computeContextPlan(input) {
|
|
|
2048
2048
|
}
|
|
2049
2049
|
}
|
|
2050
2050
|
push.sort((a, b) => byPath2(a.sourcePath, b.sourcePath));
|
|
2051
|
-
unchangedLocal.sort(byPath2);
|
|
2052
2051
|
removed.sort(byPath2);
|
|
2052
|
+
const moves = pairMoves(lock, removed, push);
|
|
2053
|
+
const moved = new Set(moves.map((move) => move.from));
|
|
2054
|
+
const arrived = new Set(moves.map((move) => move.to));
|
|
2055
|
+
unchangedLocal.sort(byPath2);
|
|
2053
2056
|
forgotten.sort(byPath2);
|
|
2054
2057
|
skipped.sort((a, b) => byPath2(a.path, b.path));
|
|
2055
|
-
return {
|
|
2058
|
+
return {
|
|
2059
|
+
push: push.filter((entry) => !arrived.has(entry.sourcePath)),
|
|
2060
|
+
moves,
|
|
2061
|
+
unchangedLocal,
|
|
2062
|
+
removed: removed.filter((sourcePath) => !moved.has(sourcePath)),
|
|
2063
|
+
forgotten,
|
|
2064
|
+
skipped
|
|
2065
|
+
};
|
|
2056
2066
|
});
|
|
2057
2067
|
}
|
|
2068
|
+
function pairMoves(lock, removed, push) {
|
|
2069
|
+
const added = push.filter(
|
|
2070
|
+
(entry) => (lock == null ? void 0 : lock.files[entry.sourcePath]) === void 0
|
|
2071
|
+
);
|
|
2072
|
+
const taken = /* @__PURE__ */ new Set();
|
|
2073
|
+
const moves = [];
|
|
2074
|
+
for (const from of removed) {
|
|
2075
|
+
const entry = lock == null ? void 0 : lock.files[from];
|
|
2076
|
+
if (!entry || entry.state === "duplicate") {
|
|
2077
|
+
continue;
|
|
2078
|
+
}
|
|
2079
|
+
const match = added.find(
|
|
2080
|
+
(candidate) => !taken.has(candidate.sourcePath) && candidate.sha256 === entry.sha256
|
|
2081
|
+
);
|
|
2082
|
+
if (!match) {
|
|
2083
|
+
continue;
|
|
2084
|
+
}
|
|
2085
|
+
taken.add(match.sourcePath);
|
|
2086
|
+
moves.push({
|
|
2087
|
+
from,
|
|
2088
|
+
to: match.sourcePath,
|
|
2089
|
+
diskPath: match.diskPath,
|
|
2090
|
+
sha256: match.sha256,
|
|
2091
|
+
bytes: match.bytes,
|
|
2092
|
+
contextId: entry.contextId
|
|
2093
|
+
});
|
|
2094
|
+
}
|
|
2095
|
+
return moves;
|
|
2096
|
+
}
|
|
2058
2097
|
|
|
2059
2098
|
// src/lib/context-sync/push.ts
|
|
2099
|
+
var DELETE_STATUSES = /* @__PURE__ */ new Set([
|
|
2100
|
+
"deleted",
|
|
2101
|
+
"already-gone",
|
|
2102
|
+
"delete-in-progress",
|
|
2103
|
+
"delete-conflict",
|
|
2104
|
+
"delete-failed"
|
|
2105
|
+
]);
|
|
2060
2106
|
var RUN_LEVEL_STATUSES = /* @__PURE__ */ new Set([401, 403, 404, 429]);
|
|
2061
2107
|
var RUN_LEVEL_CODES = /* @__PURE__ */ new Set(["NETWORK_ERROR", "TIMEOUT"]);
|
|
2062
2108
|
function stopsTheRun(error) {
|
|
@@ -2094,158 +2140,439 @@ function readPlannedContent(root, entry) {
|
|
|
2094
2140
|
return verdict.content;
|
|
2095
2141
|
});
|
|
2096
2142
|
}
|
|
2097
|
-
function fromResult(sourcePath, result) {
|
|
2098
|
-
if (result.status === "
|
|
2143
|
+
function fromResult(sourcePath, result, movedFrom) {
|
|
2144
|
+
if (result.status === "moved") {
|
|
2099
2145
|
return {
|
|
2146
|
+
sourcePath,
|
|
2147
|
+
status: "moved",
|
|
2148
|
+
movedFrom: movedFrom != null ? movedFrom : result.movedFromSourcePath,
|
|
2149
|
+
contextId: result.contextId,
|
|
2150
|
+
contentHash: result.contentHash
|
|
2151
|
+
};
|
|
2152
|
+
}
|
|
2153
|
+
const move = movedFrom === void 0 ? {} : __spreadValues({
|
|
2154
|
+
movedFrom
|
|
2155
|
+
}, result.moveNotApplied ? { moveNotApplied: result.moveNotApplied.reason } : {});
|
|
2156
|
+
if (result.status === "duplicate") {
|
|
2157
|
+
return __spreadValues({
|
|
2100
2158
|
sourcePath,
|
|
2101
2159
|
status: "duplicate",
|
|
2102
2160
|
contentHash: result.contentHash,
|
|
2103
2161
|
duplicateOfContextId: result.duplicateOfContextId,
|
|
2104
2162
|
duplicateOfSourcePath: result.duplicateOfSourcePath
|
|
2105
|
-
};
|
|
2163
|
+
}, move);
|
|
2106
2164
|
}
|
|
2107
|
-
return {
|
|
2165
|
+
return __spreadValues({
|
|
2108
2166
|
sourcePath,
|
|
2109
2167
|
status: result.status,
|
|
2110
2168
|
contextId: result.contextId,
|
|
2111
2169
|
contentHash: result.contentHash
|
|
2112
|
-
};
|
|
2170
|
+
}, move);
|
|
2171
|
+
}
|
|
2172
|
+
function moveKeptOldPath(result) {
|
|
2173
|
+
if ((result.status === "created" || result.status === "updated" || result.status === "unchanged" || result.status === "duplicate") && result.movedFrom !== void 0 && result.moveNotApplied !== "source-missing") {
|
|
2174
|
+
return result.movedFrom;
|
|
2175
|
+
}
|
|
2176
|
+
return null;
|
|
2113
2177
|
}
|
|
2114
2178
|
function pushContextPlan(input) {
|
|
2115
2179
|
return __async(this, null, function* () {
|
|
2116
2180
|
var _a2;
|
|
2117
2181
|
const results = [];
|
|
2118
|
-
const
|
|
2182
|
+
const pruneTargets = [];
|
|
2183
|
+
const { force } = input;
|
|
2184
|
+
const send = (sourcePath, content, expectedContentHash, movedFromSourcePath) => input.client.contexts.upsertSyncedFile(
|
|
2119
2185
|
input.projectId,
|
|
2120
|
-
__spreadValues({
|
|
2121
|
-
sourcePath
|
|
2186
|
+
__spreadValues(__spreadValues({
|
|
2187
|
+
sourcePath,
|
|
2122
2188
|
content
|
|
2123
|
-
}, expectedContentHash !== void 0 ? { expectedContentHash } : {}),
|
|
2189
|
+
}, expectedContentHash !== void 0 ? { expectedContentHash } : {}), movedFromSourcePath !== void 0 ? { movedFromSourcePath } : {}),
|
|
2124
2190
|
{ org: input.org }
|
|
2125
2191
|
);
|
|
2126
|
-
|
|
2192
|
+
const pushEntry = (entry) => __async(null, null, function* () {
|
|
2193
|
+
var _a3;
|
|
2194
|
+
const content = yield readPlannedContent(input.root, entry);
|
|
2195
|
+
if (content === null) {
|
|
2196
|
+
return {
|
|
2197
|
+
sourcePath: entry.sourcePath,
|
|
2198
|
+
status: "changed-during-run"
|
|
2199
|
+
};
|
|
2200
|
+
}
|
|
2127
2201
|
try {
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2202
|
+
return fromResult(
|
|
2203
|
+
entry.sourcePath,
|
|
2204
|
+
yield send(
|
|
2205
|
+
entry.sourcePath,
|
|
2206
|
+
content,
|
|
2207
|
+
entry.expectedContentHash
|
|
2208
|
+
)
|
|
2209
|
+
);
|
|
2210
|
+
} catch (error) {
|
|
2211
|
+
const conflict = conflictOf(error);
|
|
2212
|
+
if (conflict === null) {
|
|
2213
|
+
throw error;
|
|
2214
|
+
}
|
|
2215
|
+
const { current } = conflict;
|
|
2216
|
+
if (!force || current !== null && current.contentHash === null) {
|
|
2217
|
+
return {
|
|
2218
|
+
sourcePath: entry.sourcePath,
|
|
2219
|
+
status: "conflict",
|
|
2220
|
+
contentHash: conflict.contentHash,
|
|
2221
|
+
wasLocked: entry.expectedContentHash !== void 0,
|
|
2222
|
+
afterForce: false,
|
|
2223
|
+
current
|
|
2224
|
+
};
|
|
2225
|
+
}
|
|
2226
|
+
const forcedContent = yield readPlannedContent(input.root, entry);
|
|
2227
|
+
if (forcedContent === null) {
|
|
2228
|
+
return {
|
|
2131
2229
|
sourcePath: entry.sourcePath,
|
|
2132
2230
|
status: "changed-during-run"
|
|
2133
|
-
}
|
|
2134
|
-
continue;
|
|
2231
|
+
};
|
|
2135
2232
|
}
|
|
2136
2233
|
try {
|
|
2137
|
-
|
|
2138
|
-
|
|
2234
|
+
const forced = fromResult(
|
|
2235
|
+
entry.sourcePath,
|
|
2236
|
+
yield send(
|
|
2139
2237
|
entry.sourcePath,
|
|
2140
|
-
|
|
2238
|
+
forcedContent,
|
|
2239
|
+
current === null ? void 0 : (_a3 = current.contentHash) != null ? _a3 : void 0
|
|
2141
2240
|
)
|
|
2142
2241
|
);
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2242
|
+
return forced.status === "updated" && current !== null ? __spreadProps(__spreadValues({}, forced), { overwrote: current }) : forced;
|
|
2243
|
+
} catch (retryError) {
|
|
2244
|
+
const again = conflictOf(retryError);
|
|
2245
|
+
if (again === null) {
|
|
2246
|
+
throw retryError;
|
|
2147
2247
|
}
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2248
|
+
return {
|
|
2249
|
+
sourcePath: entry.sourcePath,
|
|
2250
|
+
status: "conflict",
|
|
2251
|
+
contentHash: again.contentHash,
|
|
2252
|
+
wasLocked: entry.expectedContentHash !== void 0,
|
|
2253
|
+
afterForce: true,
|
|
2254
|
+
current: again.current
|
|
2255
|
+
};
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
});
|
|
2259
|
+
const pushMove = (move) => __async(null, null, function* () {
|
|
2260
|
+
var _a3, _b, _c, _d;
|
|
2261
|
+
const entry = {
|
|
2262
|
+
sourcePath: move.to,
|
|
2263
|
+
diskPath: move.diskPath,
|
|
2264
|
+
sha256: move.sha256,
|
|
2265
|
+
bytes: move.bytes
|
|
2266
|
+
};
|
|
2267
|
+
const moveFields = { movedFrom: move.from };
|
|
2268
|
+
const content = yield readPlannedContent(input.root, entry);
|
|
2269
|
+
if (content === null) {
|
|
2270
|
+
return __spreadValues({
|
|
2271
|
+
sourcePath: move.to,
|
|
2272
|
+
status: "changed-during-run"
|
|
2273
|
+
}, moveFields);
|
|
2274
|
+
}
|
|
2275
|
+
const asConflict = (conflict, afterForce) => {
|
|
2276
|
+
var _a4;
|
|
2277
|
+
return __spreadValues(__spreadValues({
|
|
2278
|
+
sourcePath: move.to,
|
|
2279
|
+
status: "conflict",
|
|
2280
|
+
contentHash: conflict.contentHash,
|
|
2281
|
+
// About the old path (which the lock names) or the new one.
|
|
2282
|
+
wasLocked: ((_a4 = conflict.moveNotApplied) == null ? void 0 : _a4.reason) === "source-changed",
|
|
2283
|
+
afterForce,
|
|
2284
|
+
current: conflict.current
|
|
2285
|
+
}, moveFields), conflict.moveNotApplied ? { moveNotApplied: conflict.moveNotApplied.reason } : {});
|
|
2286
|
+
};
|
|
2287
|
+
try {
|
|
2288
|
+
return fromResult(
|
|
2289
|
+
move.to,
|
|
2290
|
+
yield send(move.to, content, move.sha256, move.from),
|
|
2291
|
+
move.from
|
|
2292
|
+
);
|
|
2293
|
+
} catch (error) {
|
|
2294
|
+
const conflict = conflictOf(error);
|
|
2295
|
+
if (conflict === null) {
|
|
2296
|
+
throw error;
|
|
2297
|
+
}
|
|
2298
|
+
const { current } = conflict;
|
|
2299
|
+
if (current === null && conflict.moveNotApplied === void 0) {
|
|
2300
|
+
return {
|
|
2301
|
+
sourcePath: move.to,
|
|
2302
|
+
status: "move-unsupported",
|
|
2303
|
+
movedFrom: move.from
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
if (!force || current !== null && current.contentHash === null) {
|
|
2307
|
+
return asConflict(conflict, false);
|
|
2308
|
+
}
|
|
2309
|
+
const forcedContent = yield readPlannedContent(input.root, entry);
|
|
2310
|
+
if (forcedContent === null) {
|
|
2311
|
+
return __spreadValues({
|
|
2312
|
+
sourcePath: move.to,
|
|
2313
|
+
status: "changed-during-run"
|
|
2314
|
+
}, moveFields);
|
|
2315
|
+
}
|
|
2316
|
+
const aboutOldPath = ((_a3 = conflict.moveNotApplied) == null ? void 0 : _a3.reason) === "source-changed";
|
|
2317
|
+
try {
|
|
2318
|
+
if (aboutOldPath && current === null) {
|
|
2319
|
+
const created = fromResult(
|
|
2320
|
+
move.to,
|
|
2321
|
+
yield send(move.to, forcedContent)
|
|
2322
|
+
);
|
|
2323
|
+
return created.status === "moved" ? created : __spreadProps(__spreadValues(__spreadValues({}, created), moveFields), {
|
|
2324
|
+
moveNotApplied: "source-missing"
|
|
2168
2325
|
});
|
|
2169
|
-
continue;
|
|
2170
2326
|
}
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2327
|
+
if (aboutOldPath) {
|
|
2328
|
+
return fromResult(
|
|
2329
|
+
move.to,
|
|
2174
2330
|
yield send(
|
|
2175
|
-
|
|
2331
|
+
move.to,
|
|
2176
2332
|
forcedContent,
|
|
2177
|
-
current
|
|
2178
|
-
|
|
2333
|
+
(_b = current == null ? void 0 : current.contentHash) != null ? _b : void 0,
|
|
2334
|
+
move.from
|
|
2335
|
+
),
|
|
2336
|
+
move.from
|
|
2179
2337
|
);
|
|
2180
|
-
results.push(
|
|
2181
|
-
forced.status === "updated" && current !== null ? __spreadProps(__spreadValues({}, forced), { overwrote: current }) : forced
|
|
2182
|
-
);
|
|
2183
|
-
} catch (retryError) {
|
|
2184
|
-
const again = conflictOf(retryError);
|
|
2185
|
-
if (again === null) {
|
|
2186
|
-
throw retryError;
|
|
2187
|
-
}
|
|
2188
|
-
results.push({
|
|
2189
|
-
sourcePath: entry.sourcePath,
|
|
2190
|
-
status: "conflict",
|
|
2191
|
-
contentHash: again.contentHash,
|
|
2192
|
-
wasLocked: entry.expectedContentHash !== void 0,
|
|
2193
|
-
afterForce: true,
|
|
2194
|
-
current: again.current
|
|
2195
|
-
});
|
|
2196
2338
|
}
|
|
2339
|
+
const forced = fromResult(
|
|
2340
|
+
move.to,
|
|
2341
|
+
yield send(
|
|
2342
|
+
move.to,
|
|
2343
|
+
forcedContent,
|
|
2344
|
+
(_c = current == null ? void 0 : current.contentHash) != null ? _c : void 0
|
|
2345
|
+
)
|
|
2346
|
+
);
|
|
2347
|
+
if (forced.status === "moved") {
|
|
2348
|
+
return forced;
|
|
2349
|
+
}
|
|
2350
|
+
return __spreadValues(__spreadValues(__spreadValues({}, forced.status === "updated" && current !== null ? __spreadProps(__spreadValues({}, forced), { overwrote: current }) : forced), moveFields), conflict.moveNotApplied ? { moveNotApplied: conflict.moveNotApplied.reason } : {});
|
|
2351
|
+
} catch (retryError) {
|
|
2352
|
+
const again = conflictOf(retryError);
|
|
2353
|
+
if (again === null) {
|
|
2354
|
+
throw retryError;
|
|
2355
|
+
}
|
|
2356
|
+
if (again.moveNotApplied !== void 0) {
|
|
2357
|
+
return asConflict(again, true);
|
|
2358
|
+
}
|
|
2359
|
+
const reason = aboutOldPath ? current === null ? "source-missing" : void 0 : (_d = conflict.moveNotApplied) == null ? void 0 : _d.reason;
|
|
2360
|
+
return asConflict(
|
|
2361
|
+
reason === void 0 ? again : __spreadProps(__spreadValues({}, again), {
|
|
2362
|
+
moveNotApplied: {
|
|
2363
|
+
movedFromSourcePath: move.from,
|
|
2364
|
+
reason
|
|
2365
|
+
}
|
|
2366
|
+
}),
|
|
2367
|
+
true
|
|
2368
|
+
);
|
|
2197
2369
|
}
|
|
2370
|
+
}
|
|
2371
|
+
});
|
|
2372
|
+
const deleteEntry = (sourcePath, sha256) => __async(null, null, function* () {
|
|
2373
|
+
const remove = (expectedContentHash) => input.client.contexts.deleteSyncedFile(
|
|
2374
|
+
input.projectId,
|
|
2375
|
+
{ sourcePath, expectedContentHash },
|
|
2376
|
+
{ org: input.org }
|
|
2377
|
+
);
|
|
2378
|
+
const fromAnswer = (answer, overwrote) => {
|
|
2379
|
+
switch (answer.status) {
|
|
2380
|
+
case "deleted":
|
|
2381
|
+
return __spreadValues({
|
|
2382
|
+
sourcePath,
|
|
2383
|
+
status: "deleted",
|
|
2384
|
+
contextId: answer.contextId,
|
|
2385
|
+
contentHash: answer.contentHash
|
|
2386
|
+
}, overwrote ? { overwrote } : {});
|
|
2387
|
+
case "absent":
|
|
2388
|
+
return { sourcePath, status: "already-gone" };
|
|
2389
|
+
case "in-progress":
|
|
2390
|
+
return { sourcePath, status: "delete-in-progress" };
|
|
2391
|
+
}
|
|
2392
|
+
};
|
|
2393
|
+
try {
|
|
2394
|
+
return fromAnswer(yield remove(sha256));
|
|
2395
|
+
} catch (error) {
|
|
2396
|
+
const conflict = conflictOf(error);
|
|
2397
|
+
if (conflict === null || conflict.current === null) {
|
|
2398
|
+
throw error;
|
|
2399
|
+
}
|
|
2400
|
+
const { current } = conflict;
|
|
2401
|
+
if (!force || current.contentHash === null) {
|
|
2402
|
+
return {
|
|
2403
|
+
sourcePath,
|
|
2404
|
+
status: "delete-conflict",
|
|
2405
|
+
afterForce: false,
|
|
2406
|
+
current
|
|
2407
|
+
};
|
|
2408
|
+
}
|
|
2409
|
+
try {
|
|
2410
|
+
return fromAnswer(yield remove(current.contentHash), current);
|
|
2411
|
+
} catch (retryError) {
|
|
2412
|
+
const again = conflictOf(retryError);
|
|
2413
|
+
if (again === null || again.current === null) {
|
|
2414
|
+
throw retryError;
|
|
2415
|
+
}
|
|
2416
|
+
return {
|
|
2417
|
+
sourcePath,
|
|
2418
|
+
status: "delete-conflict",
|
|
2419
|
+
afterForce: true,
|
|
2420
|
+
current: again.current
|
|
2421
|
+
};
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
});
|
|
2425
|
+
const step = (run3, failed) => __async(null, null, function* () {
|
|
2426
|
+
try {
|
|
2427
|
+
results.push(yield run3());
|
|
2428
|
+
return null;
|
|
2198
2429
|
} catch (error) {
|
|
2199
2430
|
const failure = asCliFailure(error);
|
|
2200
2431
|
if (stopsTheRun(error)) {
|
|
2201
|
-
return
|
|
2432
|
+
return failure;
|
|
2202
2433
|
}
|
|
2203
|
-
results.push(
|
|
2434
|
+
results.push(failed(error, failure.exitCode));
|
|
2435
|
+
return null;
|
|
2436
|
+
}
|
|
2437
|
+
});
|
|
2438
|
+
const pruneTargetsSoFar = () => {
|
|
2439
|
+
const keptByMoves = results.map(moveKeptOldPath).filter((path9) => path9 !== null);
|
|
2440
|
+
return [.../* @__PURE__ */ new Set([...input.plan.removed, ...keptByMoves])].filter((path9) => {
|
|
2441
|
+
var _a3;
|
|
2442
|
+
const locked = (_a3 = input.lock) == null ? void 0 : _a3.files[path9];
|
|
2443
|
+
return locked !== void 0 && locked.state !== "duplicate";
|
|
2444
|
+
}).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
|
|
2445
|
+
};
|
|
2446
|
+
const stopped = (stoppedBy) => {
|
|
2447
|
+
if (input.prune && pruneTargets.length === 0) {
|
|
2448
|
+
pruneTargets.push(...pruneTargetsSoFar());
|
|
2449
|
+
}
|
|
2450
|
+
return { results, stoppedBy, pruneTargets };
|
|
2451
|
+
};
|
|
2452
|
+
for (const move of input.plan.moves) {
|
|
2453
|
+
const stoppedBy = yield step(
|
|
2454
|
+
() => pushMove(move),
|
|
2455
|
+
(error, exitCode) => ({
|
|
2456
|
+
sourcePath: move.to,
|
|
2457
|
+
status: "failed",
|
|
2458
|
+
error: describeError(error),
|
|
2459
|
+
exitCode,
|
|
2460
|
+
movedFrom: move.from
|
|
2461
|
+
})
|
|
2462
|
+
);
|
|
2463
|
+
if (stoppedBy) {
|
|
2464
|
+
return stopped(stoppedBy);
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
for (const entry of input.plan.push) {
|
|
2468
|
+
const stoppedBy = yield step(
|
|
2469
|
+
() => pushEntry(entry),
|
|
2470
|
+
(error, exitCode) => ({
|
|
2204
2471
|
sourcePath: entry.sourcePath,
|
|
2205
2472
|
status: "failed",
|
|
2206
2473
|
error: describeError(error),
|
|
2207
|
-
exitCode
|
|
2208
|
-
})
|
|
2474
|
+
exitCode
|
|
2475
|
+
})
|
|
2476
|
+
);
|
|
2477
|
+
if (stoppedBy) {
|
|
2478
|
+
return stopped(stoppedBy);
|
|
2209
2479
|
}
|
|
2210
2480
|
}
|
|
2211
|
-
|
|
2481
|
+
if (input.prune) {
|
|
2482
|
+
pruneTargets.push(...pruneTargetsSoFar());
|
|
2483
|
+
for (const sourcePath of pruneTargets) {
|
|
2484
|
+
const locked = (_a2 = input.lock) == null ? void 0 : _a2.files[sourcePath];
|
|
2485
|
+
if (!locked || locked.state === "duplicate") {
|
|
2486
|
+
continue;
|
|
2487
|
+
}
|
|
2488
|
+
const stoppedBy = yield step(
|
|
2489
|
+
() => deleteEntry(sourcePath, locked.sha256),
|
|
2490
|
+
(error, exitCode) => ({
|
|
2491
|
+
sourcePath,
|
|
2492
|
+
status: "delete-failed",
|
|
2493
|
+
error: describeError(error),
|
|
2494
|
+
exitCode
|
|
2495
|
+
})
|
|
2496
|
+
);
|
|
2497
|
+
if (stoppedBy) {
|
|
2498
|
+
return stopped(stoppedBy);
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
return { results, stoppedBy: null, pruneTargets };
|
|
2212
2503
|
});
|
|
2213
2504
|
}
|
|
2214
2505
|
function nextContextLock(input) {
|
|
2215
2506
|
var _a2, _b, _c;
|
|
2216
2507
|
const files = __spreadValues({}, (_b = (_a2 = input.previous) == null ? void 0 : _a2.files) != null ? _b : {});
|
|
2217
2508
|
let changed = false;
|
|
2218
|
-
|
|
2509
|
+
const drop = (sourcePath) => {
|
|
2219
2510
|
if (sourcePath in files) {
|
|
2220
2511
|
delete files[sourcePath];
|
|
2221
2512
|
changed = true;
|
|
2222
2513
|
}
|
|
2514
|
+
};
|
|
2515
|
+
const confirm = (sourcePath, sha256, contextId) => {
|
|
2516
|
+
const before = files[sourcePath];
|
|
2517
|
+
if ((before == null ? void 0 : before.state) === void 0 && (before == null ? void 0 : before.sha256) === sha256 && before.contextId === contextId) {
|
|
2518
|
+
return;
|
|
2519
|
+
}
|
|
2520
|
+
files[sourcePath] = { sha256, contextId };
|
|
2521
|
+
changed = true;
|
|
2522
|
+
};
|
|
2523
|
+
for (const sourcePath of (_c = input.forgotten) != null ? _c : []) {
|
|
2524
|
+
drop(sourcePath);
|
|
2223
2525
|
}
|
|
2224
2526
|
for (const result of input.results) {
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2527
|
+
switch (result.status) {
|
|
2528
|
+
case "deleted":
|
|
2529
|
+
case "already-gone":
|
|
2530
|
+
drop(result.sourcePath);
|
|
2531
|
+
break;
|
|
2532
|
+
case "delete-in-progress":
|
|
2533
|
+
break;
|
|
2534
|
+
case "moved":
|
|
2535
|
+
drop(result.movedFrom);
|
|
2536
|
+
confirm(
|
|
2537
|
+
result.sourcePath,
|
|
2538
|
+
result.contentHash,
|
|
2539
|
+
result.contextId
|
|
2540
|
+
);
|
|
2541
|
+
break;
|
|
2542
|
+
case "duplicate": {
|
|
2543
|
+
const before = files[result.sourcePath];
|
|
2544
|
+
if ((before == null ? void 0 : before.state) !== "duplicate" || before.sha256 !== result.contentHash) {
|
|
2545
|
+
files[result.sourcePath] = {
|
|
2546
|
+
sha256: result.contentHash,
|
|
2547
|
+
state: "duplicate"
|
|
2548
|
+
};
|
|
2549
|
+
changed = true;
|
|
2550
|
+
}
|
|
2551
|
+
if (result.moveNotApplied === "source-missing" && result.movedFrom) {
|
|
2552
|
+
drop(result.movedFrom);
|
|
2553
|
+
}
|
|
2554
|
+
break;
|
|
2229
2555
|
}
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2556
|
+
case "created":
|
|
2557
|
+
case "updated":
|
|
2558
|
+
case "unchanged":
|
|
2559
|
+
confirm(
|
|
2560
|
+
result.sourcePath,
|
|
2561
|
+
result.contentHash,
|
|
2562
|
+
result.contextId
|
|
2563
|
+
);
|
|
2564
|
+
if (result.moveNotApplied === "source-missing" && result.movedFrom) {
|
|
2565
|
+
drop(result.movedFrom);
|
|
2566
|
+
}
|
|
2567
|
+
break;
|
|
2568
|
+
case "conflict":
|
|
2569
|
+
if (result.moveNotApplied === "source-missing" && result.movedFrom) {
|
|
2570
|
+
drop(result.movedFrom);
|
|
2571
|
+
}
|
|
2572
|
+
break;
|
|
2573
|
+
default:
|
|
2574
|
+
break;
|
|
2243
2575
|
}
|
|
2244
|
-
files[result.sourcePath] = {
|
|
2245
|
-
sha256: result.contentHash,
|
|
2246
|
-
contextId: result.contextId
|
|
2247
|
-
};
|
|
2248
|
-
changed = true;
|
|
2249
2576
|
}
|
|
2250
2577
|
if (!changed) {
|
|
2251
2578
|
return null;
|
|
@@ -2266,11 +2593,18 @@ function countOutcomes(plan, results) {
|
|
|
2266
2593
|
updated: count("updated"),
|
|
2267
2594
|
unchanged: count("unchanged") + plan.unchangedLocal.length,
|
|
2268
2595
|
duplicate: count("duplicate"),
|
|
2596
|
+
moved: count("moved"),
|
|
2597
|
+
moveUnsupported: count("move-unsupported"),
|
|
2269
2598
|
conflict: count("conflict"),
|
|
2270
2599
|
changedDuringRun: count("changed-during-run"),
|
|
2271
2600
|
failed: count("failed"),
|
|
2272
2601
|
removed: plan.removed.length,
|
|
2273
|
-
skipped: plan.skipped.length
|
|
2602
|
+
skipped: plan.skipped.length,
|
|
2603
|
+
deleted: count("deleted"),
|
|
2604
|
+
alreadyGone: count("already-gone"),
|
|
2605
|
+
deleteInProgress: count("delete-in-progress"),
|
|
2606
|
+
deleteConflict: count("delete-conflict"),
|
|
2607
|
+
deleteFailed: count("delete-failed")
|
|
2274
2608
|
};
|
|
2275
2609
|
}
|
|
2276
2610
|
function who(current) {
|
|
@@ -2281,7 +2615,30 @@ function when(current) {
|
|
|
2281
2615
|
var _a2;
|
|
2282
2616
|
return (_a2 = current.contentUpdatedAt) != null ? _a2 : "an unknown time";
|
|
2283
2617
|
}
|
|
2618
|
+
function moveSourceConflictLine(result, from) {
|
|
2619
|
+
const { current } = result;
|
|
2620
|
+
if (current === null) {
|
|
2621
|
+
return `${from}: deleted on the server since your last push; not moved to ${result.sourcePath}`;
|
|
2622
|
+
}
|
|
2623
|
+
let text = result.afterForce ? `changed on the server again by ${who(current)} at ${when(current)} while --force was moving it` : `changed on the server by ${who(current)} at ${when(current)} since your last push`;
|
|
2624
|
+
if (current.contentHash === null) {
|
|
2625
|
+
text += "; that version has no content hash, so --force cannot move it";
|
|
2626
|
+
}
|
|
2627
|
+
return `${from}: ${text}; not moved to ${result.sourcePath}`;
|
|
2628
|
+
}
|
|
2284
2629
|
function conflictLine(result) {
|
|
2630
|
+
if (result.movedFrom !== void 0) {
|
|
2631
|
+
if (result.moveNotApplied === "source-changed") {
|
|
2632
|
+
return moveSourceConflictLine(result, result.movedFrom);
|
|
2633
|
+
}
|
|
2634
|
+
if (result.moveNotApplied === "source-missing") {
|
|
2635
|
+
return `${pushConflictLine(result)}; ${result.movedFrom} gone on the server`;
|
|
2636
|
+
}
|
|
2637
|
+
return `${pushConflictLine(result)}; ${result.movedFrom} not moved`;
|
|
2638
|
+
}
|
|
2639
|
+
return pushConflictLine(result);
|
|
2640
|
+
}
|
|
2641
|
+
function pushConflictLine(result) {
|
|
2285
2642
|
const { current } = result;
|
|
2286
2643
|
if (current === null) {
|
|
2287
2644
|
return `${result.sourcePath}: deleted on the server since your last push`;
|
|
@@ -2299,12 +2656,47 @@ function conflictLine(result) {
|
|
|
2299
2656
|
}
|
|
2300
2657
|
return `${result.sourcePath}: ${text}`;
|
|
2301
2658
|
}
|
|
2659
|
+
function deleteConflictLine(result) {
|
|
2660
|
+
const { current } = result;
|
|
2661
|
+
let text = result.afterForce ? `changed on the server again by ${who(current)} at ${when(current)} while --force was deleting it` : `changed on the server by ${who(current)} at ${when(current)} since your last push`;
|
|
2662
|
+
if (current.contentHash === null) {
|
|
2663
|
+
text += "; that version has no content hash, so --force cannot delete it";
|
|
2664
|
+
}
|
|
2665
|
+
return `${result.sourcePath}: ${text}; not deleted`;
|
|
2666
|
+
}
|
|
2302
2667
|
function storedLine(result) {
|
|
2303
2668
|
if (result.overwrote) {
|
|
2304
2669
|
return `${result.sourcePath}: replaced the version ${who(result.overwrote)} changed at ${when(result.overwrote)} (--force)`;
|
|
2305
2670
|
}
|
|
2306
2671
|
return result.sourcePath;
|
|
2307
2672
|
}
|
|
2673
|
+
function isMoveFallback(result) {
|
|
2674
|
+
return (result.status === "created" || result.status === "updated" || result.status === "unchanged" || result.status === "duplicate") && result.movedFrom !== void 0;
|
|
2675
|
+
}
|
|
2676
|
+
function moveFallbackLine(result, prune) {
|
|
2677
|
+
var _a2, _b;
|
|
2678
|
+
const from = (_a2 = result.movedFrom) != null ? _a2 : "";
|
|
2679
|
+
const to = result.sourcePath;
|
|
2680
|
+
let pushed;
|
|
2681
|
+
if (result.status === "duplicate") {
|
|
2682
|
+
pushed = `${to} pushed as a duplicate of ${(_b = result.duplicateOfSourcePath) != null ? _b : "another source in this project"}`;
|
|
2683
|
+
} else if (result.overwrote) {
|
|
2684
|
+
pushed = `${to} replaced the version ${who(result.overwrote)} changed at ${when(result.overwrote)} (--force)`;
|
|
2685
|
+
} else {
|
|
2686
|
+
pushed = `${to} pushed as ${result.status}`;
|
|
2687
|
+
}
|
|
2688
|
+
const kept = prune ? "" : `; ${from} kept`;
|
|
2689
|
+
switch (result.moveNotApplied) {
|
|
2690
|
+
case "source-missing":
|
|
2691
|
+
return `${from}: gone on the server; ${pushed}`;
|
|
2692
|
+
case "target-exists":
|
|
2693
|
+
return `${from}: not moved, ${to} is already on the server; ${pushed}${kept}`;
|
|
2694
|
+
case "content-differs":
|
|
2695
|
+
return `${from}: not moved, the server's version of it differs from ${to}; ${pushed}${kept}`;
|
|
2696
|
+
default:
|
|
2697
|
+
return `${from}: not moved; ${pushed}${kept}`;
|
|
2698
|
+
}
|
|
2699
|
+
}
|
|
2308
2700
|
function skippedLine(skip) {
|
|
2309
2701
|
if (skip.reason === "ignored") {
|
|
2310
2702
|
return `${skip.path}: now excluded by the ignore rules; server entry kept`;
|
|
@@ -2321,24 +2713,42 @@ function group(lines, label, items) {
|
|
|
2321
2713
|
}
|
|
2322
2714
|
}
|
|
2323
2715
|
function formatPushReport(input) {
|
|
2716
|
+
var _a2;
|
|
2324
2717
|
const { plan, results } = input;
|
|
2325
|
-
const
|
|
2718
|
+
const prune = Boolean(input.prune);
|
|
2719
|
+
const of = (status) => results.filter(
|
|
2720
|
+
(r) => r.status === status && !isMoveFallback(r)
|
|
2721
|
+
);
|
|
2326
2722
|
const lines = [
|
|
2327
2723
|
`Context push from ${input.directory} to project ${input.projectId}:`
|
|
2328
2724
|
];
|
|
2329
2725
|
group(lines, "created", of("created").map(storedLine));
|
|
2330
2726
|
group(lines, "updated", of("updated").map(storedLine));
|
|
2727
|
+
group(
|
|
2728
|
+
lines,
|
|
2729
|
+
"moved",
|
|
2730
|
+
of("moved").map((r) => `${r.movedFrom} -> ${r.sourcePath}`)
|
|
2731
|
+
);
|
|
2732
|
+
group(lines, "not moved", [
|
|
2733
|
+
...results.filter(isMoveFallback).map((r) => moveFallbackLine(r, prune)),
|
|
2734
|
+
...of("move-unsupported").map(
|
|
2735
|
+
(r) => `${r.movedFrom} -> ${r.sourcePath}: the server does not support moves yet; ${r.movedFrom} kept, ${r.sourcePath} not pushed`
|
|
2736
|
+
)
|
|
2737
|
+
]);
|
|
2331
2738
|
group(
|
|
2332
2739
|
lines,
|
|
2333
2740
|
"duplicate",
|
|
2334
2741
|
of("duplicate").map(
|
|
2335
2742
|
(r) => {
|
|
2336
|
-
var
|
|
2337
|
-
return `${r.sourcePath}: duplicate of ${(
|
|
2743
|
+
var _a3;
|
|
2744
|
+
return `${r.sourcePath}: duplicate of ${(_a3 = r.duplicateOfSourcePath) != null ? _a3 : "another source in this project"}`;
|
|
2338
2745
|
}
|
|
2339
2746
|
)
|
|
2340
2747
|
);
|
|
2341
|
-
group(lines, "conflict",
|
|
2748
|
+
group(lines, "conflict", [
|
|
2749
|
+
...of("conflict").map(conflictLine),
|
|
2750
|
+
...of("delete-conflict").map(deleteConflictLine)
|
|
2751
|
+
]);
|
|
2342
2752
|
group(
|
|
2343
2753
|
lines,
|
|
2344
2754
|
"changed during the run",
|
|
@@ -2346,15 +2756,44 @@ function formatPushReport(input) {
|
|
|
2346
2756
|
(r) => `${r.sourcePath}: changed-during-run; not sent, the next push sends the new content`
|
|
2347
2757
|
)
|
|
2348
2758
|
);
|
|
2759
|
+
group(lines, "failed", [
|
|
2760
|
+
...of("failed").map((r) => `${r.sourcePath}: ${r.error}`),
|
|
2761
|
+
...of("delete-failed").map(
|
|
2762
|
+
(r) => `${r.sourcePath}: ${r.error}; not deleted`
|
|
2763
|
+
)
|
|
2764
|
+
]);
|
|
2349
2765
|
group(
|
|
2350
2766
|
lines,
|
|
2351
|
-
"
|
|
2352
|
-
of("
|
|
2767
|
+
"deleted",
|
|
2768
|
+
of("deleted").map(
|
|
2769
|
+
(r) => r.overwrote ? `${r.sourcePath}: deleted the version ${who(r.overwrote)} changed at ${when(r.overwrote)} (--force)` : r.sourcePath
|
|
2770
|
+
)
|
|
2353
2771
|
);
|
|
2772
|
+
group(
|
|
2773
|
+
lines,
|
|
2774
|
+
"already gone",
|
|
2775
|
+
of("already-gone").map(
|
|
2776
|
+
(r) => `${r.sourcePath}: already gone on the server`
|
|
2777
|
+
)
|
|
2778
|
+
);
|
|
2779
|
+
group(
|
|
2780
|
+
lines,
|
|
2781
|
+
"deletion still running",
|
|
2782
|
+
of("delete-in-progress").map(
|
|
2783
|
+
(r) => `${r.sourcePath}: deletion still running on the server; run again to confirm`
|
|
2784
|
+
)
|
|
2785
|
+
);
|
|
2786
|
+
const pruned = new Set(
|
|
2787
|
+
results.filter((r) => DELETE_STATUSES.has(r.status)).map((r) => r.sourcePath)
|
|
2788
|
+
);
|
|
2789
|
+
const kept = [
|
|
2790
|
+
...plan.removed,
|
|
2791
|
+
...((_a2 = input.pruneTargets) != null ? _a2 : []).filter((p) => !plan.removed.includes(p))
|
|
2792
|
+
];
|
|
2354
2793
|
group(
|
|
2355
2794
|
lines,
|
|
2356
2795
|
"removed",
|
|
2357
|
-
|
|
2796
|
+
kept.filter((p) => !pruned.has(p)).map((p) => `${p}: removed locally; server entry kept`)
|
|
2358
2797
|
);
|
|
2359
2798
|
group(lines, "skipped", plan.skipped.map(skippedLine));
|
|
2360
2799
|
const unchanged = countOutcomes(plan, results).unchanged;
|
|
@@ -2368,6 +2807,11 @@ function formatDryRunReport(input) {
|
|
|
2368
2807
|
const lines = [
|
|
2369
2808
|
`Dry run of a context push from ${input.directory} to project ${input.projectId}: nothing was sent and the lock was not written.`
|
|
2370
2809
|
];
|
|
2810
|
+
group(
|
|
2811
|
+
lines,
|
|
2812
|
+
"moved",
|
|
2813
|
+
plan.moves.map((move) => `${move.from} -> ${move.to}`)
|
|
2814
|
+
);
|
|
2371
2815
|
group(
|
|
2372
2816
|
lines,
|
|
2373
2817
|
"new",
|
|
@@ -2378,13 +2822,17 @@ function formatDryRunReport(input) {
|
|
|
2378
2822
|
"changed",
|
|
2379
2823
|
plan.push.filter((entry) => entry.expectedContentHash !== void 0).map((entry) => entry.sourcePath)
|
|
2380
2824
|
);
|
|
2381
|
-
|
|
2382
|
-
lines,
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2825
|
+
if (input.prune) {
|
|
2826
|
+
group(lines, "would delete", plan.removed);
|
|
2827
|
+
} else {
|
|
2828
|
+
group(
|
|
2829
|
+
lines,
|
|
2830
|
+
"removed",
|
|
2831
|
+
plan.removed.map(
|
|
2832
|
+
(p) => `${p}: removed locally; server entry would be kept`
|
|
2833
|
+
)
|
|
2834
|
+
);
|
|
2835
|
+
}
|
|
2388
2836
|
group(lines, "skipped", plan.skipped.map(skippedLine));
|
|
2389
2837
|
if (plan.unchangedLocal.length > 0) {
|
|
2390
2838
|
lines.push(`unchanged (${plan.unchangedLocal.length})`);
|
|
@@ -2397,6 +2845,7 @@ function contextPushJson(input) {
|
|
|
2397
2845
|
directory: input.directory,
|
|
2398
2846
|
dryRun: input.dryRun,
|
|
2399
2847
|
force: input.force,
|
|
2848
|
+
prune: input.prune,
|
|
2400
2849
|
lock: input.lockPath,
|
|
2401
2850
|
lockWritten: input.lockWritten,
|
|
2402
2851
|
plan: {
|
|
@@ -2409,6 +2858,12 @@ function contextPushJson(input) {
|
|
|
2409
2858
|
expectedContentHash: (_a2 = entry.expectedContentHash) != null ? _a2 : null
|
|
2410
2859
|
};
|
|
2411
2860
|
}),
|
|
2861
|
+
moves: input.plan.moves.map((move) => ({
|
|
2862
|
+
from: move.from,
|
|
2863
|
+
to: move.to,
|
|
2864
|
+
sha256: move.sha256,
|
|
2865
|
+
contextId: move.contextId
|
|
2866
|
+
})),
|
|
2412
2867
|
unchangedLocal: input.plan.unchangedLocal,
|
|
2413
2868
|
removed: input.plan.removed,
|
|
2414
2869
|
forgotten: input.plan.forgotten,
|
|
@@ -2437,6 +2892,9 @@ function buildContextCommand() {
|
|
|
2437
2892
|
).requiredOption("--project <id>", "Project ID").option("--org <slug>", "Organization context").option(
|
|
2438
2893
|
"--force",
|
|
2439
2894
|
"On a conflict, replace the server's version once with this folder's"
|
|
2895
|
+
).option(
|
|
2896
|
+
"--prune",
|
|
2897
|
+
"Delete the server entries of files removed locally, only in the version last pushed"
|
|
2440
2898
|
).option("--dry-run", "Print the plan; send nothing and write no lock").option(
|
|
2441
2899
|
"--exclude <pattern>",
|
|
2442
2900
|
"Also leave out paths matching this gitignore pattern (repeatable)",
|
|
@@ -2544,7 +3002,8 @@ function runPush(dir, opts, format) {
|
|
|
2544
3002
|
formatDryRunReport({
|
|
2545
3003
|
projectId: opts.project,
|
|
2546
3004
|
directory: root,
|
|
2547
|
-
plan
|
|
3005
|
+
plan,
|
|
3006
|
+
prune: Boolean(opts.prune)
|
|
2548
3007
|
})
|
|
2549
3008
|
);
|
|
2550
3009
|
return;
|
|
@@ -2555,7 +3014,9 @@ function runPush(dir, opts, format) {
|
|
|
2555
3014
|
org: opts.org,
|
|
2556
3015
|
root,
|
|
2557
3016
|
plan,
|
|
2558
|
-
force: Boolean(opts.force)
|
|
3017
|
+
force: Boolean(opts.force),
|
|
3018
|
+
prune: Boolean(opts.prune),
|
|
3019
|
+
lock
|
|
2559
3020
|
});
|
|
2560
3021
|
const next = nextContextLock({
|
|
2561
3022
|
previous: lock,
|
|
@@ -2584,14 +3045,20 @@ function runPush(dir, opts, format) {
|
|
|
2584
3045
|
projectId: opts.project,
|
|
2585
3046
|
directory: root,
|
|
2586
3047
|
plan,
|
|
2587
|
-
results: pushed.results
|
|
3048
|
+
results: pushed.results,
|
|
3049
|
+
prune: Boolean(opts.prune),
|
|
3050
|
+
pruneTargets: pushed.pruneTargets
|
|
2588
3051
|
})
|
|
2589
3052
|
);
|
|
2590
3053
|
}
|
|
3054
|
+
const prune = Boolean(opts.prune);
|
|
2591
3055
|
if (pushed.stoppedBy !== null) {
|
|
2592
|
-
throw
|
|
3056
|
+
throw prune ? new CliFailure(
|
|
3057
|
+
`${pushed.stoppedBy.message} (${pruneSummary(pushed.results, pushed.pruneTargets)})`,
|
|
3058
|
+
pushed.stoppedBy.exitCode
|
|
3059
|
+
) : pushed.stoppedBy;
|
|
2593
3060
|
}
|
|
2594
|
-
throwIfIncomplete(pushed.results);
|
|
3061
|
+
throwIfIncomplete(pushed.results, prune, pushed.pruneTargets);
|
|
2595
3062
|
});
|
|
2596
3063
|
}
|
|
2597
3064
|
function jsonOutcome(input) {
|
|
@@ -2602,36 +3069,93 @@ function jsonOutcome(input) {
|
|
|
2602
3069
|
lockWritten: input.lockWritten,
|
|
2603
3070
|
dryRun: Boolean(input.opts.dryRun),
|
|
2604
3071
|
force: Boolean(input.opts.force),
|
|
3072
|
+
prune: Boolean(input.opts.prune),
|
|
2605
3073
|
plan: input.plan,
|
|
2606
3074
|
results: input.results
|
|
2607
3075
|
});
|
|
2608
3076
|
}
|
|
2609
|
-
function
|
|
2610
|
-
const
|
|
2611
|
-
const
|
|
2612
|
-
|
|
3077
|
+
function pruneSummary(results, targets) {
|
|
3078
|
+
const count = (status) => results.filter((r) => r.status === status).length;
|
|
3079
|
+
const settled = new Set(
|
|
3080
|
+
results.filter(
|
|
3081
|
+
(r) => r.status === "deleted" || r.status === "already-gone"
|
|
3082
|
+
).map((r) => r.sourcePath)
|
|
3083
|
+
);
|
|
3084
|
+
const notDeleted = targets.filter((path9) => !settled.has(path9)).length;
|
|
3085
|
+
let text = `--prune: ${count("deleted")} deleted, ${count("already-gone")} already gone, ${notDeleted} not deleted`;
|
|
3086
|
+
const first = results.find((r) => r.status === "delete-failed");
|
|
3087
|
+
if (first && first.status === "delete-failed") {
|
|
3088
|
+
text += `, first ${first.sourcePath}: ${first.error}`;
|
|
3089
|
+
}
|
|
3090
|
+
return text;
|
|
3091
|
+
}
|
|
3092
|
+
function throwIfIncomplete(results, prune, pruneTargets) {
|
|
3093
|
+
var _a2;
|
|
3094
|
+
const pushes = results.filter((r) => !DELETE_STATUSES.has(r.status));
|
|
3095
|
+
const failed = pushes.filter((r) => r.status === "failed");
|
|
3096
|
+
const conflicts = pushes.filter((r) => r.status === "conflict");
|
|
3097
|
+
const unsupported = pushes.filter((r) => r.status === "move-unsupported");
|
|
3098
|
+
const deleteFailed = results.filter((r) => r.status === "delete-failed");
|
|
3099
|
+
const deleteConflicts = results.filter(
|
|
3100
|
+
(r) => r.status === "delete-conflict"
|
|
3101
|
+
);
|
|
3102
|
+
const stillDeleting = results.filter(
|
|
3103
|
+
(r) => r.status === "delete-in-progress"
|
|
3104
|
+
);
|
|
3105
|
+
if (failed.length === 0 && conflicts.length === 0 && unsupported.length === 0 && deleteFailed.length === 0 && deleteConflicts.length === 0 && stillDeleting.length === 0) {
|
|
2613
3106
|
return;
|
|
2614
3107
|
}
|
|
2615
|
-
const
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
3108
|
+
const sentences = [];
|
|
3109
|
+
const total = conflicts.length + failed.length + unsupported.length;
|
|
3110
|
+
if (total > 0) {
|
|
3111
|
+
const parts = [];
|
|
3112
|
+
if (conflicts.length > 0) {
|
|
3113
|
+
parts.push(
|
|
3114
|
+
`${conflicts.length} conflict${conflicts.length === 1 ? "" : "s"}`
|
|
3115
|
+
);
|
|
3116
|
+
}
|
|
3117
|
+
if (unsupported.length > 0) {
|
|
3118
|
+
parts.push(
|
|
3119
|
+
`${unsupported.length} move${unsupported.length === 1 ? "" : "s"} the server does not support yet`
|
|
3120
|
+
);
|
|
3121
|
+
}
|
|
3122
|
+
const first = failed[0];
|
|
3123
|
+
if (first && first.status === "failed") {
|
|
3124
|
+
parts.push(
|
|
3125
|
+
`${failed.length} failed, first ${first.sourcePath}: ${first.error}`
|
|
3126
|
+
);
|
|
3127
|
+
}
|
|
3128
|
+
sentences.push(
|
|
3129
|
+
`${total} of ${pushes.length} file${pushes.length === 1 ? "" : "s"} sent ${total === 1 ? "was" : "were"} not stored (${parts.join(", ")}).`
|
|
2619
3130
|
);
|
|
3131
|
+
if (conflicts.length > 0) {
|
|
3132
|
+
sentences.push(
|
|
3133
|
+
"A conflict means the server holds a version this folder did not name, or deleted the one it named: compare the two in the project's Context tab, and use --force to replace the version the conflict reported with this folder's (or to send a deleted file again with no version, which recreates it, or answers duplicate if that content is already stored under another path)."
|
|
3134
|
+
);
|
|
3135
|
+
}
|
|
2620
3136
|
}
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
`${failed.length} failed, first ${first.sourcePath}: ${first.error}`
|
|
3137
|
+
if (unsupported.length > 0) {
|
|
3138
|
+
sentences.push(
|
|
3139
|
+
"This server does not support moves yet: a moved file's old path stays on the server and in the lock, its new path is not pushed, and the move is sent again on the next push."
|
|
2625
3140
|
);
|
|
2626
3141
|
}
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
3142
|
+
if (prune) {
|
|
3143
|
+
sentences.push(`${pruneSummary(results, pruneTargets)}.`);
|
|
3144
|
+
if (deleteConflicts.length > 0) {
|
|
3145
|
+
sentences.push(
|
|
3146
|
+
"A file changed on the server since your last push is not deleted: compare it in the project's Context tab, and use --force to delete the version the conflict reported."
|
|
3147
|
+
);
|
|
3148
|
+
}
|
|
3149
|
+
if (stillDeleting.length > 0) {
|
|
3150
|
+
sentences.push(
|
|
3151
|
+
"A deletion still running on the server keeps its lock entry: run again to confirm it."
|
|
3152
|
+
);
|
|
3153
|
+
}
|
|
2631
3154
|
}
|
|
3155
|
+
const firstFailure = (_a2 = failed[0]) != null ? _a2 : deleteFailed[0];
|
|
2632
3156
|
throw new CliFailure(
|
|
2633
|
-
|
|
2634
|
-
|
|
3157
|
+
sentences.join(" "),
|
|
3158
|
+
firstFailure && (firstFailure.status === "failed" || firstFailure.status === "delete-failed") ? firstFailure.exitCode : 1
|
|
2635
3159
|
);
|
|
2636
3160
|
}
|
|
2637
3161
|
|