mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Knip fixes
This commit is contained in:
parent
0e7a14e68a
commit
29d73dce4c
3 changed files with 2 additions and 433 deletions
11
knip.json
11
knip.json
|
|
@ -1,12 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://unpkg.com/knip@latest/schema.json",
|
"$schema": "https://unpkg.com/knip@latest/schema.json",
|
||||||
"entry": [
|
"entry": ["src/extension.ts", "src/activate/index.ts", "webview-ui/src/index.tsx"],
|
||||||
"src/extension.ts",
|
|
||||||
"src/activate/index.ts",
|
|
||||||
"src/core/mentions/index.ts",
|
|
||||||
"webview-ui/src/index.tsx",
|
|
||||||
"src/core/webview/webviewMessageHandler.ts"
|
|
||||||
],
|
|
||||||
"project": ["src/**/*.ts", "webview-ui/src/**/*.{ts,tsx}"],
|
"project": ["src/**/*.ts", "webview-ui/src/**/*.{ts,tsx}"],
|
||||||
"ignore": [
|
"ignore": [
|
||||||
"**/__mocks__/**",
|
"**/__mocks__/**",
|
||||||
|
|
@ -25,9 +19,8 @@
|
||||||
"src/exports/**",
|
"src/exports/**",
|
||||||
"src/schemas/ipc.ts",
|
"src/schemas/ipc.ts",
|
||||||
"src/extension.ts",
|
"src/extension.ts",
|
||||||
"scripts/**",
|
|
||||||
"marketplace-template/**",
|
"marketplace-template/**",
|
||||||
"src/utils/git.ts"
|
"scripts/**"
|
||||||
],
|
],
|
||||||
"workspaces": {
|
"workspaces": {
|
||||||
"webview-ui": {
|
"webview-ui": {
|
||||||
|
|
|
||||||
|
|
@ -1,295 +0,0 @@
|
||||||
import { jest } from "@jest/globals";
|
|
||||||
import { searchCommits, getCommitInfo, getWorkingState } from "../git";
|
|
||||||
// Mock child_process.exec
|
|
||||||
jest.mock("child_process", () => ({
|
|
||||||
exec: jest.fn(),
|
|
||||||
}));
|
|
||||||
// Mock util.promisify to return our own mock function
|
|
||||||
jest.mock("util", () => ({
|
|
||||||
promisify: jest.fn((fn) => {
|
|
||||||
return async (command, options) => {
|
|
||||||
// Call the original mock to maintain the mock implementation
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
fn(command, options || {}, (error, result) => {
|
|
||||||
if (error) {
|
|
||||||
reject(error);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resolve(result);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
}));
|
|
||||||
// Mock extract-text
|
|
||||||
jest.mock("../../integrations/misc/extract-text", () => ({
|
|
||||||
truncateOutput: jest.fn((text) => text),
|
|
||||||
}));
|
|
||||||
describe("git utils", () => {
|
|
||||||
// Get the mock with proper typing
|
|
||||||
const { exec } = jest.requireMock("child_process");
|
|
||||||
const cwd = "/test/path";
|
|
||||||
beforeEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
describe("searchCommits", () => {
|
|
||||||
const mockCommitData = [
|
|
||||||
"abc123def456",
|
|
||||||
"abc123",
|
|
||||||
"fix: test commit",
|
|
||||||
"John Doe",
|
|
||||||
"2024-01-06",
|
|
||||||
"def456abc789",
|
|
||||||
"def456",
|
|
||||||
"feat: new feature",
|
|
||||||
"Jane Smith",
|
|
||||||
"2024-01-05",
|
|
||||||
].join("\n");
|
|
||||||
it("should return commits when git is installed and repo exists", async () => {
|
|
||||||
// Set up mock responses
|
|
||||||
const responses = new Map([
|
|
||||||
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
|
|
||||||
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
|
|
||||||
[
|
|
||||||
'git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --grep="test" --regexp-ignore-case',
|
|
||||||
{ stdout: mockCommitData, stderr: "" },
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
// Find matching response
|
|
||||||
for (const [cmd, response] of responses) {
|
|
||||||
if (command === cmd) {
|
|
||||||
callback(null, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(new Error(`Unexpected command: ${command}`));
|
|
||||||
});
|
|
||||||
const result = await searchCommits("test", cwd);
|
|
||||||
// First verify the result is correct
|
|
||||||
expect(result).toHaveLength(2);
|
|
||||||
expect(result[0]).toEqual({
|
|
||||||
hash: "abc123def456",
|
|
||||||
shortHash: "abc123",
|
|
||||||
subject: "fix: test commit",
|
|
||||||
author: "John Doe",
|
|
||||||
date: "2024-01-06",
|
|
||||||
});
|
|
||||||
// Then verify all commands were called correctly
|
|
||||||
expect(exec).toHaveBeenCalledWith("git --version", {}, expect.any(Function));
|
|
||||||
expect(exec).toHaveBeenCalledWith("git rev-parse --git-dir", { cwd }, expect.any(Function));
|
|
||||||
expect(exec).toHaveBeenCalledWith('git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --grep="test" --regexp-ignore-case', { cwd }, expect.any(Function));
|
|
||||||
});
|
|
||||||
it("should return empty array when git is not installed", async () => {
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
if (command === "git --version") {
|
|
||||||
callback(new Error("git not found"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
});
|
|
||||||
const result = await searchCommits("test", cwd);
|
|
||||||
expect(result).toEqual([]);
|
|
||||||
expect(exec).toHaveBeenCalledWith("git --version", {}, expect.any(Function));
|
|
||||||
});
|
|
||||||
it("should return empty array when not in a git repository", async () => {
|
|
||||||
const responses = new Map([
|
|
||||||
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
|
|
||||||
["git rev-parse --git-dir", null], // null indicates error should be called
|
|
||||||
]);
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
const response = responses.get(command);
|
|
||||||
if (response === null) {
|
|
||||||
callback(new Error("not a git repository"));
|
|
||||||
}
|
|
||||||
else if (response) {
|
|
||||||
callback(null, response);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const result = await searchCommits("test", cwd);
|
|
||||||
expect(result).toEqual([]);
|
|
||||||
expect(exec).toHaveBeenCalledWith("git --version", {}, expect.any(Function));
|
|
||||||
expect(exec).toHaveBeenCalledWith("git rev-parse --git-dir", { cwd }, expect.any(Function));
|
|
||||||
});
|
|
||||||
it("should handle hash search when grep search returns no results", async () => {
|
|
||||||
const responses = new Map([
|
|
||||||
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
|
|
||||||
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
|
|
||||||
[
|
|
||||||
'git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --grep="abc123" --regexp-ignore-case',
|
|
||||||
{ stdout: "", stderr: "" },
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short --author-date-order abc123',
|
|
||||||
{ stdout: mockCommitData, stderr: "" },
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
for (const [cmd, response] of responses) {
|
|
||||||
if (command === cmd) {
|
|
||||||
callback(null, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
});
|
|
||||||
const result = await searchCommits("abc123", cwd);
|
|
||||||
expect(result).toHaveLength(2);
|
|
||||||
expect(result[0]).toEqual({
|
|
||||||
hash: "abc123def456",
|
|
||||||
shortHash: "abc123",
|
|
||||||
subject: "fix: test commit",
|
|
||||||
author: "John Doe",
|
|
||||||
date: "2024-01-06",
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("getCommitInfo", () => {
|
|
||||||
const mockCommitInfo = [
|
|
||||||
"abc123def456",
|
|
||||||
"abc123",
|
|
||||||
"fix: test commit",
|
|
||||||
"John Doe",
|
|
||||||
"2024-01-06",
|
|
||||||
"Detailed description",
|
|
||||||
].join("\n");
|
|
||||||
const mockStats = "1 file changed, 2 insertions(+), 1 deletion(-)";
|
|
||||||
const mockDiff = "@@ -1,1 +1,2 @@\n-old line\n+new line";
|
|
||||||
it("should return formatted commit info", async () => {
|
|
||||||
const responses = new Map([
|
|
||||||
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
|
|
||||||
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
|
|
||||||
[
|
|
||||||
'git show --format="%H%n%h%n%s%n%an%n%ad%n%b" --no-patch abc123',
|
|
||||||
{ stdout: mockCommitInfo, stderr: "" },
|
|
||||||
],
|
|
||||||
['git show --stat --format="" abc123', { stdout: mockStats, stderr: "" }],
|
|
||||||
['git show --format="" abc123', { stdout: mockDiff, stderr: "" }],
|
|
||||||
]);
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
for (const [cmd, response] of responses) {
|
|
||||||
if (command.startsWith(cmd)) {
|
|
||||||
callback(null, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
});
|
|
||||||
const result = await getCommitInfo("abc123", cwd);
|
|
||||||
expect(result).toContain("Commit: abc123");
|
|
||||||
expect(result).toContain("Author: John Doe");
|
|
||||||
expect(result).toContain("Files Changed:");
|
|
||||||
expect(result).toContain("Full Changes:");
|
|
||||||
});
|
|
||||||
it("should return error message when git is not installed", async () => {
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
if (command === "git --version") {
|
|
||||||
callback(new Error("git not found"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
});
|
|
||||||
const result = await getCommitInfo("abc123", cwd);
|
|
||||||
expect(result).toBe("Git is not installed");
|
|
||||||
});
|
|
||||||
it("should return error message when not in a git repository", async () => {
|
|
||||||
const responses = new Map([
|
|
||||||
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
|
|
||||||
["git rev-parse --git-dir", null], // null indicates error should be called
|
|
||||||
]);
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
const response = responses.get(command);
|
|
||||||
if (response === null) {
|
|
||||||
callback(new Error("not a git repository"));
|
|
||||||
}
|
|
||||||
else if (response) {
|
|
||||||
callback(null, response);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const result = await getCommitInfo("abc123", cwd);
|
|
||||||
expect(result).toBe("Not a git repository");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe("getWorkingState", () => {
|
|
||||||
const mockStatus = " M src/file1.ts\n?? src/file2.ts";
|
|
||||||
const mockDiff = "@@ -1,1 +1,2 @@\n-old line\n+new line";
|
|
||||||
it("should return working directory changes", async () => {
|
|
||||||
const responses = new Map([
|
|
||||||
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
|
|
||||||
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
|
|
||||||
["git status --short", { stdout: mockStatus, stderr: "" }],
|
|
||||||
["git diff HEAD", { stdout: mockDiff, stderr: "" }],
|
|
||||||
]);
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
for (const [cmd, response] of responses) {
|
|
||||||
if (command === cmd) {
|
|
||||||
callback(null, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
});
|
|
||||||
const result = await getWorkingState(cwd);
|
|
||||||
expect(result).toContain("Working directory changes:");
|
|
||||||
expect(result).toContain("src/file1.ts");
|
|
||||||
expect(result).toContain("src/file2.ts");
|
|
||||||
});
|
|
||||||
it("should return message when working directory is clean", async () => {
|
|
||||||
const responses = new Map([
|
|
||||||
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
|
|
||||||
["git rev-parse --git-dir", { stdout: ".git", stderr: "" }],
|
|
||||||
["git status --short", { stdout: "", stderr: "" }],
|
|
||||||
]);
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
for (const [cmd, response] of responses) {
|
|
||||||
if (command === cmd) {
|
|
||||||
callback(null, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
});
|
|
||||||
const result = await getWorkingState(cwd);
|
|
||||||
expect(result).toBe("No changes in working directory");
|
|
||||||
});
|
|
||||||
it("should return error message when git is not installed", async () => {
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
if (command === "git --version") {
|
|
||||||
callback(new Error("git not found"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
});
|
|
||||||
const result = await getWorkingState(cwd);
|
|
||||||
expect(result).toBe("Git is not installed");
|
|
||||||
});
|
|
||||||
it("should return error message when not in a git repository", async () => {
|
|
||||||
const responses = new Map([
|
|
||||||
["git --version", { stdout: "git version 2.39.2", stderr: "" }],
|
|
||||||
["git rev-parse --git-dir", null], // null indicates error should be called
|
|
||||||
]);
|
|
||||||
exec.mockImplementation((command, options, callback) => {
|
|
||||||
const response = responses.get(command);
|
|
||||||
if (response === null) {
|
|
||||||
callback(new Error("not a git repository"));
|
|
||||||
}
|
|
||||||
else if (response) {
|
|
||||||
callback(null, response);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
callback(new Error("Unexpected command"));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const result = await getWorkingState(cwd);
|
|
||||||
expect(result).toBe("Not a git repository");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
//# sourceMappingURL=git.test.js.map
|
|
||||||
129
src/utils/git.js
129
src/utils/git.js
|
|
@ -1,129 +0,0 @@
|
||||||
import { exec } from "child_process";
|
|
||||||
import { promisify } from "util";
|
|
||||||
import { truncateOutput } from "../integrations/misc/extract-text";
|
|
||||||
const execAsync = promisify(exec);
|
|
||||||
const GIT_OUTPUT_LINE_LIMIT = 500;
|
|
||||||
async function checkGitRepo(cwd) {
|
|
||||||
try {
|
|
||||||
await execAsync("git rev-parse --git-dir", { cwd });
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async function checkGitInstalled() {
|
|
||||||
try {
|
|
||||||
await execAsync("git --version");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export async function searchCommits(query, cwd) {
|
|
||||||
try {
|
|
||||||
const isInstalled = await checkGitInstalled();
|
|
||||||
if (!isInstalled) {
|
|
||||||
console.error("Git is not installed");
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
const isRepo = await checkGitRepo(cwd);
|
|
||||||
if (!isRepo) {
|
|
||||||
console.error("Not a git repository");
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
// Search commits by hash or message, limiting to 10 results
|
|
||||||
const { stdout } = await execAsync(`git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short ` + `--grep="${query}" --regexp-ignore-case`, { cwd });
|
|
||||||
let output = stdout;
|
|
||||||
if (!output.trim() && /^[a-f0-9]+$/i.test(query)) {
|
|
||||||
// If no results from grep search and query looks like a hash, try searching by hash
|
|
||||||
const { stdout: hashStdout } = await execAsync(`git log -n 10 --format="%H%n%h%n%s%n%an%n%ad" --date=short ` + `--author-date-order ${query}`, { cwd }).catch(() => ({ stdout: "" }));
|
|
||||||
if (!hashStdout.trim()) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
output = hashStdout;
|
|
||||||
}
|
|
||||||
const commits = [];
|
|
||||||
const lines = output
|
|
||||||
.trim()
|
|
||||||
.split("\n")
|
|
||||||
.filter((line) => line !== "--");
|
|
||||||
for (let i = 0; i < lines.length; i += 5) {
|
|
||||||
commits.push({
|
|
||||||
hash: lines[i],
|
|
||||||
shortHash: lines[i + 1],
|
|
||||||
subject: lines[i + 2],
|
|
||||||
author: lines[i + 3],
|
|
||||||
date: lines[i + 4],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return commits;
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error("Error searching commits:", error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export async function getCommitInfo(hash, cwd) {
|
|
||||||
try {
|
|
||||||
const isInstalled = await checkGitInstalled();
|
|
||||||
if (!isInstalled) {
|
|
||||||
return "Git is not installed";
|
|
||||||
}
|
|
||||||
const isRepo = await checkGitRepo(cwd);
|
|
||||||
if (!isRepo) {
|
|
||||||
return "Not a git repository";
|
|
||||||
}
|
|
||||||
// Get commit info, stats, and diff separately
|
|
||||||
const { stdout: info } = await execAsync(`git show --format="%H%n%h%n%s%n%an%n%ad%n%b" --no-patch ${hash}`, {
|
|
||||||
cwd,
|
|
||||||
});
|
|
||||||
const [fullHash, shortHash, subject, author, date, body] = info.trim().split("\n");
|
|
||||||
const { stdout: stats } = await execAsync(`git show --stat --format="" ${hash}`, { cwd });
|
|
||||||
const { stdout: diff } = await execAsync(`git show --format="" ${hash}`, { cwd });
|
|
||||||
const summary = [
|
|
||||||
`Commit: ${shortHash} (${fullHash})`,
|
|
||||||
`Author: ${author}`,
|
|
||||||
`Date: ${date}`,
|
|
||||||
`\nMessage: ${subject}`,
|
|
||||||
body ? `\nDescription:\n${body}` : "",
|
|
||||||
"\nFiles Changed:",
|
|
||||||
stats.trim(),
|
|
||||||
"\nFull Changes:",
|
|
||||||
].join("\n");
|
|
||||||
const output = summary + "\n\n" + diff.trim();
|
|
||||||
return truncateOutput(output, GIT_OUTPUT_LINE_LIMIT);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error("Error getting commit info:", error);
|
|
||||||
return `Failed to get commit info: ${error instanceof Error ? error.message : String(error)}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export async function getWorkingState(cwd) {
|
|
||||||
try {
|
|
||||||
const isInstalled = await checkGitInstalled();
|
|
||||||
if (!isInstalled) {
|
|
||||||
return "Git is not installed";
|
|
||||||
}
|
|
||||||
const isRepo = await checkGitRepo(cwd);
|
|
||||||
if (!isRepo) {
|
|
||||||
return "Not a git repository";
|
|
||||||
}
|
|
||||||
// Get status of working directory
|
|
||||||
const { stdout: status } = await execAsync("git status --short", { cwd });
|
|
||||||
if (!status.trim()) {
|
|
||||||
return "No changes in working directory";
|
|
||||||
}
|
|
||||||
// Get all changes (both staged and unstaged) compared to HEAD
|
|
||||||
const { stdout: diff } = await execAsync("git diff HEAD", { cwd });
|
|
||||||
const lineLimit = GIT_OUTPUT_LINE_LIMIT;
|
|
||||||
const output = `Working directory changes:\n\n${status}\n\n${diff}`.trim();
|
|
||||||
return truncateOutput(output, lineLimit);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error("Error getting working state:", error);
|
|
||||||
return `Failed to get working state: ${error instanceof Error ? error.message : String(error)}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//# sourceMappingURL=git.js.map
|
|
||||||
Loading…
Add table
Reference in a new issue