Skip to content

Commit 466230c

Browse files
Git support (#80)
Co-authored-by: Jason Varga <jason@pixelfear.com>
1 parent 5d3f82b commit 466230c

1 file changed

Lines changed: 177 additions & 1 deletion

File tree

src/NewCommand.php

Lines changed: 177 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Symfony\Component\Console\Output\OutputInterface;
2121
use Symfony\Component\Console\Question\Question;
2222
use Symfony\Component\Console\Style\SymfonyStyle;
23+
use Symfony\Component\Process\Process;
2324

2425
use function Laravel\Prompts\confirm;
2526
use function Laravel\Prompts\error;
@@ -43,7 +44,7 @@ class NewCommand extends Command
4344

4445
/** @var OutputInterface */
4546
public $output;
46-
47+
4748
public $relativePath;
4849
public $absolutePath;
4950
public $name;
@@ -59,6 +60,10 @@ class NewCommand extends Command
5960
public $baseInstallSuccessful;
6061
public $shouldUpdateCliToVersion = false;
6162
public $makeUser = false;
63+
public $initializeGitRepository = false;
64+
public $shouldPushToGithub = false;
65+
public $githubRepository;
66+
public $repositoryVisibility;
6267
public $pro = true;
6368

6469
/**
@@ -80,6 +85,10 @@ protected function configure()
8085
->addOption('without-dependencies', null, InputOption::VALUE_NONE, 'Optionally install starter kit without dependencies')
8186
->addOption('pro', null, InputOption::VALUE_NONE, 'Enable Statamic Pro for additional features')
8287
->addOption('ssg', null, InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY, 'Optionally install the Static Site Generator addon', [])
88+
->addOption('git', null, InputOption::VALUE_NONE, 'Initialize a Git repository')
89+
->addOption('branch', null, InputOption::VALUE_REQUIRED, 'The branch that should be created for a new repository')
90+
->addOption('github', null, InputOption::VALUE_OPTIONAL, 'Create a new repository on GitHub', false)
91+
->addOption('repo', null, InputOption::VALUE_REQUIRED, 'Optionally specify the name of the GitHub repository')
8392
->addOption('force', 'f', InputOption::VALUE_NONE, 'Force install even if the directory already exists');
8493
}
8594

@@ -127,12 +136,16 @@ protected function execute(InputInterface $input, OutputInterface $output)
127136
->askToEnableStatamicPro()
128137
->askToInstallSsg()
129138
->askToMakeSuperUser()
139+
->askToInitializeGitRepository()
140+
->askToPushToGithub()
130141
->askToSpreadJoy()
131142
->installBaseProject()
132143
->installStarterKit()
133144
->enableStatamicPro()
134145
->makeSuperUser()
135146
->installSsg()
147+
->initializeGitRepository()
148+
->pushToGithub()
136149
->notifyIfOldCliVersion()
137150
->showSuccessMessage()
138151
->showPostInstallInstructions();
@@ -257,6 +270,10 @@ protected function processArguments()
257270
$this->pro = $this->input->getOption('pro') ?? true;
258271
$this->ssg = $this->input->getOption('ssg');
259272
$this->force = $this->input->getOption('force');
273+
$this->initializeGitRepository = $this->input->getOption('git') !== false || $this->input->getOption('github') !== false;
274+
$this->shouldPushToGithub = $this->input->getOption('github') !== false;
275+
$this->githubRepository = $this->input->getOption('repo');
276+
$this->repositoryVisibility = $this->input->getOption('github');
260277

261278
return $this;
262279
}
@@ -664,6 +681,165 @@ protected function makeSuperUserInWindows()
664681
return $this;
665682
}
666683

684+
/**
685+
* Ask to initialize a Git repository.
686+
*
687+
* @return $this
688+
*/
689+
protected function askToInitializeGitRepository()
690+
{
691+
if (
692+
$this->initializeGitRepository
693+
|| ! $this->isGitInstalled()
694+
|| ! $this->input->isInteractive()
695+
) {
696+
return $this;
697+
}
698+
699+
$this->initializeGitRepository = confirm(
700+
label: 'Would you like to initialize a Git repository?',
701+
default: false
702+
);
703+
704+
return $this;
705+
}
706+
707+
/**
708+
* Initialize a Git repository.
709+
*
710+
* @return $this
711+
*/
712+
protected function initializeGitRepository()
713+
{
714+
if (! $this->initializeGitRepository || ! $this->isGitInstalled()) {
715+
return $this;
716+
}
717+
718+
$branch = $this->input->getOption('branch') ?: $this->defaultBranch();
719+
720+
$commands = [
721+
'git init -q',
722+
'git add .',
723+
'git commit -q -m "Set up a fresh Statamic site"',
724+
"git branch -M {$branch}",
725+
];
726+
727+
$this->runCommands($commands, workingPath: $this->absolutePath);
728+
729+
return $this;
730+
}
731+
732+
/**
733+
* Check if Git is installed.
734+
*
735+
* @return bool
736+
*/
737+
protected function isGitInstalled(): bool
738+
{
739+
$process = new Process(['git', '--version']);
740+
741+
$process->run();
742+
743+
return $process->isSuccessful();
744+
}
745+
746+
/**
747+
* Return the local machine's default Git branch if set or default to `main`.
748+
*
749+
* @return string
750+
*/
751+
protected function defaultBranch(): string
752+
{
753+
$process = new Process(['git', 'config', '--global', 'init.defaultBranch']);
754+
$process->run();
755+
756+
$output = trim($process->getOutput());
757+
758+
return $process->isSuccessful() && $output ? $output : 'main';
759+
}
760+
761+
/**
762+
* Ask if the user wants to push the repository to GitHub.
763+
*
764+
* @return $this
765+
*/
766+
protected function askToPushToGithub()
767+
{
768+
if (
769+
! $this->initializeGitRepository
770+
|| ! $this->isGitInstalled()
771+
|| ! $this->isGhInstalled()
772+
|| ! $this->input->isInteractive()
773+
) {
774+
return $this;
775+
}
776+
777+
if (! $this->shouldPushToGithub) {
778+
$this->shouldPushToGithub = confirm(
779+
label: 'Would you like to create a new repository on GitHub?',
780+
default: false
781+
);
782+
783+
if ($this->shouldPushToGithub && ! $this->githubRepository) {
784+
$this->githubRepository = text(
785+
label: 'What should be your full repository name?',
786+
default: $this->name,
787+
required: true,
788+
);
789+
}
790+
791+
if ($this->shouldPushToGithub && ! $this->repositoryVisibility) {
792+
$this->repositoryVisibility = select(
793+
label: 'Should the repository be public or private?',
794+
options: [
795+
'public' => 'Public',
796+
'private' => 'Private',
797+
],
798+
default: 'private',
799+
);
800+
}
801+
}
802+
803+
return $this;
804+
}
805+
806+
/**
807+
* Create a GitHub repository and push the git log to it.
808+
*
809+
* @return $this
810+
*/
811+
protected function pushToGithub()
812+
{
813+
if (! $this->shouldPushToGithub) {
814+
return $this;
815+
}
816+
817+
$name = $this->githubRepository ?? $this->name;
818+
$visibility = $this->repositoryVisibility ?? 'private';
819+
820+
$commands = [
821+
"gh repo create {$name} --source=. --push --{$visibility}",
822+
];
823+
824+
$this->runCommands($commands, $this->absolutePath, disableOutput: true);
825+
826+
return $this;
827+
}
828+
829+
/**
830+
* Check if GitHub's GH CLI tool is installed.
831+
*
832+
* @return bool
833+
*/
834+
protected function isGhInstalled(): bool
835+
{
836+
$process = new Process(['gh', 'auth', 'status']);
837+
838+
$process->run();
839+
840+
return $process->isSuccessful();
841+
}
842+
667843
/**
668844
* Ask for basic input.
669845
*

0 commit comments

Comments
 (0)