Skip to content

Commit 795847a

Browse files
committed
address codeql
1 parent 66daa2c commit 795847a

File tree

3 files changed

+37
-16
lines changed

3 files changed

+37
-16
lines changed

apps/cli/src/cli.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import {
4545

4646
const CMD_WIDTH = 22;
4747

48-
const TAGLINE = `Array (arr) is a CLI for stacked PRs using Jujutsu (jj).
48+
const TAGLINE = `arr is a CLI for stacked PRs using jj.
4949
It enables stacking changes on top of each other to keep you unblocked
5050
and your changes small, focused, and reviewable.`;
5151

@@ -98,19 +98,19 @@ ${coreCommands.map(formatCoreCommand).join("\n")}
9898
Run ${cyan("arr --help --all")} for a full command reference.
9999
100100
${bold("CORE WORKFLOW")}
101-
1. ${cyan('arr create "add user auth"')} Create a new change
102-
2. ${dim("(make edits - jj tracks automatically)")}
103-
3. ${cyan('arr create "add tests"')} Stack another change
104-
4. ${cyan("arr submit")} Create PRs for the stack
105-
5. ${cyan("arr sync")} Fetch & rebase after reviews
101+
1. ${cyan('arr create "add user auth"')}\tCreate a new change
102+
2. ${dim("(make edits)")}\t\t\t jj tracks automatically
103+
3. ${cyan('arr create "add tests"')}\tStack another change
104+
4. ${cyan("arr submit")}\t\t\tCreate PRs for the stack
105+
5. ${cyan("arr sync")}\t\t\tFetch & rebase after reviews
106106
107107
${bold("ESCAPE HATCH")}
108-
${cyan("arr exit")} Switch back to plain git if you need it.
109-
Your jj changes are preserved and you can return anytime.
108+
${cyan("arr exit")}\t\t\tSwitch back to plain git if you need it.
109+
\t\t\t\tYour jj changes are preserved and you can return anytime.
110110
111111
${bold("LEARN MORE")}
112-
Documentation: https://github.com/posthog/array
113-
jj documentation: https://www.jj-vcs.dev/latest/
112+
Documentation\t\t\thttps://github.com/posthog/array
113+
jj documentation\t\thttps://www.jj-vcs.dev/latest/
114114
`);
115115
}
116116

packages/core/src/ci.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ on:
1414
pull_request_target:
1515
types: [closed]
1616
17+
permissions:
18+
contents: read
19+
1720
jobs:
1821
check:
1922
runs-on: ubuntu-latest
2023
if: github.event_name == 'pull_request'
24+
permissions:
25+
pull-requests: read
26+
issues: read
2127
steps:
2228
- name: Check stack dependencies
2329
uses: actions/github-script@v7
@@ -86,6 +92,9 @@ jobs:
8692
github.event_name == 'pull_request_target' &&
8793
github.event.action == 'closed' &&
8894
github.event.pull_request.merged == true
95+
permissions:
96+
pull-requests: write
97+
issues: read
8998
steps:
9099
- name: Trigger recheck of dependent PRs
91100
uses: actions/github-script@v7
@@ -168,14 +177,17 @@ export function getRepoInfoFromRemote(
168177
remoteUrl: string,
169178
): Result<{ owner: string; repo: string }> {
170179
// Handle SSH format: git@github.com:owner/repo.git
171-
const sshMatch = remoteUrl.match(/git@github\.com:([^/]+)\/([^/.\s]+)/);
180+
// Use [\w-]+ to match valid GitHub usernames/org names (alphanumeric, underscore, hyphen)
181+
const sshMatch = remoteUrl.match(
182+
/^git@github\.com:([\w-]+)\/([\w.-]+?)(?:\.git)?$/,
183+
);
172184
if (sshMatch) {
173185
return ok({ owner: sshMatch[1], repo: sshMatch[2] });
174186
}
175187

176188
// Handle HTTPS format: https://github.com/owner/repo.git
177189
const httpsMatch = remoteUrl.match(
178-
/https:\/\/github\.com\/([^/]+)\/([^/.\s]+)/,
190+
/^https:\/\/github\.com\/([\w-]+)\/([\w.-]+?)(?:\.git)?$/,
179191
);
180192
if (httpsMatch) {
181193
return ok({ owner: httpsMatch[1], repo: httpsMatch[2] });

packages/core/src/jj.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,8 @@ export class JJ {
217217
}
218218

219219
// Search by description and bookmarks
220-
const escaped = query.replace(/"/g, '\\"');
220+
// Escape backslashes first, then quotes
221+
const escaped = query.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
221222
const revset = options.includeBookmarks
222223
? `description(substring-i:"${escaped}") | bookmarks(substring-i:"${escaped}")`
223224
: `description(substring-i:"${escaped}")`;
@@ -601,7 +602,9 @@ export class JJ {
601602
if (stack.changeCount !== 1) return true;
602603
const only = stack.changes[0];
603604
if (!only.isWorkingCopy) return true;
604-
return !only.isEmpty || only.description.trim() !== "" || only.hasConflicts;
605+
return (
606+
!only.isEmpty || only.description.trim() !== "" || only.hasConflicts
607+
);
605608
});
606609

607610
// Sort by whether it contains current, then by timestamp
@@ -849,9 +852,15 @@ export class JJ {
849852
}
850853

851854
async exitToGit(): Promise<Result<{ trunk: string }>> {
852-
const result = await this.executor.execute("git", ["checkout", this.trunk], { cwd: this.cwd });
855+
const result = await this.executor.execute(
856+
"git",
857+
["checkout", this.trunk],
858+
{ cwd: this.cwd },
859+
);
853860
if (result.exitCode !== 0) {
854-
return err(createError("COMMAND_FAILED", result.stderr || "git checkout failed"));
861+
return err(
862+
createError("COMMAND_FAILED", result.stderr || "git checkout failed"),
863+
);
855864
}
856865
return ok({ trunk: this.trunk });
857866
}

0 commit comments

Comments
 (0)