mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
This reverts commit 7eee3e0878.
Middle-out truncation is a really great feature and it should still be
implemented, however it unnecessarily interferes with #1365 because it
hooked into the low-level chunk management that comes directly from VSCE
shell integration.
The best place to hook OutputBuilder is as follows depending on the
state of terminal interaction:
1. Foreground terminals:
Cline.ts:
executeCommandTool(...) {
process.on("line", (line) => {
lines.push(line)
...
}
}
2. For background terminals: hook in at the point that getUnretrievedOutput is consumed for active or
inactive terminals in Cline.ts:getEnvironmentDetails()
Please note:
The Terminal classes are very sensitive to change, partially because of
the complicated way that shell integration works with VSCE, and
partially because of the way that Cline interacts with the Terminal*
class abstractions that make VSCE shell integration easier to work with.
At the point that PR#1365 is merged, it is unlikely that any Terminal*
classes will need to be modified substantially. Generally speaking, we
should think of this is a stable interface and minimize changes.
Reverts: #1390
160 lines
4.2 KiB
TypeScript
160 lines
4.2 KiB
TypeScript
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
|
|
|
|
export interface GitCommit {
|
|
hash: string
|
|
shortHash: string
|
|
subject: string
|
|
author: string
|
|
date: string
|
|
}
|
|
|
|
async function checkGitRepo(cwd: string): Promise<boolean> {
|
|
try {
|
|
await execAsync("git rev-parse --git-dir", { cwd })
|
|
return true
|
|
} catch (error) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
async function checkGitInstalled(): Promise<boolean> {
|
|
try {
|
|
await execAsync("git --version")
|
|
return true
|
|
} catch (error) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export async function searchCommits(query: string, cwd: string): Promise<GitCommit[]> {
|
|
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: GitCommit[] = []
|
|
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: string, cwd: string): Promise<string> {
|
|
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: string): Promise<string> {
|
|
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)}`
|
|
}
|
|
}
|