ai-cmg 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +44 -16
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { execSync, spawnSync } from 'child_process';
3
- import { readFileSync } from 'fs';
4
- import { dirname, join } from 'path';
3
+ import { readFileSync, existsSync } from 'fs';
4
+ import { dirname, join, resolve } from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
  import prompts from 'prompts';
7
7
  import clipboardy from 'clipboardy';
@@ -103,13 +103,39 @@ function getGitEnv() {
103
103
  delete env.GIT_CEILING_DIRECTORIES;
104
104
  return env;
105
105
  }
106
- function resolveRepoRoot() {
106
+ function isGitAvailable() {
107
107
  try {
108
- const root = execSync('git rev-parse --show-toplevel', { env: getGitEnv() }).toString().trim();
108
+ execSync('git --version', { env: getGitEnv(), stdio: 'ignore' });
109
+ return true;
110
+ }
111
+ catch {
112
+ return false;
113
+ }
114
+ }
115
+ function findRepoRootByFs(startDir) {
116
+ let current = resolve(startDir);
117
+ while (true) {
118
+ const gitPath = join(current, '.git');
119
+ if (existsSync(gitPath))
120
+ return current;
121
+ const parent = dirname(current);
122
+ if (parent === current)
123
+ return null;
124
+ current = parent;
125
+ }
126
+ }
127
+ function resolveRepoRoot(baseDir) {
128
+ try {
129
+ const root = execSync('git rev-parse --show-toplevel', {
130
+ env: getGitEnv(),
131
+ cwd: baseDir
132
+ }).toString().trim();
109
133
  return root || null;
110
134
  }
111
135
  catch {
112
- return null;
136
+ if (!baseDir)
137
+ return null;
138
+ return findRepoRootByFs(baseDir);
113
139
  }
114
140
  }
115
141
  function parseMessageArgs(rawArgs) {
@@ -148,8 +174,7 @@ function parseMessageArgs(rawArgs) {
148
174
  function getNameStatus(repoRoot) {
149
175
  const map = new Map();
150
176
  try {
151
- const output = execSync('git diff --cached --name-status', {
152
- cwd: repoRoot,
177
+ const output = execSync(`git -C "${repoRoot}" diff --cached --name-status`, {
153
178
  env: getGitEnv()
154
179
  }).toString();
155
180
  output.split('\n').forEach((line) => {
@@ -168,8 +193,7 @@ function getNameStatus(repoRoot) {
168
193
  }
169
194
  function getChangedFiles(repoRoot) {
170
195
  try {
171
- const output = execSync('git status --porcelain -z', {
172
- cwd: repoRoot,
196
+ const output = execSync(`git -C "${repoRoot}" status --porcelain -z`, {
173
197
  env: getGitEnv()
174
198
  }).toString();
175
199
  if (!output)
@@ -229,7 +253,7 @@ async function promptStageFiles(repoRoot) {
229
253
  if (action === 'cancel')
230
254
  return false;
231
255
  if (action === 'all') {
232
- spawnSync('git', ['add', '.'], { stdio: 'inherit', cwd: repoRoot, env: getGitEnv() });
256
+ spawnSync('git', ['-C', repoRoot, 'add', '.'], { stdio: 'inherit', env: getGitEnv() });
233
257
  return true;
234
258
  }
235
259
  const fileChoices = candidates.map((entry) => ({
@@ -246,7 +270,7 @@ async function promptStageFiles(repoRoot) {
246
270
  const files = picked.files;
247
271
  if (!files || files.length === 0)
248
272
  return false;
249
- spawnSync('git', ['add', '--', ...files], { stdio: 'inherit', cwd: repoRoot, env: getGitEnv() });
273
+ spawnSync('git', ['-C', repoRoot, 'add', '--', ...files], { stdio: 'inherit', env: getGitEnv() });
250
274
  return true;
251
275
  }
252
276
  function getExtension(filePath) {
@@ -361,7 +385,11 @@ async function main() {
361
385
  return;
362
386
  console.log('Analyzing staged changes...');
363
387
  try {
364
- const repoRoot = resolveRepoRoot();
388
+ if (!isGitAvailable()) {
389
+ console.log('Error: git is not available in PATH.');
390
+ return;
391
+ }
392
+ const repoRoot = resolveRepoRoot(process.cwd());
365
393
  if (!repoRoot) {
366
394
  console.log('Error: not a git repository.');
367
395
  return;
@@ -369,7 +397,7 @@ async function main() {
369
397
  // 3. Git Diff 가져오기
370
398
  let diff;
371
399
  try {
372
- diff = execSync('git diff --cached', { cwd: repoRoot, env: getGitEnv() }).toString();
400
+ diff = execSync(`git -C "${repoRoot}" diff --cached`, { env: getGitEnv() }).toString();
373
401
  }
374
402
  catch (e) {
375
403
  console.log('Error: not a git repository or git is unavailable.');
@@ -379,7 +407,7 @@ async function main() {
379
407
  const staged = await promptStageFiles(repoRoot);
380
408
  if (!staged)
381
409
  return;
382
- diff = execSync('git diff --cached', { cwd: repoRoot, env: getGitEnv() }).toString();
410
+ diff = execSync(`git -C "${repoRoot}" diff --cached`, { env: getGitEnv() }).toString();
383
411
  if (!diff.trim()) {
384
412
  console.log('No staged changes. Nothing to commit.');
385
413
  return;
@@ -438,11 +466,11 @@ async function main() {
438
466
  const action = actions[choice - 1].value;
439
467
  switch (action) {
440
468
  case 'commit':
441
- spawnSync('git', ['commit', '-m', message], { stdio: 'inherit', cwd: repoRoot, env: getGitEnv() });
469
+ spawnSync('git', ['-C', repoRoot, 'commit', '-m', message], { stdio: 'inherit', env: getGitEnv() });
442
470
  console.log('Commit complete.');
443
471
  break;
444
472
  case 'edit':
445
- spawnSync('git', ['commit', '-e', '-m', message], { stdio: 'inherit', cwd: repoRoot, env: getGitEnv() });
473
+ spawnSync('git', ['-C', repoRoot, 'commit', '-e', '-m', message], { stdio: 'inherit', env: getGitEnv() });
446
474
  console.log('Commit complete.');
447
475
  break;
448
476
  case 'copy':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-cmg",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "AI Commit Message Generator",
5
5
  "type": "module",
6
6
  "bin": {