git-bolt
Version:
Git utilities for faster development
137 lines (124 loc) • 4.59 kB
JavaScript
import chalk from 'chalk';
import fs from 'fs';
import git from 'isomorphic-git';
import path from 'path';
async function addCommand(filepath) {
try {
// Get the status matrix first for all files
const status = await git.statusMatrix({ fs, dir: '.' });
if (filepath === '.') {
// Handle adding all changes
await Promise.all(
status.map(async ([filepath, headStatus, workdirStatus, stageStatus]) => {
try {
if (headStatus === 1 && workdirStatus === 0) {
// File exists in HEAD but not in working directory (deleted)
// Use git.remove() for deleted files
await git.remove({ fs, dir: '.', filepath });
console.log(chalk.green(`Staged deletion: ${filepath}`));
} else if (workdirStatus === 2) {
// File exists in working directory
await git.add({ fs, dir: '.', filepath });
console.log(chalk.green(`Added: ${filepath}`));
}
} catch (err) {
console.warn(chalk.yellow(`Warning: Could not add ${filepath}: ${err.message}`));
}
})
);
console.log(chalk.green('All changes staged'));
return;
}
// For specific path
const matchingFiles = status.filter(([f]) => {
// For directories, match files that start with the directory path
if (filepath.endsWith('/') || filepath === '.') {
return f.startsWith(filepath);
}
// For files, exact match
return f === filepath;
});
if (matchingFiles.length > 0) {
// Add all matching files
await Promise.all(
matchingFiles.map(async ([f, headStatus, workdirStatus, stageStatus]) => {
try {
if (headStatus === 1 && workdirStatus === 0) {
// File exists in HEAD but not in working directory (deleted)
// Use git.remove() for deleted files
await git.remove({ fs, dir: '.', filepath: f });
console.log(chalk.green(`Staged deletion: ${f}`));
} else if (workdirStatus === 2) {
// File exists in working directory
await git.add({ fs, dir: '.', filepath: f });
console.log(chalk.green(`Added: ${f}`));
}
} catch (err) {
console.warn(chalk.yellow(`Warning: Could not add ${f}: ${err.message}`));
}
})
);
return;
}
// If no matching files in git status, check filesystem for new files
if (!fs.existsSync(filepath)) {
console.error(chalk.red(`Error: '${filepath}' does not exist and is not tracked by git`));
process.exit(1);
}
// Handle new files/directories
const stats = fs.statSync(filepath);
if (stats.isDirectory()) {
const getAllFiles = (dir) => {
let files = [];
try {
const items = fs.readdirSync(dir);
for (const item of items) {
const itemPath = path.join(dir, item);
try {
const itemStats = fs.statSync(itemPath);
if (itemStats.isDirectory()) {
files = [...files, ...getAllFiles(itemPath)];
} else {
files.push(itemPath);
}
} catch (err) {
console.warn(chalk.yellow(`Warning: Could not access ${itemPath}, skipping`));
}
}
} catch (err) {
console.warn(chalk.yellow(`Warning: Could not read directory ${dir}, skipping`));
}
return files;
};
const files = getAllFiles(filepath);
if (files.length === 0) {
console.log(chalk.yellow(`Warning: No files found in directory ${filepath}`));
return;
}
// Add all new files
await Promise.all(
files.map(async (file) => {
try {
await git.add({ fs, dir: '.', filepath: file });
console.log(chalk.green(`Added: ${file}`));
} catch (err) {
console.warn(chalk.yellow(`Warning: Could not add ${file}: ${err.message}`));
}
})
);
} else {
// Add new single file
try {
await git.add({ fs, dir: '.', filepath });
console.log(chalk.green(`Added: ${filepath}`));
} catch (err) {
console.error(chalk.red(`Error adding ${filepath}: ${err.message}`));
process.exit(1);
}
}
} catch (error) {
console.error(chalk.red('Error during add:'), error.message);
process.exit(1);
}
}
export { addCommand };