@p4pilot/core 0.1.0
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/browser.cjs +873 -0
- package/dist/browser.d.cts +3 -0
- package/dist/browser.d.ts +3 -0
- package/dist/browser.js +26 -0
- package/dist/changelist-BD8jDKA6.d.ts +123 -0
- package/dist/changelist-D-VWhdnq.d.cts +123 -0
- package/dist/chunk-HLG24B6W.js +387 -0
- package/dist/chunk-QIZ2GXWH.js +453 -0
- package/dist/index.cjs +566 -0
- package/dist/index.d.cts +25 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +97 -0
- package/dist/p4-runner-CmZD1E6u.d.cts +69 -0
- package/dist/p4-runner-CmZD1E6u.d.ts +69 -0
- package/dist/testing/mock-runner.cjs +411 -0
- package/dist/testing/mock-runner.d.cts +48 -0
- package/dist/testing/mock-runner.d.ts +48 -0
- package/dist/testing/mock-runner.js +6 -0
- package/package.json +67 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
type P4Action = "edit" | "add" | "delete" | "branch" | "integrate" | "move/add" | "move/delete";
|
|
2
|
+
interface OpenedFile {
|
|
3
|
+
depotFile: string;
|
|
4
|
+
clientFile?: string;
|
|
5
|
+
rev?: number;
|
|
6
|
+
action: P4Action;
|
|
7
|
+
change: string;
|
|
8
|
+
type: string;
|
|
9
|
+
}
|
|
10
|
+
interface FileStat {
|
|
11
|
+
depotFile: string;
|
|
12
|
+
clientFile?: string;
|
|
13
|
+
headType?: string;
|
|
14
|
+
headRev?: number;
|
|
15
|
+
haveRev?: number;
|
|
16
|
+
action?: P4Action;
|
|
17
|
+
isOpened: boolean;
|
|
18
|
+
isTracked: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface ChangelistSummary {
|
|
21
|
+
change: string;
|
|
22
|
+
description: string;
|
|
23
|
+
status: "pending" | "submitted" | "shelved";
|
|
24
|
+
user?: string;
|
|
25
|
+
client?: string;
|
|
26
|
+
files?: string[];
|
|
27
|
+
}
|
|
28
|
+
interface DescribeResult {
|
|
29
|
+
change: string;
|
|
30
|
+
description: string;
|
|
31
|
+
user?: string;
|
|
32
|
+
files: Array<{
|
|
33
|
+
depotFile: string;
|
|
34
|
+
action: P4Action;
|
|
35
|
+
rev?: number;
|
|
36
|
+
}>;
|
|
37
|
+
diff?: string;
|
|
38
|
+
}
|
|
39
|
+
declare class P4PilotError extends Error {
|
|
40
|
+
readonly code: P4PilotErrorCode;
|
|
41
|
+
readonly detail?: string | undefined;
|
|
42
|
+
constructor(message: string, code: P4PilotErrorCode, detail?: string | undefined);
|
|
43
|
+
}
|
|
44
|
+
type P4PilotErrorCode = "P4_NOT_FOUND" | "P4_COMMAND_FAILED" | "NOT_CONNECTED" | "FILE_NOT_IN_CLIENT" | "INVALID_INPUT";
|
|
45
|
+
|
|
46
|
+
interface P4Result {
|
|
47
|
+
stdout: string;
|
|
48
|
+
stderr: string;
|
|
49
|
+
exitCode: number;
|
|
50
|
+
}
|
|
51
|
+
interface P4RunOptions {
|
|
52
|
+
cwd?: string;
|
|
53
|
+
input?: string;
|
|
54
|
+
env?: Record<string, string>;
|
|
55
|
+
}
|
|
56
|
+
interface P4Runner {
|
|
57
|
+
run(args: string[], opts?: P4RunOptions): Promise<P4Result>;
|
|
58
|
+
}
|
|
59
|
+
interface ExecaP4RunnerOptions {
|
|
60
|
+
p4Path?: string;
|
|
61
|
+
env?: Record<string, string>;
|
|
62
|
+
}
|
|
63
|
+
declare class ExecaP4Runner implements P4Runner {
|
|
64
|
+
#private;
|
|
65
|
+
constructor(options?: ExecaP4RunnerOptions);
|
|
66
|
+
run(args: string[], opts?: P4RunOptions): Promise<P4Result>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { type ChangelistSummary as C, type DescribeResult as D, ExecaP4Runner as E, type FileStat as F, type OpenedFile as O, type P4Action as P, P4PilotError as a, type P4PilotErrorCode as b, type P4Result as c, type P4RunOptions as d, type P4Runner as e, type ExecaP4RunnerOptions as f };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
type P4Action = "edit" | "add" | "delete" | "branch" | "integrate" | "move/add" | "move/delete";
|
|
2
|
+
interface OpenedFile {
|
|
3
|
+
depotFile: string;
|
|
4
|
+
clientFile?: string;
|
|
5
|
+
rev?: number;
|
|
6
|
+
action: P4Action;
|
|
7
|
+
change: string;
|
|
8
|
+
type: string;
|
|
9
|
+
}
|
|
10
|
+
interface FileStat {
|
|
11
|
+
depotFile: string;
|
|
12
|
+
clientFile?: string;
|
|
13
|
+
headType?: string;
|
|
14
|
+
headRev?: number;
|
|
15
|
+
haveRev?: number;
|
|
16
|
+
action?: P4Action;
|
|
17
|
+
isOpened: boolean;
|
|
18
|
+
isTracked: boolean;
|
|
19
|
+
}
|
|
20
|
+
interface ChangelistSummary {
|
|
21
|
+
change: string;
|
|
22
|
+
description: string;
|
|
23
|
+
status: "pending" | "submitted" | "shelved";
|
|
24
|
+
user?: string;
|
|
25
|
+
client?: string;
|
|
26
|
+
files?: string[];
|
|
27
|
+
}
|
|
28
|
+
interface DescribeResult {
|
|
29
|
+
change: string;
|
|
30
|
+
description: string;
|
|
31
|
+
user?: string;
|
|
32
|
+
files: Array<{
|
|
33
|
+
depotFile: string;
|
|
34
|
+
action: P4Action;
|
|
35
|
+
rev?: number;
|
|
36
|
+
}>;
|
|
37
|
+
diff?: string;
|
|
38
|
+
}
|
|
39
|
+
declare class P4PilotError extends Error {
|
|
40
|
+
readonly code: P4PilotErrorCode;
|
|
41
|
+
readonly detail?: string | undefined;
|
|
42
|
+
constructor(message: string, code: P4PilotErrorCode, detail?: string | undefined);
|
|
43
|
+
}
|
|
44
|
+
type P4PilotErrorCode = "P4_NOT_FOUND" | "P4_COMMAND_FAILED" | "NOT_CONNECTED" | "FILE_NOT_IN_CLIENT" | "INVALID_INPUT";
|
|
45
|
+
|
|
46
|
+
interface P4Result {
|
|
47
|
+
stdout: string;
|
|
48
|
+
stderr: string;
|
|
49
|
+
exitCode: number;
|
|
50
|
+
}
|
|
51
|
+
interface P4RunOptions {
|
|
52
|
+
cwd?: string;
|
|
53
|
+
input?: string;
|
|
54
|
+
env?: Record<string, string>;
|
|
55
|
+
}
|
|
56
|
+
interface P4Runner {
|
|
57
|
+
run(args: string[], opts?: P4RunOptions): Promise<P4Result>;
|
|
58
|
+
}
|
|
59
|
+
interface ExecaP4RunnerOptions {
|
|
60
|
+
p4Path?: string;
|
|
61
|
+
env?: Record<string, string>;
|
|
62
|
+
}
|
|
63
|
+
declare class ExecaP4Runner implements P4Runner {
|
|
64
|
+
#private;
|
|
65
|
+
constructor(options?: ExecaP4RunnerOptions);
|
|
66
|
+
run(args: string[], opts?: P4RunOptions): Promise<P4Result>;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { type ChangelistSummary as C, type DescribeResult as D, ExecaP4Runner as E, type FileStat as F, type OpenedFile as O, type P4Action as P, P4PilotError as a, type P4PilotErrorCode as b, type P4Result as c, type P4RunOptions as d, type P4Runner as e, type ExecaP4RunnerOptions as f };
|
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/testing/mock-runner.ts
|
|
21
|
+
var mock_runner_exports = {};
|
|
22
|
+
__export(mock_runner_exports, {
|
|
23
|
+
MockP4Runner: () => MockP4Runner
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(mock_runner_exports);
|
|
26
|
+
var success = (stdout = "") => ({
|
|
27
|
+
stdout,
|
|
28
|
+
stderr: "",
|
|
29
|
+
exitCode: 0
|
|
30
|
+
});
|
|
31
|
+
var failure = (stderr) => ({
|
|
32
|
+
stdout: "",
|
|
33
|
+
stderr,
|
|
34
|
+
exitCode: 1
|
|
35
|
+
});
|
|
36
|
+
function formatRecord(fields) {
|
|
37
|
+
return fields.filter(
|
|
38
|
+
(field) => field[1] !== void 0
|
|
39
|
+
).map(([key, rawValue]) => {
|
|
40
|
+
const [firstLine = "", ...continuationLines] = String(rawValue).split("\n");
|
|
41
|
+
return [`... ${key} ${firstLine}`, ...continuationLines].join("\n");
|
|
42
|
+
}).join("\n");
|
|
43
|
+
}
|
|
44
|
+
function formatRecords(records) {
|
|
45
|
+
if (records.length === 0) {
|
|
46
|
+
return "";
|
|
47
|
+
}
|
|
48
|
+
return `${records.map(formatRecord).join("\n\n")}
|
|
49
|
+
`;
|
|
50
|
+
}
|
|
51
|
+
function normalizePath(value) {
|
|
52
|
+
return value.replaceAll("\\", "/");
|
|
53
|
+
}
|
|
54
|
+
function relativePosix(from, to) {
|
|
55
|
+
const fromParts = from.replace(/\/+$/, "").split("/").filter(Boolean);
|
|
56
|
+
const toParts = to.split("/").filter(Boolean);
|
|
57
|
+
let i = 0;
|
|
58
|
+
while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i])
|
|
59
|
+
i += 1;
|
|
60
|
+
const up = fromParts.slice(i).map(() => "..");
|
|
61
|
+
return [...up, ...toParts.slice(i)].join("/");
|
|
62
|
+
}
|
|
63
|
+
function parseCommandFiles(args) {
|
|
64
|
+
let change = "default";
|
|
65
|
+
const files = [];
|
|
66
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
67
|
+
const argument = args[index];
|
|
68
|
+
if (argument === void 0) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (argument === "-c") {
|
|
72
|
+
change = args[index + 1] ?? "default";
|
|
73
|
+
index += 1;
|
|
74
|
+
} else if (!argument.startsWith("-")) {
|
|
75
|
+
files.push(argument);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return { change, files };
|
|
79
|
+
}
|
|
80
|
+
var MockP4Runner = class {
|
|
81
|
+
#state;
|
|
82
|
+
constructor(state) {
|
|
83
|
+
this.#state = state;
|
|
84
|
+
}
|
|
85
|
+
get state() {
|
|
86
|
+
return this.#state;
|
|
87
|
+
}
|
|
88
|
+
async run(args, opts) {
|
|
89
|
+
const commandArgs = args[0] === "-ztag" ? args.slice(1) : [...args];
|
|
90
|
+
const command = commandArgs[0];
|
|
91
|
+
switch (command) {
|
|
92
|
+
case "info":
|
|
93
|
+
return this.runInfo();
|
|
94
|
+
case "fstat":
|
|
95
|
+
return this.runFstat(commandArgs);
|
|
96
|
+
case "opened":
|
|
97
|
+
return this.runOpened(commandArgs);
|
|
98
|
+
case "edit":
|
|
99
|
+
return this.runEdit(commandArgs);
|
|
100
|
+
case "add":
|
|
101
|
+
return this.runAdd(commandArgs);
|
|
102
|
+
case "revert":
|
|
103
|
+
return this.runRevert(commandArgs);
|
|
104
|
+
case "where":
|
|
105
|
+
return this.runWhere(commandArgs);
|
|
106
|
+
case "changes":
|
|
107
|
+
return this.runChanges(commandArgs);
|
|
108
|
+
case "describe":
|
|
109
|
+
return this.runDescribe(commandArgs);
|
|
110
|
+
case "change":
|
|
111
|
+
return this.runChange(commandArgs, opts);
|
|
112
|
+
case "sync":
|
|
113
|
+
return this.runSync();
|
|
114
|
+
case "filelog":
|
|
115
|
+
return this.runFilelog(commandArgs);
|
|
116
|
+
default:
|
|
117
|
+
return failure(`Unsupported mock p4 command: ${command ?? ""}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
runInfo() {
|
|
121
|
+
return success(
|
|
122
|
+
formatRecords([
|
|
123
|
+
[
|
|
124
|
+
["userName", this.#state.user],
|
|
125
|
+
["clientName", this.#state.client],
|
|
126
|
+
["clientRoot", this.#state.root],
|
|
127
|
+
["serverAddress", this.#state.port]
|
|
128
|
+
]
|
|
129
|
+
])
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
runFstat(args) {
|
|
133
|
+
const requested = args.slice(1).filter((argument) => !argument.startsWith("-"));
|
|
134
|
+
const files = requested.length === 0 ? this.#state.files : requested.flatMap((file) => this.findFiles(file));
|
|
135
|
+
return success(
|
|
136
|
+
formatRecords(files.map((file) => this.fileStatFields(file)))
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
runOpened(args) {
|
|
140
|
+
const { files } = parseCommandFiles(args);
|
|
141
|
+
const changeIndex = args.indexOf("-c");
|
|
142
|
+
const requestedChange = changeIndex === -1 ? void 0 : args[changeIndex + 1];
|
|
143
|
+
const openedFiles = this.#state.files.filter((file) => {
|
|
144
|
+
if (file.opened === void 0) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
if (requestedChange !== void 0 && file.opened.change !== requestedChange) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
return files.length === 0 || files.some((requested) => this.matches(file, requested));
|
|
151
|
+
});
|
|
152
|
+
return success(
|
|
153
|
+
formatRecords(openedFiles.map((file) => this.openedFields(file)))
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
runEdit(args) {
|
|
157
|
+
const { change, files } = parseCommandFiles(args);
|
|
158
|
+
const edited = [];
|
|
159
|
+
for (const requested of files) {
|
|
160
|
+
const file = this.findFile(requested);
|
|
161
|
+
if (file === void 0 || file.headRev === void 0) {
|
|
162
|
+
return failure(`${requested} - no such file(s).`);
|
|
163
|
+
}
|
|
164
|
+
file.opened = { action: "edit", change };
|
|
165
|
+
edited.push(file);
|
|
166
|
+
}
|
|
167
|
+
return success(
|
|
168
|
+
formatRecords(edited.map((file) => this.openedFields(file)))
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
runAdd(args) {
|
|
172
|
+
const { change, files } = parseCommandFiles(args);
|
|
173
|
+
const added = [];
|
|
174
|
+
for (const requested of files) {
|
|
175
|
+
let file = this.findFile(requested);
|
|
176
|
+
if (file === void 0) {
|
|
177
|
+
const clientFile = normalizePath(requested);
|
|
178
|
+
file = {
|
|
179
|
+
depotFile: this.toDepotFile(clientFile),
|
|
180
|
+
clientFile,
|
|
181
|
+
headType: "text"
|
|
182
|
+
};
|
|
183
|
+
this.#state.files.push(file);
|
|
184
|
+
}
|
|
185
|
+
file.opened = { action: "add", change };
|
|
186
|
+
added.push(file);
|
|
187
|
+
}
|
|
188
|
+
return success(formatRecords(added.map((file) => this.openedFields(file))));
|
|
189
|
+
}
|
|
190
|
+
runRevert(args) {
|
|
191
|
+
const { files } = parseCommandFiles(args);
|
|
192
|
+
const reverted = [];
|
|
193
|
+
for (const requested of files) {
|
|
194
|
+
const fileIndex = this.#state.files.findIndex(
|
|
195
|
+
(file2) => this.matches(file2, requested)
|
|
196
|
+
);
|
|
197
|
+
const file = this.#state.files[fileIndex];
|
|
198
|
+
if (file === void 0 || file.opened === void 0) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
reverted.push([["depotFile", file.depotFile]]);
|
|
202
|
+
if (file.opened.action === "add" && file.headRev === void 0) {
|
|
203
|
+
this.#state.files.splice(fileIndex, 1);
|
|
204
|
+
} else {
|
|
205
|
+
delete file.opened;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return success(formatRecords(reverted));
|
|
209
|
+
}
|
|
210
|
+
runWhere(args) {
|
|
211
|
+
const requested = args.find(
|
|
212
|
+
(argument, index) => index > 0 && !argument.startsWith("-")
|
|
213
|
+
);
|
|
214
|
+
const file = requested === void 0 ? void 0 : this.findFile(requested);
|
|
215
|
+
if (file === void 0) {
|
|
216
|
+
return failure(`${requested ?? ""} - file(s) not in client view.`);
|
|
217
|
+
}
|
|
218
|
+
return success(
|
|
219
|
+
formatRecords([
|
|
220
|
+
[
|
|
221
|
+
["depotFile", file.depotFile],
|
|
222
|
+
["clientFile", file.clientFile],
|
|
223
|
+
["path", file.clientFile]
|
|
224
|
+
]
|
|
225
|
+
])
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
runChanges(args) {
|
|
229
|
+
let status;
|
|
230
|
+
let max;
|
|
231
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
232
|
+
if (args[index] === "-s") {
|
|
233
|
+
status = args[index + 1];
|
|
234
|
+
index += 1;
|
|
235
|
+
} else if (args[index] === "-m") {
|
|
236
|
+
max = Number(args[index + 1]);
|
|
237
|
+
index += 1;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
let changelists = [...this.#state.changelists ?? []];
|
|
241
|
+
if (status !== void 0) {
|
|
242
|
+
changelists = changelists.filter(
|
|
243
|
+
(changelist) => changelist.status === status
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (max !== void 0 && Number.isFinite(max)) {
|
|
247
|
+
changelists = changelists.slice(0, max);
|
|
248
|
+
}
|
|
249
|
+
return success(
|
|
250
|
+
formatRecords(
|
|
251
|
+
changelists.map((changelist) => [
|
|
252
|
+
["change", changelist.change],
|
|
253
|
+
["desc", changelist.description],
|
|
254
|
+
["status", changelist.status],
|
|
255
|
+
["user", changelist.user],
|
|
256
|
+
["client", changelist.client]
|
|
257
|
+
])
|
|
258
|
+
)
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
runDescribe(args) {
|
|
262
|
+
const change = [...args].reverse().find((argument) => !argument.startsWith("-"));
|
|
263
|
+
const changelist = this.#state.changelists?.find(
|
|
264
|
+
(item) => item.change === change
|
|
265
|
+
);
|
|
266
|
+
if (changelist === void 0) {
|
|
267
|
+
return failure(`Change ${change ?? ""} unknown.`);
|
|
268
|
+
}
|
|
269
|
+
const fields = [
|
|
270
|
+
["change", changelist.change],
|
|
271
|
+
["desc", changelist.description],
|
|
272
|
+
["user", changelist.user],
|
|
273
|
+
["status", changelist.status]
|
|
274
|
+
];
|
|
275
|
+
for (const [index, depotFile] of (changelist.files ?? []).entries()) {
|
|
276
|
+
const file = this.findFile(depotFile);
|
|
277
|
+
fields.push([`depotFile${index}`, depotFile]);
|
|
278
|
+
fields.push([`action${index}`, file?.opened?.action ?? "edit"]);
|
|
279
|
+
fields.push([`rev${index}`, file?.headRev]);
|
|
280
|
+
}
|
|
281
|
+
return success(formatRecords([fields]));
|
|
282
|
+
}
|
|
283
|
+
runChange(args, opts) {
|
|
284
|
+
if (!args.includes("-i")) {
|
|
285
|
+
return failure("MockP4Runner only supports change -i.");
|
|
286
|
+
}
|
|
287
|
+
const changelists = this.#state.changelists ?? [];
|
|
288
|
+
this.#state.changelists = changelists;
|
|
289
|
+
const nextChange = String(
|
|
290
|
+
changelists.reduce((highest, changelist) => {
|
|
291
|
+
const value = Number(changelist.change);
|
|
292
|
+
return Number.isFinite(value) ? Math.max(highest, value) : highest;
|
|
293
|
+
}, 0) + 1
|
|
294
|
+
);
|
|
295
|
+
const description = this.parseDescription(opts?.input ?? "");
|
|
296
|
+
changelists.push({
|
|
297
|
+
change: nextChange,
|
|
298
|
+
description,
|
|
299
|
+
status: "pending",
|
|
300
|
+
user: this.#state.user,
|
|
301
|
+
client: this.#state.client,
|
|
302
|
+
files: []
|
|
303
|
+
});
|
|
304
|
+
return success(formatRecords([[["change", nextChange]]]));
|
|
305
|
+
}
|
|
306
|
+
runSync() {
|
|
307
|
+
const records = this.#state.files.filter((file) => file.headRev !== void 0).map((file) => [
|
|
308
|
+
["depotFile", file.depotFile],
|
|
309
|
+
["rev", file.headRev]
|
|
310
|
+
]);
|
|
311
|
+
return success(formatRecords(records));
|
|
312
|
+
}
|
|
313
|
+
runFilelog(args) {
|
|
314
|
+
const files = [];
|
|
315
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
316
|
+
const argument = args[index];
|
|
317
|
+
if (argument === "-m") {
|
|
318
|
+
index += 1;
|
|
319
|
+
} else if (argument !== void 0 && !argument.startsWith("-")) {
|
|
320
|
+
files.push(argument);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const requested = files[0];
|
|
324
|
+
const file = requested === void 0 ? void 0 : this.findFile(requested);
|
|
325
|
+
if (file === void 0 || file.headRev === void 0) {
|
|
326
|
+
return failure(`${requested ?? ""} - no such file(s).`);
|
|
327
|
+
}
|
|
328
|
+
const fields = [
|
|
329
|
+
["depotFile", file.depotFile],
|
|
330
|
+
["rev0", file.headRev],
|
|
331
|
+
["change0", "1"],
|
|
332
|
+
["action0", "add"],
|
|
333
|
+
["user0", this.#state.user],
|
|
334
|
+
["desc0", "initial revision"]
|
|
335
|
+
];
|
|
336
|
+
return success(formatRecords([fields]));
|
|
337
|
+
}
|
|
338
|
+
fileStatFields(file) {
|
|
339
|
+
return [
|
|
340
|
+
["depotFile", file.depotFile],
|
|
341
|
+
["clientFile", file.clientFile],
|
|
342
|
+
["headType", file.headType],
|
|
343
|
+
["headRev", file.headRev],
|
|
344
|
+
["fileSize", file.sizeBytes],
|
|
345
|
+
["action", file.opened?.action],
|
|
346
|
+
["change", file.opened?.change]
|
|
347
|
+
];
|
|
348
|
+
}
|
|
349
|
+
openedFields(file) {
|
|
350
|
+
return [
|
|
351
|
+
["depotFile", file.depotFile],
|
|
352
|
+
["clientFile", file.clientFile],
|
|
353
|
+
["rev", file.headRev],
|
|
354
|
+
["action", file.opened?.action],
|
|
355
|
+
["change", file.opened?.change],
|
|
356
|
+
["type", file.headType ?? "text"]
|
|
357
|
+
];
|
|
358
|
+
}
|
|
359
|
+
findFiles(requested) {
|
|
360
|
+
return this.#state.files.filter((file) => this.matches(file, requested));
|
|
361
|
+
}
|
|
362
|
+
findFile(requested) {
|
|
363
|
+
return this.#state.files.find((file) => this.matches(file, requested));
|
|
364
|
+
}
|
|
365
|
+
matches(file, requested) {
|
|
366
|
+
const normalized = normalizePath(requested);
|
|
367
|
+
if (normalized.endsWith("/...")) {
|
|
368
|
+
const prefix = normalized.slice(0, -3);
|
|
369
|
+
return normalizePath(file.clientFile).startsWith(prefix) || file.depotFile.startsWith(prefix);
|
|
370
|
+
}
|
|
371
|
+
return normalizePath(file.clientFile) === normalized || file.depotFile === normalized;
|
|
372
|
+
}
|
|
373
|
+
toDepotFile(clientFile) {
|
|
374
|
+
const normalizedRoot = normalizePath(this.#state.root).replace(/\/$/, "");
|
|
375
|
+
const relative = relativePosix(normalizedRoot, clientFile);
|
|
376
|
+
const trackedFile = this.#state.files.find(
|
|
377
|
+
(file) => file.headRev !== void 0
|
|
378
|
+
);
|
|
379
|
+
if (trackedFile !== void 0) {
|
|
380
|
+
const trackedRelative = relativePosix(
|
|
381
|
+
normalizedRoot,
|
|
382
|
+
normalizePath(trackedFile.clientFile)
|
|
383
|
+
);
|
|
384
|
+
const suffix = `/${trackedRelative}`;
|
|
385
|
+
const depotRoot = trackedFile.depotFile.endsWith(suffix) ? trackedFile.depotFile.slice(0, -suffix.length) : "//depot";
|
|
386
|
+
return `${depotRoot}/${relative}`;
|
|
387
|
+
}
|
|
388
|
+
return `//depot/${relative}`;
|
|
389
|
+
}
|
|
390
|
+
parseDescription(input) {
|
|
391
|
+
const lines = input.split(/\r?\n/);
|
|
392
|
+
const descriptionIndex = lines.findIndex(
|
|
393
|
+
(line) => line.startsWith("Description:")
|
|
394
|
+
);
|
|
395
|
+
if (descriptionIndex === -1) {
|
|
396
|
+
return "";
|
|
397
|
+
}
|
|
398
|
+
const descriptionLines = [];
|
|
399
|
+
for (const line of lines.slice(descriptionIndex + 1)) {
|
|
400
|
+
if (/^[A-Za-z][A-Za-z0-9-]*:/.test(line)) {
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
descriptionLines.push(line.replace(/^\t/, ""));
|
|
404
|
+
}
|
|
405
|
+
return descriptionLines.join("\n").trim();
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
409
|
+
0 && (module.exports = {
|
|
410
|
+
MockP4Runner
|
|
411
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { P as P4Action, C as ChangelistSummary, e as P4Runner, d as P4RunOptions, c as P4Result } from '../p4-runner-CmZD1E6u.cjs';
|
|
2
|
+
|
|
3
|
+
interface FakeFile {
|
|
4
|
+
depotFile: string;
|
|
5
|
+
clientFile: string;
|
|
6
|
+
headType?: string;
|
|
7
|
+
headRev?: number;
|
|
8
|
+
sizeBytes?: number;
|
|
9
|
+
opened?: {
|
|
10
|
+
action: P4Action;
|
|
11
|
+
change: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
interface FakeDepotState {
|
|
15
|
+
root: string;
|
|
16
|
+
port?: string;
|
|
17
|
+
client?: string;
|
|
18
|
+
user?: string;
|
|
19
|
+
files: FakeFile[];
|
|
20
|
+
changelists?: ChangelistSummary[];
|
|
21
|
+
}
|
|
22
|
+
declare class MockP4Runner implements P4Runner {
|
|
23
|
+
#private;
|
|
24
|
+
constructor(state: FakeDepotState);
|
|
25
|
+
get state(): FakeDepotState;
|
|
26
|
+
run(args: string[], opts?: P4RunOptions): Promise<P4Result>;
|
|
27
|
+
private runInfo;
|
|
28
|
+
private runFstat;
|
|
29
|
+
private runOpened;
|
|
30
|
+
private runEdit;
|
|
31
|
+
private runAdd;
|
|
32
|
+
private runRevert;
|
|
33
|
+
private runWhere;
|
|
34
|
+
private runChanges;
|
|
35
|
+
private runDescribe;
|
|
36
|
+
private runChange;
|
|
37
|
+
private runSync;
|
|
38
|
+
private runFilelog;
|
|
39
|
+
private fileStatFields;
|
|
40
|
+
private openedFields;
|
|
41
|
+
private findFiles;
|
|
42
|
+
private findFile;
|
|
43
|
+
private matches;
|
|
44
|
+
private toDepotFile;
|
|
45
|
+
private parseDescription;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { type FakeDepotState, type FakeFile, MockP4Runner };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { P as P4Action, C as ChangelistSummary, e as P4Runner, d as P4RunOptions, c as P4Result } from '../p4-runner-CmZD1E6u.js';
|
|
2
|
+
|
|
3
|
+
interface FakeFile {
|
|
4
|
+
depotFile: string;
|
|
5
|
+
clientFile: string;
|
|
6
|
+
headType?: string;
|
|
7
|
+
headRev?: number;
|
|
8
|
+
sizeBytes?: number;
|
|
9
|
+
opened?: {
|
|
10
|
+
action: P4Action;
|
|
11
|
+
change: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
interface FakeDepotState {
|
|
15
|
+
root: string;
|
|
16
|
+
port?: string;
|
|
17
|
+
client?: string;
|
|
18
|
+
user?: string;
|
|
19
|
+
files: FakeFile[];
|
|
20
|
+
changelists?: ChangelistSummary[];
|
|
21
|
+
}
|
|
22
|
+
declare class MockP4Runner implements P4Runner {
|
|
23
|
+
#private;
|
|
24
|
+
constructor(state: FakeDepotState);
|
|
25
|
+
get state(): FakeDepotState;
|
|
26
|
+
run(args: string[], opts?: P4RunOptions): Promise<P4Result>;
|
|
27
|
+
private runInfo;
|
|
28
|
+
private runFstat;
|
|
29
|
+
private runOpened;
|
|
30
|
+
private runEdit;
|
|
31
|
+
private runAdd;
|
|
32
|
+
private runRevert;
|
|
33
|
+
private runWhere;
|
|
34
|
+
private runChanges;
|
|
35
|
+
private runDescribe;
|
|
36
|
+
private runChange;
|
|
37
|
+
private runSync;
|
|
38
|
+
private runFilelog;
|
|
39
|
+
private fileStatFields;
|
|
40
|
+
private openedFields;
|
|
41
|
+
private findFiles;
|
|
42
|
+
private findFile;
|
|
43
|
+
private matches;
|
|
44
|
+
private toDepotFile;
|
|
45
|
+
private parseDescription;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { type FakeDepotState, type FakeFile, MockP4Runner };
|