2020use Symfony \Component \Console \Output \OutputInterface ;
2121use Symfony \Component \Console \Question \Question ;
2222use Symfony \Component \Console \Style \SymfonyStyle ;
23+ use Symfony \Component \Process \Process ;
2324
2425use function Laravel \Prompts \confirm ;
2526use 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