Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 0 additions & 46 deletions apps/server/src/files/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,6 @@ router.get("/:taskId/file-changes", async (req, res) => {
try {
const { taskId } = req.params;

console.log(
`[FILE_CHANGES_DEBUG] Route entry - taskId: ${taskId}, timestamp: ${new Date().toISOString()}`
);

// Validate task exists and get full status
const task = await prisma.task.findUnique({
where: { id: taskId },
Expand All @@ -178,12 +174,7 @@ router.get("/:taskId/file-changes", async (req, res) => {
},
});

console.log(
`[FILE_CHANGES_DEBUG] Task lookup result - taskId: ${taskId}, found: ${!!task}, status: ${task?.status}, initStatus: ${task?.initStatus}, workspacePath: ${task?.workspacePath}`
);

if (!task) {
console.log(`[FILE_CHANGES_DEBUG] Task not found - taskId: ${taskId}`);
return res.status(404).json({
success: false,
error: "Task not found",
Expand All @@ -192,9 +183,6 @@ router.get("/:taskId/file-changes", async (req, res) => {

// Don't return file changes if task is still initializing
if (task.status === "INITIALIZING") {
console.log(
`[FILE_CHANGES_DEBUG] Task still initializing - taskId: ${taskId}, returning empty changes`
);
return res.json({
success: true,
fileChanges: [],
Expand All @@ -204,34 +192,21 @@ router.get("/:taskId/file-changes", async (req, res) => {

// If task workspace is INACTIVE (cleaned up), use GitHub API
if (task.initStatus === "INACTIVE") {
console.log(
`[FILE_CHANGES_DEBUG] Task workspace INACTIVE - taskId: ${taskId}, using GitHub API path`
);

if (!task.repoFullName || !task.shadowBranch) {
console.log(
`[FILE_CHANGES_DEBUG] Missing GitHub info - taskId: ${taskId}, repoFullName: ${task.repoFullName}, shadowBranch: ${task.shadowBranch}`
);
return res.json({
success: true,
fileChanges: [],
diffStats: { additions: 0, deletions: 0, totalFiles: 0 },
});
}

console.log(
`[FILE_CHANGES_DEBUG] Calling GitHub API - taskId: ${taskId}, repo: ${task.repoFullName}, base: ${task.baseBranch}, shadow: ${task.shadowBranch}`
);
const { fileChanges, diffStats } = await getGitHubFileChanges(
task.repoFullName,
task.baseBranch,
task.shadowBranch,
task.userId
);

console.log(
`[FILE_CHANGES_DEBUG] GitHub API response - taskId: ${taskId}, fileChanges: ${fileChanges.length}, additions: ${diffStats.additions}, deletions: ${diffStats.deletions}`
);
return res.json({
success: true,
fileChanges,
Expand All @@ -240,29 +215,13 @@ router.get("/:taskId/file-changes", async (req, res) => {
}

// For ACTIVE tasks, use GitService abstraction (handles both local and remote modes)
console.log(
`[FILE_CHANGES_DEBUG] Task ACTIVE - taskId: ${taskId}, using GitService abstraction`
);

try {
const gitService = await createGitService(taskId);
console.log(
`[FILE_CHANGES_DEBUG] GitService created - taskId: ${taskId}, calling getFileChanges with baseBranch: ${task.baseBranch}`
);

const { fileChanges, diffStats } = await gitService.getFileChanges(
task.baseBranch
);

console.log(
`[FILE_CHANGES_DEBUG] GitService response - taskId: ${taskId}, fileChanges: ${fileChanges.length}, additions: ${diffStats.additions}, deletions: ${diffStats.deletions}`
);

const duration = Date.now() - startTime;
console.log(
`[FILE_CHANGES_DEBUG] Final response - taskId: ${taskId}, fileChanges: ${fileChanges.length}, additions: ${diffStats.additions}, deletions: ${diffStats.deletions}, duration: ${duration}ms`
);

res.json({
Copy link

Copilot AI Aug 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The startTime variable is no longer defined in this function since the timing debug logs were removed, but it may still be referenced elsewhere. Ensure all references to startTime have been properly cleaned up.

Copilot uses AI. Check for mistakes.
success: true,
fileChanges,
Expand All @@ -276,11 +235,6 @@ router.get("/:taskId/file-changes", async (req, res) => {
);

// Fallback to empty response on error
const duration = Date.now() - startTime;
console.log(
`[FILE_CHANGES_DEBUG] Returning empty fallback response - taskId: ${taskId}, duration: ${duration}ms`
);

res.json({
success: true,
fileChanges: [],
Expand Down
151 changes: 5 additions & 146 deletions apps/server/src/utils/git-operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,45 +39,23 @@ async function getCommittedChanges(
now: string,
baseBranch: string
) {
const startTime = Date.now();
console.log(
`[FILE_CHANGES_DEBUG] getCommittedChanges start - baseBranch: ${baseBranch}, workspacePath: ${workspacePath}`
);

const diffCommand = `git diff --name-status ${baseBranch}...HEAD`;
console.log(`[FILE_CHANGES_DEBUG] Running git diff command: ${diffCommand}`);

const { stdout: committedStatusOutput } = await execAsync(diffCommand, {
cwd: workspacePath,
});

console.log(
`[FILE_CHANGES_DEBUG] Git diff status output length: ${committedStatusOutput.length}, hasContent: ${!!committedStatusOutput.trim()}`
);

if (committedStatusOutput.trim()) {
// Detailed diff stats for committed changes
const diffStatsCommand = `git diff --numstat ${baseBranch}...HEAD`;
console.log(
`[FILE_CHANGES_DEBUG] Running git numstat command: ${diffStatsCommand}`
);

const { stdout: committedStatsOutput } = await execAsync(diffStatsCommand, {
cwd: workspacePath,
});

console.log(
`[FILE_CHANGES_DEBUG] Git numstat output length: ${committedStatsOutput.length}`
);

// Parse committed changes
const statusLines = committedStatusOutput.trim().split("\n");
const statsLines = committedStatsOutput.trim().split("\n");

console.log(
`[FILE_CHANGES_DEBUG] Parsing committed changes - statusLines: ${statusLines.length}, statsLines: ${statsLines.length}`
);

// Create a map of filePath -> {additions, deletions}
const statsMap = new Map<
string,
Expand All @@ -94,12 +72,7 @@ async function getCommittedChanges(
}
}

console.log(
`[FILE_CHANGES_DEBUG] Stats map created - entries: ${statsMap.size}`
);

// Process committed changes
Copy link

Copilot AI Aug 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The variable processedFiles was removed but the loop that incremented it remains. Consider adding a comment explaining the purpose of this loop since the processing logic is now less obvious without the debug counters.

Suggested change
// Process committed changes
// Process committed changes
// Iterate over each line in statusLines to update the allFiles map with parsed file change information.
// This replaces the previous debug counter and ensures all relevant file changes are recorded.

Copilot uses AI. Check for mistakes.
let processedFiles = 0;
for (const line of statusLines) {
if (!line.trim()) continue;

Expand All @@ -119,18 +92,7 @@ async function getCommittedChanges(
deletions: stats.deletions,
createdAt: now,
});
processedFiles++;
}

const duration = Date.now() - startTime;
console.log(
`[FILE_CHANGES_DEBUG] getCommittedChanges completed - processedFiles: ${processedFiles}, duration: ${duration}ms`
);
} else {
const duration = Date.now() - startTime;
console.log(
`[FILE_CHANGES_DEBUG] getCommittedChanges - no committed changes found, duration: ${duration}ms`
);
}
}

Expand All @@ -139,24 +101,12 @@ async function getUncommittedChanges(
allFiles: Map<string, FileChange>,
now: string
) {
const startTime = Date.now();
console.log(
`[FILE_CHANGES_DEBUG] getUncommittedChanges start - workspacePath: ${workspacePath}`
);

const statusCommand = "git status --porcelain";
console.log(
`[FILE_CHANGES_DEBUG] Running git status command: ${statusCommand}`
);

const { stdout: uncommittedOutput } = await execAsync(statusCommand, {
cwd: workspacePath,
});

console.log(
`[FILE_CHANGES_DEBUG] Git status output length: ${uncommittedOutput.length}, hasContent: ${!!uncommittedOutput.trim()}`
);

if (uncommittedOutput.trim()) {
const uncommittedLines = uncommittedOutput.trim().split("\n");
const uncommittedFiles: Array<{
Expand Down Expand Up @@ -374,10 +324,6 @@ async function getUncommittedChanges(
);

// Phase 3: Create file change objects with accurate stats
console.log(
`[FILE_CHANGES_DEBUG] Creating file change objects - uncommittedFiles: ${uncommittedFiles.length}, diffResults: ${diffResults.length}`
);

for (const { filePath, operation } of uncommittedFiles) {
const stats = diffStatsMap.get(filePath) || {
additions: 0,
Expand All @@ -392,16 +338,6 @@ async function getUncommittedChanges(
createdAt: now,
});
}

const duration = Date.now() - startTime;
console.log(
`[FILE_CHANGES_DEBUG] getUncommittedChanges completed - processedFiles: ${uncommittedFiles.length}, duration: ${duration}ms`
);
} else {
const duration = Date.now() - startTime;
console.log(
`[FILE_CHANGES_DEBUG] getUncommittedChanges - no uncommitted changes found, duration: ${duration}ms`
);
}
}
}
Expand All @@ -414,87 +350,28 @@ export async function getFileChangesForWorkspace(
workspacePath: string,
baseBranch: string = "main"
): Promise<{ fileChanges: FileChange[]; diffStats: DiffStats }> {
const startTime = Date.now();

console.log(
`[FILE_CHANGES_DEBUG] getFileChangesForWorkspace entry - workspacePath: ${workspacePath}, baseBranch: ${baseBranch}`
);

if (!(await hasGitRepositoryAtPath(workspacePath))) {
console.log(
`[FILE_CHANGES_DEBUG] No git repository found at ${workspacePath}, returning empty changes`
);
return {
fileChanges: [],
diffStats: { additions: 0, deletions: 0, totalFiles: 0 },
};
}

console.log(
`[FILE_CHANGES_DEBUG] Git repository confirmed at ${workspacePath}, proceeding with git operations`
);

try {
console.log(
`[FILE_CHANGES_DEBUG] Refreshing git index - workspacePath: ${workspacePath}`
);
// Refresh git index to ensure consistency after potential checkout operations
await execAsync("git update-index --refresh", { cwd: workspacePath }).catch(
(error) => {
console.log(
`[FILE_CHANGES_DEBUG] Git index refresh failed (non-blocking) - workspacePath: ${workspacePath}, error: ${error}`
);
// Non-blocking - update-index may fail if no changes, which is fine
}
() => {}
);

const now = new Date().toISOString();
const allFiles = new Map<string, FileChange>();

console.log(
`[FILE_CHANGES_DEBUG] Starting parallel git operations - workspacePath: ${workspacePath}, timestamp: ${now}`
);

const commitTime = Date.now();
const uncommitTime = Date.now();

await Promise.all([
getCommittedChanges(workspacePath, allFiles, now, baseBranch).then(() => {
const duration = Date.now() - commitTime;
console.log(
`[FILE_CHANGES_DEBUG] getCommittedChanges completed - workspacePath: ${workspacePath}, duration: ${duration}ms, files: ${Array.from(allFiles.keys()).filter((f) => Array.from(allFiles.values()).find((v) => v.filePath === f)?.createdAt === now).length}`
);
}),
getUncommittedChanges(workspacePath, allFiles, now).then(() => {
const duration = Date.now() - uncommitTime;
const uncommittedFiles = Array.from(allFiles.values()).filter(
(f) => f.createdAt === now
);
console.log(
`[FILE_CHANGES_DEBUG] getUncommittedChanges completed - workspacePath: ${workspacePath}, duration: ${duration}ms, uncommitted files: ${uncommittedFiles.length}`
);
}),
getCommittedChanges(workspacePath, allFiles, now, baseBranch),
getUncommittedChanges(workspacePath, allFiles, now),
]);

const fileChanges = Array.from(allFiles.values());
console.log(
`[FILE_CHANGES_DEBUG] All files aggregated - workspacePath: ${workspacePath}, total files: ${fileChanges.length}`
);

// Log detailed file information
fileChanges.forEach((file, index) => {
if (index < 10) {
// Log first 10 files to avoid spam
console.log(
`[FILE_CHANGES_DEBUG] File ${index + 1} - workspacePath: ${workspacePath}, path: ${file.filePath}, operation: ${file.operation}, +${file.additions}/-${file.deletions}`
);
}
});
if (fileChanges.length > 10) {
console.log(
`[FILE_CHANGES_DEBUG] ... and ${fileChanges.length - 10} more files - workspacePath: ${workspacePath}`
);
}

const diffStats = fileChanges.reduce(
(acc, file) => ({
Expand All @@ -505,19 +382,12 @@ export async function getFileChangesForWorkspace(
{ additions: 0, deletions: 0, totalFiles: 0 }
);

const totalDuration = Date.now() - startTime;
console.log(
`[FILE_CHANGES_DEBUG] getFileChangesForWorkspace completed - workspacePath: ${workspacePath}, totalFiles: ${diffStats.totalFiles}, additions: ${diffStats.additions}, deletions: ${diffStats.deletions}, totalDuration: ${totalDuration}ms`
);

return { fileChanges, diffStats };
} catch (error) {
const duration = Date.now() - startTime;
console.error(
`[FILE_CHANGES_DEBUG] Error getting file changes for workspace ${workspacePath} (duration: ${duration}ms):`,
`Error getting file changes for workspace ${workspacePath}:`,
error
);
// Return empty array instead of throwing to avoid breaking the UI
return {
fileChanges: [],
diffStats: { additions: 0, deletions: 0, totalFiles: 0 },
Expand Down Expand Up @@ -564,10 +434,6 @@ function mapGitStatusToOperation(status: string): FileChange["operation"] {
export async function hasGitRepositoryAtPath(
workspacePath: string
): Promise<boolean> {
console.log(
`[FILE_CHANGES_DEBUG] hasGitRepositoryAtPath check - workspacePath: ${workspacePath}`
);

try {
const { stdout } = await execAsync("git rev-parse --git-dir", {
cwd: workspacePath,
Expand All @@ -576,15 +442,8 @@ export async function hasGitRepositoryAtPath(
const gitDir = stdout.trim();
const hasGit = gitDir === `.git`;

console.log(
`[FILE_CHANGES_DEBUG] Git directory check - workspacePath: ${workspacePath}, gitDir: "${gitDir}", hasGit: ${hasGit}`
);

return hasGit;
} catch (error) {
console.log(
`[FILE_CHANGES_DEBUG] Git repository check failed - workspacePath: ${workspacePath}, error: ${error}`
);
} catch (_error) {
return false;
}
}
Loading
Loading