Files
git-agent-sync/src/utils/file-utils.ts
7000pctAUTO 1e706b7d93
Some checks failed
/ test (push) Has been cancelled
feat: add file utilities module
2026-02-03 09:03:12 +00:00

104 lines
4.6 KiB
TypeScript

import * as fs from 'fs-extra';
import * as path from 'path';
import * as os from 'os';
import { GlobalConfig, WorkspaceConfig, WorkspaceInfo } from '../types/index';
import { GitAgentSyncError } from './errors';
const GLOBAL_CONFIG_DIR = '.git-agent-sync';
const GLOBAL_CONFIG_FILE = 'config.json';
const WORKSPACE_CONFIG_FILE = '.agent-workspace.json';
export function getGlobalConfigDir(): string {
return process.env.GIT_AGENT_SYNC_CONFIG ? path.dirname(process.env.GIT_AGENT_SYNC_CONFIG) : path.join(os.homedir(), GLOBAL_CONFIG_DIR);
}
export function getGlobalConfigPath(): string {
return process.env.GIT_AGENT_SYNC_CONFIG || path.join(getGlobalConfigDir(), GLOBAL_CONFIG_FILE);
}
export async function loadGlobalConfig(): Promise<GlobalConfig> {
const configPath = getGlobalConfigPath();
if (await fs.pathExists(configPath)) {
const config = await fs.readJson(configPath);
return { ...getDefaultGlobalConfig(), ...config };
}
return getDefaultGlobalConfig();
}
export function getDefaultGlobalConfig(): GlobalConfig {
return { workspacePath: process.env.GIT_AGENT_SYNC_PATH || './.agent-workspaces', defaultBranch: 'main', autoInstall: process.env.GIT_AGENT_SYNC_AUTO_INSTALL !== 'false', templates: { default: process.env.GIT_AGENT_SYNC_TEMPLATE || path.join(os.homedir(), GLOBAL_CONFIG_DIR, 'templates', 'default') } };
}
export async function saveGlobalConfig(config: GlobalConfig): Promise<void> {
await fs.ensureDir(getGlobalConfigDir());
await fs.writeJson(getGlobalConfigPath(), config, { spaces: 2 });
}
export function getWorkspacePath(basePath: string, agentName: string): string {
return path.join(basePath, '.agent-workspaces', `agent-${agentName}`);
}
export async function loadWorkspaceConfig(workspacePath: string): Promise<WorkspaceConfig | null> {
const configPath = path.join(workspacePath, WORKSPACE_CONFIG_FILE);
if (await fs.pathExists(configPath)) {
return fs.readJson(configPath);
}
return null;
}
export async function saveWorkspaceConfig(workspacePath: string, config: WorkspaceConfig): Promise<void> {
const configPath = path.join(workspacePath, WORKSPACE_CONFIG_FILE);
await fs.writeJson(configPath, config, { spaces: 2 });
}
export async function getAllWorkspaces(basePath: string): Promise<WorkspaceInfo[]> {
const workspaceRoot = path.join(basePath, '.agent-workspaces');
if (!await fs.pathExists(workspaceRoot)) return [];
const entries = await fs.readdir(workspaceRoot);
const workspaces: WorkspaceInfo[] = [];
for (const entry of entries) {
if (entry.startsWith('agent-')) {
const workspacePath = path.join(workspaceRoot, entry);
const stat = await fs.stat(workspacePath);
if (stat.isDirectory()) {
workspaces.push({ name: entry, path: workspacePath, branch: entry, exists: true, hasChanges: false, changeCount: 0 });
}
}
}
return workspaces;
}
export function sanitizeAgentName(name: string): string {
return name.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
}
export function isValidAgentName(name: string): boolean {
return /^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/.test(name) && name.length >= 1 && name.length <= 100;
}
export async function isGitRepository(basePath: string): Promise<boolean> {
try {
await fs.access(path.join(basePath, '.git'), fs.constants.R_OK);
return true;
} catch { return false; }
}
export async function hasUncommittedChanges(workspacePath: string): Promise<boolean> {
const { execa } = await import('execa');
try {
const result = await execa('git', ['status', '--porcelain'], { cwd: workspacePath });
return result.stdout.trim().length > 0;
} catch { return false; }
}
export async function detectPackageJson(workspacePath: string): Promise<boolean> {
return fs.pathExists(path.join(workspacePath, 'package.json'));
}
export async function installDependencies(workspacePath: string): Promise<void> {
const { execa } = await import('execa');
await execa('npm', ['install'], { cwd: workspacePath });
}
export async function readPackageJson(workspacePath: string): Promise<{ scripts?: Record<string, string> } | null> {
const pkgPath = path.join(workspacePath, 'package.json');
if (await fs.pathExists(pkgPath)) {
return fs.readJson(pkgPath);
}
return null;
}
export async function getGitUserInfo(): Promise<{ name: string; email: string }> {
const { execa } = await import('execa');
try {
const nameResult = await execa('git', ['config', 'user.name']);
const emailResult = await execa('git', ['config', 'user.email']);
return { name: nameResult.stdout.trim(), email: emailResult.stdout.trim() };
} catch {
return { name: 'Unknown', email: 'unknown@example.com' };
}
}