- Enhanced the configureThrottling function to prevent changes to maxConcurrency while operations are in flight. - Added comprehensive unit tests for secure-fs throttling and retry logic, ensuring correct behavior and configuration. - Removed outdated secure-fs test file and replaced it with a new, updated version to improve test coverage.
@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