@@ -257,14 +257,25 @@ public function getLatestCommit(string $owner, string $repositoryName, string $b
257257 /**
258258 * Create a file in a repository
259259 *
260- * Gogs uses PUT /repos/{owner}/{repo}/contents/{path}.
261- * For non-default branches we use git CLI, because the Gogs API `branch`
262- * param creates a new branch rather than targeting an existing one .
260+ * For the default branch (or when no branch is specified), uses the Gogs
261+ * contents API. For non-default branches, uses git CLI because the Gogs
262+ * API returns 500 when targeting an existing non-default branch .
263263 *
264264 * @return array<mixed>
265265 */
266266 public function createFile (string $ owner , string $ repositoryName , string $ filepath , string $ content , string $ message = 'Add file ' , string $ branch = '' ): array
267267 {
268+ if (!empty ($ branch )) {
269+ // Check if branch is the default branch
270+ $ url = "/repos/ {$ owner }/ {$ repositoryName }" ;
271+ $ response = $ this ->call (self ::METHOD_GET , $ url , ['Authorization ' => "token $ this ->accessToken " ]);
272+ $ defaultBranch = $ response ['body ' ]['default_branch ' ] ?? 'master ' ;
273+
274+ if ($ branch !== $ defaultBranch ) {
275+ return $ this ->createFileViaCli ($ owner , $ repositoryName , $ filepath , $ content , $ message , $ branch );
276+ }
277+ }
278+
268279 $ url = "/repos/ {$ owner }/ {$ repositoryName }/contents/ {$ filepath }" ;
269280
270281 $ response = $ this ->call (
@@ -274,7 +285,6 @@ public function createFile(string $owner, string $repositoryName, string $filepa
274285 [
275286 'content ' => base64_encode ($ content ),
276287 'message ' => $ message ,
277- 'branch ' => $ branch
278288 ]
279289 );
280290
@@ -287,6 +297,33 @@ public function createFile(string $owner, string $repositoryName, string $filepa
287297 return $ response ['body ' ] ?? [];
288298 }
289299
300+ /**
301+ * Create a file on a non-default branch using git CLI.
302+ *
303+ * @return array<mixed>
304+ */
305+ private function createFileViaCli (string $ owner , string $ repositoryName , string $ filepath , string $ content , string $ message , string $ branch ): array
306+ {
307+ $ dir = $ this ->gitClone ($ owner , $ repositoryName , $ branch );
308+
309+ try {
310+ $ fullPath = $ dir . '/ ' . $ filepath ;
311+ $ dirPath = dirname ($ fullPath );
312+ if (!is_dir ($ dirPath )) {
313+ mkdir ($ dirPath , 0777 , true );
314+ }
315+ file_put_contents ($ fullPath , $ content );
316+
317+ $ this ->exec ("git -C {$ dir } add " . escapeshellarg ($ filepath ));
318+ $ this ->exec ("git -C {$ dir } commit -m " . escapeshellarg ($ message ));
319+ $ this ->exec ("git -C {$ dir } push origin " . escapeshellarg ($ branch ));
320+ } finally {
321+ $ this ->exec ("rm -rf {$ dir }" );
322+ }
323+
324+ return ['content ' => ['path ' => $ filepath ]];
325+ }
326+
290327 /**
291328 * Create a branch
292329 *
@@ -364,13 +401,32 @@ public function listRepositoryLanguages(string $owner, string $repositoryName):
364401 /**
365402 * Create a tag
366403 *
367- * Gogs does not support tag creation via API.
404+ * Gogs does not support tag creation via API, so we use git CLI .
368405 *
369406 * @return array<mixed>
370407 */
371408 public function createTag (string $ owner , string $ repositoryName , string $ tagName , string $ target , string $ message = '' ): array
372409 {
373- throw new Exception ("Tag creation via API is not supported by Gogs " );
410+ $ dir = $ this ->gitClone ($ owner , $ repositoryName );
411+
412+ try {
413+ $ this ->exec ("git -C {$ dir } fetch origin " . escapeshellarg ($ target ));
414+ if (!empty ($ message )) {
415+ $ this ->exec ("git -C {$ dir } tag -a " . escapeshellarg ($ tagName ) . " " . escapeshellarg ($ target ) . " -m " . escapeshellarg ($ message ));
416+ } else {
417+ $ this ->exec ("git -C {$ dir } tag " . escapeshellarg ($ tagName ) . " " . escapeshellarg ($ target ));
418+ }
419+ $ this ->exec ("git -C {$ dir } push origin " . escapeshellarg ($ tagName ));
420+ } finally {
421+ $ this ->exec ("rm -rf {$ dir }" );
422+ }
423+
424+ return [
425+ 'name ' => $ tagName ,
426+ 'commit ' => [
427+ 'sha ' => $ target ,
428+ ],
429+ ];
374430 }
375431
376432 /**
0 commit comments