Skip to content

Commit b5407d3

Browse files
author
ityaozm@gmail.com
committedNov 19, 2024
refactor(CommitCommand): Simplify message generation process
- Streamline commit message generation by utilizing collections. - Ensure git installation check and cached diff retrieval are performed before generating messages. - Improve code readability and maintainability by removing redundant steps.
1 parent 75a2f49 commit b5407d3

File tree

3 files changed

+92
-90
lines changed

3 files changed

+92
-90
lines changed
 

‎app/Commands/CommitCommand.php

+82-80
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
namespace App\Commands;
1414

1515
use App\ConfigManager;
16-
use App\Exceptions\TaskException;
16+
use App\Exceptions\RuntimeException;
1717
use App\GeneratorManager;
1818
use App\Support\JsonFixer;
1919
use Illuminate\Console\Scheduling\Schedule;
@@ -59,92 +59,94 @@ public function __construct(GeneratorManager $generatorManager)
5959

6060
/**
6161
* @psalm-suppress InvalidArgument
62+
*
63+
* @throws \Exception
6264
*/
6365
public function handle(): void
6466
{
65-
// Ensure git is installed and the current directory is a git repository.
66-
$this->createProcess(['git', 'rev-parse', '--is-inside-work-tree'])->mustRun();
67-
68-
$cachedDiff = $this->option('diff') ?: $this->createProcess($this->diffCommand())->mustRun()->getOutput();
69-
if ('' === $cachedDiff) {
70-
throw new TaskException('There are no cached files to commit. Try running `git add` to cache some files.');
71-
}
72-
73-
$type = $this->choice(
74-
'Please choice commit type',
75-
$types = $this->configManager->get('types'),
76-
array_key_first($types)
77-
);
78-
79-
$message = retry(
80-
$this->option('retry-times'),
81-
function ($attempts) use ($cachedDiff, $type): string {
82-
if ($attempts > 1) {
83-
$this->output->note('retrying...');
67+
collect()
68+
->tap(function () use (&$message): void {
69+
// Ensure git is installed and the current directory is a git repository.
70+
$this->createProcess(['git', 'rev-parse', '--is-inside-work-tree'])->mustRun();
71+
72+
$cachedDiff = $this->option('diff') ?: $this->createProcess($this->diffCommand())->mustRun()->getOutput();
73+
if (empty($cachedDiff)) {
74+
throw new RuntimeException('There are no cached files to commit. Try running `git add` to cache some files.');
8475
}
8576

86-
$originalMessage = $this->generatorManager
87-
->driver($this->option('generator'))
88-
->generate($this->promptFor($cachedDiff, $type));
89-
$message = $this->tryFixMessage($originalMessage);
90-
if (! str($message)->jsonValidate()) {
91-
throw new TaskException(sprintf(
92-
'The generated commit message(%s) is an invalid JSON.',
93-
var_export($originalMessage, true)
94-
));
95-
}
77+
$type = $this->choice(
78+
'Please choice commit type',
79+
$types = $this->configManager->get('types'),
80+
array_key_first($types)
81+
);
82+
83+
$message = retry(
84+
$this->option('retry-times'),
85+
function ($attempts) use ($cachedDiff, $type): string {
86+
if ($attempts > 1) {
87+
$this->output->note('retrying...');
88+
}
89+
90+
$originalMessage = $this->generatorManager
91+
->driver($this->option('generator'))
92+
->generate($this->promptFor($cachedDiff, $type));
93+
$message = $this->tryFixMessage($originalMessage);
94+
if (! str($message)->jsonValidate()) {
95+
throw new RuntimeException(sprintf(
96+
'The generated commit message(%s) is an invalid JSON.',
97+
var_export($originalMessage, true)
98+
));
99+
}
100+
101+
return $message;
102+
},
103+
$this->option('retry-sleep'),
104+
$this->configManager->get('retry.when')
105+
);
106+
})
107+
->tap(function () use (&$message): void {
108+
$message = collect(json_decode($message, true, 512, JSON_THROW_ON_ERROR | JSON_PARTIAL_OUTPUT_ON_ERROR))
109+
->map(static function ($content) {
110+
if (\is_array($content)) {
111+
return collect($content)
112+
->transform(static function (string $line): string {
113+
return (string) str($line)->trim(" \t\n\r\x0B")->start('- ');
114+
})
115+
->implode(PHP_EOL);
116+
}
117+
118+
return $content;
119+
})
120+
->tap(function (Collection $message): void {
121+
$message = $message->put('', '')->sortKeysUsing(static function (string $a, string $b): int {
122+
$rules = ['subject', '', 'body'];
123+
124+
return array_search($a, $rules, true) <=> array_search($b, $rules, true);
125+
});
126+
// $this->table($message->keys()->all(), [$message->all()]);
127+
$this->output->horizontalTable($message->keys()->all(), [$message->all()]);
128+
})
129+
->tap(function (): void {
130+
if (! $this->confirm('Do you want to commit this message?', true)) {
131+
$this->output->note('regenerating...');
132+
$this->handle();
133+
}
134+
});
135+
})
136+
->tap(function () use ($message): void {
137+
if ($this->option('dry-run')) {
138+
$this->info($this->hydrateMessage($message));
96139

97-
return $message;
98-
},
99-
$this->option('retry-sleep'),
100-
$this->configManager->get('retry.when')
101-
);
102-
// $this->task('1. Generating commit message', function () use (&$message): void {
103-
// }, 'generating...'.PHP_EOL);
104-
105-
$message = collect(json_decode($message, true, 512, JSON_THROW_ON_ERROR | JSON_PARTIAL_OUTPUT_ON_ERROR))
106-
->map(static function ($content) {
107-
if (\is_array($content)) {
108-
return collect($content)
109-
->transform(static function (string $line): string {
110-
return (string) str($line)->trim(" \t\n\r\x0B")->start('- ');
111-
})
112-
->implode(PHP_EOL);
140+
return;
113141
}
114142

115-
return $content;
116-
})
117-
->tap(function (Collection $message): void {
118-
$message = $message->put('', '')->sortKeysUsing(static function (string $a, string $b): int {
119-
$rules = ['subject', '', 'body'];
120-
121-
return array_search($a, $rules, true) <=> array_search($b, $rules, true);
122-
});
123-
// $this->table($message->keys()->all(), [$message->all()]);
124-
$this->output->horizontalTable($message->keys()->all(), [$message->all()]);
143+
tap($this->createProcess($this->commitCommandFor($message)), function (Process $process): void {
144+
$this->shouldEdit() and $process->setTty(true);
145+
})->setTimeout(null)->mustRun();
125146
})
126147
->tap(function (): void {
127-
if (! $this->confirm('Do you want to commit this message?', true)) {
128-
$this->output->note('regenerating...');
129-
$this->handle();
130-
}
148+
$this->output->success('Successfully generated and committed message.');
131149
});
132-
// $this->task(PHP_EOL.'2. Confirming commit message', function () use (&$message): void {
133-
// }, 'confirming...'.PHP_EOL);
134-
135-
if ($this->option('dry-run')) {
136-
$this->info($this->hydrateMessage($message));
137-
138-
return;
139-
}
140-
141-
tap($this->createProcess($this->commitCommandFor($message)), function (Process $process): void {
142-
$this->shouldEdit() and $process->setTty(true);
143-
})->setTimeout(null)->mustRun();
144-
// $this->task(PHP_EOL.'3. Committing message', function (): void {
145-
// }, 'committing...'.PHP_EOL);
146-
147-
$this->output->success('Successfully generated and committed message.');
148150
}
149151

150152
public function schedule(Schedule $schedule): void
@@ -384,6 +386,8 @@ private function hydrateMessage(Collection $message): string
384386
* @param null|mixed $input
385387
*
386388
* @noinspection CallableParameterUseCaseInTypeContextInspection
389+
* @noinspection PhpSameParameterValueInspection
390+
* @noinspection MissingParameterTypeDeclarationInspection
387391
*/
388392
private function createProcess(
389393
array $command,
@@ -392,12 +396,10 @@ private function createProcess(
392396
$input = null,
393397
?float $timeout = 60
394398
): Process {
395-
if (null === $cwd) {
396-
$cwd = $this->argument('path');
397-
}
399+
null === $cwd and $cwd = $this->argument('path');
398400

399401
return tap(new Process($command, $cwd, $env, $input, $timeout), function (Process $process): void {
400-
if ($this->option('verbose')) {
402+
if ($this->output->isDebug()) {
401403
$this->output->note($process->getCommandLine());
402404
}
403405
});

‎config/ai-commit.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
'times' => 3,
4040
'sleep' => 200,
4141
'when' => static function (Exception $exception): bool {
42-
return $exception instanceof App\Exceptions\TaskException;
42+
return $exception instanceof App\Exceptions\RuntimeException;
4343
},
4444
],
4545

‎tests/Feature/CommitCommandTest.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
*/
2020

2121
use App\Commands\CommitCommand;
22-
use App\Exceptions\TaskException;
22+
use App\Exceptions\RuntimeException;
2323
use GuzzleHttp\Promise\PromiseInterface;
2424
use Illuminate\Support\Facades\Http;
2525
use Illuminate\Support\Str;
@@ -33,7 +33,7 @@
3333
expect($createProcess->call(app(CommitCommand::class)))->toBeInstanceOf(Process::class);
3434
})->group(__DIR__, __FILE__)->skip();
3535

36-
it('will throw TaskException(not a git repository)', function (): void {
36+
it('will throw RuntimeException(not a git repository)', function (): void {
3737
$this->artisan(CommitCommand::class, [
3838
'path' => $this->app->basePath('../'),
3939
'--config' => config_path('ai-commit.php'),
@@ -42,7 +42,7 @@
4242
->group(__DIR__, __FILE__)
4343
->throws(ProcessFailedException::class, 'fatal: ');
4444

45-
it('will throw TaskException(no cached files to commit)', function (): void {
45+
it('will throw RuntimeException(no cached files to commit)', function (): void {
4646
// 重置暂存区
4747
Process::fromShellCommandline('git reset', repository_path())->mustRun();
4848

@@ -51,11 +51,11 @@
5151
'--generator' => 'openai',
5252
]);
5353
})
54-
->depends('it will throw TaskException(not a git repository)')
54+
->depends('it will throw RuntimeException(not a git repository)')
5555
->group(__DIR__, __FILE__)
56-
->throws(TaskException::class, 'There are no cached files to commit. Try running `git add` to cache some files.');
56+
->throws(RuntimeException::class, 'There are no cached files to commit. Try running `git add` to cache some files.');
5757

58-
it('will throw TaskException(The generated commit message is an invalid JSON)', function (): void {
58+
it('will throw RuntimeException(The generated commit message is an invalid JSON)', function (): void {
5959
// 添加文件到暂存区
6060
file_put_contents(repository_path('playground.random'), Str::random());
6161
Process::fromShellCommandline('git rm -rf --cached repository/', fixtures_path())->mustRun();
@@ -91,9 +91,9 @@
9191
// ->expectsChoice('Please choice commit type', array_key_first($types = config('ai-commit.types')), $types)
9292
->expectsQuestion('Please choice commit type', array_key_first(config('ai-commit.types')));
9393
})
94-
->depends('it will throw TaskException(no cached files to commit)')
94+
->depends('it will throw RuntimeException(no cached files to commit)')
9595
->group(__DIR__, __FILE__)
96-
->throws(TaskException::class, 'The generated commit message(');
96+
->throws(RuntimeException::class, 'The generated commit message(');
9797

9898
it('can generate and commit message', function (array $parameters): void {
9999
// 添加文件到暂存区
@@ -132,7 +132,7 @@
132132
->assertSuccessful();
133133
})
134134
->with('commit command parameters')
135-
->depends('it will throw TaskException(The generated commit message is an invalid JSON)')
135+
->depends('it will throw RuntimeException(The generated commit message is an invalid JSON)')
136136
->group(__DIR__, __FILE__);
137137

138138
afterAll(static function (): void {

0 commit comments

Comments
 (0)
Please sign in to comment.