66use Phug \Split ;
77use Phug \Split \Command \Options \HashPrefix ;
88use Phug \Split \Git \Author ;
9+ use Phug \Split \Git \Commit ;
910use Phug \Split \Git \EmptyLogList ;
1011use Phug \Split \Git \Log ;
1112
@@ -83,6 +84,98 @@ protected function setGitCommitter(Author $author): void
8384 $ this ->git ('config user.email ' .$ this ->gitEscape ($ author ->getEmail ()));
8485 }
8586
87+ /**
88+ * Copy the current directory recursively to a given destination path.
89+ *
90+ * @suppressWarnings(PHPMD.LongVariableName)
91+ *
92+ * @param string $destination
93+ */
94+ protected function copyCurrentDirectory (string $ destination ): void
95+ {
96+ shell_exec ('cp -r . ' .escapeshellarg ($ destination ).' 2>&1 ' );
97+
98+ // @codeCoverageIgnoreStart
99+ if (!file_exists ($ destination )) {
100+ shell_exec ('xcopy . ' .escapeshellarg ($ destination ).' /e /i /h ' );
101+ }
102+ // @codeCoverageIgnoreEnd
103+ }
104+
105+ /**
106+ * Get GIT local user config (.git/config file settings).
107+ *
108+ * @return array
109+ */
110+ protected function getLocalUserConfig (): array
111+ {
112+ static $ localUser = null ;
113+
114+ if ($ localUser === null ) {
115+ $ localUser = file ('.git/config ' )
116+ ? parse_ini_file ('.git/config ' , true )['user ' ] ?? []
117+ : [];
118+ }
119+
120+ return $ localUser ;
121+ }
122+
123+ /**
124+ * Apply the given commit in the current repository.
125+ *
126+ * @param Split $cli
127+ * @param array $package
128+ * @param Commit $commit
129+ * @param string $distributionDirectory
130+ * @param string $branch
131+ *
132+ * @suppressWarnings(PHPMD.LongVariableName)
133+ */
134+ protected function cherryPickCommit (
135+ Split $ cli ,
136+ array $ package ,
137+ Commit $ commit ,
138+ string $ distributionDirectory ,
139+ string $ branch
140+ ): void {
141+ $ hash = $ commit ->getHash ();
142+ $ this ->git ('config advice.detachedHead false ' );
143+ $ this ->git ("checkout -f $ hash " , [], '2>&1 ' );
144+ rename ("$ distributionDirectory/.git " , $ this ->output .'/.git.temp ' );
145+ $ this ->remove ($ distributionDirectory );
146+ $ this ->copyCurrentDirectory ($ distributionDirectory );
147+
148+ $ this ->remove ("$ distributionDirectory/.git " );
149+ rename ($ this ->output .'/.git.temp ' , "$ distributionDirectory/.git " );
150+ $ cli ->chdir ($ distributionDirectory );
151+ $ this ->setGitCommitter ($ commit ->getCommit ()->getAuthor ());
152+ $ author = $ commit ->getAuthor ();
153+
154+ $ commitMessageFile = sys_get_temp_dir ().'/commit-message- ' .mt_rand (0 , 99999999 );
155+ file_put_contents ($ commitMessageFile , $ commit ->getMessage ()."\n\n" .$ this ->hashPrefix .$ hash );
156+ $ this ->git ('add . ' );
157+ $ this ->git ('commit --file= ' .escapeshellarg ($ commitMessageFile ), [
158+ 'author ' => $ author ,
159+ 'date ' => $ author ->getDate (),
160+ ], '2>&1 ' );
161+ unlink ($ commitMessageFile );
162+
163+ if (!$ this ->noPush ) {
164+ $ name = $ package ['name ' ];
165+ $ push = (string ) $ this ->git ("push origin $ branch " , [], '2>&1 ' );
166+ $ cli ->writeLine ("Pushing $ name \n" .$ push , strpos ($ push , 'error: ' ) === false ? 'light_cyan ' : 'red ' );
167+ }
168+
169+ $ localUser = $ this ->getLocalUserConfig ();
170+
171+ foreach (['name ' , 'email ' ] as $ userConfig ) {
172+ $ config = empty ($ localUser [$ userConfig ])
173+ ? "--unset user. $ userConfig "
174+ : "user. $ userConfig " .$ this ->gitEscape ($ localUser [$ userConfig ]);
175+ $ this ->git ('config ' .$ config );
176+ }
177+ }
178+
86179 /**
87180 * Distribute and update the sub-package.
88181 *
@@ -92,6 +185,8 @@ protected function setGitCommitter(Author $author): void
92185 *
93186 * @throws Exception
94187 *
188+ * @suppressWarnings(PHPMD.LongVariableName)
189+ *
95190 * @return bool
96191 */
97192 protected function distributePackage (Split $ cli , array $ package , string $ branch ): bool
@@ -103,9 +198,6 @@ protected function distributePackage(Split $cli, array $package, string $branch)
103198 $ hash = $ this ->getCurrentLinkedCommitHash ();
104199 $ distributionDirectory = getcwd ();
105200 $ sourceDirectory = $ package ['directory ' ];
106- $ localUser = file ('.git/config ' )
107- ? parse_ini_file ('.git/config ' , true )['user ' ] ?? []
108- : [];
109201
110202 $ cli ->chdir ($ sourceDirectory );
111203 $ this ->git ('stash ' , [], '2>&1 ' );
@@ -115,46 +207,7 @@ protected function distributePackage(Split $cli, array $package, string $branch)
115207
116208 foreach ($ log as $ commit ) {
117209 $ cli ->chdir ($ sourceDirectory );
118- $ hash = $ commit ->getHash ();
119- $ this ->git ('config advice.detachedHead false ' );
120- $ this ->git ("checkout -f $ hash " , [], '2>&1 ' );
121- rename ("$ distributionDirectory/.git " , $ this ->output .'/.git.temp ' );
122- $ this ->remove ($ distributionDirectory );
123- shell_exec ('cp -r . ' .escapeshellarg ($ distributionDirectory ).' 2>&1 ' );
124-
125- // @codeCoverageIgnoreStart
126- if (!file_exists ($ distributionDirectory )) {
127- shell_exec ('xcopy . ' .escapeshellarg ($ distributionDirectory ).' /e /i /h ' );
128- }
129- // @codeCoverageIgnoreEnd
130-
131- $ this ->remove ("$ distributionDirectory/.git " );
132- rename ($ this ->output .'/.git.temp ' , "$ distributionDirectory/.git " );
133- $ cli ->chdir ($ distributionDirectory );
134- $ this ->setGitCommitter ($ commit ->getCommit ()->getAuthor ());
135- $ author = $ commit ->getAuthor ();
136-
137- $ commitMessageFile = sys_get_temp_dir ().'/commit-message- ' .mt_rand (0 , 99999999 );
138- file_put_contents ($ commitMessageFile , $ commit ->getMessage ()."\n\n" .$ this ->hashPrefix .$ hash );
139- $ this ->git ('add . ' );
140- $ this ->git ('commit --file= ' .escapeshellarg ($ commitMessageFile ), [
141- 'author ' => $ author ,
142- 'date ' => $ author ->getDate (),
143- ], '2>&1 ' );
144- unlink ($ commitMessageFile );
145-
146- if (!$ this ->noPush ) {
147- $ name = $ package ['name ' ];
148- $ push = (string ) $ this ->git ("push origin $ branch " , [], '2>&1 ' );
149- $ cli ->writeLine ("Pushing $ name \n" .$ push , strpos ($ push , 'error: ' ) === false ? 'light_cyan ' : 'red ' );
150- }
151-
152- foreach (['name ' , 'email ' ] as $ userConfig ) {
153- $ config = empty ($ localUser [$ userConfig ])
154- ? "--unset user. $ userConfig "
155- : "user. $ userConfig " .$ this ->gitEscape ($ localUser [$ userConfig ]);
156- $ this ->git ('config ' .$ config );
157- }
210+ $ this ->cherryPickCommit ($ cli , $ package , $ commit , $ distributionDirectory , $ branch );
158211 }
159212 } catch (EmptyLogList $ exception ) {
160213 $ cli ->writeLine ($ package ['name ' ].' is already up to date. ' , 'green ' );
0 commit comments