@aaronshaf/ger 2.0.8 → 2.0.10
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/package.json +1 -1
- package/src/cli/index.ts +37 -0
- package/src/schemas/gerrit.ts +138 -123
- package/tests/diff.test.ts +2 -0
- package/tests/unit/schemas/gerrit.test.ts +52 -1
package/package.json
CHANGED
package/src/cli/index.ts
CHANGED
|
@@ -48,6 +48,43 @@ const program = new Command()
|
|
|
48
48
|
|
|
49
49
|
program.name('ger').description('LLM-centric Gerrit CLI tool').version(getVersion())
|
|
50
50
|
|
|
51
|
+
program.addHelpText(
|
|
52
|
+
'after',
|
|
53
|
+
`
|
|
54
|
+
CHANGE-ID FORMATS
|
|
55
|
+
Accepts numeric change numbers (12345) or full Change-IDs (I1234abc...).
|
|
56
|
+
Many commands auto-detect from HEAD commit's Change-Id footer when the
|
|
57
|
+
argument is omitted.
|
|
58
|
+
|
|
59
|
+
OUTPUT FORMATS
|
|
60
|
+
--json Structured JSON output for programmatic consumption
|
|
61
|
+
--xml XML with CDATA-wrapped content, optimized for LLM consumption
|
|
62
|
+
(default) Plain text for human reading
|
|
63
|
+
Most commands support both --json and --xml.
|
|
64
|
+
|
|
65
|
+
PIPING / STDIN
|
|
66
|
+
comment Reads message from stdin if no -m flag is provided
|
|
67
|
+
comment --batch Reads a JSON array from stdin for bulk commenting
|
|
68
|
+
|
|
69
|
+
AUTO-DETECTION
|
|
70
|
+
These commands auto-detect the change from HEAD's Change-Id footer when
|
|
71
|
+
the change-id argument is omitted:
|
|
72
|
+
show, build-status, topic, rebase, extract-url, diff, comments, vote
|
|
73
|
+
|
|
74
|
+
COMMON LLM WORKFLOWS
|
|
75
|
+
Review a change: ger show <id> → ger diff <id> → ger comments <id>
|
|
76
|
+
Post a review: ger comment <id> -m "..." → ger vote <id> <label> <score>
|
|
77
|
+
Manage changes: ger push, ger checkout <id>, ger abandon <id>, ger submit <id>
|
|
78
|
+
Check CI: ger build-status <id> --exit-status
|
|
79
|
+
|
|
80
|
+
EXIT CODES
|
|
81
|
+
build-status --exit-status returns non-zero on build failure (useful for scripting).
|
|
82
|
+
|
|
83
|
+
SUBCOMMAND HELP
|
|
84
|
+
Run ger <command> --help for detailed usage and examples.
|
|
85
|
+
`,
|
|
86
|
+
)
|
|
87
|
+
|
|
51
88
|
registerCommands(program)
|
|
52
89
|
|
|
53
90
|
program.parse(process.argv)
|
package/src/schemas/gerrit.ts
CHANGED
|
@@ -19,8 +19,34 @@ export const GerritCredentials: Schema.Schema<{
|
|
|
19
19
|
),
|
|
20
20
|
})
|
|
21
21
|
export type GerritCredentials = Schema.Schema.Type<typeof GerritCredentials>
|
|
22
|
+
export const FileInfo: Schema.Schema<{
|
|
23
|
+
readonly status?: 'A' | 'D' | 'R' | 'C' | 'M'
|
|
24
|
+
readonly lines_inserted?: number
|
|
25
|
+
readonly lines_deleted?: number
|
|
26
|
+
readonly size?: number
|
|
27
|
+
readonly size_delta?: number
|
|
28
|
+
readonly old_path?: string
|
|
29
|
+
readonly binary?: boolean
|
|
30
|
+
}> = Schema.Struct({
|
|
31
|
+
status: Schema.optional(Schema.Literal('A', 'D', 'R', 'C', 'M')), // Added, Deleted, Renamed, Copied, Modified
|
|
32
|
+
lines_inserted: Schema.optional(Schema.Number),
|
|
33
|
+
lines_deleted: Schema.optional(Schema.Number),
|
|
34
|
+
size_delta: Schema.optional(Schema.Number),
|
|
35
|
+
size: Schema.optional(Schema.Number),
|
|
36
|
+
old_path: Schema.optional(Schema.String),
|
|
37
|
+
binary: Schema.optional(Schema.Boolean),
|
|
38
|
+
})
|
|
39
|
+
export type FileInfo = Schema.Schema.Type<typeof FileInfo>
|
|
22
40
|
|
|
23
|
-
|
|
41
|
+
type PersonDate = { readonly name: string; readonly email: string; readonly date: string }
|
|
42
|
+
type ChangeMessage = {
|
|
43
|
+
readonly id: string
|
|
44
|
+
readonly message: string
|
|
45
|
+
readonly date: string
|
|
46
|
+
readonly _revision_number?: number
|
|
47
|
+
readonly tag?: string
|
|
48
|
+
}
|
|
49
|
+
type RevisionShape = {
|
|
24
50
|
readonly kind?: string
|
|
25
51
|
readonly _number: number
|
|
26
52
|
readonly created: string
|
|
@@ -28,39 +54,21 @@ export interface RevisionInfoType {
|
|
|
28
54
|
readonly _account_id: number
|
|
29
55
|
readonly name?: string
|
|
30
56
|
readonly email?: string
|
|
57
|
+
readonly username?: string
|
|
31
58
|
}
|
|
32
59
|
readonly ref: string
|
|
33
60
|
readonly fetch?: Record<string, unknown>
|
|
61
|
+
readonly description?: string
|
|
34
62
|
readonly commit?: {
|
|
35
63
|
readonly commit: string
|
|
36
|
-
readonly parents: ReadonlyArray<{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}>
|
|
40
|
-
readonly author: {
|
|
41
|
-
readonly name: string
|
|
42
|
-
readonly email: string
|
|
43
|
-
readonly date: string
|
|
44
|
-
}
|
|
45
|
-
readonly committer: {
|
|
46
|
-
readonly name: string
|
|
47
|
-
readonly email: string
|
|
48
|
-
readonly date: string
|
|
49
|
-
}
|
|
64
|
+
readonly parents: ReadonlyArray<{ readonly commit: string; readonly subject: string }>
|
|
65
|
+
readonly author: PersonDate
|
|
66
|
+
readonly committer: PersonDate
|
|
50
67
|
readonly subject: string
|
|
51
68
|
readonly message: string
|
|
52
69
|
}
|
|
53
|
-
readonly files?: Record<
|
|
54
|
-
|
|
55
|
-
{
|
|
56
|
-
readonly status?: 'A' | 'D' | 'R' | 'C' | 'M'
|
|
57
|
-
readonly lines_inserted?: number
|
|
58
|
-
readonly lines_deleted?: number
|
|
59
|
-
readonly size?: number
|
|
60
|
-
readonly size_delta?: number
|
|
61
|
-
readonly old_path?: string
|
|
62
|
-
}
|
|
63
|
-
>
|
|
70
|
+
readonly files?: Record<string, FileInfo>
|
|
71
|
+
readonly actions?: Record<string, unknown>
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
type ChangeReviewerAccount = {
|
|
@@ -68,12 +76,16 @@ type ChangeReviewerAccount = {
|
|
|
68
76
|
readonly name?: string
|
|
69
77
|
readonly email?: string
|
|
70
78
|
readonly username?: string
|
|
79
|
+
readonly display_name?: string
|
|
80
|
+
readonly tags?: ReadonlyArray<string>
|
|
71
81
|
}
|
|
72
82
|
const ChangeReviewerAccountInfo: Schema.Schema<ChangeReviewerAccount> = Schema.Struct({
|
|
73
83
|
_account_id: Schema.optional(Schema.Number),
|
|
74
84
|
name: Schema.optional(Schema.String),
|
|
75
85
|
email: Schema.optional(Schema.String),
|
|
76
86
|
username: Schema.optional(Schema.String),
|
|
87
|
+
display_name: Schema.optional(Schema.String),
|
|
88
|
+
tags: Schema.optional(Schema.Array(Schema.String)),
|
|
77
89
|
})
|
|
78
90
|
type ChangeReviewerMap = Partial<
|
|
79
91
|
Record<'REVIEWER' | 'CC' | 'REMOVED', ReadonlyArray<ChangeReviewerAccount>>
|
|
@@ -84,11 +96,19 @@ export const AccountInfo: Schema.Schema<{
|
|
|
84
96
|
readonly name?: string
|
|
85
97
|
readonly email?: string
|
|
86
98
|
readonly username?: string
|
|
99
|
+
readonly display_name?: string
|
|
100
|
+
readonly tags?: ReadonlyArray<string>
|
|
101
|
+
readonly inactive?: boolean
|
|
102
|
+
readonly status?: string
|
|
87
103
|
}> = Schema.Struct({
|
|
88
104
|
_account_id: Schema.Number,
|
|
89
105
|
name: Schema.optional(Schema.String),
|
|
90
106
|
email: Schema.optional(Schema.String),
|
|
91
107
|
username: Schema.optional(Schema.String),
|
|
108
|
+
display_name: Schema.optional(Schema.String),
|
|
109
|
+
tags: Schema.optional(Schema.Array(Schema.String)),
|
|
110
|
+
inactive: Schema.optional(Schema.Boolean),
|
|
111
|
+
status: Schema.optional(Schema.String),
|
|
92
112
|
})
|
|
93
113
|
export type AccountInfo = Schema.Schema.Type<typeof AccountInfo>
|
|
94
114
|
|
|
@@ -101,51 +121,35 @@ export const ChangeInfo: Schema.Schema<{
|
|
|
101
121
|
readonly status: 'NEW' | 'MERGED' | 'ABANDONED' | 'DRAFT'
|
|
102
122
|
readonly created?: string
|
|
103
123
|
readonly updated?: string
|
|
124
|
+
readonly submitted?: string
|
|
104
125
|
readonly insertions?: number
|
|
105
126
|
readonly deletions?: number
|
|
106
127
|
readonly _number: number
|
|
107
|
-
readonly owner?:
|
|
108
|
-
readonly _account_id: number
|
|
109
|
-
readonly name?: string
|
|
110
|
-
readonly email?: string
|
|
111
|
-
readonly username?: string
|
|
112
|
-
}
|
|
128
|
+
readonly owner?: AccountInfo
|
|
113
129
|
readonly labels?: Record<
|
|
114
130
|
string,
|
|
115
131
|
{
|
|
116
|
-
readonly approved?:
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
readonly username?: string
|
|
121
|
-
}
|
|
122
|
-
readonly rejected?: {
|
|
123
|
-
readonly _account_id: number
|
|
124
|
-
readonly name?: string
|
|
125
|
-
readonly email?: string
|
|
126
|
-
readonly username?: string
|
|
127
|
-
}
|
|
128
|
-
readonly recommended?: {
|
|
129
|
-
readonly _account_id: number
|
|
130
|
-
readonly name?: string
|
|
131
|
-
readonly email?: string
|
|
132
|
-
readonly username?: string
|
|
133
|
-
}
|
|
134
|
-
readonly disliked?: {
|
|
135
|
-
readonly _account_id: number
|
|
136
|
-
readonly name?: string
|
|
137
|
-
readonly email?: string
|
|
138
|
-
readonly username?: string
|
|
139
|
-
}
|
|
132
|
+
readonly approved?: AccountInfo
|
|
133
|
+
readonly rejected?: AccountInfo
|
|
134
|
+
readonly recommended?: AccountInfo
|
|
135
|
+
readonly disliked?: AccountInfo
|
|
140
136
|
readonly value?: number
|
|
141
137
|
}
|
|
142
138
|
>
|
|
143
139
|
readonly submittable?: boolean
|
|
144
140
|
readonly work_in_progress?: boolean
|
|
141
|
+
readonly is_private?: boolean
|
|
145
142
|
readonly current_revision?: string
|
|
146
|
-
readonly revisions?: Record<string,
|
|
143
|
+
readonly revisions?: Record<string, RevisionShape>
|
|
147
144
|
readonly topic?: string
|
|
145
|
+
readonly hashtags?: ReadonlyArray<string>
|
|
148
146
|
readonly reviewers?: ChangeReviewerMap
|
|
147
|
+
readonly mergeable?: boolean
|
|
148
|
+
readonly unresolved_comment_count?: number
|
|
149
|
+
readonly total_comment_count?: number
|
|
150
|
+
readonly attention_set?: Record<string, unknown>
|
|
151
|
+
readonly submit_type?: string
|
|
152
|
+
readonly messages?: ReadonlyArray<ChangeMessage>
|
|
149
153
|
}> = Schema.Struct({
|
|
150
154
|
id: Schema.String,
|
|
151
155
|
project: Schema.String,
|
|
@@ -155,6 +159,7 @@ export const ChangeInfo: Schema.Schema<{
|
|
|
155
159
|
status: Schema.Literal('NEW', 'MERGED', 'ABANDONED', 'DRAFT'),
|
|
156
160
|
created: Schema.optional(Schema.String),
|
|
157
161
|
updated: Schema.optional(Schema.String),
|
|
162
|
+
submitted: Schema.optional(Schema.String),
|
|
158
163
|
insertions: Schema.optional(Schema.Number),
|
|
159
164
|
deletions: Schema.optional(Schema.Number),
|
|
160
165
|
_number: Schema.Number,
|
|
@@ -171,6 +176,7 @@ export const ChangeInfo: Schema.Schema<{
|
|
|
171
176
|
default_value: Schema.optional(Schema.Number),
|
|
172
177
|
blocking: Schema.optional(Schema.Boolean),
|
|
173
178
|
optional: Schema.optional(Schema.Boolean),
|
|
179
|
+
description: Schema.optional(Schema.String),
|
|
174
180
|
values: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.String })),
|
|
175
181
|
all: Schema.optional(
|
|
176
182
|
Schema.Array(
|
|
@@ -180,6 +186,7 @@ export const ChangeInfo: Schema.Schema<{
|
|
|
180
186
|
email: Schema.optional(Schema.String),
|
|
181
187
|
username: Schema.optional(Schema.String),
|
|
182
188
|
value: Schema.optional(Schema.Number),
|
|
189
|
+
post_submit: Schema.optional(Schema.Boolean),
|
|
183
190
|
permitted_voting_range: Schema.optional(
|
|
184
191
|
Schema.Struct({ min: Schema.Number, max: Schema.Number }),
|
|
185
192
|
),
|
|
@@ -193,9 +200,11 @@ export const ChangeInfo: Schema.Schema<{
|
|
|
193
200
|
),
|
|
194
201
|
submittable: Schema.optional(Schema.Boolean),
|
|
195
202
|
work_in_progress: Schema.optional(Schema.Boolean),
|
|
203
|
+
is_private: Schema.optional(Schema.Boolean),
|
|
196
204
|
current_revision: Schema.optional(Schema.String),
|
|
197
205
|
revisions: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),
|
|
198
206
|
topic: Schema.optional(Schema.String),
|
|
207
|
+
hashtags: Schema.optional(Schema.Array(Schema.String)),
|
|
199
208
|
reviewers: Schema.optional(
|
|
200
209
|
Schema.Struct({
|
|
201
210
|
REVIEWER: Schema.optional(Schema.Array(ChangeReviewerAccountInfo)),
|
|
@@ -203,6 +212,22 @@ export const ChangeInfo: Schema.Schema<{
|
|
|
203
212
|
REMOVED: Schema.optional(Schema.Array(ChangeReviewerAccountInfo)),
|
|
204
213
|
}),
|
|
205
214
|
),
|
|
215
|
+
mergeable: Schema.optional(Schema.Boolean),
|
|
216
|
+
unresolved_comment_count: Schema.optional(Schema.Number),
|
|
217
|
+
total_comment_count: Schema.optional(Schema.Number),
|
|
218
|
+
attention_set: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),
|
|
219
|
+
submit_type: Schema.optional(Schema.String),
|
|
220
|
+
messages: Schema.optional(
|
|
221
|
+
Schema.Array(
|
|
222
|
+
Schema.Struct({
|
|
223
|
+
id: Schema.String,
|
|
224
|
+
message: Schema.String,
|
|
225
|
+
date: Schema.String,
|
|
226
|
+
_revision_number: Schema.optional(Schema.Number),
|
|
227
|
+
tag: Schema.optional(Schema.String),
|
|
228
|
+
}),
|
|
229
|
+
),
|
|
230
|
+
),
|
|
206
231
|
})
|
|
207
232
|
export type ChangeInfo = Schema.Schema.Type<typeof ChangeInfo>
|
|
208
233
|
|
|
@@ -221,6 +246,8 @@ export type CommentInput = Schema.Schema.Type<typeof CommentInput>
|
|
|
221
246
|
export const CommentInfo: Schema.Schema<{
|
|
222
247
|
readonly id: string
|
|
223
248
|
readonly path?: string
|
|
249
|
+
readonly patch_set?: number
|
|
250
|
+
readonly side?: 'PARENT' | 'REVISION'
|
|
224
251
|
readonly line?: number
|
|
225
252
|
readonly range?: {
|
|
226
253
|
readonly start_line: number
|
|
@@ -229,17 +256,18 @@ export const CommentInfo: Schema.Schema<{
|
|
|
229
256
|
readonly end_character?: number
|
|
230
257
|
}
|
|
231
258
|
readonly message: string
|
|
232
|
-
readonly author?:
|
|
233
|
-
readonly name?: string
|
|
234
|
-
readonly email?: string
|
|
235
|
-
readonly _account_id?: number
|
|
236
|
-
}
|
|
259
|
+
readonly author?: ChangeReviewerAccount
|
|
237
260
|
readonly updated?: string
|
|
238
261
|
readonly unresolved?: boolean
|
|
239
262
|
readonly in_reply_to?: string
|
|
263
|
+
readonly tag?: string
|
|
264
|
+
readonly change_message_id?: string
|
|
265
|
+
readonly commit_id?: string
|
|
240
266
|
}> = Schema.Struct({
|
|
241
267
|
id: Schema.String,
|
|
242
268
|
path: Schema.optional(Schema.String),
|
|
269
|
+
patch_set: Schema.optional(Schema.Number),
|
|
270
|
+
side: Schema.optional(Schema.Literal('PARENT', 'REVISION')),
|
|
243
271
|
line: Schema.optional(Schema.Number),
|
|
244
272
|
range: Schema.optional(
|
|
245
273
|
Schema.Struct({
|
|
@@ -250,40 +278,29 @@ export const CommentInfo: Schema.Schema<{
|
|
|
250
278
|
}),
|
|
251
279
|
),
|
|
252
280
|
message: Schema.String,
|
|
253
|
-
author: Schema.optional(
|
|
254
|
-
Schema.Struct({
|
|
255
|
-
name: Schema.optional(Schema.String),
|
|
256
|
-
email: Schema.optional(Schema.String),
|
|
257
|
-
_account_id: Schema.optional(Schema.Number),
|
|
258
|
-
}),
|
|
259
|
-
),
|
|
281
|
+
author: Schema.optional(ChangeReviewerAccountInfo),
|
|
260
282
|
updated: Schema.optional(Schema.String),
|
|
261
283
|
unresolved: Schema.optional(Schema.Boolean),
|
|
262
284
|
in_reply_to: Schema.optional(Schema.String),
|
|
285
|
+
tag: Schema.optional(Schema.String),
|
|
286
|
+
change_message_id: Schema.optional(Schema.String),
|
|
287
|
+
commit_id: Schema.optional(Schema.String),
|
|
263
288
|
})
|
|
264
289
|
export type CommentInfo = Schema.Schema.Type<typeof CommentInfo>
|
|
265
290
|
|
|
266
291
|
export const MessageInfo: Schema.Schema<{
|
|
267
292
|
readonly id: string
|
|
268
293
|
readonly message: string
|
|
269
|
-
readonly author?:
|
|
270
|
-
|
|
271
|
-
readonly name?: string
|
|
272
|
-
readonly email?: string
|
|
273
|
-
}
|
|
294
|
+
readonly author?: AccountInfo
|
|
295
|
+
readonly real_author?: AccountInfo
|
|
274
296
|
readonly date: string
|
|
275
297
|
readonly _revision_number?: number
|
|
276
298
|
readonly tag?: string
|
|
277
299
|
}> = Schema.Struct({
|
|
278
300
|
id: Schema.String,
|
|
279
301
|
message: Schema.String,
|
|
280
|
-
author: Schema.optional(
|
|
281
|
-
|
|
282
|
-
_account_id: Schema.Number,
|
|
283
|
-
name: Schema.optional(Schema.String),
|
|
284
|
-
email: Schema.optional(Schema.String),
|
|
285
|
-
}),
|
|
286
|
-
),
|
|
302
|
+
author: Schema.optional(AccountInfo),
|
|
303
|
+
real_author: Schema.optional(AccountInfo),
|
|
287
304
|
date: Schema.String,
|
|
288
305
|
_revision_number: Schema.optional(Schema.Number),
|
|
289
306
|
tag: Schema.optional(Schema.String),
|
|
@@ -341,35 +358,35 @@ export const ProjectInfo: Schema.Schema<{
|
|
|
341
358
|
readonly id: string
|
|
342
359
|
readonly name: string
|
|
343
360
|
readonly parent?: string
|
|
361
|
+
readonly description?: string
|
|
344
362
|
readonly state?: 'ACTIVE' | 'READ_ONLY' | 'HIDDEN'
|
|
345
363
|
}> = Schema.Struct({
|
|
346
364
|
id: Schema.String,
|
|
347
365
|
name: Schema.String,
|
|
348
366
|
parent: Schema.optional(Schema.String),
|
|
367
|
+
description: Schema.optional(Schema.String),
|
|
349
368
|
state: Schema.optional(Schema.Literal('ACTIVE', 'READ_ONLY', 'HIDDEN')),
|
|
350
369
|
})
|
|
351
370
|
export type ProjectInfo = Schema.Schema.Type<typeof ProjectInfo>
|
|
352
371
|
|
|
353
|
-
export const
|
|
354
|
-
readonly
|
|
355
|
-
readonly
|
|
356
|
-
readonly
|
|
357
|
-
readonly size?: number
|
|
358
|
-
readonly size_delta?: number
|
|
359
|
-
readonly old_path?: string
|
|
372
|
+
export const DiffFileMeta: Schema.Schema<{
|
|
373
|
+
readonly name: string
|
|
374
|
+
readonly content_type: string
|
|
375
|
+
readonly lines?: number
|
|
360
376
|
}> = Schema.Struct({
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
size_delta: Schema.optional(Schema.Number),
|
|
365
|
-
size: Schema.optional(Schema.Number),
|
|
366
|
-
old_path: Schema.optional(Schema.String),
|
|
377
|
+
name: Schema.String,
|
|
378
|
+
content_type: Schema.String,
|
|
379
|
+
lines: Schema.optional(Schema.Number),
|
|
367
380
|
})
|
|
368
|
-
export type
|
|
381
|
+
export type DiffFileMeta = Schema.Schema.Type<typeof DiffFileMeta>
|
|
369
382
|
|
|
370
383
|
export const FileDiffContent: Schema.Schema<{
|
|
371
|
-
readonly
|
|
372
|
-
readonly
|
|
384
|
+
readonly meta_a?: DiffFileMeta
|
|
385
|
+
readonly meta_b?: DiffFileMeta
|
|
386
|
+
readonly binary?: boolean
|
|
387
|
+
readonly change_type?: 'ADDED' | 'MODIFIED' | 'DELETED' | 'RENAMED' | 'COPIED' | 'REWRITE'
|
|
388
|
+
readonly diff_header?: ReadonlyArray<string>
|
|
389
|
+
readonly intraline_status?: 'OK' | 'TIMEOUT' | 'ERROR'
|
|
373
390
|
readonly content: ReadonlyArray<{
|
|
374
391
|
readonly a?: ReadonlyArray<string>
|
|
375
392
|
readonly b?: ReadonlyArray<string>
|
|
@@ -382,11 +399,15 @@ export const FileDiffContent: Schema.Schema<{
|
|
|
382
399
|
readonly due_to_rebase?: boolean
|
|
383
400
|
readonly skip?: number
|
|
384
401
|
}>
|
|
385
|
-
readonly change_type?: 'ADDED' | 'MODIFIED' | 'DELETED' | 'RENAMED' | 'COPIED'
|
|
386
|
-
readonly diff_header?: ReadonlyArray<string>
|
|
387
402
|
}> = Schema.Struct({
|
|
388
|
-
|
|
389
|
-
|
|
403
|
+
meta_a: Schema.optional(DiffFileMeta),
|
|
404
|
+
meta_b: Schema.optional(DiffFileMeta),
|
|
405
|
+
binary: Schema.optional(Schema.Boolean),
|
|
406
|
+
change_type: Schema.optional(
|
|
407
|
+
Schema.Literal('ADDED', 'MODIFIED', 'DELETED', 'RENAMED', 'COPIED', 'REWRITE'),
|
|
408
|
+
),
|
|
409
|
+
diff_header: Schema.optional(Schema.Array(Schema.String)),
|
|
410
|
+
intraline_status: Schema.optional(Schema.Literal('OK', 'TIMEOUT', 'ERROR')),
|
|
390
411
|
content: Schema.Array(
|
|
391
412
|
Schema.Struct({
|
|
392
413
|
a: Schema.optional(Schema.Array(Schema.String)), // Lines from old file
|
|
@@ -405,8 +426,6 @@ export const FileDiffContent: Schema.Schema<{
|
|
|
405
426
|
skip: Schema.optional(Schema.Number),
|
|
406
427
|
}),
|
|
407
428
|
),
|
|
408
|
-
change_type: Schema.optional(Schema.Literal('ADDED', 'MODIFIED', 'DELETED', 'RENAMED', 'COPIED')),
|
|
409
|
-
diff_header: Schema.optional(Schema.Array(Schema.String)),
|
|
410
429
|
})
|
|
411
430
|
export type FileDiffContent = Schema.Schema.Type<typeof FileDiffContent>
|
|
412
431
|
|
|
@@ -418,25 +437,16 @@ export const RevisionInfo: Schema.Schema<{
|
|
|
418
437
|
readonly _account_id: number
|
|
419
438
|
readonly name?: string
|
|
420
439
|
readonly email?: string
|
|
440
|
+
readonly username?: string
|
|
421
441
|
}
|
|
422
442
|
readonly ref: string
|
|
423
443
|
readonly fetch?: Record<string, unknown>
|
|
444
|
+
readonly description?: string
|
|
424
445
|
readonly commit?: {
|
|
425
446
|
readonly commit: string
|
|
426
|
-
readonly parents: ReadonlyArray<{
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}>
|
|
430
|
-
readonly author: {
|
|
431
|
-
readonly name: string
|
|
432
|
-
readonly email: string
|
|
433
|
-
readonly date: string
|
|
434
|
-
}
|
|
435
|
-
readonly committer: {
|
|
436
|
-
readonly name: string
|
|
437
|
-
readonly email: string
|
|
438
|
-
readonly date: string
|
|
439
|
-
}
|
|
447
|
+
readonly parents: ReadonlyArray<{ readonly commit: string; readonly subject: string }>
|
|
448
|
+
readonly author: PersonDate
|
|
449
|
+
readonly committer: PersonDate
|
|
440
450
|
readonly subject: string
|
|
441
451
|
readonly message: string
|
|
442
452
|
}
|
|
@@ -449,8 +459,10 @@ export const RevisionInfo: Schema.Schema<{
|
|
|
449
459
|
readonly size?: number
|
|
450
460
|
readonly size_delta?: number
|
|
451
461
|
readonly old_path?: string
|
|
462
|
+
readonly binary?: boolean
|
|
452
463
|
}
|
|
453
464
|
>
|
|
465
|
+
readonly actions?: Record<string, unknown>
|
|
454
466
|
}> = Schema.Struct({
|
|
455
467
|
kind: Schema.optional(Schema.String),
|
|
456
468
|
_number: Schema.Number,
|
|
@@ -459,9 +471,11 @@ export const RevisionInfo: Schema.Schema<{
|
|
|
459
471
|
_account_id: Schema.Number,
|
|
460
472
|
name: Schema.optional(Schema.String),
|
|
461
473
|
email: Schema.optional(Schema.String),
|
|
474
|
+
username: Schema.optional(Schema.String),
|
|
462
475
|
}),
|
|
463
476
|
ref: Schema.String,
|
|
464
477
|
fetch: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),
|
|
478
|
+
description: Schema.optional(Schema.String),
|
|
465
479
|
commit: Schema.optional(
|
|
466
480
|
Schema.Struct({
|
|
467
481
|
commit: Schema.String,
|
|
@@ -486,8 +500,11 @@ export const RevisionInfo: Schema.Schema<{
|
|
|
486
500
|
}),
|
|
487
501
|
),
|
|
488
502
|
files: Schema.optional(Schema.Record({ key: Schema.String, value: FileInfo })),
|
|
503
|
+
actions: Schema.optional(Schema.Record({ key: Schema.String, value: Schema.Any })),
|
|
489
504
|
})
|
|
490
505
|
export type RevisionInfo = Schema.Schema.Type<typeof RevisionInfo>
|
|
506
|
+
// Backwards-compatible alias used by mock-generator and other consumers
|
|
507
|
+
export type RevisionInfoType = RevisionShape
|
|
491
508
|
|
|
492
509
|
// Diff output format options
|
|
493
510
|
export const DiffFormat: Schema.Schema<'unified' | 'json' | 'files'> = Schema.Literal(
|
|
@@ -550,6 +567,7 @@ const ReviewerAccountInfo = Schema.Struct({
|
|
|
550
567
|
_account_id: Schema.Number,
|
|
551
568
|
name: Schema.optional(Schema.String),
|
|
552
569
|
email: Schema.optional(Schema.String),
|
|
570
|
+
username: Schema.optional(Schema.String),
|
|
553
571
|
})
|
|
554
572
|
|
|
555
573
|
export const ReviewerResult: Schema.Schema<{
|
|
@@ -558,11 +576,13 @@ export const ReviewerResult: Schema.Schema<{
|
|
|
558
576
|
readonly _account_id: number
|
|
559
577
|
readonly name?: string
|
|
560
578
|
readonly email?: string
|
|
579
|
+
readonly username?: string
|
|
561
580
|
}>
|
|
562
581
|
readonly ccs?: ReadonlyArray<{
|
|
563
582
|
readonly _account_id: number
|
|
564
583
|
readonly name?: string
|
|
565
584
|
readonly email?: string
|
|
585
|
+
readonly username?: string
|
|
566
586
|
}>
|
|
567
587
|
readonly error?: string
|
|
568
588
|
readonly confirm?: boolean
|
|
@@ -645,12 +665,7 @@ export const GroupDetailInfo: Schema.Schema<{
|
|
|
645
665
|
readonly owner?: string
|
|
646
666
|
readonly owner_id?: string
|
|
647
667
|
readonly created_on?: string
|
|
648
|
-
readonly members?: ReadonlyArray<
|
|
649
|
-
readonly _account_id: number
|
|
650
|
-
readonly name?: string
|
|
651
|
-
readonly email?: string
|
|
652
|
-
readonly username?: string
|
|
653
|
-
}>
|
|
668
|
+
readonly members?: ReadonlyArray<AccountInfo>
|
|
654
669
|
readonly includes?: ReadonlyArray<{
|
|
655
670
|
readonly id: string
|
|
656
671
|
readonly name?: string
|
package/tests/diff.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from 'bun:test'
|
|
2
2
|
import { Schema } from '@effect/schema'
|
|
3
|
-
import { CommentInput, GerritCredentials } from '@/schemas/gerrit'
|
|
3
|
+
import { CommentInput, FileDiffContent, GerritCredentials } from '@/schemas/gerrit'
|
|
4
4
|
|
|
5
5
|
describe('Gerrit Schemas', () => {
|
|
6
6
|
describe('GerritCredentials', () => {
|
|
@@ -82,4 +82,55 @@ describe('Gerrit Schemas', () => {
|
|
|
82
82
|
}).toThrow()
|
|
83
83
|
})
|
|
84
84
|
})
|
|
85
|
+
|
|
86
|
+
describe('FileDiffContent', () => {
|
|
87
|
+
const baseContent = { content: [] }
|
|
88
|
+
|
|
89
|
+
test('should accept change_type REWRITE', () => {
|
|
90
|
+
const result = Schema.decodeUnknownSync(FileDiffContent)({
|
|
91
|
+
...baseContent,
|
|
92
|
+
change_type: 'REWRITE',
|
|
93
|
+
})
|
|
94
|
+
expect(result.change_type).toBe('REWRITE')
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
test('should accept intraline_status ERROR', () => {
|
|
98
|
+
const result = Schema.decodeUnknownSync(FileDiffContent)({
|
|
99
|
+
...baseContent,
|
|
100
|
+
intraline_status: 'ERROR',
|
|
101
|
+
})
|
|
102
|
+
expect(result.intraline_status).toBe('ERROR')
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
test('should accept all valid change_type values', () => {
|
|
106
|
+
const values = ['ADDED', 'MODIFIED', 'DELETED', 'RENAMED', 'COPIED', 'REWRITE'] as const
|
|
107
|
+
for (const change_type of values) {
|
|
108
|
+
const result = Schema.decodeUnknownSync(FileDiffContent)({ ...baseContent, change_type })
|
|
109
|
+
expect(result.change_type).toBe(change_type)
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
test('should accept all valid intraline_status values', () => {
|
|
114
|
+
const values = ['OK', 'TIMEOUT', 'ERROR'] as const
|
|
115
|
+
for (const intraline_status of values) {
|
|
116
|
+
const result = Schema.decodeUnknownSync(FileDiffContent)({
|
|
117
|
+
...baseContent,
|
|
118
|
+
intraline_status,
|
|
119
|
+
})
|
|
120
|
+
expect(result.intraline_status).toBe(intraline_status)
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
test('should reject invalid change_type', () => {
|
|
125
|
+
expect(() => {
|
|
126
|
+
Schema.decodeUnknownSync(FileDiffContent)({ ...baseContent, change_type: 'FAILURE' })
|
|
127
|
+
}).toThrow()
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
test('should reject invalid intraline_status', () => {
|
|
131
|
+
expect(() => {
|
|
132
|
+
Schema.decodeUnknownSync(FileDiffContent)({ ...baseContent, intraline_status: 'FAILURE' })
|
|
133
|
+
}).toThrow()
|
|
134
|
+
})
|
|
135
|
+
})
|
|
85
136
|
})
|