@pilatos/bitbucket-cli 1.16.0 → 1.17.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/index.js +541 -288
- package/dist/index.js.map +231 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -17633,7 +17633,16 @@ class ConfigService {
|
|
|
17633
17633
|
await this.verifyPermissions(this.configDir, CONFIG_DIR_MODE, "directory");
|
|
17634
17634
|
await this.verifyPermissions(this.configFile, CONFIG_FILE_MODE, "file");
|
|
17635
17635
|
const data = await fs.readFile(this.configFile, "utf-8");
|
|
17636
|
-
|
|
17636
|
+
try {
|
|
17637
|
+
this.configCache = JSON.parse(data);
|
|
17638
|
+
} catch (parseError) {
|
|
17639
|
+
throw new BBError({
|
|
17640
|
+
code: 4001 /* CONFIG_READ_FAILED */,
|
|
17641
|
+
message: `Config file is not valid JSON: ${this.configFile}. Fix the file by hand or remove it and run \`bb auth login\` again.`,
|
|
17642
|
+
cause: parseError instanceof Error ? parseError : undefined,
|
|
17643
|
+
context: { configFile: this.configFile }
|
|
17644
|
+
});
|
|
17645
|
+
}
|
|
17637
17646
|
return this.configCache;
|
|
17638
17647
|
} catch (error) {
|
|
17639
17648
|
if (error.code === "ENOENT") {
|
|
@@ -17771,10 +17780,14 @@ class ConfigService {
|
|
|
17771
17780
|
}
|
|
17772
17781
|
}
|
|
17773
17782
|
// src/services/git.service.ts
|
|
17783
|
+
var DEFAULT_GIT_TIMEOUT_MS = 60000;
|
|
17784
|
+
|
|
17774
17785
|
class GitService {
|
|
17775
17786
|
cwd;
|
|
17776
|
-
|
|
17787
|
+
timeoutMs;
|
|
17788
|
+
constructor(cwd, options = {}) {
|
|
17777
17789
|
this.cwd = cwd ?? process.cwd();
|
|
17790
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
|
|
17778
17791
|
}
|
|
17779
17792
|
async exec(args, cwd) {
|
|
17780
17793
|
const proc = Bun.spawn(["git", ...args], {
|
|
@@ -17782,14 +17795,28 @@ class GitService {
|
|
|
17782
17795
|
stdout: "pipe",
|
|
17783
17796
|
stderr: "pipe"
|
|
17784
17797
|
});
|
|
17785
|
-
|
|
17786
|
-
const
|
|
17787
|
-
|
|
17788
|
-
|
|
17789
|
-
|
|
17790
|
-
|
|
17791
|
-
|
|
17792
|
-
|
|
17798
|
+
let timedOut = false;
|
|
17799
|
+
const timer = setTimeout(() => {
|
|
17800
|
+
timedOut = true;
|
|
17801
|
+
try {
|
|
17802
|
+
proc.kill();
|
|
17803
|
+
} catch {}
|
|
17804
|
+
}, this.timeoutMs);
|
|
17805
|
+
try {
|
|
17806
|
+
const stdout = await new Response(proc.stdout).text();
|
|
17807
|
+
const stderr = await new Response(proc.stderr).text();
|
|
17808
|
+
const exitCode = await proc.exited;
|
|
17809
|
+
if (timedOut) {
|
|
17810
|
+
throw new GitError(`git ${args.join(" ")} timed out after ${this.timeoutMs}ms`, `git ${args.join(" ")}`, exitCode);
|
|
17811
|
+
}
|
|
17812
|
+
return {
|
|
17813
|
+
stdout: stdout.trim(),
|
|
17814
|
+
stderr: stderr.trim(),
|
|
17815
|
+
exitCode
|
|
17816
|
+
};
|
|
17817
|
+
} finally {
|
|
17818
|
+
clearTimeout(timer);
|
|
17819
|
+
}
|
|
17793
17820
|
}
|
|
17794
17821
|
async execOrError(args, cwd) {
|
|
17795
17822
|
const result = await this.exec(args, cwd);
|
|
@@ -17840,7 +17867,7 @@ class GitService {
|
|
|
17840
17867
|
return result.stdout;
|
|
17841
17868
|
}
|
|
17842
17869
|
withCwd(cwd) {
|
|
17843
|
-
return new GitService(cwd);
|
|
17870
|
+
return new GitService(cwd, { timeoutMs: this.timeoutMs });
|
|
17844
17871
|
}
|
|
17845
17872
|
}
|
|
17846
17873
|
// src/services/context.service.ts
|
|
@@ -17940,6 +17967,12 @@ class ContextService {
|
|
|
17940
17967
|
}
|
|
17941
17968
|
return result.context;
|
|
17942
17969
|
}
|
|
17970
|
+
async requireRepoContextFor(options, context) {
|
|
17971
|
+
return this.requireRepoContext({
|
|
17972
|
+
...context.globalOptions,
|
|
17973
|
+
...options
|
|
17974
|
+
});
|
|
17975
|
+
}
|
|
17943
17976
|
buildRepoNotFoundMessage(reason, remoteUrl) {
|
|
17944
17977
|
const fallback = "Use --workspace and --repo options, or run this command from within a Bitbucket repository.";
|
|
17945
17978
|
switch (reason) {
|
|
@@ -18462,6 +18495,54 @@ var chalk = createChalk();
|
|
|
18462
18495
|
var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
|
|
18463
18496
|
var source_default = chalk;
|
|
18464
18497
|
|
|
18498
|
+
// src/services/locale.ts
|
|
18499
|
+
var DEFAULT_LOCALE = "en-US";
|
|
18500
|
+
function normalizePosixLocale(value) {
|
|
18501
|
+
const trimmed = value.trim();
|
|
18502
|
+
if (trimmed.length === 0) {
|
|
18503
|
+
return;
|
|
18504
|
+
}
|
|
18505
|
+
const base = trimmed.split(/[.@]/, 1)[0];
|
|
18506
|
+
if (base.length === 0) {
|
|
18507
|
+
return;
|
|
18508
|
+
}
|
|
18509
|
+
const upper = base.toUpperCase();
|
|
18510
|
+
if (upper === "C" || upper === "POSIX") {
|
|
18511
|
+
return DEFAULT_LOCALE;
|
|
18512
|
+
}
|
|
18513
|
+
return base.replace(/_/g, "-");
|
|
18514
|
+
}
|
|
18515
|
+
function detectSystemLocale(env2 = process.env) {
|
|
18516
|
+
const candidates = [env2.LC_TIME, env2.LC_ALL, env2.LANG];
|
|
18517
|
+
for (const candidate of candidates) {
|
|
18518
|
+
if (typeof candidate !== "string") {
|
|
18519
|
+
continue;
|
|
18520
|
+
}
|
|
18521
|
+
const normalized = normalizePosixLocale(candidate);
|
|
18522
|
+
if (normalized) {
|
|
18523
|
+
return normalized;
|
|
18524
|
+
}
|
|
18525
|
+
}
|
|
18526
|
+
return DEFAULT_LOCALE;
|
|
18527
|
+
}
|
|
18528
|
+
function resolveLocale(options) {
|
|
18529
|
+
const env2 = options.env ?? process.env;
|
|
18530
|
+
if (typeof options.explicit === "string") {
|
|
18531
|
+
const trimmed = options.explicit.trim();
|
|
18532
|
+
if (trimmed.length > 0) {
|
|
18533
|
+
return trimmed;
|
|
18534
|
+
}
|
|
18535
|
+
}
|
|
18536
|
+
const fromEnvVar = env2.BB_LOCALE;
|
|
18537
|
+
if (typeof fromEnvVar === "string") {
|
|
18538
|
+
const trimmed = fromEnvVar.trim();
|
|
18539
|
+
if (trimmed.length > 0) {
|
|
18540
|
+
return trimmed;
|
|
18541
|
+
}
|
|
18542
|
+
}
|
|
18543
|
+
return detectSystemLocale(env2);
|
|
18544
|
+
}
|
|
18545
|
+
|
|
18465
18546
|
// src/services/output.project.ts
|
|
18466
18547
|
function projectFields(item, fields) {
|
|
18467
18548
|
if (item === null || typeof item !== "object") {
|
|
@@ -18488,7 +18569,143 @@ function deepGet(source, path) {
|
|
|
18488
18569
|
return current === undefined ? null : current;
|
|
18489
18570
|
}
|
|
18490
18571
|
|
|
18572
|
+
// src/services/spinner.ts
|
|
18573
|
+
var FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
18574
|
+
var FRAME_INTERVAL_MS = 80;
|
|
18575
|
+
var ESC = "\x1B";
|
|
18576
|
+
var CLEAR_LINE = `\r${ESC}[2K`;
|
|
18577
|
+
var HIDE_CURSOR = `${ESC}[?25l`;
|
|
18578
|
+
var SHOW_CURSOR = `${ESC}[?25h`;
|
|
18579
|
+
var COLOR_CYAN = `${ESC}[36m`;
|
|
18580
|
+
var COLOR_GREEN = `${ESC}[32m`;
|
|
18581
|
+
var COLOR_RED = `${ESC}[31m`;
|
|
18582
|
+
var COLOR_RESET = `${ESC}[0m`;
|
|
18583
|
+
|
|
18584
|
+
class Spinner {
|
|
18585
|
+
text;
|
|
18586
|
+
enabled;
|
|
18587
|
+
noColor;
|
|
18588
|
+
stream;
|
|
18589
|
+
onStop;
|
|
18590
|
+
timer = null;
|
|
18591
|
+
frameIndex = 0;
|
|
18592
|
+
active = false;
|
|
18593
|
+
exitHandler = null;
|
|
18594
|
+
constructor(text, options) {
|
|
18595
|
+
this.text = text;
|
|
18596
|
+
this.enabled = options.enabled;
|
|
18597
|
+
this.noColor = options.noColor;
|
|
18598
|
+
this.stream = options.stream;
|
|
18599
|
+
this.onStop = options.onStop;
|
|
18600
|
+
}
|
|
18601
|
+
start() {
|
|
18602
|
+
if (!this.enabled || this.active) {
|
|
18603
|
+
return this;
|
|
18604
|
+
}
|
|
18605
|
+
this.active = true;
|
|
18606
|
+
this.stream.write(HIDE_CURSOR);
|
|
18607
|
+
this.render();
|
|
18608
|
+
this.timer = setInterval(() => {
|
|
18609
|
+
this.frameIndex = (this.frameIndex + 1) % FRAMES.length;
|
|
18610
|
+
this.render();
|
|
18611
|
+
}, FRAME_INTERVAL_MS);
|
|
18612
|
+
this.timer.unref?.();
|
|
18613
|
+
this.exitHandler = () => {
|
|
18614
|
+
if (this.active) {
|
|
18615
|
+
this.active = false;
|
|
18616
|
+
if (this.timer) {
|
|
18617
|
+
clearInterval(this.timer);
|
|
18618
|
+
this.timer = null;
|
|
18619
|
+
}
|
|
18620
|
+
this.stream.write(`${CLEAR_LINE}${SHOW_CURSOR}`);
|
|
18621
|
+
}
|
|
18622
|
+
};
|
|
18623
|
+
process.once("SIGINT", this.exitHandler);
|
|
18624
|
+
process.once("SIGTERM", this.exitHandler);
|
|
18625
|
+
process.once("exit", this.exitHandler);
|
|
18626
|
+
return this;
|
|
18627
|
+
}
|
|
18628
|
+
stop() {
|
|
18629
|
+
if (!this.active) {
|
|
18630
|
+
return this.detach();
|
|
18631
|
+
}
|
|
18632
|
+
this.active = false;
|
|
18633
|
+
if (this.timer) {
|
|
18634
|
+
clearInterval(this.timer);
|
|
18635
|
+
this.timer = null;
|
|
18636
|
+
}
|
|
18637
|
+
this.stream.write(`${CLEAR_LINE}${SHOW_CURSOR}`);
|
|
18638
|
+
return this.detach();
|
|
18639
|
+
}
|
|
18640
|
+
succeed(message) {
|
|
18641
|
+
this.stop();
|
|
18642
|
+
if (this.enabled && message) {
|
|
18643
|
+
const symbol = this.colorize("\u2713", COLOR_GREEN);
|
|
18644
|
+
this.stream.write(`${symbol} ${message}
|
|
18645
|
+
`);
|
|
18646
|
+
}
|
|
18647
|
+
return this;
|
|
18648
|
+
}
|
|
18649
|
+
fail(message) {
|
|
18650
|
+
this.stop();
|
|
18651
|
+
if (this.enabled && message) {
|
|
18652
|
+
const symbol = this.colorize("\u2717", COLOR_RED);
|
|
18653
|
+
this.stream.write(`${symbol} ${message}
|
|
18654
|
+
`);
|
|
18655
|
+
}
|
|
18656
|
+
return this;
|
|
18657
|
+
}
|
|
18658
|
+
setText(text) {
|
|
18659
|
+
this.text = text;
|
|
18660
|
+
if (this.active) {
|
|
18661
|
+
this.render();
|
|
18662
|
+
}
|
|
18663
|
+
return this;
|
|
18664
|
+
}
|
|
18665
|
+
render() {
|
|
18666
|
+
if (!this.active)
|
|
18667
|
+
return;
|
|
18668
|
+
const frame = FRAMES[this.frameIndex] ?? FRAMES[0];
|
|
18669
|
+
const symbol = this.colorize(frame, COLOR_CYAN);
|
|
18670
|
+
this.stream.write(`${CLEAR_LINE}${symbol} ${this.text}`);
|
|
18671
|
+
}
|
|
18672
|
+
colorize(text, color) {
|
|
18673
|
+
return this.noColor ? text : `${color}${text}${COLOR_RESET}`;
|
|
18674
|
+
}
|
|
18675
|
+
detach() {
|
|
18676
|
+
if (this.exitHandler) {
|
|
18677
|
+
process.removeListener("SIGINT", this.exitHandler);
|
|
18678
|
+
process.removeListener("SIGTERM", this.exitHandler);
|
|
18679
|
+
process.removeListener("exit", this.exitHandler);
|
|
18680
|
+
this.exitHandler = null;
|
|
18681
|
+
}
|
|
18682
|
+
if (this.onStop) {
|
|
18683
|
+
const cb = this.onStop;
|
|
18684
|
+
this.onStop = undefined;
|
|
18685
|
+
cb();
|
|
18686
|
+
}
|
|
18687
|
+
return this;
|
|
18688
|
+
}
|
|
18689
|
+
}
|
|
18690
|
+
function createNoopSpinner() {
|
|
18691
|
+
const noop = {
|
|
18692
|
+
start: () => noop,
|
|
18693
|
+
stop: () => noop,
|
|
18694
|
+
succeed: () => noop,
|
|
18695
|
+
fail: () => noop,
|
|
18696
|
+
setText: () => noop
|
|
18697
|
+
};
|
|
18698
|
+
return noop;
|
|
18699
|
+
}
|
|
18700
|
+
|
|
18491
18701
|
// src/services/output.service.ts
|
|
18702
|
+
var DATE_FORMAT_OPTIONS = {
|
|
18703
|
+
year: "numeric",
|
|
18704
|
+
month: "short",
|
|
18705
|
+
day: "numeric",
|
|
18706
|
+
hour: "2-digit",
|
|
18707
|
+
minute: "2-digit"
|
|
18708
|
+
};
|
|
18492
18709
|
var CONTROL_CHARS = /(\x1b\[[0-9;?]*m)|\x1b\[[0-9;?]*[A-Za-ln-z]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|[\x00-\x08\x0B\x0C\x0E-\x1F\x7F\x9B\x9D]/g;
|
|
18493
18710
|
function stripControl(value) {
|
|
18494
18711
|
return value.replace(CONTROL_CHARS, (_match, sgr) => sgr ?? "");
|
|
@@ -18507,14 +18724,42 @@ var WRAPPER_ARRAY_KEYS = [
|
|
|
18507
18724
|
|
|
18508
18725
|
class OutputService {
|
|
18509
18726
|
noColor;
|
|
18727
|
+
noUnicode;
|
|
18728
|
+
locale;
|
|
18510
18729
|
jsonFormatOptions = {};
|
|
18730
|
+
activeSpinner = null;
|
|
18511
18731
|
constructor(options) {
|
|
18512
18732
|
this.noColor = options?.noColor ?? false;
|
|
18733
|
+
this.noUnicode = options?.noUnicode ?? false;
|
|
18734
|
+
this.locale = options?.locale ?? DEFAULT_LOCALE;
|
|
18513
18735
|
}
|
|
18514
18736
|
setJsonFormatOptions(options) {
|
|
18515
18737
|
this.jsonFormatOptions = { ...options };
|
|
18516
18738
|
}
|
|
18739
|
+
isJsonMode() {
|
|
18740
|
+
return this.jsonFormatOptions.json === true;
|
|
18741
|
+
}
|
|
18742
|
+
spinner(text) {
|
|
18743
|
+
const enabled = !this.isJsonMode() && !!process.stdout.isTTY && true;
|
|
18744
|
+
if (!enabled) {
|
|
18745
|
+
return createNoopSpinner();
|
|
18746
|
+
}
|
|
18747
|
+
this.activeSpinner?.stop();
|
|
18748
|
+
const spinner = new Spinner(text, {
|
|
18749
|
+
enabled: true,
|
|
18750
|
+
noColor: this.noColor,
|
|
18751
|
+
stream: process.stdout,
|
|
18752
|
+
onStop: () => {
|
|
18753
|
+
if (this.activeSpinner === spinner) {
|
|
18754
|
+
this.activeSpinner = null;
|
|
18755
|
+
}
|
|
18756
|
+
}
|
|
18757
|
+
});
|
|
18758
|
+
this.activeSpinner = spinner;
|
|
18759
|
+
return spinner;
|
|
18760
|
+
}
|
|
18517
18761
|
async json(data) {
|
|
18762
|
+
this.stopActiveSpinner();
|
|
18518
18763
|
const { fields, jq } = this.jsonFormatOptions;
|
|
18519
18764
|
let result = data;
|
|
18520
18765
|
if (fields && fields.length > 0) {
|
|
@@ -18532,9 +18777,11 @@ class OutputService {
|
|
|
18532
18777
|
console.log(JSON.stringify(result, null, 2));
|
|
18533
18778
|
}
|
|
18534
18779
|
jsonError(data) {
|
|
18780
|
+
this.stopActiveSpinner();
|
|
18535
18781
|
console.error(JSON.stringify(data));
|
|
18536
18782
|
}
|
|
18537
18783
|
table(headers, rows) {
|
|
18784
|
+
this.stopActiveSpinner();
|
|
18538
18785
|
if (rows.length === 0) {
|
|
18539
18786
|
return;
|
|
18540
18787
|
}
|
|
@@ -18553,33 +18800,63 @@ class OutputService {
|
|
|
18553
18800
|
}
|
|
18554
18801
|
}
|
|
18555
18802
|
success(message) {
|
|
18556
|
-
|
|
18803
|
+
this.stopActiveSpinner();
|
|
18804
|
+
const symbol = this.format(this.symbol("\u2713", "OK"), source_default.green);
|
|
18557
18805
|
console.log(`${symbol} ${stripControl(message)}`);
|
|
18558
18806
|
}
|
|
18559
18807
|
error(message) {
|
|
18560
|
-
|
|
18808
|
+
this.stopActiveSpinner();
|
|
18809
|
+
const symbol = this.format(this.symbol("\u2717", "ERR"), source_default.red);
|
|
18561
18810
|
console.error(`${symbol} ${stripControl(message)}`);
|
|
18562
18811
|
}
|
|
18563
18812
|
warning(message) {
|
|
18564
|
-
|
|
18813
|
+
this.stopActiveSpinner();
|
|
18814
|
+
const symbol = this.format(this.symbol("\u26A0", "!!"), source_default.yellow);
|
|
18565
18815
|
console.warn(`${symbol} ${stripControl(message)}`);
|
|
18566
18816
|
}
|
|
18567
18817
|
info(message) {
|
|
18568
|
-
|
|
18818
|
+
this.stopActiveSpinner();
|
|
18819
|
+
const symbol = this.format(this.symbol("\u2139", "i"), source_default.blue);
|
|
18569
18820
|
console.log(`${symbol} ${stripControl(message)}`);
|
|
18570
18821
|
}
|
|
18822
|
+
symbol(unicode, ascii) {
|
|
18823
|
+
return this.noUnicode ? ascii : unicode;
|
|
18824
|
+
}
|
|
18571
18825
|
text(message) {
|
|
18826
|
+
this.stopActiveSpinner();
|
|
18572
18827
|
console.log(stripControl(message));
|
|
18573
18828
|
}
|
|
18829
|
+
separator(width = 60) {
|
|
18830
|
+
this.stopActiveSpinner();
|
|
18831
|
+
if (width <= 0) {
|
|
18832
|
+
console.log("");
|
|
18833
|
+
return;
|
|
18834
|
+
}
|
|
18835
|
+
console.log(this.format(this.symbol("\u2500", "-").repeat(width), source_default.gray));
|
|
18836
|
+
}
|
|
18837
|
+
stopActiveSpinner() {
|
|
18838
|
+
if (this.activeSpinner) {
|
|
18839
|
+
const spinner = this.activeSpinner;
|
|
18840
|
+
this.activeSpinner = null;
|
|
18841
|
+
spinner.stop();
|
|
18842
|
+
}
|
|
18843
|
+
}
|
|
18844
|
+
truncate(text, maxLength, suffix = "...") {
|
|
18845
|
+
if (maxLength <= 0 || text.length <= maxLength) {
|
|
18846
|
+
return text;
|
|
18847
|
+
}
|
|
18848
|
+
if (suffix.length >= maxLength) {
|
|
18849
|
+
return text.slice(0, maxLength);
|
|
18850
|
+
}
|
|
18851
|
+
return text.slice(0, maxLength - suffix.length) + suffix;
|
|
18852
|
+
}
|
|
18574
18853
|
formatDate(date) {
|
|
18575
18854
|
const d = typeof date === "string" ? new Date(date) : date;
|
|
18576
|
-
|
|
18577
|
-
|
|
18578
|
-
|
|
18579
|
-
|
|
18580
|
-
|
|
18581
|
-
minute: "2-digit"
|
|
18582
|
-
});
|
|
18855
|
+
try {
|
|
18856
|
+
return d.toLocaleDateString(this.locale, DATE_FORMAT_OPTIONS);
|
|
18857
|
+
} catch {
|
|
18858
|
+
return d.toLocaleDateString(DEFAULT_LOCALE, DATE_FORMAT_OPTIONS);
|
|
18859
|
+
}
|
|
18583
18860
|
}
|
|
18584
18861
|
format(text, formatter) {
|
|
18585
18862
|
if (this.noColor) {
|
|
@@ -18640,7 +18917,17 @@ function projectByFieldsRespectingWrapper(data, fields) {
|
|
|
18640
18917
|
return projectFields(data, fields);
|
|
18641
18918
|
}
|
|
18642
18919
|
async function runJq(data, expression) {
|
|
18643
|
-
|
|
18920
|
+
let jq;
|
|
18921
|
+
try {
|
|
18922
|
+
jq = await Promise.resolve().then(() => __toESM(require_dist(), 1));
|
|
18923
|
+
} catch (error) {
|
|
18924
|
+
throw new BBError({
|
|
18925
|
+
code: 8001 /* JQ_FAILED */,
|
|
18926
|
+
message: "Failed to load the embedded jq runtime (jq-wasm). Reinstall the CLI or report this issue.",
|
|
18927
|
+
cause: error instanceof Error ? error : undefined,
|
|
18928
|
+
context: { expression }
|
|
18929
|
+
});
|
|
18930
|
+
}
|
|
18644
18931
|
let result;
|
|
18645
18932
|
try {
|
|
18646
18933
|
result = await jq.raw(data, expression);
|
|
@@ -18812,7 +19099,11 @@ class VersionService {
|
|
|
18812
19099
|
latestVersion,
|
|
18813
19100
|
updateAvailable
|
|
18814
19101
|
};
|
|
18815
|
-
} catch {
|
|
19102
|
+
} catch (error) {
|
|
19103
|
+
if (process.env.DEBUG === "true") {
|
|
19104
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
19105
|
+
console.error(`[version-check] skipped: ${message}`);
|
|
19106
|
+
}
|
|
18816
19107
|
return null;
|
|
18817
19108
|
}
|
|
18818
19109
|
}
|
|
@@ -22594,7 +22885,7 @@ function redactRequestUrl(requestUrl, baseUrl) {
|
|
|
22594
22885
|
return queryIdx === -1 ? raw : `${raw.slice(0, queryIdx)}?[redacted]`;
|
|
22595
22886
|
}
|
|
22596
22887
|
}
|
|
22597
|
-
function createApiClient(credentialStore, oauthService) {
|
|
22888
|
+
function createApiClient(credentialStore, output, oauthService) {
|
|
22598
22889
|
const instance = axios_default.create({
|
|
22599
22890
|
baseURL: BASE_URL,
|
|
22600
22891
|
headers: {
|
|
@@ -22658,7 +22949,9 @@ function createApiClient(credentialStore, oauthService) {
|
|
|
22658
22949
|
const delay = getRetryDelay(error, config.__retryCount);
|
|
22659
22950
|
const status = error.response.status;
|
|
22660
22951
|
const label = status === 429 ? "Rate limited" : `Server error (${status})`;
|
|
22661
|
-
|
|
22952
|
+
if (!output.isJsonMode()) {
|
|
22953
|
+
output.warning(`${label}, retrying in ${(delay / 1000).toFixed(1)}s (attempt ${config.__retryCount}/${MAX_RETRIES})...`);
|
|
22954
|
+
}
|
|
22662
22955
|
await sleep(delay);
|
|
22663
22956
|
return instance(config);
|
|
22664
22957
|
}
|
|
@@ -22946,7 +23239,12 @@ class OAuthService {
|
|
|
22946
23239
|
try {
|
|
22947
23240
|
const open2 = (await Promise.resolve().then(() => (init_open(), exports_open))).default;
|
|
22948
23241
|
await open2(authUrl);
|
|
22949
|
-
} catch {
|
|
23242
|
+
} catch (err) {
|
|
23243
|
+
if (process.env.DEBUG === "true") {
|
|
23244
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
23245
|
+
console.error(`[oauth] could not open browser: ${message}`);
|
|
23246
|
+
}
|
|
23247
|
+
}
|
|
22950
23248
|
console.error(`If the browser doesn't open, visit:
|
|
22951
23249
|
${authUrl}
|
|
22952
23250
|
`);
|
|
@@ -27184,6 +27482,7 @@ class BaseCommand {
|
|
|
27184
27482
|
}
|
|
27185
27483
|
async run(options, context) {
|
|
27186
27484
|
this.output.setJsonFormatOptions({
|
|
27485
|
+
json: !!context.globalOptions.json,
|
|
27187
27486
|
fields: context.globalOptions.jsonFields,
|
|
27188
27487
|
jq: context.globalOptions.jq
|
|
27189
27488
|
});
|
|
@@ -27267,6 +27566,33 @@ class BaseCommand {
|
|
|
27267
27566
|
}
|
|
27268
27567
|
return parsed;
|
|
27269
27568
|
}
|
|
27569
|
+
parsePositiveInt(value, name) {
|
|
27570
|
+
const trimmed = value.trim();
|
|
27571
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
27572
|
+
if (!Number.isFinite(parsed) || parsed < 1 || String(parsed) !== trimmed) {
|
|
27573
|
+
throw new BBError({
|
|
27574
|
+
code: 5002 /* VALIDATION_INVALID */,
|
|
27575
|
+
message: this.appendHelpHint(`--${name} must be a positive integer.`),
|
|
27576
|
+
context: { [name]: value }
|
|
27577
|
+
});
|
|
27578
|
+
}
|
|
27579
|
+
return parsed;
|
|
27580
|
+
}
|
|
27581
|
+
truncateText(text, maxLength, opts = {}) {
|
|
27582
|
+
if (opts.noTruncate) {
|
|
27583
|
+
return text;
|
|
27584
|
+
}
|
|
27585
|
+
return this.output.truncate(text, maxLength);
|
|
27586
|
+
}
|
|
27587
|
+
requireConfirmation(confirmed, warning) {
|
|
27588
|
+
if (confirmed)
|
|
27589
|
+
return;
|
|
27590
|
+
throw new BBError({
|
|
27591
|
+
code: 5001 /* VALIDATION_REQUIRED */,
|
|
27592
|
+
message: `${warning}
|
|
27593
|
+
Use --yes to confirm.`
|
|
27594
|
+
});
|
|
27595
|
+
}
|
|
27270
27596
|
parseEnumOption(value, name, allowed) {
|
|
27271
27597
|
if (!allowed.includes(value)) {
|
|
27272
27598
|
throw new BBError({
|
|
@@ -27555,7 +27881,12 @@ class CloneCommand extends BaseCommand {
|
|
|
27555
27881
|
async execute(options, context) {
|
|
27556
27882
|
const { repository, directory } = options;
|
|
27557
27883
|
const repoUrl = await this.resolveRepositoryUrl(repository);
|
|
27558
|
-
|
|
27884
|
+
const spinner = this.output.spinner(`Cloning ${repository}...`).start();
|
|
27885
|
+
try {
|
|
27886
|
+
await this.gitService.clone(repoUrl, directory);
|
|
27887
|
+
} finally {
|
|
27888
|
+
spinner.stop();
|
|
27889
|
+
}
|
|
27559
27890
|
const targetDir = directory || this.extractRepoName(repository);
|
|
27560
27891
|
if (context.globalOptions.json) {
|
|
27561
27892
|
await this.output.json({
|
|
@@ -27968,13 +28299,13 @@ class ListReposCommand extends BaseCommand {
|
|
|
27968
28299
|
return;
|
|
27969
28300
|
}
|
|
27970
28301
|
if (repos.length === 0) {
|
|
27971
|
-
this.output.
|
|
28302
|
+
this.output.info("No repositories found");
|
|
27972
28303
|
return;
|
|
27973
28304
|
}
|
|
27974
28305
|
const rows = repos.map((repo) => [
|
|
27975
28306
|
repo.full_name ?? "",
|
|
27976
28307
|
repo.is_private ? "private" : "public",
|
|
27977
|
-
(repo.description
|
|
28308
|
+
this.truncateText(repo.description ?? "", 50, context.globalOptions)
|
|
27978
28309
|
]);
|
|
27979
28310
|
this.output.table(["REPOSITORY", "VISIBILITY", "DESCRIPTION"], rows);
|
|
27980
28311
|
}
|
|
@@ -28059,13 +28390,7 @@ class DeleteRepoCommand extends BaseCommand {
|
|
|
28059
28390
|
contextOptions.repo = repository;
|
|
28060
28391
|
}
|
|
28061
28392
|
const repoContext = await this.contextService.requireRepoContext(contextOptions);
|
|
28062
|
-
|
|
28063
|
-
throw new BBError({
|
|
28064
|
-
code: 5001 /* VALIDATION_REQUIRED */,
|
|
28065
|
-
message: `This will permanently delete ${repoContext.workspace}/${repoContext.repoSlug}.
|
|
28066
|
-
` + "Use --yes to confirm deletion."
|
|
28067
|
-
});
|
|
28068
|
-
}
|
|
28393
|
+
this.requireConfirmation(yes, `This will permanently delete ${repoContext.workspace}/${repoContext.repoSlug}.`);
|
|
28069
28394
|
await this.repositoriesApi.repositoriesWorkspaceRepoSlugDelete({
|
|
28070
28395
|
workspace: repoContext.workspace,
|
|
28071
28396
|
repoSlug: repoContext.repoSlug
|
|
@@ -28094,10 +28419,7 @@ class ListDefaultReviewersCommand extends BaseCommand {
|
|
|
28094
28419
|
this.contextService = contextService;
|
|
28095
28420
|
}
|
|
28096
28421
|
async execute(options, context) {
|
|
28097
|
-
const repoContext = await this.contextService.
|
|
28098
|
-
...context.globalOptions,
|
|
28099
|
-
...options
|
|
28100
|
-
});
|
|
28422
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
28101
28423
|
const mode = options.repoOnly ? "direct" : "effective";
|
|
28102
28424
|
const reviewers = await this.defaultReviewerService.list(repoContext, mode);
|
|
28103
28425
|
if (context.globalOptions.json) {
|
|
@@ -28140,10 +28462,7 @@ class AddDefaultReviewerCommand extends BaseCommand {
|
|
|
28140
28462
|
this.contextService = contextService;
|
|
28141
28463
|
}
|
|
28142
28464
|
async execute(options, context) {
|
|
28143
|
-
const repoContext = await this.contextService.
|
|
28144
|
-
...context.globalOptions,
|
|
28145
|
-
...options
|
|
28146
|
-
});
|
|
28465
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
28147
28466
|
const userResponse = await this.usersApi.usersSelectedUserGet({
|
|
28148
28467
|
selectedUser: options.username
|
|
28149
28468
|
});
|
|
@@ -28177,17 +28496,8 @@ class RemoveDefaultReviewerCommand extends BaseCommand {
|
|
|
28177
28496
|
this.contextService = contextService;
|
|
28178
28497
|
}
|
|
28179
28498
|
async execute(options, context) {
|
|
28180
|
-
const repoContext = await this.contextService.
|
|
28181
|
-
|
|
28182
|
-
...options
|
|
28183
|
-
});
|
|
28184
|
-
if (!options.yes) {
|
|
28185
|
-
throw new BBError({
|
|
28186
|
-
code: 5001 /* VALIDATION_REQUIRED */,
|
|
28187
|
-
message: `This will remove ${options.username} from the default reviewers of ` + `${repoContext.workspace}/${repoContext.repoSlug}.
|
|
28188
|
-
` + "Use --yes to confirm."
|
|
28189
|
-
});
|
|
28190
|
-
}
|
|
28499
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
28500
|
+
this.requireConfirmation(options.yes, `This will remove ${options.username} from the default reviewers of ` + `${repoContext.workspace}/${repoContext.repoSlug}.`);
|
|
28191
28501
|
const userResponse = await this.usersApi.usersSelectedUserGet({
|
|
28192
28502
|
selectedUser: options.username
|
|
28193
28503
|
});
|
|
@@ -28232,10 +28542,7 @@ class CreatePRCommand extends BaseCommand {
|
|
|
28232
28542
|
message: this.appendHelpHint("Pull request title is required. Use --title option.")
|
|
28233
28543
|
});
|
|
28234
28544
|
}
|
|
28235
|
-
const repoContext = await this.contextService.
|
|
28236
|
-
...context.globalOptions,
|
|
28237
|
-
...options
|
|
28238
|
-
});
|
|
28545
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
28239
28546
|
let sourceBranch = options.source;
|
|
28240
28547
|
if (!sourceBranch) {
|
|
28241
28548
|
sourceBranch = await this.gitService.getCurrentBranch();
|
|
@@ -28266,12 +28573,18 @@ class CreatePRCommand extends BaseCommand {
|
|
|
28266
28573
|
if (reviewers.length > 0) {
|
|
28267
28574
|
request.reviewers = reviewers.map((r) => ({ type: "user", uuid: r.uuid }));
|
|
28268
28575
|
}
|
|
28269
|
-
const
|
|
28270
|
-
|
|
28271
|
-
|
|
28272
|
-
|
|
28273
|
-
|
|
28274
|
-
|
|
28576
|
+
const spinner = this.output.spinner("Creating pull request...").start();
|
|
28577
|
+
let pr;
|
|
28578
|
+
try {
|
|
28579
|
+
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPost({
|
|
28580
|
+
workspace: repoContext.workspace,
|
|
28581
|
+
repoSlug: repoContext.repoSlug,
|
|
28582
|
+
pullrequest: request
|
|
28583
|
+
});
|
|
28584
|
+
pr = response.data;
|
|
28585
|
+
} finally {
|
|
28586
|
+
spinner.stop();
|
|
28587
|
+
}
|
|
28275
28588
|
const links = pr.links;
|
|
28276
28589
|
if (context.globalOptions.json) {
|
|
28277
28590
|
await this.output.json(pr);
|
|
@@ -28360,10 +28673,7 @@ class ListPRsCommand extends BaseCommand {
|
|
|
28360
28673
|
this.contextService = contextService;
|
|
28361
28674
|
}
|
|
28362
28675
|
async execute(options, context) {
|
|
28363
|
-
const repoContext = await this.contextService.
|
|
28364
|
-
...context.globalOptions,
|
|
28365
|
-
...options
|
|
28366
|
-
});
|
|
28676
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
28367
28677
|
const state = options.state ? this.parseEnumOption(options.state, "state", PR_STATES) : "OPEN";
|
|
28368
28678
|
const limit = parseLimit(options.limit);
|
|
28369
28679
|
const reviewerQuery = options.mine ? await this.buildMineFilter() : undefined;
|
|
@@ -28398,28 +28708,23 @@ class ListPRsCommand extends BaseCommand {
|
|
|
28398
28708
|
return;
|
|
28399
28709
|
}
|
|
28400
28710
|
if (values.length === 0) {
|
|
28401
|
-
this.output.
|
|
28711
|
+
this.output.info(`No ${state.toLowerCase()} pull requests found`);
|
|
28402
28712
|
return;
|
|
28403
28713
|
}
|
|
28714
|
+
const arrow = this.output.symbol("\u2192", "->");
|
|
28404
28715
|
const rows = values.map((pr) => {
|
|
28405
28716
|
const title = pr.draft ? `[DRAFT] ${pr.title}` : pr.title;
|
|
28406
28717
|
const source = pr.source;
|
|
28407
28718
|
const destination = pr.destination;
|
|
28408
28719
|
return [
|
|
28409
28720
|
`#${pr.id}`,
|
|
28410
|
-
this.
|
|
28721
|
+
this.truncateText(title ?? "", 50, context.globalOptions),
|
|
28411
28722
|
pr.author?.display_name ?? "Unknown",
|
|
28412
|
-
`${source?.branch?.name ?? "unknown"}
|
|
28723
|
+
`${source?.branch?.name ?? "unknown"} ${arrow} ${destination?.branch?.name ?? "unknown"}`
|
|
28413
28724
|
];
|
|
28414
28725
|
});
|
|
28415
28726
|
this.output.table(["ID", "TITLE", "AUTHOR", "BRANCHES"], rows);
|
|
28416
28727
|
}
|
|
28417
|
-
truncate(text, maxLength) {
|
|
28418
|
-
if (text.length <= maxLength) {
|
|
28419
|
-
return text;
|
|
28420
|
-
}
|
|
28421
|
-
return text.substring(0, maxLength - 3) + "...";
|
|
28422
|
-
}
|
|
28423
28728
|
async buildMineFilter() {
|
|
28424
28729
|
const response = await this.usersApi.userGet();
|
|
28425
28730
|
const userUuid = response.data.uuid;
|
|
@@ -28443,11 +28748,8 @@ class ViewPRCommand extends BaseCommand {
|
|
|
28443
28748
|
this.contextService = contextService;
|
|
28444
28749
|
}
|
|
28445
28750
|
async execute(options, context) {
|
|
28446
|
-
const repoContext = await this.contextService.
|
|
28447
|
-
|
|
28448
|
-
...options
|
|
28449
|
-
});
|
|
28450
|
-
const prId = this.parseIntOption(options.id, "id");
|
|
28751
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
28752
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
28451
28753
|
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
|
|
28452
28754
|
workspace: repoContext.workspace,
|
|
28453
28755
|
repoSlug: repoContext.repoSlug,
|
|
@@ -28470,7 +28772,7 @@ class ViewPRCommand extends BaseCommand {
|
|
|
28470
28772
|
const draftLabel = pr.draft ? this.output.yellow(" [DRAFT]") : "";
|
|
28471
28773
|
this.output.text("");
|
|
28472
28774
|
this.output.text(`${this.output.bold(`#${pr.id}`)} ${pr.title}${draftLabel} ${stateColor(`[${pr.state}]`)}`);
|
|
28473
|
-
this.output.
|
|
28775
|
+
this.output.separator();
|
|
28474
28776
|
}
|
|
28475
28777
|
renderDescription(pr) {
|
|
28476
28778
|
if (pr.description) {
|
|
@@ -28483,7 +28785,7 @@ class ViewPRCommand extends BaseCommand {
|
|
|
28483
28785
|
const destination = pr.destination;
|
|
28484
28786
|
const sourceBranch = this.output.cyan(source?.branch?.name ?? "unknown");
|
|
28485
28787
|
const destBranch = this.output.cyan(destination?.branch?.name ?? "unknown");
|
|
28486
|
-
const arrow = this.output.gray(" \u2192 ");
|
|
28788
|
+
const arrow = this.output.gray(this.output.symbol(" \u2192 ", " -> "));
|
|
28487
28789
|
this.output.text(`${this.output.dim("Branch:")} ${sourceBranch}${arrow}${destBranch}`);
|
|
28488
28790
|
if (source?.commit?.hash || destination?.commit?.hash) {
|
|
28489
28791
|
const sourceHash = source?.commit?.hash ? this.output.gray(source.commit.hash.slice(0, 7)) : this.output.gray("unknown");
|
|
@@ -28505,7 +28807,7 @@ class ViewPRCommand extends BaseCommand {
|
|
|
28505
28807
|
if (mergeCommit?.hash) {
|
|
28506
28808
|
this.output.text(`${this.output.dim("Merge:")} ${this.output.magenta(mergeCommit.hash.slice(0, 7))}`);
|
|
28507
28809
|
}
|
|
28508
|
-
const closeBranchIndicator = pr.close_source_branch ? this.output.green("\u2713") : this.output.gray("\u2717");
|
|
28810
|
+
const closeBranchIndicator = pr.close_source_branch ? this.output.green(this.output.symbol("\u2713", "yes")) : this.output.gray(this.output.symbol("\u2717", "no"));
|
|
28509
28811
|
this.output.text(`${this.output.dim("Close Src:")} ${closeBranchIndicator} ${this.output.gray("(close source branch on merge)")}`);
|
|
28510
28812
|
this.output.text(`${this.output.dim("Activity:")} ${pr.comment_count ?? 0} comments \xB7 ${pr.task_count ?? 0} tasks`);
|
|
28511
28813
|
}
|
|
@@ -28514,7 +28816,7 @@ class ViewPRCommand extends BaseCommand {
|
|
|
28514
28816
|
const reviewers = participants.filter((p) => p.role === "REVIEWER");
|
|
28515
28817
|
if (reviewers.length === 0) {
|
|
28516
28818
|
this.output.text("");
|
|
28517
|
-
this.output.
|
|
28819
|
+
this.output.info("No reviewers assigned");
|
|
28518
28820
|
return;
|
|
28519
28821
|
}
|
|
28520
28822
|
this.output.text("");
|
|
@@ -28529,17 +28831,26 @@ class ViewPRCommand extends BaseCommand {
|
|
|
28529
28831
|
}
|
|
28530
28832
|
getReviewerStatus(reviewer) {
|
|
28531
28833
|
if (reviewer.approved) {
|
|
28532
|
-
return {
|
|
28834
|
+
return {
|
|
28835
|
+
icon: this.output.green(this.output.symbol("\u2713", "[OK]")),
|
|
28836
|
+
label: "approved"
|
|
28837
|
+
};
|
|
28533
28838
|
}
|
|
28534
28839
|
if (reviewer.state === "changes_requested") {
|
|
28535
|
-
return {
|
|
28840
|
+
return {
|
|
28841
|
+
icon: this.output.red(this.output.symbol("\u2717", "[X]")),
|
|
28842
|
+
label: "changes requested"
|
|
28843
|
+
};
|
|
28536
28844
|
}
|
|
28537
|
-
return {
|
|
28845
|
+
return {
|
|
28846
|
+
icon: this.output.yellow(this.output.symbol("\u25CB", "[ ]")),
|
|
28847
|
+
label: "pending"
|
|
28848
|
+
};
|
|
28538
28849
|
}
|
|
28539
28850
|
renderFooter(pr) {
|
|
28540
28851
|
const links = pr.links;
|
|
28541
28852
|
this.output.text("");
|
|
28542
|
-
this.output.
|
|
28853
|
+
this.output.separator();
|
|
28543
28854
|
this.output.text(`${this.output.dim("URL:")} ${this.output.underline(this.output.blue(links?.html?.href ?? ""))}`);
|
|
28544
28855
|
this.output.text("");
|
|
28545
28856
|
}
|
|
@@ -28572,13 +28883,10 @@ class EditPRCommand extends BaseCommand {
|
|
|
28572
28883
|
this.gitService = gitService;
|
|
28573
28884
|
}
|
|
28574
28885
|
async execute(options, context) {
|
|
28575
|
-
const repoContext = await this.contextService.
|
|
28576
|
-
...context.globalOptions,
|
|
28577
|
-
...options
|
|
28578
|
-
});
|
|
28886
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
28579
28887
|
let prId;
|
|
28580
28888
|
if (options.id) {
|
|
28581
|
-
prId =
|
|
28889
|
+
prId = this.parsePositiveInt(options.id, "id");
|
|
28582
28890
|
} else {
|
|
28583
28891
|
const currentBranch = await this.gitService.getCurrentBranch();
|
|
28584
28892
|
const matches = await collectPages({
|
|
@@ -28653,7 +28961,7 @@ class EditPRCommand extends BaseCommand {
|
|
|
28653
28961
|
this.output.success(`Updated pull request #${pr.id}`);
|
|
28654
28962
|
this.output.text(` ${this.output.dim("Title:")} ${pr.title}`);
|
|
28655
28963
|
if (pr.description) {
|
|
28656
|
-
const truncatedDesc =
|
|
28964
|
+
const truncatedDesc = this.truncateText(pr.description, 100, context.globalOptions);
|
|
28657
28965
|
this.output.text(` ${this.output.dim("Description:")} ${truncatedDesc}`);
|
|
28658
28966
|
}
|
|
28659
28967
|
this.output.text(` ${this.output.dim("URL:")} ${links?.html?.href}`);
|
|
@@ -28674,11 +28982,8 @@ class MergePRCommand extends BaseCommand {
|
|
|
28674
28982
|
this.contextService = contextService;
|
|
28675
28983
|
}
|
|
28676
28984
|
async execute(options, context) {
|
|
28677
|
-
const repoContext = await this.contextService.
|
|
28678
|
-
|
|
28679
|
-
...options
|
|
28680
|
-
});
|
|
28681
|
-
const prId = this.parseIntOption(options.id, "id");
|
|
28985
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
28986
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
28682
28987
|
const request = {
|
|
28683
28988
|
type: "pullrequest_merge_parameters"
|
|
28684
28989
|
};
|
|
@@ -28691,13 +28996,19 @@ class MergePRCommand extends BaseCommand {
|
|
|
28691
28996
|
if (options.strategy) {
|
|
28692
28997
|
request.merge_strategy = this.parseEnumOption(options.strategy, "strategy", VALID_STRATEGIES);
|
|
28693
28998
|
}
|
|
28694
|
-
const
|
|
28695
|
-
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
28699
|
-
|
|
28700
|
-
|
|
28999
|
+
const spinner = this.output.spinner(`Merging pull request #${prId}...`).start();
|
|
29000
|
+
let pr;
|
|
29001
|
+
try {
|
|
29002
|
+
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdMergePost({
|
|
29003
|
+
workspace: repoContext.workspace,
|
|
29004
|
+
repoSlug: repoContext.repoSlug,
|
|
29005
|
+
pullRequestId: prId,
|
|
29006
|
+
pullrequestMergeParameters: request
|
|
29007
|
+
});
|
|
29008
|
+
pr = response.data;
|
|
29009
|
+
} finally {
|
|
29010
|
+
spinner.stop();
|
|
29011
|
+
}
|
|
28701
29012
|
if (context.globalOptions.json) {
|
|
28702
29013
|
await this.output.json({
|
|
28703
29014
|
success: true,
|
|
@@ -28722,11 +29033,8 @@ class ApprovePRCommand extends BaseCommand {
|
|
|
28722
29033
|
this.contextService = contextService;
|
|
28723
29034
|
}
|
|
28724
29035
|
async execute(options, context) {
|
|
28725
|
-
const repoContext = await this.contextService.
|
|
28726
|
-
|
|
28727
|
-
...options
|
|
28728
|
-
});
|
|
28729
|
-
const prId = Number.parseInt(options.id, 10);
|
|
29036
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29037
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
28730
29038
|
await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdApprovePost({
|
|
28731
29039
|
workspace: repoContext.workspace,
|
|
28732
29040
|
repoSlug: repoContext.repoSlug,
|
|
@@ -28755,11 +29063,8 @@ class DeclinePRCommand extends BaseCommand {
|
|
|
28755
29063
|
this.contextService = contextService;
|
|
28756
29064
|
}
|
|
28757
29065
|
async execute(options, context) {
|
|
28758
|
-
const repoContext = await this.contextService.
|
|
28759
|
-
|
|
28760
|
-
...options
|
|
28761
|
-
});
|
|
28762
|
-
const prId = Number.parseInt(options.id, 10);
|
|
29066
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29067
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
28763
29068
|
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdDeclinePost({
|
|
28764
29069
|
workspace: repoContext.workspace,
|
|
28765
29070
|
repoSlug: repoContext.repoSlug,
|
|
@@ -28790,11 +29095,8 @@ class ReadyPRCommand extends BaseCommand {
|
|
|
28790
29095
|
this.contextService = contextService;
|
|
28791
29096
|
}
|
|
28792
29097
|
async execute(options, context) {
|
|
28793
|
-
const repoContext = await this.contextService.
|
|
28794
|
-
|
|
28795
|
-
...options
|
|
28796
|
-
});
|
|
28797
|
-
const prId = Number.parseInt(options.id, 10);
|
|
29098
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29099
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
28798
29100
|
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdPut({
|
|
28799
29101
|
workspace: repoContext.workspace,
|
|
28800
29102
|
repoSlug: repoContext.repoSlug,
|
|
@@ -28832,11 +29134,8 @@ class CheckoutPRCommand extends BaseCommand {
|
|
|
28832
29134
|
this.gitService = gitService;
|
|
28833
29135
|
}
|
|
28834
29136
|
async execute(options, context) {
|
|
28835
|
-
const repoContext = await this.contextService.
|
|
28836
|
-
|
|
28837
|
-
...options
|
|
28838
|
-
});
|
|
28839
|
-
const prId = Number.parseInt(options.id, 10);
|
|
29137
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29138
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
28840
29139
|
const prResponse = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
|
|
28841
29140
|
workspace: repoContext.workspace,
|
|
28842
29141
|
repoSlug: repoContext.repoSlug,
|
|
@@ -28899,20 +29198,10 @@ class DiffPRCommand extends BaseCommand {
|
|
|
28899
29198
|
this.gitService = gitService;
|
|
28900
29199
|
}
|
|
28901
29200
|
async execute(options, context) {
|
|
28902
|
-
const repoContext = await this.contextService.
|
|
28903
|
-
...context.globalOptions,
|
|
28904
|
-
...options
|
|
28905
|
-
});
|
|
29201
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
28906
29202
|
let prId;
|
|
28907
29203
|
if (options.id) {
|
|
28908
|
-
prId =
|
|
28909
|
-
if (Number.isNaN(prId)) {
|
|
28910
|
-
throw new BBError({
|
|
28911
|
-
code: 5002 /* VALIDATION_INVALID */,
|
|
28912
|
-
message: "Invalid PR ID",
|
|
28913
|
-
context: { id: options.id }
|
|
28914
|
-
});
|
|
28915
|
-
}
|
|
29204
|
+
prId = this.parsePositiveInt(options.id, "id");
|
|
28916
29205
|
} else {
|
|
28917
29206
|
const currentBranch = await this.gitService.getCurrentBranch();
|
|
28918
29207
|
const matches = await collectPages({
|
|
@@ -29129,11 +29418,8 @@ class ActivityPRCommand extends BaseCommand {
|
|
|
29129
29418
|
this.contextService = contextService;
|
|
29130
29419
|
}
|
|
29131
29420
|
async execute(options, context) {
|
|
29132
|
-
const repoContext = await this.contextService.
|
|
29133
|
-
|
|
29134
|
-
...options
|
|
29135
|
-
});
|
|
29136
|
-
const prId = this.parseIntOption(options.id, "id");
|
|
29421
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29422
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
29137
29423
|
const filterTypes = this.parseTypeFilter(options.type);
|
|
29138
29424
|
const limit = parseLimit(options.limit);
|
|
29139
29425
|
const activities = await collectPages({
|
|
@@ -29182,7 +29468,7 @@ class ActivityPRCommand extends BaseCommand {
|
|
|
29182
29468
|
activityType.toUpperCase(),
|
|
29183
29469
|
this.getActorName(activity),
|
|
29184
29470
|
this.formatActivityDate(activity),
|
|
29185
|
-
this.buildActivityDetails(activity, activityType)
|
|
29471
|
+
this.buildActivityDetails(activity, activityType, context.globalOptions)
|
|
29186
29472
|
];
|
|
29187
29473
|
});
|
|
29188
29474
|
this.output.table(["TYPE", "ACTOR", "DATE", "DETAILS"], rows);
|
|
@@ -29237,19 +29523,19 @@ class ActivityPRCommand extends BaseCommand {
|
|
|
29237
29523
|
}
|
|
29238
29524
|
return this.output.formatDate(date);
|
|
29239
29525
|
}
|
|
29240
|
-
buildActivityDetails(activity, type) {
|
|
29526
|
+
buildActivityDetails(activity, type, globalOptions) {
|
|
29241
29527
|
switch (type) {
|
|
29242
29528
|
case "comment": {
|
|
29243
29529
|
const content = getRawContent(activity.comment?.content) ?? "";
|
|
29244
29530
|
const id = activity.comment?.id ? `#${activity.comment.id}` : "";
|
|
29245
|
-
const snippet = this.
|
|
29531
|
+
const snippet = this.truncateText(content, 80, globalOptions);
|
|
29246
29532
|
return [id, snippet].filter(Boolean).join(" ");
|
|
29247
29533
|
}
|
|
29248
29534
|
case "approval":
|
|
29249
29535
|
return "approved";
|
|
29250
29536
|
case "changes_requested": {
|
|
29251
29537
|
const reason = activity.changes_requested?.reason;
|
|
29252
|
-
return reason ? this.
|
|
29538
|
+
return reason ? this.truncateText(reason, 80, globalOptions) : "changes requested";
|
|
29253
29539
|
}
|
|
29254
29540
|
case "merge":
|
|
29255
29541
|
return this.formatCommitDetail(activity.merge?.commit?.hash, "merged");
|
|
@@ -29262,7 +29548,7 @@ class ActivityPRCommand extends BaseCommand {
|
|
|
29262
29548
|
return `state: ${activity.update.state}`;
|
|
29263
29549
|
}
|
|
29264
29550
|
if (activity.update?.title) {
|
|
29265
|
-
return `title: ${this.
|
|
29551
|
+
return `title: ${this.truncateText(activity.update.title, 60, globalOptions)}`;
|
|
29266
29552
|
}
|
|
29267
29553
|
if (activity.update?.description) {
|
|
29268
29554
|
return "description updated";
|
|
@@ -29280,12 +29566,6 @@ class ActivityPRCommand extends BaseCommand {
|
|
|
29280
29566
|
const shortHash = hash.slice(0, 7);
|
|
29281
29567
|
return label ? `${label} ${shortHash}` : shortHash;
|
|
29282
29568
|
}
|
|
29283
|
-
truncate(text, maxLength) {
|
|
29284
|
-
if (text.length <= maxLength) {
|
|
29285
|
-
return text;
|
|
29286
|
-
}
|
|
29287
|
-
return text.substring(0, maxLength - 3) + "...";
|
|
29288
|
-
}
|
|
29289
29569
|
}
|
|
29290
29570
|
|
|
29291
29571
|
// src/commands/pr/comment.command.ts
|
|
@@ -29319,33 +29599,14 @@ class CommentPRCommand extends BaseCommand {
|
|
|
29319
29599
|
}
|
|
29320
29600
|
});
|
|
29321
29601
|
}
|
|
29322
|
-
|
|
29323
|
-
|
|
29324
|
-
|
|
29325
|
-
|
|
29326
|
-
code: 5002 /* VALIDATION_INVALID */,
|
|
29327
|
-
message: "--line-to must be a positive integer"
|
|
29328
|
-
});
|
|
29329
|
-
}
|
|
29330
|
-
}
|
|
29331
|
-
if (options.lineFrom) {
|
|
29332
|
-
const parsed = Number.parseInt(options.lineFrom, 10);
|
|
29333
|
-
if (Number.isNaN(parsed) || parsed < 1) {
|
|
29334
|
-
throw new BBError({
|
|
29335
|
-
code: 5002 /* VALIDATION_INVALID */,
|
|
29336
|
-
message: "--line-from must be a positive integer"
|
|
29337
|
-
});
|
|
29338
|
-
}
|
|
29339
|
-
}
|
|
29340
|
-
const repoContext = await this.contextService.requireRepoContext({
|
|
29341
|
-
...context.globalOptions,
|
|
29342
|
-
...options
|
|
29343
|
-
});
|
|
29344
|
-
const prId = Number.parseInt(options.id, 10);
|
|
29602
|
+
const lineTo = options.lineTo ? this.parsePositiveInt(options.lineTo, "line-to") : undefined;
|
|
29603
|
+
const lineFrom = options.lineFrom ? this.parsePositiveInt(options.lineFrom, "line-from") : undefined;
|
|
29604
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29605
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
29345
29606
|
const inline = options.file ? {
|
|
29346
29607
|
path: options.file,
|
|
29347
|
-
...
|
|
29348
|
-
...
|
|
29608
|
+
...lineTo !== undefined ? { to: lineTo } : {},
|
|
29609
|
+
...lineFrom !== undefined ? { from: lineFrom } : {}
|
|
29349
29610
|
} : undefined;
|
|
29350
29611
|
const body = {
|
|
29351
29612
|
content: {
|
|
@@ -29395,11 +29656,8 @@ class ListCommentsPRCommand extends BaseCommand {
|
|
|
29395
29656
|
this.contextService = contextService;
|
|
29396
29657
|
}
|
|
29397
29658
|
async execute(options, context) {
|
|
29398
|
-
const repoContext = await this.contextService.
|
|
29399
|
-
|
|
29400
|
-
...options
|
|
29401
|
-
});
|
|
29402
|
-
const prId = this.parseIntOption(options.id, "id");
|
|
29659
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29660
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
29403
29661
|
const limit = parseLimit(options.limit);
|
|
29404
29662
|
const values = await collectPages({
|
|
29405
29663
|
limit,
|
|
@@ -29416,6 +29674,8 @@ class ListCommentsPRCommand extends BaseCommand {
|
|
|
29416
29674
|
});
|
|
29417
29675
|
if (context.globalOptions.json) {
|
|
29418
29676
|
await this.output.json({
|
|
29677
|
+
workspace: repoContext.workspace,
|
|
29678
|
+
repoSlug: repoContext.repoSlug,
|
|
29419
29679
|
pullRequestId: prId,
|
|
29420
29680
|
count: values.length,
|
|
29421
29681
|
comments: values
|
|
@@ -29431,7 +29691,7 @@ class ListCommentsPRCommand extends BaseCommand {
|
|
|
29431
29691
|
return [
|
|
29432
29692
|
comment.id?.toString() ?? "",
|
|
29433
29693
|
getUserDisplayName(comment.user) ?? "Unknown",
|
|
29434
|
-
comment.deleted ? "[deleted]" :
|
|
29694
|
+
comment.deleted ? "[deleted]" : this.truncateText(content, 60, context.globalOptions),
|
|
29435
29695
|
this.output.formatDate(comment.created_on ?? "")
|
|
29436
29696
|
];
|
|
29437
29697
|
});
|
|
@@ -29451,12 +29711,9 @@ class EditCommentPRCommand extends BaseCommand {
|
|
|
29451
29711
|
this.contextService = contextService;
|
|
29452
29712
|
}
|
|
29453
29713
|
async execute(options, context) {
|
|
29454
|
-
const repoContext = await this.contextService.
|
|
29455
|
-
|
|
29456
|
-
|
|
29457
|
-
});
|
|
29458
|
-
const prId = this.parseIntOption(options.prId, "pr-id");
|
|
29459
|
-
const commentId = this.parseIntOption(options.commentId, "comment-id");
|
|
29714
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29715
|
+
const prId = this.parsePositiveInt(options.prId, "pr-id");
|
|
29716
|
+
const commentId = this.parsePositiveInt(options.commentId, "comment-id");
|
|
29460
29717
|
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsCommentIdPut({
|
|
29461
29718
|
workspace: repoContext.workspace,
|
|
29462
29719
|
repoSlug: repoContext.repoSlug,
|
|
@@ -29494,19 +29751,10 @@ class DeleteCommentPRCommand extends BaseCommand {
|
|
|
29494
29751
|
this.contextService = contextService;
|
|
29495
29752
|
}
|
|
29496
29753
|
async execute(options, context) {
|
|
29497
|
-
const repoContext = await this.contextService.
|
|
29498
|
-
|
|
29499
|
-
|
|
29500
|
-
});
|
|
29501
|
-
const prId = this.parseIntOption(options.prId, "pr-id");
|
|
29502
|
-
const commentId = this.parseIntOption(options.commentId, "comment-id");
|
|
29503
|
-
if (!options.yes) {
|
|
29504
|
-
throw new BBError({
|
|
29505
|
-
code: 5001 /* VALIDATION_REQUIRED */,
|
|
29506
|
-
message: `This will permanently delete comment #${commentId} on PR #${prId}.
|
|
29507
|
-
` + "Use --yes to confirm deletion."
|
|
29508
|
-
});
|
|
29509
|
-
}
|
|
29754
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29755
|
+
const prId = this.parsePositiveInt(options.prId, "pr-id");
|
|
29756
|
+
const commentId = this.parsePositiveInt(options.commentId, "comment-id");
|
|
29757
|
+
this.requireConfirmation(options.yes, `This will permanently delete comment #${commentId} on PR #${prId}.`);
|
|
29510
29758
|
await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdCommentsCommentIdDelete({
|
|
29511
29759
|
workspace: repoContext.workspace,
|
|
29512
29760
|
repoSlug: repoContext.repoSlug,
|
|
@@ -29539,11 +29787,8 @@ class AddReviewerPRCommand extends BaseCommand {
|
|
|
29539
29787
|
this.contextService = contextService;
|
|
29540
29788
|
}
|
|
29541
29789
|
async execute(options, context) {
|
|
29542
|
-
const repoContext = await this.contextService.
|
|
29543
|
-
|
|
29544
|
-
...options
|
|
29545
|
-
});
|
|
29546
|
-
const prId = this.parseIntOption(options.id, "id");
|
|
29790
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29791
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
29547
29792
|
const userResponse = await this.usersApi.usersSelectedUserGet({
|
|
29548
29793
|
selectedUser: options.username
|
|
29549
29794
|
});
|
|
@@ -29584,11 +29829,8 @@ class RemoveReviewerPRCommand extends BaseCommand {
|
|
|
29584
29829
|
this.contextService = contextService;
|
|
29585
29830
|
}
|
|
29586
29831
|
async execute(options, context) {
|
|
29587
|
-
const repoContext = await this.contextService.
|
|
29588
|
-
|
|
29589
|
-
...options
|
|
29590
|
-
});
|
|
29591
|
-
const prId = this.parseIntOption(options.id, "id");
|
|
29832
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29833
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
29592
29834
|
const userResponse = await this.usersApi.usersSelectedUserGet({
|
|
29593
29835
|
selectedUser: options.username
|
|
29594
29836
|
});
|
|
@@ -29622,11 +29864,8 @@ class ListReviewersPRCommand extends BaseCommand {
|
|
|
29622
29864
|
this.contextService = contextService;
|
|
29623
29865
|
}
|
|
29624
29866
|
async execute(options, context) {
|
|
29625
|
-
const repoContext = await this.contextService.
|
|
29626
|
-
|
|
29627
|
-
...options
|
|
29628
|
-
});
|
|
29629
|
-
const prId = this.parseIntOption(options.id, "id");
|
|
29867
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29868
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
29630
29869
|
const response = await this.pullrequestsApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdGet({
|
|
29631
29870
|
workspace: repoContext.workspace,
|
|
29632
29871
|
repoSlug: repoContext.repoSlug,
|
|
@@ -29636,6 +29875,8 @@ class ListReviewersPRCommand extends BaseCommand {
|
|
|
29636
29875
|
const reviewers = Array.from(pr.reviewers ?? []);
|
|
29637
29876
|
if (context.globalOptions.json) {
|
|
29638
29877
|
await this.output.json({
|
|
29878
|
+
workspace: repoContext.workspace,
|
|
29879
|
+
repoSlug: repoContext.repoSlug,
|
|
29639
29880
|
pullRequestId: prId,
|
|
29640
29881
|
count: reviewers.length,
|
|
29641
29882
|
reviewers
|
|
@@ -29662,11 +29903,8 @@ class ChecksPRCommand extends BaseCommand {
|
|
|
29662
29903
|
this.contextService = contextService;
|
|
29663
29904
|
}
|
|
29664
29905
|
async execute(options, context) {
|
|
29665
|
-
const repoContext = await this.contextService.
|
|
29666
|
-
|
|
29667
|
-
...options
|
|
29668
|
-
});
|
|
29669
|
-
const prId = this.parseIntOption(options.id, "id");
|
|
29906
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
29907
|
+
const prId = this.parsePositiveInt(options.id, "id");
|
|
29670
29908
|
const response = await this.commitStatusesApi.repositoriesWorkspaceRepoSlugPullrequestsPullRequestIdStatusesGet({
|
|
29671
29909
|
workspace: repoContext.workspace,
|
|
29672
29910
|
repoSlug: repoContext.repoSlug,
|
|
@@ -29690,7 +29928,7 @@ class ChecksPRCommand extends BaseCommand {
|
|
|
29690
29928
|
return;
|
|
29691
29929
|
}
|
|
29692
29930
|
this.renderHeader(prId, statuses.length);
|
|
29693
|
-
this.renderStatuses(statuses, summary);
|
|
29931
|
+
this.renderStatuses(statuses, summary, context.globalOptions);
|
|
29694
29932
|
}
|
|
29695
29933
|
formatStatusForJson(status) {
|
|
29696
29934
|
return {
|
|
@@ -29709,9 +29947,9 @@ class ChecksPRCommand extends BaseCommand {
|
|
|
29709
29947
|
this.output.text("");
|
|
29710
29948
|
const title = this.output.bold("Pull Request #" + prId);
|
|
29711
29949
|
this.output.text(`${title} - ${count} check${count === 1 ? "" : "s"}`);
|
|
29712
|
-
this.output.
|
|
29950
|
+
this.output.separator();
|
|
29713
29951
|
}
|
|
29714
|
-
renderStatuses(statuses, summary) {
|
|
29952
|
+
renderStatuses(statuses, summary, globalOptions) {
|
|
29715
29953
|
const rows = statuses.map((status) => {
|
|
29716
29954
|
const stateIcon = this.getStateIcon(status.state);
|
|
29717
29955
|
const stateLabel = this.getStateLabel(status.state);
|
|
@@ -29720,7 +29958,7 @@ class ChecksPRCommand extends BaseCommand {
|
|
|
29720
29958
|
return [
|
|
29721
29959
|
`${stateIcon} ${stateLabel}`,
|
|
29722
29960
|
this.output.bold(name),
|
|
29723
|
-
this.
|
|
29961
|
+
this.truncateText(description, 40, globalOptions),
|
|
29724
29962
|
status.updated_on ? this.output.formatDate(status.updated_on) : "-"
|
|
29725
29963
|
];
|
|
29726
29964
|
});
|
|
@@ -29770,12 +30008,6 @@ class ChecksPRCommand extends BaseCommand {
|
|
|
29770
30008
|
return acc;
|
|
29771
30009
|
}, { successful: 0, failed: 0, pending: 0 });
|
|
29772
30010
|
}
|
|
29773
|
-
truncate(text, maxLength) {
|
|
29774
|
-
if (text.length <= maxLength) {
|
|
29775
|
-
return text;
|
|
29776
|
-
}
|
|
29777
|
-
return text.substring(0, maxLength - 3) + "...";
|
|
29778
|
-
}
|
|
29779
30011
|
}
|
|
29780
30012
|
|
|
29781
30013
|
// src/commands/snippet/list.command.ts
|
|
@@ -29816,7 +30048,7 @@ class ListSnippetsCommand extends BaseCommand {
|
|
|
29816
30048
|
return;
|
|
29817
30049
|
}
|
|
29818
30050
|
if (snippets.length === 0) {
|
|
29819
|
-
this.output.
|
|
30051
|
+
this.output.info("No snippets found");
|
|
29820
30052
|
return;
|
|
29821
30053
|
}
|
|
29822
30054
|
const rows = snippets.map((snippet) => [
|
|
@@ -29877,9 +30109,10 @@ class ViewSnippetCommand extends BaseCommand {
|
|
|
29877
30109
|
return;
|
|
29878
30110
|
}
|
|
29879
30111
|
this.renderSnippet(snippet, fileNames);
|
|
30112
|
+
const fileSep = this.output.symbol("\u2500\u2500", "--");
|
|
29880
30113
|
for (const name of fileNames) {
|
|
29881
30114
|
this.output.text("");
|
|
29882
|
-
this.output.text(this.output.bold(
|
|
30115
|
+
this.output.text(this.output.bold(`${fileSep} ${name} ${fileSep}`));
|
|
29883
30116
|
this.output.text(contents[name] ?? "");
|
|
29884
30117
|
}
|
|
29885
30118
|
return;
|
|
@@ -29901,7 +30134,7 @@ class ViewSnippetCommand extends BaseCommand {
|
|
|
29901
30134
|
const visibility = snippet.is_private ? "private" : "public";
|
|
29902
30135
|
this.output.text("");
|
|
29903
30136
|
this.output.text(`${this.output.bold(String(snippet.id ?? ""))} ${snippet.title ?? "Untitled"} ${this.output.gray(`[${visibility}]`)}`);
|
|
29904
|
-
this.output.
|
|
30137
|
+
this.output.separator();
|
|
29905
30138
|
const creator = getUserDisplayName(snippet.creator);
|
|
29906
30139
|
if (creator) {
|
|
29907
30140
|
this.output.text(`Creator: ${creator}`);
|
|
@@ -30062,13 +30295,7 @@ class DeleteSnippetCommand extends BaseCommand {
|
|
|
30062
30295
|
}
|
|
30063
30296
|
async execute(options, context) {
|
|
30064
30297
|
const workspace = await this.contextService.requireWorkspace(options.workspace ?? context.globalOptions.workspace);
|
|
30065
|
-
|
|
30066
|
-
throw new BBError({
|
|
30067
|
-
code: 5001 /* VALIDATION_REQUIRED */,
|
|
30068
|
-
message: `This will permanently delete snippet ${options.id}.
|
|
30069
|
-
` + "Use --yes to confirm deletion."
|
|
30070
|
-
});
|
|
30071
|
-
}
|
|
30298
|
+
this.requireConfirmation(options.yes, `This will permanently delete snippet ${options.id}.`);
|
|
30072
30299
|
await this.snippetsApi.snippetsWorkspaceEncodedIdDelete({
|
|
30073
30300
|
workspace,
|
|
30074
30301
|
encodedId: options.id
|
|
@@ -30188,7 +30415,7 @@ class ListSnippetCommentsCommand extends BaseCommand {
|
|
|
30188
30415
|
String(comment.id ?? ""),
|
|
30189
30416
|
getUserDisplayName(comment.user) ?? "Unknown",
|
|
30190
30417
|
this.output.formatDate(comment.created_on ?? ""),
|
|
30191
|
-
|
|
30418
|
+
this.truncateText(content, 60, context.globalOptions)
|
|
30192
30419
|
];
|
|
30193
30420
|
});
|
|
30194
30421
|
this.output.table(["ID", "AUTHOR", "DATE", "CONTENT"], rows);
|
|
@@ -30247,7 +30474,7 @@ class EditSnippetCommentCommand extends BaseCommand {
|
|
|
30247
30474
|
}
|
|
30248
30475
|
async execute(options, context) {
|
|
30249
30476
|
const workspace = await this.contextService.requireWorkspace(options.workspace ?? context.globalOptions.workspace);
|
|
30250
|
-
const commentId = this.
|
|
30477
|
+
const commentId = this.parsePositiveInt(options.commentId, "comment-id");
|
|
30251
30478
|
const body = {
|
|
30252
30479
|
type: "snippet_comment",
|
|
30253
30480
|
content: {
|
|
@@ -30285,14 +30512,8 @@ class DeleteSnippetCommentCommand extends BaseCommand {
|
|
|
30285
30512
|
}
|
|
30286
30513
|
async execute(options, context) {
|
|
30287
30514
|
const workspace = await this.contextService.requireWorkspace(options.workspace ?? context.globalOptions.workspace);
|
|
30288
|
-
const commentId = this.
|
|
30289
|
-
|
|
30290
|
-
throw new BBError({
|
|
30291
|
-
code: 5001 /* VALIDATION_REQUIRED */,
|
|
30292
|
-
message: `This will permanently delete comment #${commentId} on snippet ${options.snippetId}.
|
|
30293
|
-
` + "Use --yes to confirm deletion."
|
|
30294
|
-
});
|
|
30295
|
-
}
|
|
30515
|
+
const commentId = this.parsePositiveInt(options.commentId, "comment-id");
|
|
30516
|
+
this.requireConfirmation(options.yes, `This will permanently delete comment #${commentId} on snippet ${options.snippetId}.`);
|
|
30296
30517
|
await this.snippetsApi.snippetsWorkspaceEncodedIdCommentsCommentIdDelete({
|
|
30297
30518
|
workspace,
|
|
30298
30519
|
encodedId: options.snippetId,
|
|
@@ -30436,7 +30657,7 @@ class ListConfigCommand extends BaseCommand {
|
|
|
30436
30657
|
String(value)
|
|
30437
30658
|
]);
|
|
30438
30659
|
if (rows.length === 0) {
|
|
30439
|
-
this.output.
|
|
30660
|
+
this.output.info("No configuration set");
|
|
30440
30661
|
} else {
|
|
30441
30662
|
this.output.table(["KEY", "VALUE"], rows);
|
|
30442
30663
|
}
|
|
@@ -30535,10 +30756,7 @@ class BrowseCommand extends BaseCommand {
|
|
|
30535
30756
|
this.urlBuilder = urlBuilder;
|
|
30536
30757
|
}
|
|
30537
30758
|
async execute(options, context) {
|
|
30538
|
-
const repoContext = await this.contextService.
|
|
30539
|
-
...context.globalOptions,
|
|
30540
|
-
...options
|
|
30541
|
-
});
|
|
30759
|
+
const repoContext = await this.contextService.requireRepoContextFor(options, context);
|
|
30542
30760
|
this.validateFlagCombination(options);
|
|
30543
30761
|
const url2 = await this.resolveUrl(options, repoContext);
|
|
30544
30762
|
const useJson = Boolean(context.globalOptions.json);
|
|
@@ -30602,7 +30820,7 @@ class BrowseCommand extends BaseCommand {
|
|
|
30602
30820
|
const target = options.target?.trim();
|
|
30603
30821
|
if (target && target.length > 0) {
|
|
30604
30822
|
if (PR_NUMBER_PATTERN.test(target)) {
|
|
30605
|
-
return this.urlBuilder.pullRequest(ctx,
|
|
30823
|
+
return this.urlBuilder.pullRequest(ctx, this.parsePositiveInt(target, "target"));
|
|
30606
30824
|
}
|
|
30607
30825
|
if (SHA_PATTERN.test(target)) {
|
|
30608
30826
|
return this.urlBuilder.commit(ctx, target);
|
|
@@ -30686,17 +30904,6 @@ class BrowseCommand extends BaseCommand {
|
|
|
30686
30904
|
return "HEAD";
|
|
30687
30905
|
}
|
|
30688
30906
|
}
|
|
30689
|
-
parsePositiveInt(value, name) {
|
|
30690
|
-
const parsed = Number.parseInt(value, 10);
|
|
30691
|
-
if (!Number.isFinite(parsed) || parsed <= 0 || String(parsed) !== value.trim()) {
|
|
30692
|
-
throw new BBError({
|
|
30693
|
-
code: 5002 /* VALIDATION_INVALID */,
|
|
30694
|
-
message: this.appendHelpHint(`--${name} must be a positive integer.`),
|
|
30695
|
-
context: { [name]: value }
|
|
30696
|
-
});
|
|
30697
|
-
}
|
|
30698
|
-
return parsed;
|
|
30699
|
-
}
|
|
30700
30907
|
async openInBrowser(url2) {
|
|
30701
30908
|
this.output.info(`Opening ${url2} in your browser...`);
|
|
30702
30909
|
const open2 = (await Promise.resolve().then(() => (init_open(), exports_open))).default;
|
|
@@ -30711,7 +30918,8 @@ function registerApiClient(container, token, ctor) {
|
|
|
30711
30918
|
container.register(token, () => {
|
|
30712
30919
|
const credentialStore = container.resolve(ServiceTokens.CredentialStore);
|
|
30713
30920
|
const oauthService = container.resolve(ServiceTokens.OAuthService);
|
|
30714
|
-
const
|
|
30921
|
+
const outputService = container.resolve(ServiceTokens.OutputService);
|
|
30922
|
+
const axiosInstance = createApiClient(credentialStore, outputService, oauthService);
|
|
30715
30923
|
return new ctor(undefined, undefined, axiosInstance);
|
|
30716
30924
|
});
|
|
30717
30925
|
}
|
|
@@ -30726,7 +30934,11 @@ function bootstrap(options = {}) {
|
|
|
30726
30934
|
container.register(ServiceTokens.ConfigService, () => new ConfigService);
|
|
30727
30935
|
container.register(ServiceTokens.CredentialStore, () => container.resolve(ServiceTokens.ConfigService));
|
|
30728
30936
|
container.register(ServiceTokens.GitService, () => new GitService);
|
|
30729
|
-
container.register(ServiceTokens.OutputService, () => new OutputService({
|
|
30937
|
+
container.register(ServiceTokens.OutputService, () => new OutputService({
|
|
30938
|
+
noColor: options.noColor,
|
|
30939
|
+
noUnicode: options.noUnicode,
|
|
30940
|
+
locale: options.locale
|
|
30941
|
+
}));
|
|
30730
30942
|
registerCommand(container, ServiceTokens.OAuthService, OAuthService, [
|
|
30731
30943
|
ServiceTokens.ConfigService,
|
|
30732
30944
|
ServiceTokens.CredentialStore
|
|
@@ -30742,7 +30954,8 @@ function bootstrap(options = {}) {
|
|
|
30742
30954
|
container.register(ServiceTokens.SnippetsAxios, () => {
|
|
30743
30955
|
const credentialStore = container.resolve(ServiceTokens.CredentialStore);
|
|
30744
30956
|
const oauthService = container.resolve(ServiceTokens.OAuthService);
|
|
30745
|
-
|
|
30957
|
+
const outputService = container.resolve(ServiceTokens.OutputService);
|
|
30958
|
+
return createApiClient(credentialStore, outputService, oauthService);
|
|
30746
30959
|
});
|
|
30747
30960
|
container.register(ServiceTokens.SnippetsApi, () => {
|
|
30748
30961
|
const axiosInstance = container.resolve(ServiceTokens.SnippetsAxios);
|
|
@@ -31087,8 +31300,11 @@ var ROOT_COMPLETIONS = [
|
|
|
31087
31300
|
"--version",
|
|
31088
31301
|
"--json",
|
|
31089
31302
|
"--no-color",
|
|
31303
|
+
"--no-unicode",
|
|
31304
|
+
"--no-truncate",
|
|
31090
31305
|
"--workspace",
|
|
31091
|
-
"--repo"
|
|
31306
|
+
"--repo",
|
|
31307
|
+
"--locale"
|
|
31092
31308
|
];
|
|
31093
31309
|
var SUBCOMMAND_COMPLETIONS = new Map([
|
|
31094
31310
|
["auth", ["login", "logout", "status", "token"]],
|
|
@@ -31155,6 +31371,25 @@ if (process.argv.includes("--get-yargs-completions") || process.env.COMP_LINE) {
|
|
|
31155
31371
|
process.exit(0);
|
|
31156
31372
|
}
|
|
31157
31373
|
}
|
|
31374
|
+
function extractLocaleArg(argv) {
|
|
31375
|
+
for (let i = 0;i < argv.length; i++) {
|
|
31376
|
+
const arg = argv[i];
|
|
31377
|
+
if (arg === undefined) {
|
|
31378
|
+
continue;
|
|
31379
|
+
}
|
|
31380
|
+
if (arg === "--locale") {
|
|
31381
|
+
const next = argv[i + 1];
|
|
31382
|
+
if (typeof next === "string" && !next.startsWith("-")) {
|
|
31383
|
+
return next;
|
|
31384
|
+
}
|
|
31385
|
+
return;
|
|
31386
|
+
}
|
|
31387
|
+
if (arg.startsWith("--locale=")) {
|
|
31388
|
+
return arg.slice("--locale=".length);
|
|
31389
|
+
}
|
|
31390
|
+
}
|
|
31391
|
+
return;
|
|
31392
|
+
}
|
|
31158
31393
|
function resolveNoColorSetting(argv, env2) {
|
|
31159
31394
|
const hasColorArg = argv.includes("--color");
|
|
31160
31395
|
const hasNoColorArg = argv.includes("--no-color");
|
|
@@ -31171,9 +31406,20 @@ function resolveNoColorSetting(argv, env2) {
|
|
|
31171
31406
|
}
|
|
31172
31407
|
return hasNoColorEnv;
|
|
31173
31408
|
}
|
|
31409
|
+
function resolveNoUnicodeSetting(argv, env2) {
|
|
31410
|
+
if (argv.includes("--no-unicode")) {
|
|
31411
|
+
return true;
|
|
31412
|
+
}
|
|
31413
|
+
return env2.BB_NO_UNICODE !== undefined && env2.BB_NO_UNICODE !== "";
|
|
31414
|
+
}
|
|
31174
31415
|
var noColor = resolveNoColorSetting(process.argv, process.env);
|
|
31416
|
+
var noUnicode = resolveNoUnicodeSetting(process.argv, process.env);
|
|
31175
31417
|
var buildHelpText = createHelpTextBuilder(noColor);
|
|
31176
|
-
var
|
|
31418
|
+
var locale = resolveLocale({
|
|
31419
|
+
explicit: extractLocaleArg(process.argv),
|
|
31420
|
+
env: process.env
|
|
31421
|
+
});
|
|
31422
|
+
var container = bootstrap({ noColor, noUnicode, locale });
|
|
31177
31423
|
function createContext(program2) {
|
|
31178
31424
|
const opts = program2.opts();
|
|
31179
31425
|
const jsonOpt = opts.json;
|
|
@@ -31204,6 +31450,8 @@ function createContext(program2) {
|
|
|
31204
31450
|
jsonFields,
|
|
31205
31451
|
jq: jqOpt,
|
|
31206
31452
|
noColor: opts.color === false,
|
|
31453
|
+
noUnicode: opts.unicode === false || noUnicode,
|
|
31454
|
+
noTruncate: opts.truncate === false,
|
|
31207
31455
|
workspace: opts.workspace,
|
|
31208
31456
|
repo: opts.repo
|
|
31209
31457
|
},
|
|
@@ -31233,13 +31481,15 @@ function withGlobalOptions(options, context) {
|
|
|
31233
31481
|
};
|
|
31234
31482
|
}
|
|
31235
31483
|
var cli = new Command;
|
|
31236
|
-
cli.name("bb").description("A command-line interface for Bitbucket Cloud").version(pkg2.version).option("--json [fields]", "Output as JSON; optionally project to a comma-separated field list (e.g. number,title,author.display_name)").option("--jq <expression>", `Filter the JSON output through a jq expression \u2014 runs in-process via embedded jq, requires --json (e.g. '.pullRequests[] | select(.state == "OPEN") | .title')`).option("--no-color", "Disable color output").option("-w, --workspace <workspace>", "Specify workspace").option("-r, --repo <repo>", "Specify repository").addHelpText("after", buildHelpText({
|
|
31484
|
+
cli.name("bb").description("A command-line interface for Bitbucket Cloud").version(pkg2.version).option("--json [fields]", "Output as JSON; optionally project to a comma-separated field list (e.g. number,title,author.display_name)").option("--jq <expression>", `Filter the JSON output through a jq expression \u2014 runs in-process via embedded jq, requires --json (e.g. '.pullRequests[] | select(.state == "OPEN") | .title')`).option("--no-color", "Disable color output").option("--no-unicode", "Use ASCII fallbacks for symbols (separators, arrows, status icons) \u2014 also enabled by BB_NO_UNICODE").option("--no-truncate", "Show full values in table output without truncation").option("--locale <locale>", "BCP-47 locale tag for date/time formatting (e.g. de-DE, ja-JP). Falls back to BB_LOCALE, then LC_TIME/LC_ALL/LANG, then en-US.").option("-w, --workspace <workspace>", "Specify workspace").option("-r, --repo <repo>", "Specify repository").addHelpText("after", buildHelpText({
|
|
31237
31485
|
envVars: {
|
|
31238
31486
|
BB_USERNAME: "Bitbucket username (fallback for auth login)",
|
|
31239
31487
|
BB_API_TOKEN: "Bitbucket API token (fallback for auth login)",
|
|
31240
31488
|
NO_COLOR: "Disable color output when set",
|
|
31241
31489
|
FORCE_COLOR: "Force color output when set (and not '0')",
|
|
31242
|
-
|
|
31490
|
+
BB_NO_UNICODE: "Use ASCII fallbacks for symbols when set (any non-empty value)",
|
|
31491
|
+
DEBUG: "Enable HTTP debug logging when 'true'",
|
|
31492
|
+
BB_LOCALE: "BCP-47 locale tag for date/time formatting; --locale takes precedence"
|
|
31243
31493
|
},
|
|
31244
31494
|
seeAlso: [
|
|
31245
31495
|
{
|
|
@@ -31263,11 +31513,11 @@ cli.name("bb").description("A command-line interface for Bitbucket Cloud").versi
|
|
|
31263
31513
|
const result = await versionService.checkForUpdate();
|
|
31264
31514
|
if (result?.updateAvailable) {
|
|
31265
31515
|
output.text("");
|
|
31266
|
-
output.
|
|
31267
|
-
output.
|
|
31268
|
-
|
|
31269
|
-
|
|
31270
|
-
output.
|
|
31516
|
+
output.separator(50);
|
|
31517
|
+
output.warning(`A new version is available: ${result.latestVersion} (you have ${result.currentVersion})
|
|
31518
|
+
` + ` Run '${versionService.getInstallCommand()}' to update
|
|
31519
|
+
` + ` Or disable with 'bb config set skipVersionCheck true'`);
|
|
31520
|
+
output.separator(50);
|
|
31271
31521
|
}
|
|
31272
31522
|
} catch {}
|
|
31273
31523
|
try {
|
|
@@ -31574,7 +31824,7 @@ prCmd.command("diff [id]").description("View pull request diff").option("--color
|
|
|
31574
31824
|
await runCommand(ServiceTokens.DiffPRCommand, withGlobalOptions({ id, ...options }, context), cli, context);
|
|
31575
31825
|
});
|
|
31576
31826
|
var prCommentsCmd = new Command("comments").description("Manage pull request comments");
|
|
31577
|
-
prCommentsCmd.command("list <id>").description("List comments on a pull request").option("--limit <number>", "Maximum number of comments (default: 25)").
|
|
31827
|
+
prCommentsCmd.command("list <id>").description("List comments on a pull request").option("--limit <number>", "Maximum number of comments (default: 25)").addHelpText("after", buildHelpText({
|
|
31578
31828
|
examples: [
|
|
31579
31829
|
"bb pr comments list 42",
|
|
31580
31830
|
"bb pr comments list 42 --no-truncate",
|
|
@@ -31841,3 +32091,6 @@ if (typeof Bun === "undefined") {
|
|
|
31841
32091
|
process.exit(1);
|
|
31842
32092
|
}
|
|
31843
32093
|
cli.parse(process.argv);
|
|
32094
|
+
|
|
32095
|
+
//# debugId=1F677A9695E119AD64756E2164756E21
|
|
32096
|
+
//# sourceMappingURL=index.js.map
|