From c85197ea5ec8e0c98b4fbea9855d8e3c1eeb72c9 Mon Sep 17 00:00:00 2001 From: gitea-mcp bot Date: Wed, 6 May 2026 14:04:36 +0000 Subject: [PATCH 1/3] fix(files): route UpsertFile to POST when sha is empty so new files can be created --- internal/gitea/files.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/internal/gitea/files.go b/internal/gitea/files.go index e579dd4..3fcd229 100644 --- a/internal/gitea/files.go +++ b/internal/gitea/files.go @@ -92,13 +92,24 @@ type FileWriteResult struct { } `json:"commit"` } +// UpsertFile creates a file when args.Sha is empty (POST) or updates an existing +// file when args.Sha is set (PUT). Gitea routes both operations by HTTP method on +// the same /contents/{path} URL, and rejects PUT without a sha. func (c *Client) UpsertFile(ctx context.Context, owner, repo, path string, args UpsertFileArgs) (*FileWriteResult, error) { p := fmt.Sprintf("/api/v1/repos/%s/%s/contents/%s", owner, repo, path) payload, err := json.Marshal(args) if err != nil { return nil, err } - body, status, err := c.PutJSON(ctx, p, payload) + var ( + body []byte + status int + ) + if args.Sha == "" { + body, status, err = c.PostJSON(ctx, p, payload) + } else { + body, status, err = c.PutJSON(ctx, p, payload) + } if err != nil { return nil, err } -- 2.49.1 From 052827320ab124b2f5925f96b6926d0de39cae95 Mon Sep 17 00:00:00 2001 From: gitea-mcp bot Date: Wed, 6 May 2026 14:05:23 +0000 Subject: [PATCH 2/3] test(file_write_branch): cover POST-on-create and PUT-on-update routing --- internal/tools/file_write_branch_test.go | 33 ++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/internal/tools/file_write_branch_test.go b/internal/tools/file_write_branch_test.go index d7f7e12..eeab221 100644 --- a/internal/tools/file_write_branch_test.go +++ b/internal/tools/file_write_branch_test.go @@ -39,9 +39,9 @@ func TestFileWriteBranchCreatesBranchAndFile(t *testing.T) { _, _ = w.Write([]byte(createBranchResp)) }) - // Upsert file → 201 + // New file (no sha) → POST to /contents/{path} mux.HandleFunc("/api/v1/repos/owner/myrepo/contents/doc.md", func(w http.ResponseWriter, r *http.Request) { - require.Equal(t, http.MethodPut, r.Method) + require.Equal(t, http.MethodPost, r.Method) w.WriteHeader(http.StatusCreated) _, _ = w.Write([]byte(upsertFileResp)) }) @@ -64,6 +64,35 @@ func TestFileWriteBranchCreatesBranchAndFile(t *testing.T) { assert.Equal(t, "cmt1", result["commit_sha"]) } +func TestFileWriteBranchUsesPutWhenShaProvided(t *testing.T) { + mux := http.NewServeMux() + + // Branch exists + mux.HandleFunc("/api/v1/repos/owner/myrepo/branches/feat/existing", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + _, _ = w.Write([]byte(branchCheckExistsResp)) + }) + + // Existing file (sha provided) → PUT + mux.HandleFunc("/api/v1/repos/owner/myrepo/contents/doc.md", func(w http.ResponseWriter, r *http.Request) { + require.Equal(t, http.MethodPut, r.Method) + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(upsertFileResp)) + }) + + srv := httptest.NewServer(mux) + defer srv.Close() + + tool := tools.NewFileWriteBranch(gitea.NewClient(srv.URL, "tok"), allowlist.New([]string{"owner"})) + out, err := tool.Call(context.Background(), json.RawMessage(`{ + "owner":"owner","name":"myrepo","path":"doc.md", + "content":"hello","branch":"feat/existing", + "sha":"oldsha","message":"update doc.md" + }`)) + require.NoError(t, err) + require.NotNil(t, out) +} + func TestFileWriteBranchUsesDefaultBaseWhenBaseEmpty(t *testing.T) { var createBody []byte mux := http.NewServeMux() -- 2.49.1 From d35ff9781ce0a04a0e45d6d433fb85123b8eb03d Mon Sep 17 00:00:00 2001 From: gitea-mcp bot Date: Wed, 6 May 2026 14:35:20 +0000 Subject: [PATCH 3/3] test(file_write_branch): assert branch and commit_sha on PUT path for parity --- internal/tools/file_write_branch_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/tools/file_write_branch_test.go b/internal/tools/file_write_branch_test.go index eeab221..483a1fd 100644 --- a/internal/tools/file_write_branch_test.go +++ b/internal/tools/file_write_branch_test.go @@ -90,7 +90,11 @@ func TestFileWriteBranchUsesPutWhenShaProvided(t *testing.T) { "sha":"oldsha","message":"update doc.md" }`)) require.NoError(t, err) - require.NotNil(t, out) + + var result map[string]any + require.NoError(t, json.Unmarshal(out, &result)) + assert.Equal(t, "feat/existing", result["branch"]) + assert.Equal(t, "cmt1", result["commit_sha"]) } func TestFileWriteBranchUsesDefaultBaseWhenBaseEmpty(t *testing.T) { -- 2.49.1