Initial upload with CI/CD workflow
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-02-05 19:31:43 +00:00
parent 5a00548f6f
commit a12aa49a05

157
src/commands/sync.ts Normal file
View File

@@ -0,0 +1,157 @@
import * as path from 'path';
import * as fs from 'fs-extra';
import { shellUtils } from '../utils/shellUtils';
import { fileUtils } from '../utils/fileUtils';
interface SyncOptions {
remote?: string;
branch?: string;
message?: string;
push?: boolean;
pull?: boolean;
init?: boolean;
}
export async function syncLayouts(options: SyncOptions): Promise<void> {
const layoutsDir = fileUtils.getLayoutsDir();
if (options.init) {
await initializeGitRepo(layoutsDir, options.remote, options.branch);
return;
}
const isGitRepo = await isGitRepository(layoutsDir);
if (!isGitRepo) {
console.log('Not a git repository. Use --init to initialize one.');
return;
}
if (options.pull) {
await pullLayouts(options.message);
}
if (options.push) {
await pushLayouts(options.message);
}
}
async function initializeGitRepo(
dirPath: string,
remoteUrl?: string,
branch?: string
): Promise<void> {
console.log(`Initializing git repository in ${dirPath}...`);
const gitResult = await shellUtils.exec('git init', { cwd: dirPath });
if (!gitResult.success) {
throw new Error(`Failed to initialize git repository: ${gitResult.stderr}`);
}
const gitignorePath = path.join(dirPath, '.gitignore');
const gitignoreContent = [
'*.lock',
'*.log',
'node_modules/',
'.DS_Store',
'*.tmp',
'config.json',
];
if (!fs.existsSync(gitignorePath)) {
fs.writeFileSync(gitignorePath, gitignoreContent.join('\n'), 'utf-8');
}
const readmePath = path.join(dirPath, 'README.md');
if (!fs.existsSync(readmePath)) {
const readmeContent = `# Terminal Layouts
This repository contains terminal workspace layouts synced by terminal-layout-sync.
## Usage
Clone this repository and import layouts using:
\`\`\`
terminal-layout-sync import <layout-file>
\`\`\`
`;
fs.writeFileSync(readmePath, readmeContent, 'utf-8');
}
if (remoteUrl) {
const remoteResult = await shellUtils.exec(`git remote add origin ${remoteUrl}`, { cwd: dirPath });
if (!remoteResult.success) {
throw new Error(`Failed to add remote: ${remoteResult.stderr}`);
}
console.log(`Remote added: ${remoteUrl}`);
}
const defaultBranch = branch || 'main';
await shellUtils.exec(`git branch -M ${defaultBranch}`, { cwd: dirPath });
console.log('Git repository initialized successfully.');
}
async function isGitRepository(dirPath: string): Promise<boolean> {
const result = await shellUtils.exec('git rev-parse --git-dir', { cwd: dirPath });
return result.success;
}
async function commitLayouts(message?: string): Promise<boolean> {
const layoutsDir = fileUtils.getLayoutsDir();
const commitMessage = message || `Update layouts - ${new Date().toISOString()}`;
const statusResult = await shellUtils.exec('git status --porcelain', { cwd: layoutsDir });
if (!statusResult.stdout.trim()) {
console.log('No changes to commit.');
return false;
}
const addResult = await shellUtils.exec('git add .', { cwd: layoutsDir });
if (!addResult.success) {
throw new Error(`Failed to stage files: ${addResult.stderr}`);
}
const commitResult = await shellUtils.exec(`git commit -m "${commitMessage}"`, { cwd: layoutsDir });
if (!commitResult.success) {
throw new Error(`Failed to commit: ${commitResult.stderr}`);
}
console.log(`Committed changes: ${commitMessage}`);
return true;
}
async function pushLayouts(message?: string): Promise<void> {
const layoutsDir = fileUtils.getLayoutsDir();
const hasChanges = await commitLayouts(message);
if (!hasChanges) {
console.log('Nothing to push.');
return;
}
const pushResult = await shellUtils.exec('git push origin main', { cwd: layoutsDir });
if (!pushResult.success) {
throw new Error(`Failed to push: ${pushResult.stderr}`);
}
console.log('Layouts pushed successfully.');
}
async function pullLayouts(_message?: string): Promise<void> {
const layoutsDir = fileUtils.getLayoutsDir();
const pullResult = await shellUtils.exec('git pull origin main', { cwd: layoutsDir });
if (!pullResult.success) {
console.log(`Failed to pull: ${pullResult.stderr}`);
console.log('You may need to resolve conflicts manually.');
return;
}
console.log('Layouts pulled successfully.');
console.log(pullResult.stdout);
}
export async function getRemoteUrl(dirPath: string): Promise<string | null> {
const result = await shellUtils.exec('git remote get-url origin', { cwd: dirPath });
return result.success ? result.stdout.trim() : null;
}