From b80936f3d207f0fa0e14494cd77fdf4d22bfdae5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 00:37:22 +0000 Subject: [PATCH] build(deps): bump code.gitea.io/sdk/gitea from 0.21.0 to 0.23.2 Bumps code.gitea.io/sdk/gitea from 0.21.0 to 0.23.2. --- updated-dependencies: - dependency-name: code.gitea.io/sdk/gitea dependency-version: 0.23.2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 +- go.sum | 8 +- vendor/code.gitea.io/sdk/gitea/action_run.go | 279 ++++++++++++++++++ vendor/code.gitea.io/sdk/gitea/activity.go | 24 ++ vendor/code.gitea.io/sdk/gitea/activitypub.go | 56 ++++ .../code.gitea.io/sdk/gitea/admin_badges.go | 79 +++++ vendor/code.gitea.io/sdk/gitea/admin_cron.go | 3 +- vendor/code.gitea.io/sdk/gitea/admin_email.go | 48 +++ vendor/code.gitea.io/sdk/gitea/admin_hooks.go | 80 +++++ vendor/code.gitea.io/sdk/gitea/admin_repo.go | 43 +++ vendor/code.gitea.io/sdk/gitea/admin_user.go | 80 ++++- vendor/code.gitea.io/sdk/gitea/attachment.go | 3 +- vendor/code.gitea.io/sdk/gitea/client.go | 48 ++- vendor/code.gitea.io/sdk/gitea/git_hook.go | 6 +- vendor/code.gitea.io/sdk/gitea/hook.go | 18 +- vendor/code.gitea.io/sdk/gitea/httpsign.go | 34 ++- vendor/code.gitea.io/sdk/gitea/issue.go | 3 +- .../code.gitea.io/sdk/gitea/issue_comment.go | 52 +++- vendor/code.gitea.io/sdk/gitea/issue_ext.go | 191 ++++++++++++ vendor/code.gitea.io/sdk/gitea/issue_label.go | 143 +-------- .../sdk/gitea/issue_milestone.go | 6 +- vendor/code.gitea.io/sdk/gitea/issue_pin.go | 73 +++++ .../code.gitea.io/sdk/gitea/issue_reaction.go | 26 +- .../sdk/gitea/issue_stopwatch.go | 29 +- .../sdk/gitea/issue_subscription.go | 20 +- .../sdk/gitea/issue_tracked_time.go | 20 +- .../code.gitea.io/sdk/gitea/miscellaneous.go | 234 +++++++++++++++ .../code.gitea.io/sdk/gitea/notifications.go | 6 +- vendor/code.gitea.io/sdk/gitea/oauth2.go | 2 +- vendor/code.gitea.io/sdk/gitea/org.go | 50 ++-- vendor/code.gitea.io/sdk/gitea/org_action.go | 146 ++++++++- vendor/code.gitea.io/sdk/gitea/org_block.go | 79 +++++ vendor/code.gitea.io/sdk/gitea/org_label.go | 116 ++++++++ vendor/code.gitea.io/sdk/gitea/org_member.go | 3 +- vendor/code.gitea.io/sdk/gitea/org_social.go | 124 ++++++++ vendor/code.gitea.io/sdk/gitea/org_team.go | 18 +- vendor/code.gitea.io/sdk/gitea/package.go | 29 +- vendor/code.gitea.io/sdk/gitea/pull.go | 57 ++-- vendor/code.gitea.io/sdk/gitea/pull_review.go | 15 +- vendor/code.gitea.io/sdk/gitea/release.go | 6 +- vendor/code.gitea.io/sdk/gitea/repo.go | 72 ++++- vendor/code.gitea.io/sdk/gitea/repo_action.go | 31 +- vendor/code.gitea.io/sdk/gitea/repo_branch.go | 31 ++ .../sdk/gitea/repo_branch_protection.go | 3 +- .../sdk/gitea/repo_collaborator.go | 6 +- vendor/code.gitea.io/sdk/gitea/repo_file.go | 6 +- .../code.gitea.io/sdk/gitea/repo_file_ext.go | 136 +++++++++ .../code.gitea.io/sdk/gitea/repo_git_notes.go | 56 ++++ vendor/code.gitea.io/sdk/gitea/repo_key.go | 3 +- vendor/code.gitea.io/sdk/gitea/repo_label.go | 153 ++++++++++ .../code.gitea.io/sdk/gitea/repo_migrate.go | 8 +- vendor/code.gitea.io/sdk/gitea/repo_mirror.go | 31 ++ vendor/code.gitea.io/sdk/gitea/repo_refs.go | 10 + vendor/code.gitea.io/sdk/gitea/repo_stars.go | 6 +- vendor/code.gitea.io/sdk/gitea/repo_tag.go | 3 +- .../sdk/gitea/repo_tag_protection.go | 3 +- vendor/code.gitea.io/sdk/gitea/repo_team.go | 6 +- vendor/code.gitea.io/sdk/gitea/repo_topics.go | 9 +- vendor/code.gitea.io/sdk/gitea/repo_wiki.go | 164 ++++++++++ vendor/code.gitea.io/sdk/gitea/secret.go | 2 + vendor/code.gitea.io/sdk/gitea/user.go | 2 + vendor/code.gitea.io/sdk/gitea/user_app.go | 6 +- vendor/code.gitea.io/sdk/gitea/user_block.go | 76 +++++ vendor/code.gitea.io/sdk/gitea/user_email.go | 5 +- vendor/code.gitea.io/sdk/gitea/user_ext.go | 58 ++++ vendor/code.gitea.io/sdk/gitea/user_follow.go | 8 +- vendor/code.gitea.io/sdk/gitea/user_gpgkey.go | 37 ++- vendor/code.gitea.io/sdk/gitea/user_key.go | 4 +- vendor/code.gitea.io/sdk/gitea/user_search.go | 4 + vendor/code.gitea.io/sdk/gitea/user_social.go | 46 +++ vendor/code.gitea.io/sdk/gitea/version.go | 1 + vendor/modules.txt | 8 +- 72 files changed, 2894 insertions(+), 361 deletions(-) create mode 100644 vendor/code.gitea.io/sdk/gitea/action_run.go create mode 100644 vendor/code.gitea.io/sdk/gitea/activity.go create mode 100644 vendor/code.gitea.io/sdk/gitea/activitypub.go create mode 100644 vendor/code.gitea.io/sdk/gitea/admin_badges.go create mode 100644 vendor/code.gitea.io/sdk/gitea/admin_email.go create mode 100644 vendor/code.gitea.io/sdk/gitea/admin_hooks.go create mode 100644 vendor/code.gitea.io/sdk/gitea/issue_ext.go create mode 100644 vendor/code.gitea.io/sdk/gitea/issue_pin.go create mode 100644 vendor/code.gitea.io/sdk/gitea/miscellaneous.go create mode 100644 vendor/code.gitea.io/sdk/gitea/org_block.go create mode 100644 vendor/code.gitea.io/sdk/gitea/org_label.go create mode 100644 vendor/code.gitea.io/sdk/gitea/org_social.go create mode 100644 vendor/code.gitea.io/sdk/gitea/repo_file_ext.go create mode 100644 vendor/code.gitea.io/sdk/gitea/repo_git_notes.go create mode 100644 vendor/code.gitea.io/sdk/gitea/repo_label.go create mode 100644 vendor/code.gitea.io/sdk/gitea/repo_wiki.go create mode 100644 vendor/code.gitea.io/sdk/gitea/user_block.go create mode 100644 vendor/code.gitea.io/sdk/gitea/user_ext.go create mode 100644 vendor/code.gitea.io/sdk/gitea/user_social.go diff --git a/go.mod b/go.mod index 54298f948bf..6bc37d859e6 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( ) require ( - code.gitea.io/sdk/gitea v0.21.0 + code.gitea.io/sdk/gitea v0.23.2 github.com/go-jose/go-jose/v3 v3.0.4 github.com/goccy/kpoward v0.1.0 github.com/google/cel-go v0.27.0 @@ -63,7 +63,7 @@ require ( cloud.google.com/go/kms v1.23.2 // indirect cloud.google.com/go/longrunning v0.6.7 // indirect fortio.org/safecast v1.2.0 // indirect - github.com/42wim/httpsig v1.2.2 // indirect + github.com/42wim/httpsig v1.2.3 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.2 // indirect diff --git a/go.sum b/go.sum index 1b85bb6f049..8ace4991397 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -code.gitea.io/sdk/gitea v0.21.0 h1:69n6oz6kEVHRo1+APQQyizkhrZrLsTLXey9142pfkD4= -code.gitea.io/sdk/gitea v0.21.0/go.mod h1:tnBjVhuKJCn8ibdyyhvUyxrR1Ca2KHEoTWoukNhXQPA= +code.gitea.io/sdk/gitea v0.23.2 h1:iJB1FDmLegwfwjX8gotBDHdPSbk/ZR8V9VmEJaVsJYg= +code.gitea.io/sdk/gitea v0.23.2/go.mod h1:yyF5+GhljqvA30sRDreoyHILruNiy4ASufugzYg0VHM= contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d h1:LblfooH1lKOpp1hIhukktmSAxFkqMPFk9KR6iZ0MJNI= contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d/go.mod h1:IshRmMJBhDfFj5Y67nVhMYTTIze91RUeT73ipWKs/GY= contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= @@ -63,8 +63,8 @@ contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= fortio.org/safecast v1.2.0 h1:ckQJNenMJHycqPsi/QrzA4EUX5WQkyd+hGO4mxt/a8w= fortio.org/safecast v1.2.0/go.mod h1:xZmcPk3vi4kuUFf+tq4SvnlVdwViqf6ZSZl91Jr9Jdg= -github.com/42wim/httpsig v1.2.2 h1:ofAYoHUNs/MJOLqQ8hIxeyz2QxOz8qdSVvp3PX/oPgA= -github.com/42wim/httpsig v1.2.2/go.mod h1:P/UYo7ytNBFwc+dg35IubuAUIs8zj5zzFIgUCEl55WY= +github.com/42wim/httpsig v1.2.3 h1:xb0YyWhkYj57SPtfSttIobJUPJZB9as1nsfo7KWVcEs= +github.com/42wim/httpsig v1.2.3/go.mod h1:nZq9OlYKDrUBhptd77IHx4/sZZD+IxTBADvAPI9G/EM= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= diff --git a/vendor/code.gitea.io/sdk/gitea/action_run.go b/vendor/code.gitea.io/sdk/gitea/action_run.go new file mode 100644 index 00000000000..eb3b6697e1c --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/action_run.go @@ -0,0 +1,279 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "fmt" + "net/url" + "time" +) + +// ActionTask represents a workflow run task (from /actions/tasks endpoint) +// This is the format returned by older Gitea versions +type ActionTask struct { + ID int64 `json:"id"` + Name string `json:"name"` // Workflow name + HeadBranch string `json:"head_branch"` + HeadSHA string `json:"head_sha"` + RunNumber int64 `json:"run_number"` + Event string `json:"event"` + DisplayTitle string `json:"display_title"` // PR title or commit message + Status string `json:"status"` + WorkflowID string `json:"workflow_id"` // e.g. "ci.yml" + URL string `json:"url"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + RunStartedAt time.Time `json:"run_started_at"` +} + +// ActionTaskResponse holds the response for listing action tasks +type ActionTaskResponse struct { + TotalCount int64 `json:"total_count"` + WorkflowRuns []*ActionTask `json:"workflow_runs"` +} + +// ActionWorkflowRun represents a workflow run (from /actions/runs endpoint) +// This is the format returned by newer Gitea versions +type ActionWorkflowRun struct { + ID int64 `json:"id"` + DisplayTitle string `json:"display_title"` + Event string `json:"event"` + HeadBranch string `json:"head_branch"` + HeadSha string `json:"head_sha"` + Path string `json:"path"` + RunAttempt int64 `json:"run_attempt"` + RunNumber int64 `json:"run_number"` + Status string `json:"status"` + Conclusion string `json:"conclusion"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + StartedAt time.Time `json:"started_at"` + CompletedAt time.Time `json:"completed_at"` + Actor *User `json:"actor"` + TriggerActor *User `json:"trigger_actor"` + Repository *Repository `json:"repository"` + HeadRepository *Repository `json:"head_repository"` + RepositoryID int64 `json:"repository_id"` +} + +// ActionWorkflowRunsResponse holds the response for listing workflow runs +type ActionWorkflowRunsResponse struct { + TotalCount int64 `json:"total_count"` + WorkflowRuns []*ActionWorkflowRun `json:"workflow_runs"` +} + +// ActionWorkflowJob represents a job within a workflow run +type ActionWorkflowJob struct { + ID int64 `json:"id"` + RunID int64 `json:"run_id"` + RunURL string `json:"run_url"` + RunAttempt int64 `json:"run_attempt"` + Name string `json:"name"` + HeadBranch string `json:"head_branch"` + HeadSha string `json:"head_sha"` + Status string `json:"status"` + Conclusion string `json:"conclusion"` + URL string `json:"url"` + HTMLURL string `json:"html_url"` + CreatedAt time.Time `json:"created_at"` + StartedAt time.Time `json:"started_at"` + CompletedAt time.Time `json:"completed_at"` + RunnerID int64 `json:"runner_id"` + RunnerName string `json:"runner_name"` + Labels []string `json:"labels"` + Steps []*ActionWorkflowStep `json:"steps"` +} + +// ActionWorkflowJobsResponse holds the response for listing workflow jobs +type ActionWorkflowJobsResponse struct { + TotalCount int64 `json:"total_count"` + Jobs []*ActionWorkflowJob `json:"jobs"` +} + +// ActionWorkflowStep represents a step within a job +type ActionWorkflowStep struct { + Name string `json:"name"` + Number int64 `json:"number"` + Status string `json:"status"` + Conclusion string `json:"conclusion"` + StartedAt time.Time `json:"started_at"` + CompletedAt time.Time `json:"completed_at"` +} + +// ListRepoActionRunsOptions options for listing repository action runs +type ListRepoActionRunsOptions struct { + ListOptions + Branch string // Filter by branch + Event string // Filter by triggering event + Status string // Filter by status (pending, queued, in_progress, failure, success, skipped) + Actor string // Filter by actor (user who triggered the run) + HeadSHA string // Filter by the SHA of the head commit +} + +// QueryEncode encodes the options to URL query parameters +func (opt *ListRepoActionRunsOptions) QueryEncode() string { + query := opt.getURLQuery() + if opt.Branch != "" { + query.Add("branch", opt.Branch) + } + if opt.Event != "" { + query.Add("event", opt.Event) + } + if opt.Status != "" { + query.Add("status", opt.Status) + } + if opt.Actor != "" { + query.Add("actor", opt.Actor) + } + if opt.HeadSHA != "" { + query.Add("head_sha", opt.HeadSHA) + } + return query.Encode() +} + +// ListRepoActionJobsOptions options for listing repository action jobs +type ListRepoActionJobsOptions struct { + ListOptions + Status string // Filter by status (pending, queued, in_progress, failure, success, skipped) +} + +// QueryEncode encodes the options to URL query parameters +func (opt *ListRepoActionJobsOptions) QueryEncode() string { + query := opt.getURLQuery() + if opt.Status != "" { + query.Add("status", opt.Status) + } + return query.Encode() +} + +// ListRepoActionRuns lists workflow runs for a repository. +// Requires Gitea 1.25.0 or later. For older versions, use ListRepoActionTasks. +func (c *Client) ListRepoActionRuns(owner, repo string, opt ListRepoActionRunsOptions) (*ActionWorkflowRunsResponse, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_25_0); err != nil { + return nil, nil, err + } + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + opt.setDefaults() + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/actions/runs", owner, repo)) + link.RawQuery = opt.QueryEncode() + + resp := new(ActionWorkflowRunsResponse) + response, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, resp) + return resp, response, err +} + +// GetRepoActionRun gets a single workflow run. +// Requires Gitea 1.25.0 or later. +func (c *Client) GetRepoActionRun(owner, repo string, runID int64) (*ActionWorkflowRun, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_25_0); err != nil { + return nil, nil, err + } + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + + run := new(ActionWorkflowRun) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/actions/runs/%d", owner, repo, runID), jsonHeader, nil, run) + return run, resp, err +} + +// ListRepoActionRunJobs lists jobs for a workflow run. +// Requires Gitea 1.25.0 or later. +func (c *Client) ListRepoActionRunJobs(owner, repo string, runID int64, opt ListRepoActionJobsOptions) (*ActionWorkflowJobsResponse, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_25_0); err != nil { + return nil, nil, err + } + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + opt.setDefaults() + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/actions/runs/%d/jobs", owner, repo, runID)) + link.RawQuery = opt.QueryEncode() + + resp := new(ActionWorkflowJobsResponse) + response, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, resp) + return resp, response, err +} + +// ListRepoActionJobs lists all jobs for a repository. +// Requires Gitea 1.25.0 or later. +func (c *Client) ListRepoActionJobs(owner, repo string, opt ListRepoActionJobsOptions) (*ActionWorkflowJobsResponse, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_25_0); err != nil { + return nil, nil, err + } + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + opt.setDefaults() + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/actions/jobs", owner, repo)) + link.RawQuery = opt.QueryEncode() + + resp := new(ActionWorkflowJobsResponse) + response, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, resp) + return resp, response, err +} + +// GetRepoActionJob gets a single job. +// Requires Gitea 1.25.0 or later. +func (c *Client) GetRepoActionJob(owner, repo string, jobID int64) (*ActionWorkflowJob, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_25_0); err != nil { + return nil, nil, err + } + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + + job := new(ActionWorkflowJob) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/actions/jobs/%d", owner, repo, jobID), jsonHeader, nil, job) + return job, resp, err +} + +// GetRepoActionJobLogs gets the logs for a specific job. +// Requires Gitea 1.25.0 or later. +func (c *Client) GetRepoActionJobLogs(owner, repo string, jobID int64) ([]byte, *Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_25_0); err != nil { + return nil, nil, err + } + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + + return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/actions/jobs/%d/logs", owner, repo, jobID), nil, nil) +} + +// ListRepoActionTasks lists workflow tasks for a repository (Gitea 1.24.x and earlier) +// Use this for older Gitea versions that don't have /actions/runs endpoint +func (c *Client) ListRepoActionTasks(owner, repo string, opt ListOptions) (*ActionTaskResponse, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + opt.setDefaults() + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/actions/tasks", owner, repo)) + link.RawQuery = opt.getURLQuery().Encode() + + resp := new(ActionTaskResponse) + response, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, resp) + return resp, response, err +} + +// DeleteRepoActionRun deletes a workflow run. +// Requires Gitea 1.25.0 or later. +func (c *Client) DeleteRepoActionRun(owner, repo string, runID int64) (*Response, error) { + if err := c.checkServerVersionGreaterThanOrEqual(version1_25_0); err != nil { + return nil, err + } + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/actions/runs/%d", owner, repo, runID), jsonHeader, nil) + return resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/activity.go b/vendor/code.gitea.io/sdk/gitea/activity.go new file mode 100644 index 00000000000..01dbf9f464d --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/activity.go @@ -0,0 +1,24 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import "time" + +// Activity represents a user or organization activity +type Activity struct { + ID int64 `json:"id"` + ActUserID int64 `json:"act_user_id"` + ActUser *User `json:"act_user"` + OpType string `json:"op_type"` + Content string `json:"content"` + RepoID int64 `json:"repo_id"` + Repo *Repository `json:"repo"` + CommentID int64 `json:"comment_id"` + Comment *Comment `json:"comment"` + RefName string `json:"ref_name"` + IsPrivate bool `json:"is_private"` + UserID int64 `json:"user_id"` + Created time.Time `json:"created"` +} diff --git a/vendor/code.gitea.io/sdk/gitea/activitypub.go b/vendor/code.gitea.io/sdk/gitea/activitypub.go new file mode 100644 index 00000000000..82c278771c3 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/activitypub.go @@ -0,0 +1,56 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" +) + +// ActivityPub represents an ActivityPub object +type ActivityPub map[string]interface{} + +// GetActivityPubPerson returns the Person actor for a user +func (c *Client) GetActivityPubPerson(userID int64) (ActivityPub, *Response, error) { + result := make(ActivityPub) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/activitypub/user-id/%d", userID), + jsonHeader, nil, &result) + return result, resp, err +} + +// SendActivityPubInbox sends an ActivityPub message to a user's inbox +func (c *Client) SendActivityPubInbox(userID int64, activity ActivityPub) (*Response, error) { + body, err := json.Marshal(activity) + if err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("POST", + fmt.Sprintf("/activitypub/user-id/%d/inbox", userID), + jsonHeader, bytes.NewReader(body)) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// GetActivityPubPersonResponse returns the raw ActivityPub Person response +func (c *Client) GetActivityPubPersonResponse(userID int64) ([]byte, *Response, error) { + resp, err := c.doRequest("GET", + fmt.Sprintf("/activitypub/user-id/%d", userID), + jsonHeader, nil) + if err != nil { + return nil, resp, err + } + defer func() { _ = resp.Body.Close() }() + data, err := io.ReadAll(resp.Body) + return data, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/admin_badges.go b/vendor/code.gitea.io/sdk/gitea/admin_badges.go new file mode 100644 index 00000000000..f9f2cc12e3d --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/admin_badges.go @@ -0,0 +1,79 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" +) + +// Badge represents a user badge +type Badge struct { + ID int64 `json:"id"` + Slug string `json:"slug"` + Description string `json:"description"` + ImageURL string `json:"image_url"` +} + +// ListUserBadges lists badges of a user +func (c *Client) ListUserBadges(username string) ([]*Badge, *Response, error) { + if err := escapeValidatePathSegments(&username); err != nil { + return nil, nil, err + } + badges := make([]*Badge, 0, 5) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/admin/users/%s/badges", username), + jsonHeader, nil, &badges) + return badges, resp, err +} + +// UserBadgeOption represents options for adding badges to a user +type UserBadgeOption struct { + BadgeSlugs []string `json:"badge_slugs"` +} + +// AddUserBadges adds badges to a user by their slugs +func (c *Client) AddUserBadges(username string, opt UserBadgeOption) (*Response, error) { + if err := escapeValidatePathSegments(&username); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("POST", + fmt.Sprintf("/admin/users/%s/badges", username), + jsonHeader, bytes.NewReader(body)) + if err != nil { + return resp, err + } + if status != http.StatusNoContent && status != http.StatusCreated { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// DeleteUserBadge deletes a user's badge +func (c *Client) DeleteUserBadge(username string, opt UserBadgeOption) (*Response, error) { + if err := escapeValidatePathSegments(&username); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("DELETE", + fmt.Sprintf("/admin/users/%s/badges", username), + jsonHeader, bytes.NewReader(body)) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} diff --git a/vendor/code.gitea.io/sdk/gitea/admin_cron.go b/vendor/code.gitea.io/sdk/gitea/admin_cron.go index 84316da2b14..de05ccb38fa 100644 --- a/vendor/code.gitea.io/sdk/gitea/admin_cron.go +++ b/vendor/code.gitea.io/sdk/gitea/admin_cron.go @@ -42,6 +42,5 @@ func (c *Client) RunCronTasks(task string) (*Response, error) { if err := escapeValidatePathSegments(&task); err != nil { return nil, err } - _, resp, err := c.getResponse("POST", fmt.Sprintf("/admin/cron/%s", task), jsonHeader, nil) - return resp, err + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/admin/cron/%s", task), jsonHeader, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/admin_email.go b/vendor/code.gitea.io/sdk/gitea/admin_email.go new file mode 100644 index 00000000000..063adb41cd9 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/admin_email.go @@ -0,0 +1,48 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "net/url" +) + +// ListAdminEmailsOptions options for listing all emails +type ListAdminEmailsOptions struct { + ListOptions +} + +// ListAdminEmails lists all email addresses +func (c *Client) ListAdminEmails(opt ListAdminEmailsOptions) ([]*Email, *Response, error) { + opt.setDefaults() + + link, _ := url.Parse("/admin/emails") + link.RawQuery = opt.getURLQuery().Encode() + + emails := make([]*Email, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &emails) + return emails, resp, err +} + +// SearchAdminEmailsOptions options for searching emails +type SearchAdminEmailsOptions struct { + ListOptions + Query string `json:"q,omitempty"` +} + +// SearchAdminEmails searches email addresses +func (c *Client) SearchAdminEmails(opt SearchAdminEmailsOptions) ([]*Email, *Response, error) { + opt.setDefaults() + + link, _ := url.Parse("/admin/emails/search") + query := opt.getURLQuery() + if opt.Query != "" { + query.Add("q", opt.Query) + } + link.RawQuery = query.Encode() + + emails := make([]*Email, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &emails) + return emails, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/admin_hooks.go b/vendor/code.gitea.io/sdk/gitea/admin_hooks.go new file mode 100644 index 00000000000..aff01e73e51 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/admin_hooks.go @@ -0,0 +1,80 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/url" +) + +// ListAdminHooksOptions options for listing admin hooks +type ListAdminHooksOptions struct { + ListOptions + // Type of hooks to list: system, default, or all + Type string `json:"type,omitempty"` +} + +// ListAdminHooks lists all system webhooks +func (c *Client) ListAdminHooks(opt ListAdminHooksOptions) ([]*Hook, *Response, error) { + opt.setDefaults() + + link, _ := url.Parse("/admin/hooks") + query := opt.getURLQuery() + if opt.Type != "" { + query.Add("type", opt.Type) + } + link.RawQuery = query.Encode() + + hooks := make([]*Hook, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &hooks) + return hooks, resp, err +} + +// CreateAdminHook creates a system webhook +func (c *Client) CreateAdminHook(opt CreateHookOption) (*Hook, *Response, error) { + if err := opt.Validate(); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + hook := new(Hook) + resp, err := c.getParsedResponse("POST", "/admin/hooks", jsonHeader, bytes.NewReader(body), hook) + return hook, resp, err +} + +// GetAdminHook gets a system webhook by ID +func (c *Client) GetAdminHook(id int64) (*Hook, *Response, error) { + hook := new(Hook) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/hooks/%d", id), jsonHeader, nil, hook) + return hook, resp, err +} + +// EditAdminHook edits a system webhook +func (c *Client) EditAdminHook(id int64, opt EditHookOption) (*Hook, *Response, error) { + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + hook := new(Hook) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/admin/hooks/%d", id), jsonHeader, bytes.NewReader(body), hook) + return hook, resp, err +} + +// DeleteAdminHook deletes a system webhook +func (c *Client) DeleteAdminHook(id int64) (*Response, error) { + status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/admin/hooks/%d", id), jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} diff --git a/vendor/code.gitea.io/sdk/gitea/admin_repo.go b/vendor/code.gitea.io/sdk/gitea/admin_repo.go index 8666690cde7..6f8fe298d27 100644 --- a/vendor/code.gitea.io/sdk/gitea/admin_repo.go +++ b/vendor/code.gitea.io/sdk/gitea/admin_repo.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/json" "fmt" + "net/url" ) // AdminCreateRepo create a repo @@ -23,3 +24,45 @@ func (c *Client) AdminCreateRepo(user string, opt CreateRepoOption) (*Repository resp, err := c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/repos", user), jsonHeader, bytes.NewReader(body), repo) return repo, resp, err } + +// ListUnadoptedReposOptions options for listing unadopted repositories +type ListUnadoptedReposOptions struct { + ListOptions + Pattern string `json:"pattern,omitempty"` +} + +// ListUnadoptedRepos lists unadopted repositories +func (c *Client) ListUnadoptedRepos(opt ListUnadoptedReposOptions) ([]string, *Response, error) { + opt.setDefaults() + + link, _ := url.Parse("/admin/unadopted") + query := opt.getURLQuery() + if opt.Pattern != "" { + query.Add("pattern", opt.Pattern) + } + link.RawQuery = query.Encode() + + repos := make([]string, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &repos) + return repos, resp, err +} + +// AdoptUnadoptedRepo adopts an unadopted repository +func (c *Client) AdoptUnadoptedRepo(owner, repo string) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + return c.doRequestWithStatusHandle("POST", + fmt.Sprintf("/admin/unadopted/%s/%s", owner, repo), + jsonHeader, nil) +} + +// DeleteUnadoptedRepo deletes an unadopted repository +func (c *Client) DeleteUnadoptedRepo(owner, repo string) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + return c.doRequestWithStatusHandle("DELETE", + fmt.Sprintf("/admin/unadopted/%s/%s", owner, repo), + jsonHeader, nil) +} diff --git a/vendor/code.gitea.io/sdk/gitea/admin_user.go b/vendor/code.gitea.io/sdk/gitea/admin_user.go index 172f0645c9b..4741d2b4b7e 100644 --- a/vendor/code.gitea.io/sdk/gitea/admin_user.go +++ b/vendor/code.gitea.io/sdk/gitea/admin_user.go @@ -14,13 +14,63 @@ import ( // AdminListUsersOptions options for listing admin users type AdminListUsersOptions struct { ListOptions + SourceID int64 + LoginName string + Query string + Sort string // "name", "created", "updated", "id" + Order string // "asc", "desc" + Visibility string + IsActive *bool + IsAdmin *bool + IsRestricted *bool + Is2FAEnabled *bool + IsProhibitLogin *bool +} + +// QueryEncode turns options into querystring argument +func (opt *AdminListUsersOptions) QueryEncode() string { + query := opt.getURLQuery() + if opt.SourceID > 0 { + query.Add("source_id", fmt.Sprintf("%d", opt.SourceID)) + } + if opt.LoginName != "" { + query.Add("login_name", opt.LoginName) + } + if opt.Query != "" { + query.Add("q", opt.Query) + } + if opt.Sort != "" { + query.Add("sort", opt.Sort) + } + if opt.Order != "" { + query.Add("order", opt.Order) + } + if opt.Visibility != "" { + query.Add("visibility", opt.Visibility) + } + if opt.IsActive != nil { + query.Add("is_active", fmt.Sprintf("%t", *opt.IsActive)) + } + if opt.IsAdmin != nil { + query.Add("is_admin", fmt.Sprintf("%t", *opt.IsAdmin)) + } + if opt.IsRestricted != nil { + query.Add("is_restricted", fmt.Sprintf("%t", *opt.IsRestricted)) + } + if opt.Is2FAEnabled != nil { + query.Add("is_2fa_enabled", fmt.Sprintf("%t", *opt.Is2FAEnabled)) + } + if opt.IsProhibitLogin != nil { + query.Add("is_prohibit_login", fmt.Sprintf("%t", *opt.IsProhibitLogin)) + } + return query.Encode() } // AdminListUsers lists all users func (c *Client) AdminListUsers(opt AdminListUsersOptions) ([]*User, *Response, error) { opt.setDefaults() users := make([]*User, 0, opt.PageSize) - resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/users?%s", opt.getURLQuery().Encode()), nil, nil, &users) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/admin/users?%s", opt.QueryEncode()), nil, nil, &users) return users, resp, err } @@ -93,8 +143,7 @@ func (c *Client) AdminEditUser(user string, opt EditUserOption) (*Response, erro if err != nil { return nil, err } - _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body)) } // AdminDeleteUser delete one user according name @@ -102,8 +151,7 @@ func (c *Client) AdminDeleteUser(user string) (*Response, error) { if err := escapeValidatePathSegments(&user); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil) } // AdminCreateUserPublicKey adds a public key for the user @@ -125,6 +173,24 @@ func (c *Client) AdminDeleteUserPublicKey(user string, keyID int) (*Response, er if err := escapeValidatePathSegments(&user); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s/keys/%d", user, keyID), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/admin/users/%s/keys/%d", user, keyID), nil, nil) +} + +// RenameUserOption options for renaming a user +type RenameUserOption struct { + NewUsername string `json:"new_username"` +} + +// AdminRenameUser renames a user +func (c *Client) AdminRenameUser(username string, opt RenameUserOption) (*Response, error) { + if err := escapeValidatePathSegments(&username); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + return c.doRequestWithStatusHandle("POST", + fmt.Sprintf("/admin/users/%s/rename", username), + jsonHeader, bytes.NewReader(body)) } diff --git a/vendor/code.gitea.io/sdk/gitea/attachment.go b/vendor/code.gitea.io/sdk/gitea/attachment.go index c19a82c85d1..89c3a503bbe 100644 --- a/vendor/code.gitea.io/sdk/gitea/attachment.go +++ b/vendor/code.gitea.io/sdk/gitea/attachment.go @@ -106,6 +106,5 @@ func (c *Client) DeleteReleaseAttachment(user, repo string, release, id int64) ( if err := escapeValidatePathSegments(&user, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/client.go b/vendor/code.gitea.io/sdk/gitea/client.go index f45961a96d9..5bf19c32ec0 100644 --- a/vendor/code.gitea.io/sdk/gitea/client.go +++ b/vendor/code.gitea.io/sdk/gitea/client.go @@ -317,7 +317,12 @@ func (c *Client) getWebResponse(method, path string, body io.Reader) ([]byte, *R return nil, nil, err } - defer resp.Body.Close() + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil && err == nil { + err = closeErr + } + }() + data, err := io.ReadAll(resp.Body) if debug { fmt.Printf("Response: %v\n\n", resp) @@ -397,7 +402,12 @@ func statusCodeToErr(resp *Response) (body []byte, err error) { // // error: body will be read for details // - defer resp.Body.Close() + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil && err == nil { + err = closeErr + } + }() + data, err := io.ReadAll(resp.Body) if err != nil { return nil, fmt.Errorf("body read on HTTP error %d: %v", resp.StatusCode, err) @@ -410,7 +420,7 @@ func statusCodeToErr(resp *Response) (body []byte, err error) { // plain string, so we try to return a helpful error anyway path := resp.Request.URL.Path method := resp.Request.Method - return data, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method and '%s' body", resp.StatusCode, path, method, string(data)) + return data, fmt.Errorf("unknown API error: %d\nRequest: '%s' with '%s' method and '%s' body", resp.StatusCode, path, method, string(data)) } if msg, ok := errMap["message"]; ok { @@ -436,12 +446,36 @@ func (c *Client) getResponseReader(method, path string, header http.Header, body return resp.Body, resp, nil } +func (c *Client) doRequestWithStatusHandle(method, path string, header http.Header, body io.Reader) (*Response, error) { + resp, err := c.doRequest(method, path, header, body) + if err != nil { + return resp, err + } + + // check for errors + if _, err = statusCodeToErr(resp); err != nil { + // resp.Body has already been closed in statusCodeToErr + return resp, err + } + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil && err == nil { + err = closeErr + } + }() + + return resp, err +} + func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, *Response, error) { resp, err := c.doRequest(method, path, header, body) if err != nil { return nil, resp, err } - defer resp.Body.Close() + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil && err == nil { + err = closeErr + } + }() // check for errors data, err := statusCodeToErr(resp) @@ -471,7 +505,11 @@ func (c *Client) getStatusCode(method, path string, header http.Header, body io. if err != nil { return -1, resp, err } - defer resp.Body.Close() + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil && err == nil { + err = closeErr + } + }() return resp.StatusCode, resp, nil } diff --git a/vendor/code.gitea.io/sdk/gitea/git_hook.go b/vendor/code.gitea.io/sdk/gitea/git_hook.go index d8fbf71bd96..6b1f042dc95 100644 --- a/vendor/code.gitea.io/sdk/gitea/git_hook.go +++ b/vendor/code.gitea.io/sdk/gitea/git_hook.go @@ -57,8 +57,7 @@ func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) ( if err != nil { return nil, err } - _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), jsonHeader, bytes.NewReader(body)) } // DeleteRepoGitHook delete one Git hook from a repository @@ -66,6 +65,5 @@ func (c *Client) DeleteRepoGitHook(user, repo, id string) (*Response, error) { if err := escapeValidatePathSegments(&user, &repo, &id); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/hook.go b/vendor/code.gitea.io/sdk/gitea/hook.go index f91b60c37cc..a18635c14db 100644 --- a/vendor/code.gitea.io/sdk/gitea/hook.go +++ b/vendor/code.gitea.io/sdk/gitea/hook.go @@ -191,8 +191,7 @@ func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) (*Respons if err != nil { return nil, err } - _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PATCH", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), jsonHeader, bytes.NewReader(body)) } // EditMyHook modify one hook of the authenticated user, with hook id and options @@ -201,8 +200,7 @@ func (c *Client) EditMyHook(id int64, opt EditHookOption) (*Response, error) { if err != nil { return nil, err } - _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/user/hooks/%d", id), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PATCH", fmt.Sprintf("/user/hooks/%d", id), jsonHeader, bytes.NewReader(body)) } // EditRepoHook modify one hook of a repository, with hook id and options @@ -214,8 +212,7 @@ func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) ( if err != nil { return nil, err } - _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body)) } // DeleteOrgHook delete one hook from an organization, with hook id @@ -223,14 +220,12 @@ func (c *Client) DeleteOrgHook(org string, id int64) (*Response, error) { if err := escapeValidatePathSegments(&org); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil) } // DeleteMyHook delete one hook from the authenticated user, with hook id func (c *Client) DeleteMyHook(id int64) (*Response, error) { - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/hooks/%d", id), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/user/hooks/%d", id), nil, nil) } // DeleteRepoHook delete one hook from a repository, with hook id @@ -238,6 +233,5 @@ func (c *Client) DeleteRepoHook(user, repo string, id int64) (*Response, error) if err := escapeValidatePathSegments(&user, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/httpsign.go b/vendor/code.gitea.io/sdk/gitea/httpsign.go index 8aecb454f5d..9b76c6ce5de 100644 --- a/vendor/code.gitea.io/sdk/gitea/httpsign.go +++ b/vendor/code.gitea.io/sdk/gitea/httpsign.go @@ -147,7 +147,7 @@ func (c *Client) SignRequest(r *http.Request) error { if c.httpsigner.cert { // add our certificate to the headers to sign - pubkey, _ := ssh.ParsePublicKey(c.httpsigner.Signer.PublicKey().Marshal()) + pubkey, _ := ssh.ParsePublicKey(c.httpsigner.PublicKey().Marshal()) if cert, ok := pubkey.(*ssh.Certificate); ok { certString := base64.RawStdEncoding.EncodeToString(cert.Marshal()) r.Header.Add("x-ssh-certificate", certString) @@ -175,17 +175,26 @@ func (c *Client) SignRequest(r *http.Request) error { } // create a signer for the request and headers, the signature will be valid for 10 seconds - var ( - signer httpsig.SSHSigner - err error - ) + var err error // use legacyhttpsig to sign with RSA-SHA1 on older gitea releases if err = c.checkServerVersionGreaterThanOrEqual(version1_23_0); err != nil { - signer, _, err = legacyhttpsig.NewSSHSigner(c.httpsigner.Signer, httpsig.DigestSha512, headersToSign, legacyhttpsig.Signature, 10) - } else { - signer, _, err = httpsig.NewSSHSigner(c.httpsigner.Signer, httpsig.DigestSha512, headersToSign, httpsig.Signature, 10) + // Legacy signer + legacySigner, _, err := legacyhttpsig.NewSSHSigner(c.httpsigner, httpsig.DigestSha512, headersToSign, legacyhttpsig.Signature, 10) + if err != nil { + return fmt.Errorf("legacy httpsig.NewSSHSigner failed: %s", err) + } + + // sign the request, use the fingerprint if we don't have a certificate + keyID := "gitea" + if !c.httpsigner.cert { + keyID = ssh.FingerprintSHA256(c.httpsigner.PublicKey()) + } + + return legacySigner.SignRequest(keyID, r, contents) } + // Modern signer + modernSigner, _, err := httpsig.NewSSHSigner(c.httpsigner, httpsig.DigestSha512, headersToSign, httpsig.Signature, 10) if err != nil { return fmt.Errorf("httpsig.NewSSHSigner failed: %s", err) } @@ -193,15 +202,10 @@ func (c *Client) SignRequest(r *http.Request) error { // sign the request, use the fingerprint if we don't have a certificate keyID := "gitea" if !c.httpsigner.cert { - keyID = ssh.FingerprintSHA256(c.httpsigner.Signer.PublicKey()) + keyID = ssh.FingerprintSHA256(c.httpsigner.PublicKey()) } - err = signer.SignRequest(keyID, r, contents) - if err != nil { - return fmt.Errorf("httpsig.Signrequest failed: %s", err) - } - - return nil + return modernSigner.SignRequest(keyID, r, contents) } // findCertSigner returns the Signer containing a valid certificate diff --git a/vendor/code.gitea.io/sdk/gitea/issue.go b/vendor/code.gitea.io/sdk/gitea/issue.go index 603d23de2d4..5f5924fab39 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue.go +++ b/vendor/code.gitea.io/sdk/gitea/issue.go @@ -294,10 +294,9 @@ func (c *Client) DeleteIssue(user, repo string, id int64) (*Response, error) { if err := escapeValidatePathSegments(&user, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d", user, repo, id), nil, nil) - return resp, err } func (c *Client) issueBackwardsCompatibility(issue *Issue) { diff --git a/vendor/code.gitea.io/sdk/gitea/issue_comment.go b/vendor/code.gitea.io/sdk/gitea/issue_comment.go index 8131a6edc27..4510e89cc70 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_comment.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_comment.go @@ -149,6 +149,54 @@ func (c *Client) DeleteIssueComment(owner, repo string, commentID int64) (*Respo if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), nil, nil) +} + +// ListIssueCommentAttachments lists all attachments for a comment +func (c *Client) ListIssueCommentAttachments(owner, repo string, commentID int64) ([]*Attachment, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + attachments := make([]*Attachment, 0, 10) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/repos/%s/%s/issues/comments/%d/assets", owner, repo, commentID), + nil, nil, &attachments) + return attachments, resp, err +} + +// GetIssueCommentAttachment gets a comment attachment +func (c *Client) GetIssueCommentAttachment(owner, repo string, commentID, attachmentID int64) (*Attachment, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + attachment := new(Attachment) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/repos/%s/%s/issues/comments/%d/assets/%d", owner, repo, commentID, attachmentID), + nil, nil, &attachment) + return attachment, resp, err +} + +// EditIssueCommentAttachment updates a comment attachment +func (c *Client) EditIssueCommentAttachment(owner, repo string, commentID, attachmentID int64, form EditAttachmentOptions) (*Attachment, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&form) + if err != nil { + return nil, nil, err + } + attachment := new(Attachment) + resp, err := c.getParsedResponse("PATCH", + fmt.Sprintf("/repos/%s/%s/issues/comments/%d/assets/%d", owner, repo, commentID, attachmentID), + jsonHeader, bytes.NewReader(body), attachment) + return attachment, resp, err +} + +// DeleteIssueCommentAttachment deletes a comment attachment +func (c *Client) DeleteIssueCommentAttachment(owner, repo string, commentID, attachmentID int64) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + return c.doRequestWithStatusHandle("DELETE", + fmt.Sprintf("/repos/%s/%s/issues/comments/%d/assets/%d", owner, repo, commentID, attachmentID), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_ext.go b/vendor/code.gitea.io/sdk/gitea/issue_ext.go new file mode 100644 index 00000000000..78c58d5b905 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/issue_ext.go @@ -0,0 +1,191 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/url" + "time" +) + +// IssueBlockedBy represents an issue that blocks another issue +type IssueBlockedBy struct { + Index int64 `json:"index"` + Title string `json:"title"` + State string `json:"state"` + CreatedAt time.Time `json:"created_at"` +} + +// ListIssueBlocksOptions options for listing issue blocks +type ListIssueBlocksOptions struct { + ListOptions +} + +// ListIssueBlocks lists issues that are blocked by the specified issue with pagination +func (c *Client) ListIssueBlocks(owner, repo string, index int64, opt ListIssueBlocksOptions) ([]*Issue, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/blocks", owner, repo, index)) + opt.setDefaults() + link.RawQuery = opt.getURLQuery().Encode() + issues := make([]*Issue, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues) + return issues, resp, err +} + +// IssueMeta represents issue reference for blocking/dependency operations +type IssueMeta struct { + Index int64 `json:"index"` +} + +// CreateIssueBlocking blocks an issue with another issue +func (c *Client) CreateIssueBlocking(owner, repo string, index int64, opt IssueMeta) (*Issue, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + issue := new(Issue) + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/issues/%d/blocks", owner, repo, index), + jsonHeader, bytes.NewReader(body), &issue) + return issue, resp, err +} + +// RemoveIssueBlocking removes an issue block +func (c *Client) RemoveIssueBlocking(owner, repo string, index int64, opt IssueMeta) (*Issue, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + issue := new(Issue) + resp, err := c.getParsedResponse("DELETE", + fmt.Sprintf("/repos/%s/%s/issues/%d/blocks", owner, repo, index), + jsonHeader, bytes.NewReader(body), &issue) + return issue, resp, err +} + +// ListIssueDependenciesOptions options for listing issue dependencies +type ListIssueDependenciesOptions struct { + ListOptions +} + +// ListIssueDependencies lists issues that block the specified issue (its dependencies) with pagination +func (c *Client) ListIssueDependencies(owner, repo string, index int64, opt ListIssueDependenciesOptions) ([]*Issue, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/dependencies", owner, repo, index)) + opt.setDefaults() + link.RawQuery = opt.getURLQuery().Encode() + issues := make([]*Issue, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues) + return issues, resp, err +} + +// CreateIssueDependency creates a new issue dependency +func (c *Client) CreateIssueDependency(owner, repo string, index int64, opt IssueMeta) (*Issue, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + issue := new(Issue) + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/issues/%d/dependencies", owner, repo, index), + jsonHeader, bytes.NewReader(body), &issue) + return issue, resp, err +} + +// RemoveIssueDependency removes an issue dependency +func (c *Client) RemoveIssueDependency(owner, repo string, index int64, opt IssueMeta) (*Issue, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + issue := new(Issue) + resp, err := c.getParsedResponse("DELETE", + fmt.Sprintf("/repos/%s/%s/issues/%d/dependencies", owner, repo, index), + jsonHeader, bytes.NewReader(body), &issue) + return issue, resp, err +} + +// LockIssueOption represents options for locking an issue +type LockIssueOption struct { + LockReason string `json:"lock_reason"` +} + +// LockIssue locks an issue +func (c *Client) LockIssue(owner, repo string, index int64, opt LockIssueOption) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("PUT", + fmt.Sprintf("/repos/%s/%s/issues/%d/lock", owner, repo, index), + jsonHeader, bytes.NewReader(body)) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// UnlockIssue unlocks an issue +func (c *Client) UnlockIssue(owner, repo string, index int64) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("DELETE", + fmt.Sprintf("/repos/%s/%s/issues/%d/lock", owner, repo, index), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// EditDeadlineOption represents options for updating issue deadline +type EditDeadlineOption struct { + Deadline *time.Time `json:"due_date"` +} + +// UpdateIssueDeadline updates an issue's deadline +func (c *Client) UpdateIssueDeadline(owner, repo string, index int64, opt EditDeadlineOption) (*Issue, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + issue := new(Issue) + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/issues/%d/deadline", owner, repo, index), + jsonHeader, bytes.NewReader(body), &issue) + return issue, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/issue_label.go b/vendor/code.gitea.io/sdk/gitea/issue_label.go index f343ee5ef6a..1868cd06953 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_label.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_label.go @@ -8,145 +8,8 @@ import ( "bytes" "encoding/json" "fmt" - "regexp" - "strings" ) -// Label a label to an issue or a pr -type Label struct { - ID int64 `json:"id"` - Name string `json:"name"` - // example: 00aabb - Color string `json:"color"` - Description string `json:"description"` - URL string `json:"url"` -} - -// ListLabelsOptions options for listing repository's labels -type ListLabelsOptions struct { - ListOptions -} - -// ListRepoLabels list labels of one repository -func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, *Response, error) { - if err := escapeValidatePathSegments(&owner, &repo); err != nil { - return nil, nil, err - } - opt.setDefaults() - labels := make([]*Label, 0, opt.PageSize) - resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels) - return labels, resp, err -} - -// GetRepoLabel get one label of repository by repo it -func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, *Response, error) { - if err := escapeValidatePathSegments(&owner, &repo); err != nil { - return nil, nil, err - } - label := new(Label) - resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label) - return label, resp, err -} - -// CreateLabelOption options for creating a label -type CreateLabelOption struct { - Name string `json:"name"` - // example: #00aabb - Color string `json:"color"` - Description string `json:"description"` -} - -// Validate the CreateLabelOption struct -func (opt CreateLabelOption) Validate() error { - aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", opt.Color) - if err != nil { - return err - } - if !aw { - return fmt.Errorf("invalid color format") - } - if len(strings.TrimSpace(opt.Name)) == 0 { - return fmt.Errorf("empty name not allowed") - } - return nil -} - -// CreateLabel create one label of repository -func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, *Response, error) { - if err := escapeValidatePathSegments(&owner, &repo); err != nil { - return nil, nil, err - } - if err := opt.Validate(); err != nil { - return nil, nil, err - } - if len(opt.Color) == 6 { - if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { - opt.Color = "#" + opt.Color - } - } - body, err := json.Marshal(&opt) - if err != nil { - return nil, nil, err - } - label := new(Label) - resp, err := c.getParsedResponse("POST", - fmt.Sprintf("/repos/%s/%s/labels", owner, repo), - jsonHeader, bytes.NewReader(body), label) - return label, resp, err -} - -// EditLabelOption options for editing a label -type EditLabelOption struct { - Name *string `json:"name"` - Color *string `json:"color"` - Description *string `json:"description"` -} - -// Validate the EditLabelOption struct -func (opt EditLabelOption) Validate() error { - if opt.Color != nil { - aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", *opt.Color) - if err != nil { - return err - } - if !aw { - return fmt.Errorf("invalid color format") - } - } - if opt.Name != nil { - if len(strings.TrimSpace(*opt.Name)) == 0 { - return fmt.Errorf("empty name not allowed") - } - } - return nil -} - -// EditLabel modify one label with options -func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, *Response, error) { - if err := escapeValidatePathSegments(&owner, &repo); err != nil { - return nil, nil, err - } - if err := opt.Validate(); err != nil { - return nil, nil, err - } - body, err := json.Marshal(&opt) - if err != nil { - return nil, nil, err - } - label := new(Label) - resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), label) - return label, resp, err -} - -// DeleteLabel delete one label of repository by id -func (c *Client) DeleteLabel(owner, repo string, id int64) (*Response, error) { - if err := escapeValidatePathSegments(&owner, &repo); err != nil { - return nil, err - } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil) - return resp, err -} - // GetIssueLabels get labels of one issue via issue id func (c *Client) GetIssueLabels(owner, repo string, index int64, opts ListLabelsOptions) ([]*Label, *Response, error) { if err := escapeValidatePathSegments(&owner, &repo); err != nil { @@ -197,8 +60,7 @@ func (c *Client) DeleteIssueLabel(owner, repo string, index, label int64) (*Resp if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil) } // ClearIssueLabels delete all the labels of one issue. @@ -206,6 +68,5 @@ func (c *Client) ClearIssueLabels(owner, repo string, index int64) (*Response, e if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_milestone.go b/vendor/code.gitea.io/sdk/gitea/issue_milestone.go index 4e0d79a9f93..87fd4936984 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_milestone.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_milestone.go @@ -192,8 +192,7 @@ func (c *Client) DeleteMilestone(owner, repo string, id int64) (*Response, error if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil) } // DeleteMilestoneByName delete one milestone by name @@ -209,8 +208,7 @@ func (c *Client) DeleteMilestoneByName(owner, repo, name string) (*Response, err if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil) } // resolveMilestoneByName is a fallback method to find milestone id by name diff --git a/vendor/code.gitea.io/sdk/gitea/issue_pin.go b/vendor/code.gitea.io/sdk/gitea/issue_pin.go new file mode 100644 index 00000000000..bd5d426f5a3 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/issue_pin.go @@ -0,0 +1,73 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "fmt" + "net/http" +) + +// ListRepoPinnedIssues lists a repo's pinned issues +func (c *Client) ListRepoPinnedIssues(owner, repo string) ([]*Issue, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + issues := make([]*Issue, 0, 5) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/repos/%s/%s/issues/pinned", owner, repo), + jsonHeader, nil, &issues) + return issues, resp, err +} + +// PinIssue pins an issue +func (c *Client) PinIssue(owner, repo string, index int64) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("POST", + fmt.Sprintf("/repos/%s/%s/issues/%d/pin", owner, repo, index), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// UnpinIssue unpins an issue +func (c *Client) UnpinIssue(owner, repo string, index int64) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("DELETE", + fmt.Sprintf("/repos/%s/%s/issues/%d/pin", owner, repo, index), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// MoveIssuePin moves a pinned issue to the given position +func (c *Client) MoveIssuePin(owner, repo string, index, position int64) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("PATCH", + fmt.Sprintf("/repos/%s/%s/issues/%d/pin/%d", owner, repo, index, position), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} diff --git a/vendor/code.gitea.io/sdk/gitea/issue_reaction.go b/vendor/code.gitea.io/sdk/gitea/issue_reaction.go index b45c0666466..ed7eb211d9c 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_reaction.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_reaction.go @@ -8,6 +8,7 @@ import ( "bytes" "encoding/json" "fmt" + "net/url" "time" ) @@ -18,13 +19,28 @@ type Reaction struct { Created time.Time `json:"created_at"` } +// ListIssueReactionsOptions options for listing issue reactions +type ListIssueReactionsOptions struct { + ListOptions +} + // GetIssueReactions get a list reactions of an issue +// +// Deprecated: Use ListIssueReactions instead, which supports pagination. func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction, *Response, error) { + return c.ListIssueReactions(owner, repo, index, ListIssueReactionsOptions{}) +} + +// ListIssueReactions get a list of reactions for an issue with pagination +func (c *Client) ListIssueReactions(owner, repo string, index int64, opt ListIssueReactionsOptions) ([]*Reaction, *Response, error) { if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, nil, err } - reactions := make([]*Reaction, 0, 10) - resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), nil, nil, &reactions) + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index)) + opt.setDefaults() + link.RawQuery = opt.getURLQuery().Encode() + reactions := make([]*Reaction, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &reactions) return reactions, resp, err } @@ -68,8 +84,7 @@ func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction s if err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), jsonHeader, bytes.NewReader(body)) } // PostIssueCommentReaction add a reaction to a comment of an issue @@ -97,8 +112,7 @@ func (c *Client) DeleteIssueCommentReaction(owner, repo string, commentID int64, if err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), jsonHeader, bytes.NewReader(body)) - return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go b/vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go index ebb0b8ae404..51d39f44c46 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go @@ -6,6 +6,7 @@ package gitea import ( "fmt" + "net/url" "time" ) @@ -20,10 +21,25 @@ type StopWatch struct { RepoName string `json:"repo_name"` } +// ListStopwatchesOptions options for listing stopwatches +type ListStopwatchesOptions struct { + ListOptions +} + // GetMyStopwatches list all stopwatches +// +// Deprecated: Use ListMyStopwatches instead, which supports pagination. func (c *Client) GetMyStopwatches() ([]*StopWatch, *Response, error) { - stopwatches := make([]*StopWatch, 0, 1) - resp, err := c.getParsedResponse("GET", "/user/stopwatches", nil, nil, &stopwatches) + return c.ListMyStopwatches(ListStopwatchesOptions{}) +} + +// ListMyStopwatches list all stopwatches with pagination +func (c *Client) ListMyStopwatches(opt ListStopwatchesOptions) ([]*StopWatch, *Response, error) { + link, _ := url.Parse("/user/stopwatches") + opt.setDefaults() + link.RawQuery = opt.getURLQuery().Encode() + stopwatches := make([]*StopWatch, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &stopwatches) return stopwatches, resp, err } @@ -32,8 +48,7 @@ func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) (*Respons if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/delete", owner, repo, index), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/delete", owner, repo, index), nil, nil) } // StartIssueStopWatch starts a stopwatch for an existing issue for a given @@ -42,8 +57,7 @@ func (c *Client) StartIssueStopWatch(owner, repo string, index int64) (*Response if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/start", owner, repo, index), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/start", owner, repo, index), nil, nil) } // StopIssueStopWatch stops an existing stopwatch for an issue in a given @@ -52,6 +66,5 @@ func (c *Client) StopIssueStopWatch(owner, repo string, index int64) (*Response, if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/stop", owner, repo, index), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/stop", owner, repo, index), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_subscription.go b/vendor/code.gitea.io/sdk/gitea/issue_subscription.go index 86853c71868..e19ca883b60 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_subscription.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_subscription.go @@ -7,15 +7,31 @@ package gitea import ( "fmt" "net/http" + "net/url" ) +// ListIssueSubscribersOptions options for listing issue subscribers +type ListIssueSubscribersOptions struct { + ListOptions +} + // GetIssueSubscribers get list of users who subscribed on an issue +// +// Deprecated: Use ListIssueSubscribers instead, which supports pagination. func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User, *Response, error) { + return c.ListIssueSubscribers(owner, repo, index, ListIssueSubscribersOptions{}) +} + +// ListIssueSubscribers get list of users who subscribed on an issue with pagination +func (c *Client) ListIssueSubscribers(owner, repo string, index int64, opt ListIssueSubscribersOptions) ([]*User, *Response, error) { if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, nil, err } - subscribers := make([]*User, 0, 10) - resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions", owner, repo, index), nil, nil, &subscribers) + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions", owner, repo, index)) + opt.setDefaults() + link.RawQuery = opt.getURLQuery().Encode() + subscribers := make([]*User, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &subscribers) return subscribers, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go b/vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go index c558516237d..286430d1d76 100644 --- a/vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go +++ b/vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go @@ -67,9 +67,19 @@ func (c *Client) ListRepoTrackedTimes(owner, repo string, opt ListTrackedTimesOp } // GetMyTrackedTimes list tracked times of the current user +// +// Deprecated: Use ListMyTrackedTimes instead, which supports pagination and filtering. func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, *Response, error) { - times := make([]*TrackedTime, 0, 10) - resp, err := c.getParsedResponse("GET", "/user/times", jsonHeader, nil, ×) + return c.ListMyTrackedTimes(ListTrackedTimesOptions{}) +} + +// ListMyTrackedTimes list tracked times of the current user with pagination and filtering +func (c *Client) ListMyTrackedTimes(opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) { + link, _ := url.Parse("/user/times") + opt.setDefaults() + link.RawQuery = opt.QueryEncode() + times := make([]*TrackedTime, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×) return times, resp, err } @@ -128,8 +138,7 @@ func (c *Client) ResetIssueTime(owner, repo string, index int64) (*Response, err if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), jsonHeader, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), jsonHeader, nil) } // DeleteTime delete a specific tracked time by id of a single issue for a given repository @@ -137,6 +146,5 @@ func (c *Client) DeleteTime(owner, repo string, index, timeID int64) (*Response, if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), jsonHeader, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), jsonHeader, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/miscellaneous.go b/vendor/code.gitea.io/sdk/gitea/miscellaneous.go new file mode 100644 index 00000000000..8cc82d54ace --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/miscellaneous.go @@ -0,0 +1,234 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "io" +) + +// GitignoreTemplateInfo represents a gitignore template +type GitignoreTemplateInfo struct { + Name string `json:"name"` + Source string `json:"source"` +} + +// LabelTemplate represents a label template +type LabelTemplate struct { + Name string `json:"name"` + Color string `json:"color"` + Description string `json:"description"` + Exclusive bool `json:"exclusive"` +} + +// LicensesTemplateListEntry represents a license in the list +type LicensesTemplateListEntry struct { + Key string `json:"key"` + Name string `json:"name"` + URL string `json:"url"` +} + +// LicenseTemplateInfo represents a license template +type LicenseTemplateInfo struct { + Key string `json:"key"` + Name string `json:"name"` + URL string `json:"url"` + Body string `json:"body"` + Implementation string `json:"implementation"` +} + +// MarkdownOption represents options for rendering markdown +type MarkdownOption struct { + Text string `json:"Text"` + Mode string `json:"Mode"` + Context string `json:"Context"` + Wiki bool `json:"Wiki"` +} + +// MarkupOption represents options for rendering markup +type MarkupOption struct { + Text string `json:"Text"` + Mode string `json:"Mode"` + Context string `json:"Context"` + FilePath string `json:"FilePath"` + Wiki bool `json:"Wiki"` +} + +// NodeInfo represents nodeinfo about the server +type NodeInfo struct { + Version string `json:"version"` + Software NodeInfoSoftware `json:"software"` + Protocols []string `json:"protocols"` + Services NodeInfoServices `json:"services"` + OpenRegistrations bool `json:"openRegistrations"` + Usage NodeInfoUsage `json:"usage"` + Metadata map[string]interface{} `json:"metadata"` +} + +// NodeInfoSoftware represents software information +type NodeInfoSoftware struct { + Name string `json:"name"` + Version string `json:"version"` + Repository string `json:"repository"` + Homepage string `json:"homepage"` +} + +// NodeInfoServices represents third party services +type NodeInfoServices struct { + Inbound []string `json:"inbound"` + Outbound []string `json:"outbound"` +} + +// NodeInfoUsage represents usage statistics +type NodeInfoUsage struct { + Users NodeInfoUsageUsers `json:"users"` + LocalPosts int64 `json:"localPosts"` + LocalComments int64 `json:"localComments"` +} + +// NodeInfoUsageUsers represents user statistics +type NodeInfoUsageUsers struct { + Total int64 `json:"total"` + ActiveHalfyear int64 `json:"activeHalfyear"` + ActiveMonth int64 `json:"activeMonth"` +} + +// ListGitignoresTemplates lists all gitignore templates +func (c *Client) ListGitignoresTemplates() ([]string, *Response, error) { + templates := make([]string, 0, 10) + resp, err := c.getParsedResponse("GET", "/gitignore/templates", jsonHeader, nil, &templates) + return templates, resp, err +} + +// GetGitignoreTemplateInfo gets information about a gitignore template +func (c *Client) GetGitignoreTemplateInfo(name string) (*GitignoreTemplateInfo, *Response, error) { + if err := escapeValidatePathSegments(&name); err != nil { + return nil, nil, err + } + template := new(GitignoreTemplateInfo) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/gitignore/templates/%s", name), + jsonHeader, nil, &template) + return template, resp, err +} + +// ListLabelTemplates lists all label templates +func (c *Client) ListLabelTemplates() ([]string, *Response, error) { + templates := make([]string, 0, 10) + resp, err := c.getParsedResponse("GET", "/label/templates", jsonHeader, nil, &templates) + return templates, resp, err +} + +// GetLabelTemplate gets all labels in a template +func (c *Client) GetLabelTemplate(name string) ([]*LabelTemplate, *Response, error) { + if err := escapeValidatePathSegments(&name); err != nil { + return nil, nil, err + } + labels := make([]*LabelTemplate, 0, 10) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/label/templates/%s", name), + jsonHeader, nil, &labels) + return labels, resp, err +} + +// ListLicenseTemplates lists all license templates +func (c *Client) ListLicenseTemplates() ([]*LicensesTemplateListEntry, *Response, error) { + licenses := make([]*LicensesTemplateListEntry, 0, 10) + resp, err := c.getParsedResponse("GET", "/licenses", jsonHeader, nil, &licenses) + return licenses, resp, err +} + +// GetLicenseTemplateInfo gets information about a license template +func (c *Client) GetLicenseTemplateInfo(name string) (*LicenseTemplateInfo, *Response, error) { + if err := escapeValidatePathSegments(&name); err != nil { + return nil, nil, err + } + license := new(LicenseTemplateInfo) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/licenses/%s", name), + jsonHeader, nil, &license) + return license, resp, err +} + +// RenderMarkdown renders a markdown document as HTML +func (c *Client) RenderMarkdown(opt MarkdownOption) (string, *Response, error) { + body, err := json.Marshal(&opt) + if err != nil { + return "", nil, err + } + + resp, err := c.doRequest("POST", "/markdown", jsonHeader, bytes.NewReader(body)) + if err != nil { + return "", resp, err + } + defer func() { _ = resp.Body.Close() }() + + html, err := io.ReadAll(resp.Body) + return string(html), resp, err +} + +// RenderMarkdownRaw renders raw markdown as HTML +func (c *Client) RenderMarkdownRaw(markdown string) (string, *Response, error) { + resp, err := c.doRequest("POST", "/markdown/raw", + map[string][]string{"Content-Type": {"text/plain"}}, + bytes.NewReader([]byte(markdown))) + if err != nil { + return "", resp, err + } + defer func() { _ = resp.Body.Close() }() + + html, err := io.ReadAll(resp.Body) + return string(html), resp, err +} + +// RenderMarkup renders a markup document as HTML +func (c *Client) RenderMarkup(opt MarkupOption) (string, *Response, error) { + body, err := json.Marshal(&opt) + if err != nil { + return "", nil, err + } + + resp, err := c.doRequest("POST", "/markup", jsonHeader, bytes.NewReader(body)) + if err != nil { + return "", resp, err + } + defer func() { _ = resp.Body.Close() }() + + html, err := io.ReadAll(resp.Body) + return string(html), resp, err +} + +// GetNodeInfo gets the nodeinfo of the Gitea application +func (c *Client) GetNodeInfo() (*NodeInfo, *Response, error) { + nodeInfo := new(NodeInfo) + resp, err := c.getParsedResponse("GET", "/nodeinfo", jsonHeader, nil, &nodeInfo) + return nodeInfo, resp, err +} + +// GetSigningKeyGPG gets the default GPG signing key +func (c *Client) GetSigningKeyGPG() (string, *Response, error) { + resp, err := c.doRequest("GET", "/signing-key.gpg", nil, nil) + if err != nil { + return "", resp, err + } + defer func() { _ = resp.Body.Close() }() + + key, err := io.ReadAll(resp.Body) + return string(key), resp, err +} + +// GetSigningKeySSH gets the default SSH signing key +func (c *Client) GetSigningKeySSH() (string, *Response, error) { + resp, err := c.doRequest("GET", "/signing-key.pub", nil, nil) + if err != nil { + return "", resp, err + } + defer func() { _ = resp.Body.Close() }() + + key, err := io.ReadAll(resp.Body) + return string(key), resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/notifications.go b/vendor/code.gitea.io/sdk/gitea/notifications.go index 640cc4daece..a75a41e9bc1 100644 --- a/vendor/code.gitea.io/sdk/gitea/notifications.go +++ b/vendor/code.gitea.io/sdk/gitea/notifications.go @@ -174,7 +174,7 @@ func (c *Client) ReadNotification(id int64, status ...NotifyStatus) (*Notificati resp, err := c.getParsedResponse("PATCH", link, nil, nil, thread) return thread, resp, err } - _, resp, err := c.getResponse("PATCH", link, nil, nil) + resp, err := c.doRequestWithStatusHandle("PATCH", link, nil, nil) return nil, resp, err } @@ -210,7 +210,7 @@ func (c *Client) ReadNotifications(opt MarkNotificationOptions) ([]*Notification resp, err := c.getParsedResponse("PUT", link.String(), nil, nil, &threads) return threads, resp, err } - _, resp, err := c.getResponse("PUT", link.String(), nil, nil) + resp, err := c.doRequestWithStatusHandle("PUT", link.String(), nil, nil) return nil, resp, err } @@ -252,6 +252,6 @@ func (c *Client) ReadRepoNotifications(owner, repo string, opt MarkNotificationO resp, err := c.getParsedResponse("PUT", link.String(), nil, nil, &threads) return threads, resp, err } - _, resp, err := c.getResponse("PUT", link.String(), nil, nil) + resp, err := c.doRequestWithStatusHandle("PUT", link.String(), nil, nil) return nil, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/oauth2.go b/vendor/code.gitea.io/sdk/gitea/oauth2.go index 86e25683876..7dfa14cac3b 100644 --- a/vendor/code.gitea.io/sdk/gitea/oauth2.go +++ b/vendor/code.gitea.io/sdk/gitea/oauth2.go @@ -88,6 +88,6 @@ func (c *Client) DeleteOauth2(oauth2id int64) (*Response, error) { if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil) + resp, err := c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil) return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/org.go b/vendor/code.gitea.io/sdk/gitea/org.go index 9df4d5318e5..59d143b892c 100644 --- a/vendor/code.gitea.io/sdk/gitea/org.go +++ b/vendor/code.gitea.io/sdk/gitea/org.go @@ -9,18 +9,23 @@ import ( "bytes" "encoding/json" "fmt" + "net/url" ) // Organization represents an organization type Organization struct { - ID int64 `json:"id"` - UserName string `json:"username"` - FullName string `json:"full_name"` - AvatarURL string `json:"avatar_url"` - Description string `json:"description"` - Website string `json:"website"` - Location string `json:"location"` - Visibility string `json:"visibility"` + ID int64 `json:"id"` + Name string `json:"name"` + // Deprecated: Use Name instead. See https://github.com/go-gitea/gitea/blob/main/modules/structs/org.go#L29 + UserName string `json:"username"` + FullName string `json:"full_name"` + Email string `json:"email"` + AvatarURL string `json:"avatar_url"` + Description string `json:"description"` + Website string `json:"website"` + Location string `json:"location"` + Visibility string `json:"visibility"` + RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"` } // VisibleType defines the visibility @@ -42,6 +47,16 @@ type ListOrgsOptions struct { ListOptions } +// ListOrgs lists all public organizations +func (c *Client) ListOrgs(opt ListOrgsOptions) ([]*Organization, *Response, error) { + opt.setDefaults() + link, _ := url.Parse("/orgs") + link.RawQuery = opt.getURLQuery().Encode() + orgs := make([]*Organization, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &orgs) + return orgs, resp, err +} + // ListMyOrgs list all of current user's organizations func (c *Client) ListMyOrgs(opt ListOrgsOptions) ([]*Organization, *Response, error) { opt.setDefaults() @@ -75,6 +90,7 @@ func (c *Client) GetOrg(orgname string) (*Organization, *Response, error) { type CreateOrgOption struct { Name string `json:"username"` FullName string `json:"full_name"` + Email string `json:"email"` Description string `json:"description"` Website string `json:"website"` Location string `json:"location"` @@ -114,11 +130,13 @@ func (c *Client) CreateOrg(opt CreateOrgOption) (*Organization, *Response, error // EditOrgOption options for editing an organization type EditOrgOption struct { - FullName string `json:"full_name"` - Description string `json:"description"` - Website string `json:"website"` - Location string `json:"location"` - Visibility VisibleType `json:"visibility"` + FullName string `json:"full_name"` + Email string `json:"email"` + Description string `json:"description"` + Website string `json:"website"` + Location string `json:"location"` + Visibility VisibleType `json:"visibility"` + RepoAdminChangeTeamAccess *bool `json:"repo_admin_change_team_access"` } // Validate the EditOrgOption struct @@ -141,8 +159,7 @@ func (c *Client) EditOrg(orgname string, opt EditOrgOption) (*Response, error) { if err != nil { return nil, err } - _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body)) } // DeleteOrg deletes an organization @@ -150,6 +167,5 @@ func (c *Client) DeleteOrg(orgname string) (*Response, error) { if err := escapeValidatePathSegments(&orgname); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/org_action.go b/vendor/code.gitea.io/sdk/gitea/org_action.go index 3ffa3f22de4..0dafa91445f 100644 --- a/vendor/code.gitea.io/sdk/gitea/org_action.go +++ b/vendor/code.gitea.io/sdk/gitea/org_action.go @@ -31,10 +31,152 @@ func (c *Client) ListOrgActionSecret(org string, opt ListOrgActionSecretOption) return secrets, resp, err } +type OrgActionVariable struct { + OwnerID int64 `json:"owner_id"` + RepoID int64 `json:"repo_id"` + Name string `json:"name"` + Data string `json:"data"` + Description string `json:"description"` +} + +// ListOrgActionVariableOption lists OrgActionVariable options +type ListOrgActionVariableOption struct { + ListOptions +} + +// ListOrgActionVariable lists an organization's action variables +func (c *Client) ListOrgActionVariable(org string, opt ListOrgActionVariableOption) ([]*OrgActionVariable, *Response, error) { + if err := escapeValidatePathSegments(&org); err != nil { + return nil, nil, err + } + opt.setDefaults() + variables := make([]*OrgActionVariable, 0, opt.PageSize) + + link, _ := url.Parse(fmt.Sprintf("/orgs/%s/actions/variables", org)) + link.RawQuery = opt.getURLQuery().Encode() + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &variables) + return variables, resp, err +} + +// GetOrgActionVariable gets a single organization's action variable by name +func (c *Client) GetOrgActionVariable(org, name string) (*OrgActionVariable, *Response, error) { + if err := escapeValidatePathSegments(&org, &name); err != nil { + return nil, nil, err + } + var variable OrgActionVariable + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/orgs/%s/actions/variables/%s", org, name), + jsonHeader, nil, &variable) + if err != nil { + return nil, resp, err + } + return &variable, resp, nil +} + +// CreateOrgActionVariableOption represents the options for creating an org action variable. +type CreateOrgActionVariableOption struct { + Name string `json:"name"` // Name is the name of the variable. + Value string `json:"value"` // Value is the value of the variable. + Description string `json:"description"` // Description is the description of the variable. +} + +// Validate checks if the CreateOrgActionVariableOption is valid. +func (opt *CreateOrgActionVariableOption) Validate() error { + if len(opt.Name) == 0 { + return fmt.Errorf("name required") + } + if len(opt.Name) > 30 { + return fmt.Errorf("name too long") + } + if len(opt.Value) == 0 { + return fmt.Errorf("value required") + } + return nil +} + +// CreateOrgActionVariable creates a variable for the specified organization in the Gitea Actions. +func (c *Client) CreateOrgActionVariable(org string, opt CreateOrgActionVariableOption) (*Response, error) { + if err := escapeValidatePathSegments(&org); err != nil { + return nil, err + } + if err := (&opt).Validate(); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + + status, resp, err := c.getStatusCode("POST", fmt.Sprintf("/orgs/%s/actions/variables/%s", org, opt.Name), jsonHeader, bytes.NewReader(body)) + if err != nil { + return nil, err + } + + switch status { + case http.StatusCreated: + return resp, nil + case http.StatusNoContent: + return resp, nil + case http.StatusNotFound: + return resp, fmt.Errorf("forbidden") + case http.StatusBadRequest: + return resp, fmt.Errorf("bad request") + default: + return resp, fmt.Errorf("unexpected Status: %d", status) + } +} + +// UpdateOrgActionVariableOption represents the options for updating an org action variable. +type UpdateOrgActionVariableOption struct { + Value string `json:"value"` // Value is the new value of the variable. + Description string `json:"description"` // Description is the new description of the variable. +} + +// Validate checks if the UpdateOrgActionVariableOption is valid. +func (opt *UpdateOrgActionVariableOption) Validate() error { + if len(opt.Value) == 0 { + return fmt.Errorf("value required") + } + return nil +} + +// UpdateOrgActionVariable updates a variable for the specified organization in the Gitea Actions. +func (c *Client) UpdateOrgActionVariable(org, name string, opt UpdateOrgActionVariableOption) (*Response, error) { + if err := escapeValidatePathSegments(&org, &name); err != nil { + return nil, err + } + if err := (&opt).Validate(); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + + status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/actions/variables/%s", org, name), jsonHeader, bytes.NewReader(body)) + if err != nil { + return nil, err + } + + switch status { + case http.StatusOK: + return resp, nil + case http.StatusNoContent: + return resp, nil + case http.StatusNotFound: + return resp, fmt.Errorf("forbidden") + case http.StatusBadRequest: + return resp, fmt.Errorf("bad request") + default: + return resp, fmt.Errorf("unexpected Status: %d", status) + } +} + // CreateSecretOption represents the options for creating a secret. type CreateSecretOption struct { - Name string `json:"name"` // Name is the name of the secret. - Data string `json:"data"` // Data is the data of the secret. + Name string `json:"name"` // Name is the name of the secret. + Data string `json:"data"` // Data is the data of the secret. + Description string `json:"description"` // Description is the description of the secret. } // Validate checks if the CreateSecretOption is valid. diff --git a/vendor/code.gitea.io/sdk/gitea/org_block.go b/vendor/code.gitea.io/sdk/gitea/org_block.go new file mode 100644 index 00000000000..4261ec89866 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/org_block.go @@ -0,0 +1,79 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "fmt" + "net/http" + "net/url" +) + +// ListOrgBlocksOptions options for listing organization blocks +type ListOrgBlocksOptions struct { + ListOptions +} + +// ListOrgBlocks lists users blocked by the organization +func (c *Client) ListOrgBlocks(org string, opt ListOrgBlocksOptions) ([]*User, *Response, error) { + if err := escapeValidatePathSegments(&org); err != nil { + return nil, nil, err + } + opt.setDefaults() + + link, _ := url.Parse(fmt.Sprintf("/orgs/%s/blocks", org)) + link.RawQuery = opt.getURLQuery().Encode() + + users := make([]*User, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users) + return users, resp, err +} + +// CheckOrgBlock checks if a user is blocked by the organization +func (c *Client) CheckOrgBlock(org, username string) (bool, *Response, error) { + if err := escapeValidatePathSegments(&org, &username); err != nil { + return false, nil, err + } + status, resp, err := c.getStatusCode("GET", + fmt.Sprintf("/orgs/%s/blocks/%s", org, username), + jsonHeader, nil) + if err != nil { + return false, resp, err + } + return status == http.StatusNoContent, resp, nil +} + +// BlockOrgUser blocks a user from the organization +func (c *Client) BlockOrgUser(org, username string) (*Response, error) { + if err := escapeValidatePathSegments(&org, &username); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("PUT", + fmt.Sprintf("/orgs/%s/blocks/%s", org, username), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// UnblockOrgUser unblocks a user from the organization +func (c *Client) UnblockOrgUser(org, username string) (*Response, error) { + if err := escapeValidatePathSegments(&org, &username); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("DELETE", + fmt.Sprintf("/orgs/%s/blocks/%s", org, username), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} diff --git a/vendor/code.gitea.io/sdk/gitea/org_label.go b/vendor/code.gitea.io/sdk/gitea/org_label.go new file mode 100644 index 00000000000..c524235e13a --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/org_label.go @@ -0,0 +1,116 @@ +// Copyright 2025 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "net/url" + "regexp" + "strings" +) + +// ListOrgLabelsOptions options for listing organization labels +type ListOrgLabelsOptions struct { + ListOptions +} + +// ListOrgLabels returns the labels defined at the org level +func (c *Client) ListOrgLabels(orgName string, opt ListOrgLabelsOptions) ([]*Label, *Response, error) { + if err := escapeValidatePathSegments(&orgName); err != nil { + return nil, nil, err + } + opt.setDefaults() + labels := make([]*Label, 0, opt.PageSize) + link, _ := url.Parse(fmt.Sprintf("/orgs/%s/labels", orgName)) + link.RawQuery = opt.getURLQuery().Encode() + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &labels) + return labels, resp, err +} + +type CreateOrgLabelOption struct { + // Name of the label + Name string `json:"name"` + // Color of the label in hex format without # + Color string `json:"color"` + // Description of the label + Description string `json:"description"` + // Whether this is an exclusive label + Exclusive bool `json:"exclusive"` +} + +// Validate the CreateLabelOption struct +func (opt CreateOrgLabelOption) Validate() error { + aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", opt.Color) + if err != nil { + return err + } + if !aw { + return fmt.Errorf("invalid color format") + } + if len(strings.TrimSpace(opt.Name)) == 0 { + return fmt.Errorf("empty name not allowed") + } + return nil +} + +// CreateOrgLabel creates a new label under an organization +func (c *Client) CreateOrgLabel(orgName string, opt CreateOrgLabelOption) (*Label, *Response, error) { + if err := escapeValidatePathSegments(&orgName); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + label := new(Label) + resp, err := c.getParsedResponse("POST", fmt.Sprintf("/orgs/%s/labels", orgName), jsonHeader, bytes.NewReader(body), label) + return label, resp, err +} + +// GetOrgLabel get one label of organization by org it +func (c *Client) GetOrgLabel(orgName string, labelID int64) (*Label, *Response, error) { + if err := escapeValidatePathSegments(&orgName); err != nil { + return nil, nil, err + } + label := new(Label) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/labels/%d", orgName, labelID), nil, nil, label) + return label, resp, err +} + +type EditOrgLabelOption struct { + // New name of the label + Name *string `json:"name"` + // New color of the label in hex format without # + Color *string `json:"color"` + // New description of the label + Description *string `json:"description"` + // Whether this is an exclusive label + Exclusive *bool `json:"exclusive,omitempty"` +} + +// EditOrgLabel edits an existing org-level label by ID +func (c *Client) EditOrgLabel(orgName string, labelID int64, opt EditOrgLabelOption) (*Label, *Response, error) { + if err := escapeValidatePathSegments(&orgName); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + label := new(Label) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/orgs/%s/labels/%d", orgName, labelID), jsonHeader, bytes.NewReader(body), label) + return label, resp, err +} + +// DeleteOrgLabel deletes a org label by ID +func (c *Client) DeleteOrgLabel(orgName string, labelID int64) (*Response, error) { + if err := escapeValidatePathSegments(&orgName); err != nil { + return nil, err + } + _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/labels/%d", orgName, labelID), jsonHeader, nil) + return resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/org_member.go b/vendor/code.gitea.io/sdk/gitea/org_member.go index 79dad4e87c6..91ac44a7890 100644 --- a/vendor/code.gitea.io/sdk/gitea/org_member.go +++ b/vendor/code.gitea.io/sdk/gitea/org_member.go @@ -15,8 +15,7 @@ func (c *Client) DeleteOrgMembership(org, user string) (*Response, error) { if err := escapeValidatePathSegments(&org, &user); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil) } // ListOrgMembershipOption list OrgMembership options diff --git a/vendor/code.gitea.io/sdk/gitea/org_social.go b/vendor/code.gitea.io/sdk/gitea/org_social.go new file mode 100644 index 00000000000..430fe94e9d6 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/org_social.go @@ -0,0 +1,124 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/url" +) + +// UpdateOrgAvatar updates the organization's avatar +func (c *Client) UpdateOrgAvatar(org string, opt UpdateUserAvatarOption) (*Response, error) { + if err := escapeValidatePathSegments(&org); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("POST", + fmt.Sprintf("/orgs/%s/avatar", org), + jsonHeader, bytes.NewReader(body)) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// DeleteOrgAvatar deletes the organization's avatar +func (c *Client) DeleteOrgAvatar(org string) (*Response, error) { + if err := escapeValidatePathSegments(&org); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("DELETE", + fmt.Sprintf("/orgs/%s/avatar", org), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// RenameOrgOption options for renaming an organization +type RenameOrgOption struct { + NewName string `json:"new_name"` +} + +// RenameOrg renames an organization +func (c *Client) RenameOrg(org string, opt RenameOrgOption) (*Response, error) { + if err := escapeValidatePathSegments(&org); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("POST", + fmt.Sprintf("/orgs/%s/rename", org), + jsonHeader, bytes.NewReader(body)) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// ListOrgActivityFeedsOptions options for listing organization activity feeds +type ListOrgActivityFeedsOptions struct { + ListOptions + Date string `json:"date,omitempty"` +} + +// ListOrgActivityFeeds lists the organization's activity feeds +func (c *Client) ListOrgActivityFeeds(org string, opt ListOrgActivityFeedsOptions) ([]*Activity, *Response, error) { + if err := escapeValidatePathSegments(&org); err != nil { + return nil, nil, err + } + opt.setDefaults() + + link, _ := url.Parse(fmt.Sprintf("/orgs/%s/activities/feeds", org)) + query := opt.getURLQuery() + if opt.Date != "" { + query.Add("date", opt.Date) + } + link.RawQuery = query.Encode() + + activities := make([]*Activity, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &activities) + return activities, resp, err +} + +// ListTeamActivityFeedsOptions options for listing team activity feeds +type ListTeamActivityFeedsOptions struct { + ListOptions + Date string `json:"date,omitempty"` +} + +// ListTeamActivityFeeds lists the team's activity feeds +func (c *Client) ListTeamActivityFeeds(teamID int64, opt ListTeamActivityFeedsOptions) ([]*Activity, *Response, error) { + opt.setDefaults() + + link, _ := url.Parse(fmt.Sprintf("/teams/%d/activities/feeds", teamID)) + query := opt.getURLQuery() + if opt.Date != "" { + query.Add("date", opt.Date) + } + link.RawQuery = query.Encode() + + activities := make([]*Activity, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &activities) + return activities, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/org_team.go b/vendor/code.gitea.io/sdk/gitea/org_team.go index d2457468084..070b4f91b05 100644 --- a/vendor/code.gitea.io/sdk/gitea/org_team.go +++ b/vendor/code.gitea.io/sdk/gitea/org_team.go @@ -202,14 +202,12 @@ func (c *Client) EditTeam(id int64, opt EditTeamOption) (*Response, error) { if err != nil { return nil, err } - _, resp, err := c.getResponse("PATCH", fmt.Sprintf("/teams/%d", id), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PATCH", fmt.Sprintf("/teams/%d", id), jsonHeader, bytes.NewReader(body)) } // DeleteTeam deletes a team of an organization func (c *Client) DeleteTeam(id int64) (*Response, error) { - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d", id), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/teams/%d", id), nil, nil) } // ListTeamMembersOptions options for listing team's members @@ -240,8 +238,7 @@ func (c *Client) AddTeamMember(id int64, user string) (*Response, error) { if err := escapeValidatePathSegments(&user); err != nil { return nil, err } - _, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("PUT", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil) } // RemoveTeamMember removes a member from a team @@ -249,8 +246,7 @@ func (c *Client) RemoveTeamMember(id int64, user string) (*Response, error) { if err := escapeValidatePathSegments(&user); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil) } // ListTeamRepositoriesOptions options for listing team's repositories @@ -271,8 +267,7 @@ func (c *Client) AddTeamRepository(id int64, org, repo string) (*Response, error if err := escapeValidatePathSegments(&org, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("PUT", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil) } // RemoveTeamRepository removes a repository from a team @@ -280,6 +275,5 @@ func (c *Client) RemoveTeamRepository(id int64, org, repo string) (*Response, er if err := escapeValidatePathSegments(&org, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/package.go b/vendor/code.gitea.io/sdk/gitea/package.go index 41ffdee6496..1a2c2cc81a1 100644 --- a/vendor/code.gitea.io/sdk/gitea/package.go +++ b/vendor/code.gitea.io/sdk/gitea/package.go @@ -78,8 +78,7 @@ func (c *Client) DeletePackage(owner, packageType, name, version string) (*Respo if err := escapeValidatePathSegments(&owner, &packageType, &name, &version); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/packages/%s/%s/%s/%s", owner, packageType, name, version), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/packages/%s/%s/%s/%s", owner, packageType, name, version), nil, nil) } // ListPackageFiles lists the files within a package @@ -91,3 +90,29 @@ func (c *Client) ListPackageFiles(owner, packageType, name, version string) ([]* resp, err := c.getParsedResponse("GET", fmt.Sprintf("/packages/%s/%s/%s/%s/files", owner, packageType, name, version), nil, nil, &packageFiles) return packageFiles, resp, err } + +// GetLatestPackage gets the details of the latest version of a package +func (c *Client) GetLatestPackage(owner, packageType, name string) (*Package, *Response, error) { + if err := escapeValidatePathSegments(&owner, &packageType, &name); err != nil { + return nil, nil, err + } + foundPackage := new(Package) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/packages/%s/%s/%s/-/latest", owner, packageType, name), nil, nil, foundPackage) + return foundPackage, resp, err +} + +// LinkPackage links a package to a repository +func (c *Client) LinkPackage(owner, packageType, name, repoName string) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &packageType, &name, &repoName); err != nil { + return nil, err + } + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/packages/%s/%s/%s/-/link/%s", owner, packageType, name, repoName), nil, nil) +} + +// UnlinkPackage unlinks a package from a repository +func (c *Client) UnlinkPackage(owner, packageType, name string) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &packageType, &name); err != nil { + return nil, err + } + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/packages/%s/%s/%s/-/unlink", owner, packageType, name), nil, nil) +} diff --git a/vendor/code.gitea.io/sdk/gitea/pull.go b/vendor/code.gitea.io/sdk/gitea/pull.go index 8ca81647222..7da58049291 100644 --- a/vendor/code.gitea.io/sdk/gitea/pull.go +++ b/vendor/code.gitea.io/sdk/gitea/pull.go @@ -25,19 +25,23 @@ type PRBranchInfo struct { // PullRequest represents a pull request type PullRequest struct { - ID int64 `json:"id"` - URL string `json:"url"` - Index int64 `json:"number"` - Poster *User `json:"user"` - Title string `json:"title"` - Body string `json:"body"` - Labels []*Label `json:"labels"` - Milestone *Milestone `json:"milestone"` - Assignee *User `json:"assignee"` - Assignees []*User `json:"assignees"` - State StateType `json:"state"` - IsLocked bool `json:"is_locked"` - Comments int `json:"comments"` + ID int64 `json:"id"` + URL string `json:"url"` + Index int64 `json:"number"` + Poster *User `json:"user"` + Title string `json:"title"` + Body string `json:"body"` + Labels []*Label `json:"labels"` + Milestone *Milestone `json:"milestone"` + Assignee *User `json:"assignee"` + Assignees []*User `json:"assignees"` + RequestedReviewers []*User `json:"requested_reviewers"` + RequestedReviewersTeams []*Team `json:"requested_reviewers_teams"` + State StateType `json:"state"` + Draft bool `json:"draft"` + IsLocked bool `json:"is_locked"` + Comments int `json:"comments"` + ReviewComments int `json:"review_comments,omitempty"` HTMLURL string `json:"html_url"` DiffURL string `json:"diff_url"` @@ -58,6 +62,11 @@ type PullRequest struct { Created *time.Time `json:"created_at"` Updated *time.Time `json:"updated_at"` Closed *time.Time `json:"closed_at"` + + Additions *int `json:"additions,omitempty"` + Deletions *int `json:"deletions,omitempty"` + ChangedFiles *int `json:"changed_files,omitempty"` + PinOrder int `json:"pin_order"` } // ChangedFile is a changed file in a diff @@ -149,15 +158,17 @@ func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest, // CreatePullRequestOption options when creating a pull request type CreatePullRequestOption struct { - Head string `json:"head"` - Base string `json:"base"` - Title string `json:"title"` - Body string `json:"body"` - Assignee string `json:"assignee"` - Assignees []string `json:"assignees"` - Milestone int64 `json:"milestone"` - Labels []int64 `json:"labels"` - Deadline *time.Time `json:"due_date"` + Head string `json:"head"` + Base string `json:"base"` + Title string `json:"title"` + Body string `json:"body"` + Assignee string `json:"assignee"` + Assignees []string `json:"assignees"` + Reviewers []string `json:"reviewers"` + TeamReviewers []string `json:"team_reviewers"` + Milestone int64 `json:"milestone"` + Labels []int64 `json:"labels"` + Deadline *time.Time `json:"due_date"` } // CreatePullRequest create pull request with options @@ -179,7 +190,7 @@ func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOpti // EditPullRequestOption options when modify pull request type EditPullRequestOption struct { Title string `json:"title"` - Body string `json:"body"` + Body *string `json:"body"` Base string `json:"base"` Assignee string `json:"assignee"` Assignees []string `json:"assignees"` diff --git a/vendor/code.gitea.io/sdk/gitea/pull_review.go b/vendor/code.gitea.io/sdk/gitea/pull_review.go index 6d32c4f1246..e5e39bd2e62 100644 --- a/vendor/code.gitea.io/sdk/gitea/pull_review.go +++ b/vendor/code.gitea.io/sdk/gitea/pull_review.go @@ -202,8 +202,7 @@ func (c *Client) DeletePullReview(owner, repo string, index, id int64) (*Respons return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil) } // CreatePullReview create a review to an pull request @@ -265,10 +264,9 @@ func (c *Client) CreateReviewRequests(owner, repo string, index int64, opt PullR return nil, err } - _, resp, err := c.getResponse("POST", + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index), jsonHeader, bytes.NewReader(body)) - return resp, err } // DeleteReviewRequests delete review requests to an pull request @@ -284,10 +282,9 @@ func (c *Client) DeleteReviewRequests(owner, repo string, index int64, opt PullR return nil, err } - _, resp, err := c.getResponse("DELETE", + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index), jsonHeader, bytes.NewReader(body)) - return resp, err } // DismissPullReview dismiss a review for a pull request @@ -303,10 +300,9 @@ func (c *Client) DismissPullReview(owner, repo string, index, id int64, opt Dism return nil, err } - _, resp, err := c.getResponse("POST", + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/dismissals", owner, repo, index, id), jsonHeader, bytes.NewReader(body)) - return resp, err } // UnDismissPullReview cancel to dismiss a review for a pull request @@ -318,8 +314,7 @@ func (c *Client) UnDismissPullReview(owner, repo string, index, id int64) (*Resp return nil, err } - _, resp, err := c.getResponse("POST", + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/undismissals", owner, repo, index, id), jsonHeader, nil) - return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/release.go b/vendor/code.gitea.io/sdk/gitea/release.go index f3707b704fb..d53be26c3e2 100644 --- a/vendor/code.gitea.io/sdk/gitea/release.go +++ b/vendor/code.gitea.io/sdk/gitea/release.go @@ -173,10 +173,9 @@ func (c *Client) DeleteRelease(user, repo string, id int64) (*Response, error) { if err := escapeValidatePathSegments(&user, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id), nil, nil) - return resp, err } // DeleteReleaseByTag deletes a release frm a repository by tag @@ -187,10 +186,9 @@ func (c *Client) DeleteReleaseByTag(user, repo, tag string) (*Response, error) { if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag), nil, nil) - return resp, err } // fallbackGetReleaseByTag is fallback for old gitea installations ( < 1.13.0 ) diff --git a/vendor/code.gitea.io/sdk/gitea/repo.go b/vendor/code.gitea.io/sdk/gitea/repo.go index b8dba5b2af7..f8d8a70d85b 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo.go +++ b/vendor/code.gitea.io/sdk/gitea/repo.go @@ -10,6 +10,7 @@ import ( "encoding/json" "fmt" "io" + "net/http" "net/url" "strings" "time" @@ -60,6 +61,13 @@ const ( ProjectsModeAll ProjectsMode = "all" ) +// RepoTransfer represents a pending repository transfer +type RepoTransfer struct { + Doer *User `json:"doer"` + Recipient *User `json:"recipient"` + Teams []*Team `json:"teams"` +} + // Repository represents a repository type Repository struct { ID int64 `json:"id"` @@ -74,7 +82,11 @@ type Repository struct { Parent *Repository `json:"parent"` Mirror bool `json:"mirror"` Size int `json:"size"` + Language string `json:"language"` + LanguagesURL string `json:"languages_url"` HTMLURL string `json:"html_url"` + URL string `json:"url"` + Link string `json:"link"` SSHURL string `json:"ssh_url"` CloneURL string `json:"clone_url"` OriginalURL string `json:"original_url"` @@ -87,10 +99,12 @@ type Repository struct { Releases int `json:"release_counter"` DefaultBranch string `json:"default_branch"` Archived bool `json:"archived"` + ArchivedAt time.Time `json:"archived_at"` Created time.Time `json:"created_at"` Updated time.Time `json:"updated_at"` Permissions *Permission `json:"permissions,omitempty"` HasIssues bool `json:"has_issues"` + HasCode bool `json:"has_code"` InternalTracker *InternalTracker `json:"internal_tracker,omitempty"` ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"` HasWiki bool `json:"has_wiki"` @@ -105,7 +119,9 @@ type Repository struct { AllowMerge bool `json:"allow_merge_commits"` AllowRebase bool `json:"allow_rebase"` AllowRebaseMerge bool `json:"allow_rebase_explicit"` + AllowRebaseUpdate bool `json:"allow_rebase_update"` AllowSquash bool `json:"allow_squash_merge"` + DefaultAllowMaintainerEdit bool `json:"default_allow_maintainer_edit"` AvatarURL string `json:"avatar_url"` Internal bool `json:"internal"` MirrorInterval string `json:"mirror_interval"` @@ -114,6 +130,9 @@ type Repository struct { ProjectsMode *ProjectsMode `json:"projects_mode"` DefaultDeleteBranchAfterMerge bool `json:"default_delete_branch_after_merge"` ObjectFormatName string `json:"object_format_name"` + Topics []string `json:"topics"` + Licenses []string `json:"licenses"` + RepoTransfer *RepoTransfer `json:"repo_transfer,omitempty"` } // RepoType represent repo type @@ -259,10 +278,10 @@ func (opt *SearchRepoOptions) QueryEncode() string { // Repo Attributes if opt.IsPrivate != nil { - query.Add("is_private", fmt.Sprintf("%v", opt.IsPrivate)) + query.Add("is_private", fmt.Sprintf("%t", *opt.IsPrivate)) } if opt.IsArchived != nil { - query.Add("archived", fmt.Sprintf("%v", opt.IsArchived)) + query.Add("archived", fmt.Sprintf("%t", *opt.IsArchived)) } if opt.ExcludeTemplate { query.Add("template", "false") @@ -506,8 +525,7 @@ func (c *Client) DeleteRepo(owner, repo string) (*Response, error) { if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil) } // MirrorSync adds a mirrored repository to the mirror sync queue. @@ -515,8 +533,7 @@ func (c *Client) MirrorSync(owner, repo string) (*Response, error) { if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil) } // GetRepoLanguages return language stats of a repo @@ -576,3 +593,46 @@ func (c *Client) GetArchiveReader(owner, repo, ref string, ext ArchiveType) (io. return resp.Body, resp, nil } + +// UpdateRepoAvatarOption options for updating repository avatar +type UpdateRepoAvatarOption struct { + Image string `json:"image"` // base64 encoded image +} + +// UpdateRepoAvatar updates a repository's avatar +func (c *Client) UpdateRepoAvatar(owner, repo string, opt UpdateRepoAvatarOption) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("POST", + fmt.Sprintf("/repos/%s/%s/avatar", owner, repo), + jsonHeader, bytes.NewReader(body)) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// DeleteRepoAvatar deletes a repository's avatar +func (c *Client) DeleteRepoAvatar(owner, repo string) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("DELETE", + fmt.Sprintf("/repos/%s/%s/avatar", owner, repo), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} diff --git a/vendor/code.gitea.io/sdk/gitea/repo_action.go b/vendor/code.gitea.io/sdk/gitea/repo_action.go index 65bccccb893..9c421c6eb3b 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_action.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_action.go @@ -42,6 +42,25 @@ func (c *Client) ListRepoActionSecret(user, repo string, opt ListRepoActionSecre return secrets, resp, err } +// ListRepoActionVariableOption lists RepoActionVariable options +type ListRepoActionVariableOption struct { + ListOptions +} + +// ListRepoActionVariable lists a repository's action variables +func (c *Client) ListRepoActionVariable(user, repo string, opt ListRepoActionVariableOption) ([]*RepoActionVariable, *Response, error) { + if err := escapeValidatePathSegments(&user, &repo); err != nil { + return nil, nil, err + } + opt.setDefaults() + variables := make([]*RepoActionVariable, 0, opt.PageSize) + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/actions/variables", user, repo)) + link.RawQuery = opt.getURLQuery().Encode() + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &variables) + return variables, resp, err +} + // CreateRepoActionSecret creates a secret for the specified repository in the Gitea Actions. // It takes the organization name and the secret options as parameters. // The function returns the HTTP response and an error, if any. @@ -84,8 +103,7 @@ func (c *Client) DeleteRepoActionSecret(user, repo, secretName string) (*Respons return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/actions/secrets/%s", user, repo, secretName), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/actions/secrets/%s", user, repo, secretName), nil, nil) } // GetRepoActionVariable returns a repository variable in the Gitea Actions. @@ -117,8 +135,7 @@ func (c *Client) CreateRepoActionVariable(user, repo, variableName, value string return nil, err } - _, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/actions/variables/%s", user, repo, variableName), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("POST", fmt.Sprintf("/repos/%s/%s/actions/variables/%s", user, repo, variableName), jsonHeader, bytes.NewReader(body)) } // UpdateRepoActionVariable updates a repository variable in the Gitea Actions. @@ -139,8 +156,7 @@ func (c *Client) UpdateRepoActionVariable(user, repo, variableName, value string return nil, err } - _, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/actions/variables/%s", user, repo, variableName), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PUT", fmt.Sprintf("/repos/%s/%s/actions/variables/%s", user, repo, variableName), jsonHeader, bytes.NewReader(body)) } // DeleteRepoActionVariable deletes a repository variable in the Gitea Actions. @@ -151,6 +167,5 @@ func (c *Client) DeleteRepoActionVariable(user, reponame, variableName string) ( return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/actions/variables/%s", user, reponame, variableName), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/actions/variables/%s", user, reponame, variableName), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_branch.go b/vendor/code.gitea.io/sdk/gitea/repo_branch.go index 0b7e873c4fa..637ad5f2fa7 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_branch.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_branch.go @@ -8,6 +8,7 @@ package gitea import ( "bytes" "encoding/json" + "errors" "fmt" "time" ) @@ -100,6 +101,36 @@ func (c *Client) DeleteRepoBranch(user, repo, branch string) (bool, *Response, e return status == 204, resp, nil } +type UpdateRepoBranchOption struct { + Name string `json:"name"` +} + +func (opt UpdateRepoBranchOption) Validate() error { + if len(opt.Name) == 0 { + return errors.New("empty Name field") + } + + return nil +} + +func (c *Client) UpdateRepoBranch(user, repo, branch string, opt UpdateRepoBranchOption) (sucessful bool, resp *Response, err error) { + if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil { + return false, nil, err + } + if err := c.checkServerVersionGreaterThanOrEqual(version1_23_0); err != nil { + return false, nil, err + } + if err := opt.Validate(); err != nil { + return false, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return false, nil, err + } + status, resp, err := c.getStatusCode("PATCH", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), jsonHeader, bytes.NewReader(body)) + return status == 204, resp, err +} + // CreateBranchOption options when creating a branch in a repository type CreateBranchOption struct { // Name of the branch to create diff --git a/vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go b/vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go index 3196d03bfd0..4f40dc36066 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go @@ -168,6 +168,5 @@ func (c *Client) DeleteBranchProtection(owner, repo, name string) (*Response, er if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_collaborator.go b/vendor/code.gitea.io/sdk/gitea/repo_collaborator.go index 41e25765505..2825a3edabb 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_collaborator.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_collaborator.go @@ -122,8 +122,7 @@ func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollabo if err != nil { return nil, err } - _, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), jsonHeader, bytes.NewReader(body)) } // DeleteCollaborator remove a collaborator from a repository @@ -131,9 +130,8 @@ func (c *Client) DeleteCollaborator(user, repo, collaborator string) (*Response, if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil) - return resp, err } // GetReviewers return all users that can be requested to review in this repo diff --git a/vendor/code.gitea.io/sdk/gitea/repo_file.go b/vendor/code.gitea.io/sdk/gitea/repo_file.go index 9285be2aaae..1c078d9d6f8 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_file.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_file.go @@ -126,7 +126,11 @@ func (c *Client) GetFile(owner, repo, ref, filepath string, resolveLFS ...bool) if reader == nil { return nil, resp, err } - defer reader.Close() + defer func() { + if closeErr := reader.Close(); closeErr != nil && err == nil { + err = closeErr + } + }() data, err2 := io.ReadAll(reader) if err2 != nil { diff --git a/vendor/code.gitea.io/sdk/gitea/repo_file_ext.go b/vendor/code.gitea.io/sdk/gitea/repo_file_ext.go new file mode 100644 index 00000000000..11126981026 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/repo_file_ext.go @@ -0,0 +1,136 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "fmt" + "io" + "net/url" +) + +// ContentsExtResponse contains extended information about a repo's contents +type ContentsExtResponse struct { + DirContents []*ContentsResponse `json:"dir_contents,omitempty"` + FileContents *ContentsResponse `json:"file_contents,omitempty"` +} + +// GetContentsExtOptions options for getting extended contents +type GetContentsExtOptions struct { + // The name of the commit/branch/tag. Default to the repository's default branch + Ref string `json:"ref,omitempty"` + // Comma-separated includes options: file_content, lfs_metadata, commit_metadata, commit_message + Includes string `json:"includes,omitempty"` +} + +// GetContentsExt gets extended file metadata and/or content from a repository +// The extended "contents" API, to get file metadata and/or content, or list a directory +func (c *Client) GetContentsExt(owner, repo, filepath string, opt GetContentsExtOptions) (*ContentsExtResponse, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + + // filepath doesn't need escaping since it's already part of the path + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/contents-ext/%s", owner, repo, filepath)) + query := link.Query() + + if opt.Ref != "" { + query.Add("ref", opt.Ref) + } + if opt.Includes != "" { + query.Add("includes", opt.Includes) + } + + link.RawQuery = query.Encode() + + result := new(ContentsExtResponse) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, result) + return result, resp, err +} + +// GetEditorConfig gets the EditorConfig definitions of a file in a repository +func (c *Client) GetEditorConfig(owner, repo, filepath string, ref ...string) ([]byte, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/editorconfig/%s", owner, repo, filepath)) + + if len(ref) > 0 && ref[0] != "" { + query := link.Query() + query.Add("ref", ref[0]) + link.RawQuery = query.Encode() + } + + resp, err := c.doRequest("GET", link.String(), nil, nil) + if err != nil { + return nil, resp, err + } + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil && err == nil { + err = closeErr + } + }() + + data, err := io.ReadAll(resp.Body) + return data, resp, err +} + +// GetRawFileOrLFS gets a file or its LFS object from a repository +// This endpoint resolves LFS pointers and returns actual LFS objects +func (c *Client) GetRawFileOrLFS(owner, repo, filepath string, ref ...string) ([]byte, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/media/%s", owner, repo, filepath)) + + if len(ref) > 0 && ref[0] != "" { + query := link.Query() + query.Add("ref", ref[0]) + link.RawQuery = query.Encode() + } + + resp, err := c.doRequest("GET", link.String(), nil, nil) + if err != nil { + return nil, resp, err + } + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil && err == nil { + err = closeErr + } + }() + + data, err := io.ReadAll(resp.Body) + return data, resp, err +} + +// GetRawFile gets a file from a repository +// Unlike GetRawFileOrLFS, this does NOT resolve LFS pointers +func (c *Client) GetRawFile(owner, repo, filepath string, ref ...string) ([]byte, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/raw/%s", owner, repo, filepath)) + + if len(ref) > 0 && ref[0] != "" { + query := link.Query() + query.Add("ref", ref[0]) + link.RawQuery = query.Encode() + } + + resp, err := c.doRequest("GET", link.String(), nil, nil) + if err != nil { + return nil, resp, err + } + defer func() { + if closeErr := resp.Body.Close(); closeErr != nil && err == nil { + err = closeErr + } + }() + + data, err := io.ReadAll(resp.Body) + return data, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/repo_git_notes.go b/vendor/code.gitea.io/sdk/gitea/repo_git_notes.go new file mode 100644 index 00000000000..fdc03ce63f6 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/repo_git_notes.go @@ -0,0 +1,56 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "fmt" + "net/url" +) + +// Note represents a git note +type Note struct { + Message string `json:"message"` + Commit *Commit `json:"commit"` +} + +// GetRepoNoteOptions options for getting a note +type GetRepoNoteOptions struct { + // include verification for every commit (disable for speedup, default 'true') + Verification *bool `json:"verification,omitempty"` + // include a list of affected files for every commit (disable for speedup, default 'true') + Files *bool `json:"files,omitempty"` +} + +// GetRepoNote gets a note corresponding to a single commit from a repository +func (c *Client) GetRepoNote(owner, repo, sha string, opt GetRepoNoteOptions) (*Note, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo, &sha); err != nil { + return nil, nil, err + } + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/git/notes/%s", owner, repo, sha)) + query := link.Query() + + if opt.Verification != nil { + if *opt.Verification { + query.Add("verification", "true") + } else { + query.Add("verification", "false") + } + } + + if opt.Files != nil { + if *opt.Files { + query.Add("files", "true") + } else { + query.Add("files", "false") + } + } + + link.RawQuery = query.Encode() + + note := new(Note) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ¬e) + return note, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/repo_key.go b/vendor/code.gitea.io/sdk/gitea/repo_key.go index ee2ff4084e3..b9964fb786b 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_key.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_key.go @@ -86,6 +86,5 @@ func (c *Client) DeleteDeployKey(owner, repo string, keyID int64) (*Response, er if err := escapeValidatePathSegments(&owner, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_label.go b/vendor/code.gitea.io/sdk/gitea/repo_label.go new file mode 100644 index 00000000000..2cee0be9902 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/repo_label.go @@ -0,0 +1,153 @@ +// Copyright 2016 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "regexp" + "strings" +) + +// Label a label to an issue or a pr +type Label struct { + ID int64 `json:"id"` + Name string `json:"name"` + // example: 00aabb + Color string `json:"color"` + Description string `json:"description"` + Exclusive bool `json:"exclusive"` + IsArchived bool `json:"is_archived"` + URL string `json:"url"` +} + +// ListLabelsOptions options for listing repository's labels +type ListLabelsOptions struct { + ListOptions +} + +// ListRepoLabels list labels of one repository +func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + opt.setDefaults() + labels := make([]*Label, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels) + return labels, resp, err +} + +// GetRepoLabel get one label of repository by repo it +func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + label := new(Label) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label) + return label, resp, err +} + +// CreateLabelOption options for creating a label +type CreateLabelOption struct { + Name string `json:"name"` + // example: #00aabb + Color string `json:"color"` + Description string `json:"description"` + Exclusive bool `json:"exclusive"` + IsArchived bool `json:"is_archived"` +} + +// Validate the CreateLabelOption struct +func (opt CreateLabelOption) Validate() error { + aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", opt.Color) + if err != nil { + return err + } + if !aw { + return fmt.Errorf("invalid color format") + } + if len(strings.TrimSpace(opt.Name)) == 0 { + return fmt.Errorf("empty name not allowed") + } + return nil +} + +// CreateLabel create one label of repository +func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + if err := opt.Validate(); err != nil { + return nil, nil, err + } + if len(opt.Color) == 6 { + if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil { + opt.Color = "#" + opt.Color + } + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + label := new(Label) + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/labels", owner, repo), + jsonHeader, bytes.NewReader(body), label) + return label, resp, err +} + +// EditLabelOption options for editing a label +type EditLabelOption struct { + Name *string `json:"name"` + Color *string `json:"color"` + Description *string `json:"description"` + Exclusive *bool `json:"exclusive"` + IsArchived *bool `json:"is_archived"` +} + +// Validate the EditLabelOption struct +func (opt EditLabelOption) Validate() error { + if opt.Color != nil { + aw, err := regexp.MatchString("^#?[0-9,a-f,A-F]{6}$", *opt.Color) + if err != nil { + return err + } + if !aw { + return fmt.Errorf("invalid color format") + } + } + if opt.Name != nil { + if len(strings.TrimSpace(*opt.Name)) == 0 { + return fmt.Errorf("empty name not allowed") + } + } + return nil +} + +// EditLabel modify one label with options +func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + if err := opt.Validate(); err != nil { + return nil, nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + label := new(Label) + resp, err := c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), label) + return label, resp, err +} + +// DeleteLabel delete one label of repository by id +func (c *Client) DeleteLabel(owner, repo string, id int64) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, err + } + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil) +} diff --git a/vendor/code.gitea.io/sdk/gitea/repo_migrate.go b/vendor/code.gitea.io/sdk/gitea/repo_migrate.go index 2de2153605f..73a04bc8f52 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_migrate.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_migrate.go @@ -55,15 +55,15 @@ type MigrateRepoOption struct { func (opt *MigrateRepoOption) Validate(c *Client) error { // check user options if len(opt.CloneAddr) == 0 { - return fmt.Errorf("CloneAddr required") + return fmt.Errorf("clone addr required") } if len(opt.RepoName) == 0 { - return fmt.Errorf("RepoName required") + return fmt.Errorf("repo name required") } else if len(opt.RepoName) > 100 { - return fmt.Errorf("RepoName to long") + return fmt.Errorf("repo name too long") } if len(opt.Description) > 2048 { - return fmt.Errorf("Description to long") + return fmt.Errorf("description too long") } switch opt.Service { case GitServiceGithub: diff --git a/vendor/code.gitea.io/sdk/gitea/repo_mirror.go b/vendor/code.gitea.io/sdk/gitea/repo_mirror.go index df320940a96..2ee806f1038 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_mirror.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_mirror.go @@ -43,3 +43,34 @@ func (c *Client) PushMirrors(user, repo string, opt CreatePushMirrorOption) (*Pu resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/push_mirrors", user, repo), jsonHeader, bytes.NewReader(body), &pm) return pm, resp, err } + +// ListPushMirrors gets all push mirrors of a repository +func (c *Client) ListPushMirrors(user, repo string, opt ListOptions) ([]*PushMirrorResponse, *Response, error) { + if err := escapeValidatePathSegments(&user, &repo); err != nil { + return nil, nil, err + } + opt.setDefaults() + pms := make([]*PushMirrorResponse, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/repos/%s/%s/push_mirrors?%s", user, repo, opt.getURLQuery().Encode()), + nil, nil, &pms) + return pms, resp, err +} + +// GetPushMirrorByRemoteName get a push mirror of the repository by remote name +func (c *Client) GetPushMirrorByRemoteName(user, repo, remoteName string) (*PushMirrorResponse, *Response, error) { + if err := escapeValidatePathSegments(&user, &repo, &remoteName); err != nil { + return nil, nil, err + } + pm := new(PushMirrorResponse) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/push_mirrors/%s", user, repo, remoteName), nil, nil, &pm) + return pm, resp, err +} + +// DeletePushMirror deletes a push mirror from a repository by remote name +func (c *Client) DeletePushMirror(user, repo, remoteName string) (*Response, error) { + if err := escapeValidatePathSegments(&user, &repo, &remoteName); err != nil { + return nil, err + } + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/push_mirrors/%s", user, repo, remoteName), nil, nil) +} diff --git a/vendor/code.gitea.io/sdk/gitea/repo_refs.go b/vendor/code.gitea.io/sdk/gitea/repo_refs.go index c954a80ef2f..bb41c36a50c 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_refs.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_refs.go @@ -76,3 +76,13 @@ func (c *Client) GetRepoRefs(user, repo, ref string) ([]*Reference, *Response, e return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", refErr, refsErr) } + +// ListAllGitRefs gets all refs from a repository without filtering +func (c *Client) ListAllGitRefs(owner, repo string) ([]*Reference, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + refs := make([]*Reference, 0, 10) + resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs", owner, repo), nil, nil, &refs) + return refs, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/repo_stars.go b/vendor/code.gitea.io/sdk/gitea/repo_stars.go index 01243c2505d..45488eb675e 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_stars.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_stars.go @@ -47,7 +47,7 @@ func (c *Client) IsRepoStarring(user, repo string) (bool, *Response, error) { if err := escapeValidatePathSegments(&user, &repo); err != nil { return false, nil, err } - _, resp, err := c.getResponse("GET", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil) + resp, err := c.doRequestWithStatusHandle("GET", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil) if resp != nil { switch resp.StatusCode { case http.StatusNotFound: @@ -66,7 +66,7 @@ func (c *Client) StarRepo(user, repo string) (*Response, error) { if err := escapeValidatePathSegments(&user, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil) + resp, err := c.doRequestWithStatusHandle("PUT", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil) if resp != nil { switch resp.StatusCode { case http.StatusNoContent: @@ -83,7 +83,7 @@ func (c *Client) UnStarRepo(user, repo string) (*Response, error) { if err := escapeValidatePathSegments(&user, &repo); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil) + resp, err := c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil) if resp != nil { switch resp.StatusCode { case http.StatusNoContent: diff --git a/vendor/code.gitea.io/sdk/gitea/repo_tag.go b/vendor/code.gitea.io/sdk/gitea/repo_tag.go index 7317d3f3931..c0dcfe81b2f 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_tag.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_tag.go @@ -123,8 +123,7 @@ func (c *Client) DeleteTag(user, repo, tag string) (*Response, error) { if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag), nil, nil) - return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_tag_protection.go b/vendor/code.gitea.io/sdk/gitea/repo_tag_protection.go index 02cd372b8e9..ec433ae9210 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_tag_protection.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_tag_protection.go @@ -120,6 +120,5 @@ func (c *Client) DeleteTagProtection(owner, repo string, id int64) (*Response, e return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/tag_protections/%d", owner, repo, id), jsonHeader, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/tag_protections/%d", owner, repo, id), jsonHeader, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_team.go b/vendor/code.gitea.io/sdk/gitea/repo_team.go index b983d8748a7..36e0863f53a 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_team.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_team.go @@ -30,8 +30,7 @@ func (c *Client) AddRepoTeam(user, repo, team string) (*Response, error) { if err := escapeValidatePathSegments(&user, &repo, &team); err != nil { return nil, err } - _, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("PUT", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil) } // RemoveRepoTeam delete a team from a repository @@ -42,8 +41,7 @@ func (c *Client) RemoveRepoTeam(user, repo, team string) (*Response, error) { if err := escapeValidatePathSegments(&user, &repo, &team); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil) } // CheckRepoTeam check if team is assigned to repo by name and return it. diff --git a/vendor/code.gitea.io/sdk/gitea/repo_topics.go b/vendor/code.gitea.io/sdk/gitea/repo_topics.go index 92f2228cd93..9a105f2b338 100644 --- a/vendor/code.gitea.io/sdk/gitea/repo_topics.go +++ b/vendor/code.gitea.io/sdk/gitea/repo_topics.go @@ -45,8 +45,7 @@ func (c *Client) SetRepoTopics(user, repo string, list []string) (*Response, err if err != nil { return nil, err } - _, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics", user, repo), jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("PUT", fmt.Sprintf("/repos/%s/%s/topics", user, repo), jsonHeader, bytes.NewReader(body)) } // AddRepoTopic adds a topic to a repo's topics list @@ -54,8 +53,7 @@ func (c *Client) AddRepoTopic(user, repo, topic string) (*Response, error) { if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil { return nil, err } - _, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("PUT", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil) } // DeleteRepoTopic deletes a topic from repo's topics list @@ -63,6 +61,5 @@ func (c *Client) DeleteRepoTopic(user, repo, topic string) (*Response, error) { if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/repo_wiki.go b/vendor/code.gitea.io/sdk/gitea/repo_wiki.go new file mode 100644 index 00000000000..6346f193f1b --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/repo_wiki.go @@ -0,0 +1,164 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "net/url" +) + +// WikiPage represents a wiki page +type WikiPage struct { + Title string `json:"title"` + ContentBase64 string `json:"content_base64"` + CommitCount int64 `json:"commit_count"` + Sidebar string `json:"sidebar"` + Footer string `json:"footer"` + HTMLURL string `json:"html_url"` + SubURL string `json:"sub_url"` + LastCommit *WikiCommit `json:"last_commit,omitempty"` +} + +// WikiPageMetaData represents metadata for a wiki page (without content) +type WikiPageMetaData struct { + Title string `json:"title"` + HTMLURL string `json:"html_url"` + SubURL string `json:"sub_url"` + LastCommit *WikiCommit `json:"last_commit,omitempty"` +} + +// WikiCommit represents a wiki commit/revision +type WikiCommit struct { + ID string `json:"sha"` + Message string `json:"message"` + Author *CommitUser `json:"author,omitempty"` + Commiter *CommitUser `json:"commiter,omitempty"` +} + +// WikiCommitList represents a list of wiki commits +type WikiCommitList struct { + WikiCommits []*WikiCommit `json:"commits"` + Count int64 `json:"count"` +} + +// CreateWikiPageOptions options for creating or editing a wiki page +type CreateWikiPageOptions struct { + Title string `json:"title,omitempty"` + ContentBase64 string `json:"content_base64,omitempty"` + Message string `json:"message,omitempty"` +} + +// ListWikiPagesOptions options for listing wiki pages +type ListWikiPagesOptions struct { + ListOptions +} + +// ListWikiPageRevisionsOptions options for listing wiki page revisions +type ListWikiPageRevisionsOptions struct { + Page int `json:"page,omitempty"` +} + +// CreateWikiPage creates a new wiki page +func (c *Client) CreateWikiPage(owner, repo string, opt CreateWikiPageOptions) (*WikiPage, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + + page := new(WikiPage) + resp, err := c.getParsedResponse("POST", + fmt.Sprintf("/repos/%s/%s/wiki/new", owner, repo), + jsonHeader, bytes.NewReader(body), &page) + return page, resp, err +} + +// GetWikiPage gets a wiki page by name +func (c *Client) GetWikiPage(owner, repo, pageName string) (*WikiPage, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo, &pageName); err != nil { + return nil, nil, err + } + + page := new(WikiPage) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/repos/%s/%s/wiki/page/%s", owner, repo, pageName), + jsonHeader, nil, &page) + return page, resp, err +} + +// EditWikiPage edits an existing wiki page +func (c *Client) EditWikiPage(owner, repo, pageName string, opt CreateWikiPageOptions) (*WikiPage, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo, &pageName); err != nil { + return nil, nil, err + } + + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + + page := new(WikiPage) + resp, err := c.getParsedResponse("PATCH", + fmt.Sprintf("/repos/%s/%s/wiki/page/%s", owner, repo, pageName), + jsonHeader, bytes.NewReader(body), &page) + return page, resp, err +} + +// DeleteWikiPage deletes a wiki page +func (c *Client) DeleteWikiPage(owner, repo, pageName string) (*Response, error) { + if err := escapeValidatePathSegments(&owner, &repo, &pageName); err != nil { + return nil, err + } + + status, resp, err := c.getStatusCode("DELETE", + fmt.Sprintf("/repos/%s/%s/wiki/page/%s", owner, repo, pageName), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// ListWikiPages lists all wiki pages in a repository +func (c *Client) ListWikiPages(owner, repo string, opt ListWikiPagesOptions) ([]*WikiPageMetaData, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo); err != nil { + return nil, nil, err + } + opt.setDefaults() + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/wiki/pages", owner, repo)) + link.RawQuery = opt.getURLQuery().Encode() + + pages := make([]*WikiPageMetaData, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &pages) + return pages, resp, err +} + +// GetWikiPageRevisions gets all revisions of a wiki page +func (c *Client) GetWikiPageRevisions(owner, repo, pageName string, opt ListWikiPageRevisionsOptions) (*WikiCommitList, *Response, error) { + if err := escapeValidatePathSegments(&owner, &repo, &pageName); err != nil { + return nil, nil, err + } + + link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/wiki/revisions/%s", owner, repo, pageName)) + if opt.Page > 0 { + query := link.Query() + query.Add("page", fmt.Sprintf("%d", opt.Page)) + link.RawQuery = query.Encode() + } + + commitList := new(WikiCommitList) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &commitList) + return commitList, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/secret.go b/vendor/code.gitea.io/sdk/gitea/secret.go index d67713d8d72..ea11ed06e80 100644 --- a/vendor/code.gitea.io/sdk/gitea/secret.go +++ b/vendor/code.gitea.io/sdk/gitea/secret.go @@ -11,6 +11,8 @@ type Secret struct { Name string `json:"name"` // the secret's data Data string `json:"data"` + // the secret's description + Description string `json:"description"` // Date and Time of secret creation Created time.Time `json:"created_at"` } diff --git a/vendor/code.gitea.io/sdk/gitea/user.go b/vendor/code.gitea.io/sdk/gitea/user.go index f44b12a9d17..ce9f85e0638 100644 --- a/vendor/code.gitea.io/sdk/gitea/user.go +++ b/vendor/code.gitea.io/sdk/gitea/user.go @@ -26,6 +26,8 @@ type User struct { Email string `json:"email"` // URL to the user's avatar AvatarURL string `json:"avatar_url"` + // URL to the user's profile + HTMLURL string `json:"html_url"` // User locale Language string `json:"language"` // Is the user an administrator diff --git a/vendor/code.gitea.io/sdk/gitea/user_app.go b/vendor/code.gitea.io/sdk/gitea/user_app.go index 92a3a2601aa..bd5b1f888b0 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_app.go +++ b/vendor/code.gitea.io/sdk/gitea/user_app.go @@ -11,6 +11,7 @@ import ( "fmt" "net/url" "reflect" + "time" ) // AccessTokenScope represents the scope for an access token. @@ -71,6 +72,8 @@ type AccessToken struct { Token string `json:"sha1"` TokenLastEight string `json:"token_last_eight"` Scopes []AccessTokenScope `json:"scopes"` + Created time.Time `json:"created_at,omitempty"` + Updated time.Time `json:"last_used_at,omitempty"` } // ListAccessTokensOptions options for listing a users's access tokens @@ -138,6 +141,5 @@ func (c *Client) DeleteAccessToken(value interface{}) (*Response, error) { return nil, fmt.Errorf("only string and int64 supported") } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%s", url.PathEscape(username), url.PathEscape(token)), jsonHeader, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/users/%s/tokens/%s", url.PathEscape(username), url.PathEscape(token)), jsonHeader, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/user_block.go b/vendor/code.gitea.io/sdk/gitea/user_block.go new file mode 100644 index 00000000000..011a5208ac7 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/user_block.go @@ -0,0 +1,76 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "fmt" + "net/http" + "net/url" +) + +// ListUserBlocksOptions options for listing user blocks +type ListUserBlocksOptions struct { + ListOptions +} + +// ListMyBlocks lists users blocked by the authenticated user +func (c *Client) ListMyBlocks(opt ListUserBlocksOptions) ([]*User, *Response, error) { + opt.setDefaults() + + link, _ := url.Parse("/user/blocks") + link.RawQuery = opt.getURLQuery().Encode() + + users := make([]*User, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users) + return users, resp, err +} + +// CheckUserBlock checks if a user is blocked by the authenticated user +func (c *Client) CheckUserBlock(username string) (bool, *Response, error) { + if err := escapeValidatePathSegments(&username); err != nil { + return false, nil, err + } + status, resp, err := c.getStatusCode("GET", + fmt.Sprintf("/user/blocks/%s", username), + jsonHeader, nil) + if err != nil { + return false, resp, err + } + return status == http.StatusNoContent, resp, nil +} + +// BlockUser blocks a user +func (c *Client) BlockUser(username string) (*Response, error) { + if err := escapeValidatePathSegments(&username); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("PUT", + fmt.Sprintf("/user/blocks/%s", username), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// UnblockUser unblocks a user +func (c *Client) UnblockUser(username string) (*Response, error) { + if err := escapeValidatePathSegments(&username); err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("DELETE", + fmt.Sprintf("/user/blocks/%s", username), + jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} diff --git a/vendor/code.gitea.io/sdk/gitea/user_email.go b/vendor/code.gitea.io/sdk/gitea/user_email.go index 4962b082b40..ca9c039a395 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_email.go +++ b/vendor/code.gitea.io/sdk/gitea/user_email.go @@ -15,6 +15,8 @@ type Email struct { Email string `json:"email"` Verified bool `json:"verified"` Primary bool `json:"primary"` + UserID int64 `json:"user_id,omitempty"` + Username string `json:"username,omitempty"` } // ListEmailsOptions options for listing current's user emails @@ -59,6 +61,5 @@ func (c *Client) DeleteEmail(opt DeleteEmailOption) (*Response, error) { if err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", "/user/emails", jsonHeader, bytes.NewReader(body)) - return resp, err + return c.doRequestWithStatusHandle("DELETE", "/user/emails", jsonHeader, bytes.NewReader(body)) } diff --git a/vendor/code.gitea.io/sdk/gitea/user_ext.go b/vendor/code.gitea.io/sdk/gitea/user_ext.go new file mode 100644 index 00000000000..36ef735db73 --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/user_ext.go @@ -0,0 +1,58 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "fmt" + "net/url" +) + +// UserHeatmapData represents the data needed to create a heatmap +type UserHeatmapData struct { + Timestamp int64 `json:"timestamp"` + Contributions int64 `json:"contributions"` +} + +// GetUserHeatmap gets a user's heatmap data +func (c *Client) GetUserHeatmap(username string) ([]*UserHeatmapData, *Response, error) { + if err := escapeValidatePathSegments(&username); err != nil { + return nil, nil, err + } + + heatmap := make([]*UserHeatmapData, 0, 365) + resp, err := c.getParsedResponse("GET", + fmt.Sprintf("/users/%s/heatmap", username), + jsonHeader, nil, &heatmap) + return heatmap, resp, err +} + +// ListUserActivityFeedsOptions options for listing user activity feeds +type ListUserActivityFeedsOptions struct { + ListOptions + OnlyPerformedBy bool `json:"only-performed-by,omitempty"` + Date string `json:"date,omitempty"` +} + +// ListUserActivityFeeds lists a user's activity feeds +func (c *Client) ListUserActivityFeeds(username string, opt ListUserActivityFeedsOptions) ([]*Activity, *Response, error) { + if err := escapeValidatePathSegments(&username); err != nil { + return nil, nil, err + } + opt.setDefaults() + + link, _ := url.Parse(fmt.Sprintf("/users/%s/activities/feeds", username)) + query := opt.getURLQuery() + if opt.OnlyPerformedBy { + query.Add("only-performed-by", "true") + } + if opt.Date != "" { + query.Add("date", opt.Date) + } + link.RawQuery = query.Encode() + + activities := make([]*Activity, 0, opt.PageSize) + resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &activities) + return activities, resp, err +} diff --git a/vendor/code.gitea.io/sdk/gitea/user_follow.go b/vendor/code.gitea.io/sdk/gitea/user_follow.go index 7bd340ca266..40072aa9a45 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_follow.go +++ b/vendor/code.gitea.io/sdk/gitea/user_follow.go @@ -60,7 +60,7 @@ func (c *Client) IsFollowing(target string) (bool, *Response) { // ToDo return err return false, nil } - _, resp, err := c.getResponse("GET", fmt.Sprintf("/user/following/%s", target), nil, nil) + resp, err := c.doRequestWithStatusHandle("GET", fmt.Sprintf("/user/following/%s", target), nil, nil) return err == nil, resp } @@ -70,7 +70,7 @@ func (c *Client) IsUserFollowing(user, target string) (bool, *Response) { // ToDo return err return false, nil } - _, resp, err := c.getResponse("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil) + resp, err := c.doRequestWithStatusHandle("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil) return err == nil, resp } @@ -79,7 +79,7 @@ func (c *Client) Follow(target string) (*Response, error) { if err := escapeValidatePathSegments(&target); err != nil { return nil, err } - _, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil) + resp, err := c.doRequestWithStatusHandle("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil) return resp, err } @@ -88,6 +88,6 @@ func (c *Client) Unfollow(target string) (*Response, error) { if err := escapeValidatePathSegments(&target); err != nil { return nil, err } - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil) + resp, err := c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil) return resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/user_gpgkey.go b/vendor/code.gitea.io/sdk/gitea/user_gpgkey.go index 6c1b9d10f34..95070cac36b 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_gpgkey.go +++ b/vendor/code.gitea.io/sdk/gitea/user_gpgkey.go @@ -23,6 +23,7 @@ type GPGKey struct { CanEncryptComms bool `json:"can_encrypt_comms"` CanEncryptStorage bool `json:"can_encrypt_storage"` CanCertify bool `json:"can_certify"` + Verified bool `json:"verified"` Created time.Time `json:"created_at,omitempty"` Expires time.Time `json:"expires_at,omitempty"` } @@ -67,8 +68,9 @@ func (c *Client) GetGPGKey(keyID int64) (*GPGKey, *Response, error) { // CreateGPGKeyOption options create user GPG key type CreateGPGKeyOption struct { // An armored GPG key to add - // ArmoredKey string `json:"armored_public_key"` + // An optional armored signature for the GPG key + Signature string `json:"armored_signature,omitempty"` } // CreateGPGKey create GPG key with options @@ -84,6 +86,35 @@ func (c *Client) CreateGPGKey(opt CreateGPGKeyOption) (*GPGKey, *Response, error // DeleteGPGKey delete GPG key with key id func (c *Client) DeleteGPGKey(keyID int64) (*Response, error) { - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/user/gpg_keys/%d", keyID), nil, nil) +} + +// GetGPGKeyVerificationToken gets a verification token for adding a GPG key. +// Returns the token as a plain string (API returns text/plain, not JSON). +// The user should sign this token with their GPG key and submit via VerifyGPGKey. +func (c *Client) GetGPGKeyVerificationToken() (string, *Response, error) { + body, resp, err := c.getResponse("GET", "/user/gpg_key_token", nil, nil) + return string(body), resp, err +} + +// VerifyGPGKeyOption options for verifying a GPG key +type VerifyGPGKeyOption struct { + // KeyID is the GPG key ID to verify + KeyID string `json:"key_id"` + // Signature is the ASCII-armored signature of the verification token + Signature string `json:"armored_signature"` +} + +// VerifyGPGKey verifies a GPG key by submitting a signed verification token. +// First call GetGPGKeyVerificationToken to get the token, sign it with the GPG key, +// then call this with the key ID and armored signature. +func (c *Client) VerifyGPGKey(opt VerifyGPGKeyOption) (*GPGKey, *Response, error) { + body, err := json.Marshal(&opt) + if err != nil { + return nil, nil, err + } + key := new(GPGKey) + resp, err := c.getParsedResponse("POST", "/user/gpg_key_verify", + jsonHeader, bytes.NewReader(body), key) + return key, resp, err } diff --git a/vendor/code.gitea.io/sdk/gitea/user_key.go b/vendor/code.gitea.io/sdk/gitea/user_key.go index 02795baefc6..d01627626bd 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_key.go +++ b/vendor/code.gitea.io/sdk/gitea/user_key.go @@ -19,6 +19,7 @@ type PublicKey struct { Title string `json:"title,omitempty"` Fingerprint string `json:"fingerprint,omitempty"` Created time.Time `json:"created_at,omitempty"` + Updated time.Time `json:"last_used_at,omitempty"` Owner *User `json:"user,omitempty"` ReadOnly bool `json:"read_only,omitempty"` KeyType string `json:"key_type,omitempty"` @@ -78,6 +79,5 @@ func (c *Client) CreatePublicKey(opt CreateKeyOption) (*PublicKey, *Response, er // DeletePublicKey delete public key with key id func (c *Client) DeletePublicKey(keyID int64) (*Response, error) { - _, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil) - return resp, err + return c.doRequestWithStatusHandle("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil) } diff --git a/vendor/code.gitea.io/sdk/gitea/user_search.go b/vendor/code.gitea.io/sdk/gitea/user_search.go index 5ea0c45f815..0e042a54b71 100644 --- a/vendor/code.gitea.io/sdk/gitea/user_search.go +++ b/vendor/code.gitea.io/sdk/gitea/user_search.go @@ -17,6 +17,7 @@ type searchUsersResponse struct { type SearchUsersOption struct { ListOptions KeyWord string + UID int64 } // QueryEncode turns options into querystring argument @@ -31,6 +32,9 @@ func (opt *SearchUsersOption) QueryEncode() string { if len(opt.KeyWord) > 0 { query.Add("q", opt.KeyWord) } + if opt.UID > 0 { + query.Add("uid", fmt.Sprintf("%d", opt.UID)) + } return query.Encode() } diff --git a/vendor/code.gitea.io/sdk/gitea/user_social.go b/vendor/code.gitea.io/sdk/gitea/user_social.go new file mode 100644 index 00000000000..eef284db55c --- /dev/null +++ b/vendor/code.gitea.io/sdk/gitea/user_social.go @@ -0,0 +1,46 @@ +// Copyright 2026 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package gitea + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" +) + +// UpdateUserAvatarOption options for updating user avatar +type UpdateUserAvatarOption struct { + Image string `json:"image"` // base64 encoded image +} + +// UpdateUserAvatar updates the authenticated user's avatar +func (c *Client) UpdateUserAvatar(opt UpdateUserAvatarOption) (*Response, error) { + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + status, resp, err := c.getStatusCode("POST", "/user/avatar", + jsonHeader, bytes.NewReader(body)) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} + +// DeleteUserAvatar deletes the authenticated user's avatar +func (c *Client) DeleteUserAvatar() (*Response, error) { + status, resp, err := c.getStatusCode("DELETE", "/user/avatar", jsonHeader, nil) + if err != nil { + return resp, err + } + if status != http.StatusNoContent { + return resp, fmt.Errorf("unexpected status: %d", status) + } + return resp, nil +} diff --git a/vendor/code.gitea.io/sdk/gitea/version.go b/vendor/code.gitea.io/sdk/gitea/version.go index 5357e7d002e..43c67dfca87 100644 --- a/vendor/code.gitea.io/sdk/gitea/version.go +++ b/vendor/code.gitea.io/sdk/gitea/version.go @@ -71,6 +71,7 @@ var ( version1_17_0 = version.Must(version.NewVersion("1.17.0")) version1_22_0 = version.Must(version.NewVersion("1.22.0")) version1_23_0 = version.Must(version.NewVersion("1.23.0")) + version1_25_0 = version.Must(version.NewVersion("1.25.0")) ) // ErrUnknownVersion is an unknown version from the API diff --git a/vendor/modules.txt b/vendor/modules.txt index 4c81be9a573..2d86545ae65 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -44,8 +44,8 @@ cloud.google.com/go/kms/internal cloud.google.com/go/longrunning cloud.google.com/go/longrunning/autogen cloud.google.com/go/longrunning/autogen/longrunningpb -# code.gitea.io/sdk/gitea v0.21.0 -## explicit; go 1.23 +# code.gitea.io/sdk/gitea v0.23.2 +## explicit; go 1.23.0 code.gitea.io/sdk/gitea # contrib.go.opencensus.io/exporter/ocagent v0.7.1-0.20200907061046-05415f1de66d ## explicit; go 1.13 @@ -56,8 +56,8 @@ contrib.go.opencensus.io/exporter/prometheus # fortio.org/safecast v1.2.0 ## explicit; go 1.20 fortio.org/safecast -# github.com/42wim/httpsig v1.2.2 -## explicit; go 1.18 +# github.com/42wim/httpsig v1.2.3 +## explicit; go 1.23.0 github.com/42wim/httpsig # github.com/Azure/azure-sdk-for-go v68.0.0+incompatible ## explicit