This update introduces a new function, createNewFileDiff, to streamline the generation of synthetic diffs for untracked files. The function reduces code duplication by handling the diff formatting for new files, including directories and large files, improving overall maintainability.
@automaker/git-utils
Git operations and utilities for AutoMaker.
Overview
This package provides git-related utilities including repository detection, status parsing, and diff generation for both tracked and untracked files.
Installation
npm install @automaker/git-utils
Exports
Repository Detection
Check if a path is a git repository.
import { isGitRepo } from '@automaker/git-utils';
const isRepo = await isGitRepo('/project/path');
if (isRepo) {
console.log('This is a git repository');
}
Status Parsing
Parse git status output into structured data.
import { parseGitStatus } from '@automaker/git-utils';
import type { FileStatus } from '@automaker/git-utils';
const statusOutput = await execAsync('git status --porcelain');
const files: FileStatus[] = parseGitStatus(statusOutput.stdout);
files.forEach((file) => {
console.log(`${file.statusText}: ${file.path}`);
// Example: "Modified: src/index.ts"
// Example: "Untracked: new-file.ts"
});
Diff Generation
Generate diffs including untracked files.
import {
generateSyntheticDiffForNewFile,
appendUntrackedFileDiffs,
getGitRepositoryDiffs,
} from '@automaker/git-utils';
// Generate diff for single untracked file
const diff = await generateSyntheticDiffForNewFile('/project/path', 'src/new-file.ts');
// Get complete repository diffs (tracked + untracked)
const result = await getGitRepositoryDiffs('/project/path');
console.log(result.diff); // Combined diff string
console.log(result.files); // Array of FileStatus
console.log(result.hasChanges); // Boolean
Non-Git Directory Support
Handle non-git directories by treating all files as new.
import { listAllFilesInDirectory, generateDiffsForNonGitDirectory } from '@automaker/git-utils';
// List all files (excluding build artifacts)
const files = await listAllFilesInDirectory('/project/path');
// Generate diffs for non-git directory
const result = await generateDiffsForNonGitDirectory('/project/path');
console.log(result.diff); // Synthetic diffs for all files
console.log(result.files); // All files as "New" status
Types
FileStatus
interface FileStatus {
status: string; // Git status code (M/A/D/R/C/U/?/!)
path: string; // File path relative to repo root
statusText: string; // Human-readable status
}
Status Codes
M- ModifiedA- AddedD- DeletedR- RenamedC- CopiedU- Updated?- Untracked!- Ignored- Unmodified
Status Text Examples
"Modified"- File has changes"Added"- New file in staging"Deleted"- File removed"Renamed"- File renamed"Untracked"- New file not in git"Modified (staged), Modified (unstaged)"- Changes in both areas
Usage Example
import { isGitRepo, getGitRepositoryDiffs, parseGitStatus } from '@automaker/git-utils';
async function getProjectChanges(projectPath: string) {
const isRepo = await isGitRepo(projectPath);
if (!isRepo) {
console.log('Not a git repository, analyzing all files...');
}
const result = await getGitRepositoryDiffs(projectPath);
if (!result.hasChanges) {
console.log('No changes detected');
return;
}
console.log(`Found ${result.files.length} changed files:\n`);
// Group by status
const byStatus = result.files.reduce(
(acc, file) => {
acc[file.statusText] = acc[file.statusText] || [];
acc[file.statusText].push(file.path);
return acc;
},
{} as Record<string, string[]>
);
Object.entries(byStatus).forEach(([status, paths]) => {
console.log(`${status}:`);
paths.forEach((path) => console.log(` - ${path}`));
});
return result.diff;
}
Features
Binary File Detection
Automatically detects binary files by extension and generates appropriate diff markers.
Supported binary extensions:
- Images:
.png,.jpg,.jpeg,.gif,.svg, etc. - Documents:
.pdf,.doc,.docx, etc. - Archives:
.zip,.tar,.gz, etc. - Media:
.mp3,.mp4,.wav, etc. - Fonts:
.ttf,.otf,.woff, etc.
Large File Handling
Files larger than 1MB show size information instead of full content.
Synthetic Diff Format
Generates unified diff format for untracked files:
diff --git a/new-file.ts b/new-file.ts
new file mode 100644
index 0000000..0000000
--- /dev/null
+++ b/new-file.ts
@@ -0,0 +1,10 @@
+export function hello() {
+ console.log('Hello');
+}
Directory Filtering
When scanning non-git directories, automatically excludes:
node_modules,.git,.automaker- Build outputs:
dist,build,out,tmp,.tmp - Framework caches:
.next,.nuxt,.cache,coverage - Language-specific:
__pycache__(Python),target(Rust),vendor(Go/PHP),.gradle(Gradle),.venv/venv(Python)
Error Handling
Git operations can fail for various reasons. This package provides graceful error handling patterns:
Common Error Scenarios
1. Repository Not Found
const isRepo = await isGitRepo('/path/does/not/exist');
// Returns: false (no exception thrown)
2. Not a Git Repository
const result = await getGitRepositoryDiffs('/not/a/git/repo');
// Fallback behavior: treats all files as "new"
// Returns synthetic diffs for all files in directory
3. Git Command Failures
// Permission errors, corrupted repos, or git not installed
try {
const result = await getGitRepositoryDiffs('/project');
} catch (error) {
// Handle errors from git commands
// Errors are logged via @automaker/utils logger
console.error('Git operation failed:', error);
}
4. File Read Errors
// When generating synthetic diffs for inaccessible files
const diff = await generateSyntheticDiffForNewFile('/path', 'locked-file.txt');
// Returns placeholder: "[Unable to read file content]"
// Error is logged but doesn't throw
Best Practices
-
Check repository status first:
const isRepo = await isGitRepo(path); if (!isRepo) { // Handle non-git case appropriately } -
Expect non-git directories:
getGitRepositoryDiffs()automatically handles both cases- Always returns a valid result structure
-
Monitor logs:
- Errors are logged with the
[GitUtils]prefix - Check logs for permission issues or git configuration problems
- Errors are logged with the
-
Handle edge cases:
- Empty repositories (no commits yet)
- Detached HEAD states
- Corrupted git repositories
- Missing git binary
Dependencies
@automaker/types- FileStatus type definition@automaker/utils- Logger utilities
Used By
@automaker/server- Git routes, worktree operations, feature context