Skip to content

Commit a40de3a

Browse files
committed
Add reset command
1 parent a9ad0e6 commit a40de3a

9 files changed

+284
-6
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
77

88
### Added
99

10-
- The `whoami` command displays the current Git branch.
10+
- The `whoami` command displays the current Git branch.
11+
- New `reset` command.
1112

1213
## [v1.4.0] - 2024-07-19
1314

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ have to be provided as a comma-separated list.
8585
git-user-bend use [<alias>|<alias1,aliasN>] [<directory>] [--from-dotfile]
8686
```
8787

88+
To reset the Git repository user to the values before, the `reset` command is available.
89+
``` bash
90+
git-user-bend reset [<directory>]
91+
```
92+
8893
To start a pair programming session, which will be identifiable in the Git commits, the `pair` command merges the user
8994
details of several personas into one pair. The email of the first persona alias in the comma-separated list will be
9095
used for the Git `user.email` configuration. If the `--branch|-b` is provided, a new Git branch will be created to pair in.

src/Commands/ResetCommand.php

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
namespace Stolt\GitUserBend\Commands;
4+
5+
use Stolt\GitUserBend\Exceptions\Exception;
6+
use Stolt\GitUserBend\Git\Repository;
7+
use Stolt\GitUserBend\Git\User;
8+
use Symfony\Component\Console\Command\Command;
9+
use Symfony\Component\Console\Input\InputArgument;
10+
use Symfony\Component\Console\Input\InputInterface;
11+
use Symfony\Component\Console\Output\OutputInterface;
12+
13+
class ResetCommand extends Command
14+
{
15+
/**
16+
* @var Repository
17+
*/
18+
private Repository $repository;
19+
20+
/**
21+
* Initialize.
22+
*
23+
* @param Repository $repository
24+
*/
25+
public function __construct(Repository $repository)
26+
{
27+
$this->repository = $repository;
28+
29+
parent::__construct();
30+
}
31+
32+
/**
33+
* Command configuration.
34+
*
35+
* @return void
36+
*/
37+
protected function configure(): void
38+
{
39+
$this->setName('reset');
40+
$this->setDescription('Resets the current user');
41+
42+
$directoryArgumentDescription = 'The directory of the Git repository';
43+
$this->addArgument(
44+
'directory',
45+
InputArgument::OPTIONAL,
46+
$directoryArgumentDescription,
47+
WORKING_DIRECTORY
48+
);
49+
}
50+
51+
/**
52+
* Execute command.
53+
*
54+
* @param InputInterface $input
55+
* @param OutputInterface $output
56+
*
57+
* @return integer
58+
*/
59+
protected function execute(InputInterface $input, OutputInterface $output): int
60+
{
61+
$directory = $input->getArgument('directory');
62+
63+
try {
64+
$this->repository->setDirectory((string) $directory);
65+
66+
$formerPersona = $this->repository->getFormerPersonaFromConfiguration();
67+
68+
$this->repository->removeFormerPersonaFromConfiguration();
69+
70+
$this->repository->setUser(new User($formerPersona->getName(), $formerPersona->getEmail()));
71+
72+
$outputContent = "<info>Reset user config to <comment>"
73+
. "'{$formerPersona->getName()} <{$formerPersona->getEmail()}>'</comment>.</info>";
74+
$output->writeln($outputContent);
75+
76+
return self::SUCCESS;
77+
78+
} catch (Exception $e) {
79+
$error = "<error>Error:</error> " . $e->getInforizedMessage();
80+
$output->writeln($error);
81+
82+
return self::FAILURE;
83+
}
84+
}
85+
}

src/Commands/UseCommand.php

+7
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
106106
$this->repository->setDirectory((string) $directory);
107107

108108
if ($isFromDotfileUse) {
109+
try {
110+
$this->repository->storePreviousUser();
111+
} catch (UnresolvablePersona $e) {
112+
// ignore because we are using user from gub file
113+
}
109114
return $this->useFromGubDotfile($input, $output);
110115
}
111116
if ($aliases) {
@@ -142,6 +147,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
142147
// ignore because we are using users from persona storage
143148
}
144149

150+
$this->repository->storePreviousUser();
151+
145152
if ($this->repository->setUser($user)) {
146153
if ($aliases) {
147154
/** @var Persona $pairPersona */

tests/Commands/ResetCommandTest.php

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
<?php
2+
3+
namespace Stolt\GitUserBend\Tests\Commands;
4+
5+
use PHPUnit\Framework\Attributes\Group;
6+
use PHPUnit\Framework\Attributes\Test;
7+
use Stolt\GitUserBend\Commands\ResetCommand;
8+
use Stolt\GitUserBend\Commands\UseCommand;
9+
use Stolt\GitUserBend\Exceptions\InvalidPersona;
10+
use Stolt\GitUserBend\Exceptions\UnresolvablePersona;
11+
use Stolt\GitUserBend\Git\Repository;
12+
use Stolt\GitUserBend\Git\User;
13+
use Stolt\GitUserBend\Helpers\Str as OsHelper;
14+
use Stolt\GitUserBend\Persona\Storage;
15+
use Stolt\GitUserBend\Tests\CommandTester;
16+
use Stolt\GitUserBend\Tests\TestCase;
17+
use Symfony\Component\Console\Application;
18+
use Symfony\Component\Console\Command\Command;
19+
20+
class ResetCommandTest extends TestCase
21+
{
22+
/**
23+
* @var Application
24+
*/
25+
private Application $application;
26+
27+
/**
28+
* @return Application
29+
*/
30+
protected function getApplication(): Application
31+
{
32+
$application = new Application();
33+
$command = new UseCommand(
34+
new Storage(STORAGE_FILE),
35+
new Repository($this->temporaryDirectory)
36+
);
37+
$resetCommand = new ResetCommand(
38+
new Repository($this->temporaryDirectory)
39+
);
40+
41+
$application->add($command);
42+
$application->add($resetCommand);
43+
44+
return $application;
45+
}
46+
47+
/**
48+
* Set up test environment.
49+
*/
50+
protected function setUp(): void
51+
{
52+
$this->setUpTemporaryDirectory();
53+
54+
if (!defined('WORKING_DIRECTORY')) {
55+
define('WORKING_DIRECTORY', $this->temporaryDirectory);
56+
}
57+
58+
if (!defined('HOME_DIRECTORY')) {
59+
define('HOME_DIRECTORY', $this->temporaryDirectory);
60+
}
61+
62+
if (!defined('STORAGE_FILE')) {
63+
define(
64+
'STORAGE_FILE',
65+
HOME_DIRECTORY . DIRECTORY_SEPARATOR . Storage::FILE_NAME
66+
);
67+
}
68+
69+
$this->application = $this->getApplication();
70+
}
71+
72+
/**
73+
* Tear down test environment.
74+
*
75+
* @return void
76+
*/
77+
protected function tearDown(): void
78+
{
79+
if (is_dir($this->temporaryDirectory)) {
80+
$this->removeDirectory($this->temporaryDirectory);
81+
}
82+
}
83+
84+
#[Test]
85+
#[Group('integration')]
86+
public function returnsExpectedWarningWhenProvidedDirectoryDoesNotExist(): void
87+
{
88+
$command = $this->application->find('reset');
89+
$commandTester = new CommandTester($command);
90+
$commandTester->execute([
91+
'command' => $command->getName(),
92+
'directory' => '/out/of/orbit',
93+
]);
94+
95+
$expectedDisplay = <<<CONTENT
96+
Error: The directory /out/of/orbit doesn't exist.
97+
98+
CONTENT;
99+
100+
$this->assertSame($expectedDisplay, $commandTester->getDisplay());
101+
$this->assertTrue($commandTester->getStatusCode() == 1);
102+
}
103+
104+
#[Test]
105+
#[Group('integration')]
106+
public function returnsExpectedWarningWhenProvidedDirectoryIsNotAGitRepository(): void
107+
{
108+
$command = $this->application->find('reset');
109+
$commandTester = new CommandTester($command);
110+
$commandTester->execute([
111+
'command' => $command->getName(),
112+
'directory' => $this->temporaryDirectory,
113+
]);
114+
115+
$expectedDisplay = <<<CONTENT
116+
Error: No Git repository in {$this->temporaryDirectory}.
117+
118+
CONTENT;
119+
120+
$this->assertSame($expectedDisplay, $commandTester->getDisplay());
121+
$this->assertTrue($commandTester->getStatusCode() == Command::FAILURE);
122+
}
123+
124+
/**
125+
* @throws UnresolvablePersona
126+
* @throws InvalidPersona
127+
*/
128+
#[Test]
129+
#[Group('integration')]
130+
public function resetsGitConfigToFormerUser(): void
131+
{
132+
/*if ((new OsHelper())->isWindows()) {
133+
$this->markTestSkipped('Skipping test on Windows systems');
134+
}*/
135+
136+
$this->createTemporaryGitRepository(new User('John Doe', '[email protected]'));
137+
138+
chdir($this->temporaryDirectory);
139+
140+
$existingStorageContent = <<<CONTENT
141+
[{"alias":"jd","name":"John Doe","email":"[email protected]","usage_frequency":11},
142+
{"alias":"so","name":"Some One","email":"[email protected]","usage_frequency":23}]
143+
CONTENT;
144+
$this->createTemporaryStorageFile($existingStorageContent);
145+
146+
$command = $this->application->find('use');
147+
$commandTester = new CommandTester($command);
148+
$commandTester->execute([
149+
'command' => $command->getName(),
150+
'directory' => $this->temporaryDirectory,
151+
'alias' => 'jd',
152+
]);
153+
154+
$commandTester->assertCommandIsSuccessful();
155+
156+
$command = $this->application->find('reset');
157+
$commandTester = new CommandTester($command);
158+
$commandTester->execute([
159+
'command' => $command->getName(),
160+
'directory' => $this->temporaryDirectory,
161+
]);
162+
163+
$expectedDisplay = <<<CONTENT
164+
Reset user config to 'John Doe <[email protected]>'.
165+
166+
CONTENT;
167+
168+
$this->assertSame($expectedDisplay, $commandTester->getDisplay());
169+
$commandTester->assertCommandIsSuccessful();
170+
171+
$repository = new Repository($this->temporaryDirectory);
172+
$personaFromConfig = $repository->getPersonaFromConfiguration();
173+
$this->assertSame('John Doe', $personaFromConfig->getName());
174+
$this->assertSame('[email protected]', $personaFromConfig->getEmail());
175+
176+
$this->expectException(UnresolvablePersona::class);
177+
$repository->getFormerPersonaFromConfiguration();
178+
}
179+
}

tests/Commands/UnpairCommandTest.php

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use Stolt\GitUserBend\Git\Repository;
1212
use Stolt\GitUserBend\Git\User;
1313
use Stolt\GitUserBend\Helpers\Str as OsHelper;
14-
use Stolt\GitUserBend\Persona;
1514
use Stolt\GitUserBend\Persona\Storage;
1615
use Stolt\GitUserBend\Tests\CommandTester;
1716
use Stolt\GitUserBend\Tests\TestCase;

tests/Commands/UseCommandTest.php

+2
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ public function returnsExpectedWarningWhenUseFromGubDotfileFails(): void
395395
. DIRECTORY_SEPARATOR
396396
. Repository::GUB_FILENAME;
397397

398+
$repository->shouldReceive('storePreviousUser')->times(1);
398399
$repository->shouldReceive('setDirectory')->times(1);
399400
$repository->shouldReceive('getGubDotfilePath')->times(1)
400401
->andReturn($localGubDotfile);
@@ -570,6 +571,7 @@ public function returnsExpectedWarningWhenUseOfAliasFails(): void
570571

571572
$storage->shouldReceive('all')->times(1)->andReturn($personas);
572573
$repository->shouldReceive('setDirectory')->times(1);
574+
$repository->shouldReceive('storePreviousUser')->times(1);
573575
$repository->shouldReceive('getPersonaFromConfiguration')
574576
->times(1)->andThrow(new UnresolvablePersona());
575577
$repository->shouldReceive('setUser')->times(1)->andReturn(false);

tests/Commands/WhoamiCommandTest.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@
1717
class WhoamiCommandTest extends TestCase
1818
{
1919
/**
20-
* @var \Symfony\Component\Console\Application
20+
* @var Application
2121
*/
22-
private $application;
22+
private Application $application;
2323

2424
/**
2525
* Set up test environment.
@@ -76,7 +76,7 @@ protected function setApplication(User $user = null): void
7676
}
7777

7878
/**
79-
* @return \Symfony\Component\Console\Application
79+
* @return Application
8080
*/
8181
protected function getApplication(): Application
8282
{

tests/TestCase.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ protected function createTemporaryGitRepository(User $user = null): void
4747
{
4848
$currentDirectory = getcwd();
4949
chdir($this->temporaryDirectory);
50-
exec('git init');
50+
exec('git init -b main 2>&1');
5151

5252
if ($user) {
5353
if ($user->hasName()) {

0 commit comments

Comments
 (0)