revert: tea 1.0 rewrite (#1122–#1126) (#1146)

Reverts #1126, #1125, #1124, #1123 and #1122.

`go.mod` keeps the Go 1.26 line with toolchain `go1.26.9` (instead of the original `go1.26.6`) so the security fix from #1131 isn't lost.

reopens #69
reopens #141
reopens #162
reopens #172
reopens #197
reopens #232
reopens #240
reopens #246
reopens #323
reopens #325
reopens #326
reopens #328
reopens #344
reopens #351
reopens #373
reopens #403
reopens #406
reopens #417
reopens #430
reopens #457
reopens #480
reopens #482
reopens #489
reopens #490
reopens #498
reopens #500
reopens #504
reopens #510
reopens #516
reopens #523
reopens #556
reopens #560
reopens #569
reopens #571
reopens #602
reopens #632
reopens #633
reopens #643
reopens #666
reopens #670
reopens #672
reopens #677
reopens #683
reopens #697
reopens #726
reopens #737
reopens #770
reopens #779
reopens #804
reopens #817
reopens #831
reopens #833
reopens #834
reopens #908
reopens #966
reopens #1023
reopens #1029
reopens #1032
reopens #1050
reopens #1052
reopens #1069
reopens #1073
reopens #1087
reopens #1091
reopens #1094
reopens #1110
reopens #1115
reopens #1116
reopens #1118

Reviewed-on: https://gitea.com/gitea/tea/pulls/1146
Reviewed-by: TheFox0x7 <95654+thefox0x7@noreply.gitea.com>
This commit is contained in:
bircni committed 2026-10-18 20:56:33 +00:00
1 parent 33bb12729e
commit c5f674111a
604 files changed
+33711 -35545

No files matched your search

+160
View File
@@ -0,0 +1,160 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repos
import (
stdctx "context"
"fmt"
"gitea.dev/sdk"
"gitea.dev/tea/cmd/flags"
"gitea.dev/tea/modules/context"
"gitea.dev/tea/modules/print"
"github.com/urfave/cli/v3"
)
// CmdRepoCreate represents a sub command of repos to create one
var CmdRepoCreate = cli.Command{
Name: "create",
Aliases: []string{"c"},
Usage: "Create a repository",
Description: "Create a repository",
ArgsUsage: " ", // command does not accept arguments
Action: runRepoCreate,
Flags: append([]cli.Flag{
&cli.StringFlag{
Name: "name",
Aliases: []string{""},
Required: true,
Usage: "name of new repo",
},
&cli.StringFlag{
Name: "owner",
Aliases: []string{"O"},
Required: false,
Usage: "name of repo owner",
},
&cli.BoolFlag{
Name: "private",
Required: false,
Value: false,
Usage: "make repo private",
},
&cli.StringFlag{
Name: "description",
Aliases: []string{"desc"},
Required: false,
Usage: "add description to repo",
},
&cli.BoolFlag{
Name: "init",
Required: false,
Value: false,
Usage: "initialize repo",
},
&cli.StringFlag{
Name: "labels",
Required: false,
Usage: "name of label set to add",
},
&cli.StringFlag{
Name: "gitignores",
Aliases: []string{"git"},
Required: false,
Usage: "list of gitignore templates (need --init)",
},
&cli.StringFlag{
Name: "license",
Required: false,
Usage: "add license (need --init)",
},
&cli.StringFlag{
Name: "readme",
Required: false,
Usage: "use readme template (need --init)",
},
&cli.StringFlag{
Name: "branch",
Required: false,
Usage: "use custom default branch (need --init)",
},
&cli.BoolFlag{
Name: "template",
Usage: "make repo a template repo",
},
&cli.StringFlag{
Name: "trustmodel",
Usage: "select trust model (committer,collaborator,collaborator+committer)",
},
&cli.StringFlag{
Name: "object-format",
Required: false,
Usage: "select git object format (sha1,sha256)",
Validator: func(v string) error {
if v != "sha1" && v != "sha256" {
return fmt.Errorf("invalid object format '%s', must be either 'sha1' or 'sha256'", v)
}
return nil
},
},
}, flags.LoginOutputFlags...),
}
func runRepoCreate(requestCtx stdctx.Context, cmd *cli.Command) error {
ctx, err := context.InitCommand(cmd)
if err != nil {
return err
}
client := ctx.Login.Client()
var (
repo *gitea.Repository
trustmodel gitea.TrustModel
)
if ctx.IsSet("trustmodel") {
switch ctx.String("trustmodel") {
case "committer":
trustmodel = gitea.TrustModelCommitter
case "collaborator":
trustmodel = gitea.TrustModelCollaborator
case "collaborator+committer":
trustmodel = gitea.TrustModelCollaboratorCommitter
default:
return fmt.Errorf("unknown trustmodel type '%s'", ctx.String("trustmodel"))
}
}
opts := gitea.CreateRepoOption{
Name: ctx.String("name"),
Description: ctx.String("description"),
Private: ctx.Bool("private"),
AutoInit: ctx.Bool("init"),
IssueLabels: ctx.String("labels"),
Gitignores: ctx.String("gitignores"),
License: ctx.String("license"),
Readme: ctx.String("readme"),
DefaultBranch: ctx.String("branch"),
Template: ctx.Bool("template"),
TrustModel: trustmodel,
ObjectFormatName: ctx.String("object-format"),
}
if len(ctx.String("owner")) != 0 {
repo, _, err = client.Repositories.CreateOrgRepo(requestCtx, ctx.String("owner"), opts)
} else {
repo, _, err = client.Repositories.CreateRepo(requestCtx, opts)
}
if err != nil {
return err
}
topics, _, err := client.Repositories.ListRepoTopics(requestCtx, repo.Owner.UserName, repo.Name, gitea.ListRepoTopicsOptions{})
if err != nil {
return err
}
print.RepoDetails(repo, topics)
fmt.Printf("%s\n", repo.HTMLURL)
return nil
}
+125
View File
@@ -0,0 +1,125 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repos
import (
"fmt"
stdctx "context"
"gitea.dev/sdk"
"github.com/urfave/cli/v3"
"gitea.dev/tea/cmd/flags"
"gitea.dev/tea/modules/context"
"gitea.dev/tea/modules/print"
"gitea.dev/tea/modules/utils"
)
// CmdRepoCreateFromTemplate represents a sub command of repos to generate one from a template repo
var CmdRepoCreateFromTemplate = cli.Command{
Name: "create-from-template",
Aliases: []string{"ct"},
Usage: "Create a repository based on an existing template",
Description: "Create a repository based on an existing template",
Action: runRepoCreateFromTemplate,
Flags: append([]cli.Flag{
&cli.StringFlag{
Name: "template",
Aliases: []string{"t"},
Required: true,
Usage: "source template to copy from",
},
&cli.StringFlag{
Name: "name",
Aliases: []string{"n"},
Required: true,
Usage: "name of new repo",
},
&cli.StringFlag{
Name: "owner",
Aliases: []string{"O"},
Usage: "name of repo owner",
},
&cli.BoolFlag{
Name: "private",
Usage: "make new repo private",
},
&cli.StringFlag{
Name: "description",
Aliases: []string{"desc"},
Usage: "add custom description to repo",
},
&cli.BoolFlag{
Name: "content",
Value: true,
Usage: "copy git content from template",
},
&cli.BoolFlag{
Name: "githooks",
Value: true,
Usage: "copy git hooks from template",
},
&cli.BoolFlag{
Name: "avatar",
Value: true,
Usage: "copy repo avatar from template",
},
&cli.BoolFlag{
Name: "labels",
Value: true,
Usage: "copy repo labels from template",
},
&cli.BoolFlag{
Name: "topics",
Value: true,
Usage: "copy topics from template",
},
&cli.BoolFlag{
Name: "webhooks",
Usage: "copy webhooks from template",
},
}, flags.LoginOutputFlags...),
}
func runRepoCreateFromTemplate(requestCtx stdctx.Context, cmd *cli.Command) error {
ctx, err := context.InitCommand(cmd)
if err != nil {
return err
}
client := ctx.Login.Client()
templateOwner, templateRepo := utils.GetOwnerAndRepo(ctx.String("template"), ctx.Login.User)
owner := ctx.Login.User
if ctx.IsSet("owner") {
owner = ctx.String("owner")
}
opts := gitea.CreateRepoFromTemplateOption{
Name: ctx.String("name"),
Owner: owner,
Description: ctx.String("description"),
Private: ctx.Bool("private"),
GitContent: ctx.Bool("content"),
GitHooks: ctx.Bool("githooks"),
Avatar: ctx.Bool("avatar"),
Labels: ctx.Bool("labels"),
Topics: ctx.Bool("topics"),
Webhooks: ctx.Bool("webhooks"),
}
repo, _, err := client.Repositories.CreateRepoFromTemplate(requestCtx, templateOwner, templateRepo, opts)
if err != nil {
return err
}
topics, _, err := client.Repositories.ListRepoTopics(requestCtx, repo.Owner.UserName, repo.Name, gitea.ListRepoTopicsOptions{})
if err != nil {
return err
}
print.RepoDetails(repo, topics)
fmt.Printf("%s\n", repo.HTMLURL)
return nil
}
+89
View File
@@ -0,0 +1,89 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repos
import (
stdctx "context"
"fmt"
"gitea.dev/tea/cmd/flags"
"gitea.dev/tea/modules/context"
"charm.land/huh/v2"
"github.com/urfave/cli/v3"
)
// CmdRepoRm represents a sub command of repos to delete an existing repo
var CmdRepoRm = cli.Command{
Name: "delete",
Aliases: []string{"rm"},
Usage: "Delete an existing repository",
Description: "Removes a repository from your Gitea instance",
ArgsUsage: " ", // command does not accept arguments
Action: runRepoDelete,
Flags: append([]cli.Flag{
&cli.StringFlag{
Name: "name",
Aliases: []string{""},
Required: true,
Usage: "name of the repo",
},
&cli.StringFlag{
Name: "owner",
Aliases: []string{"O"},
Required: false,
Usage: "owner of the repo",
},
&cli.BoolFlag{
Name: "force",
Aliases: []string{"f"},
Required: false,
Value: false,
Usage: "Force the deletion and don't ask for confirmation",
},
}, flags.LoginOutputFlags...),
}
func runRepoDelete(requestCtx stdctx.Context, cmd *cli.Command) error {
ctx, err := context.InitCommand(cmd)
if err != nil {
return err
}
client := ctx.Login.Client()
var owner string
if ctx.IsSet("owner") {
owner = ctx.String("owner")
} else {
owner = ctx.Login.User
}
repoName := ctx.String("name")
repoSlug := fmt.Sprintf("%s/%s", owner, repoName)
if !ctx.Bool("force") {
var enteredRepoSlug string
if err := huh.NewInput().
Title(fmt.Sprintf("Confirm the deletion of the repository '%s' by typing its name: ", repoSlug)).
Validate(huh.ValidateNotEmpty()).
Value(&enteredRepoSlug).
Run(); err != nil {
return err
}
if enteredRepoSlug != repoSlug {
return fmt.Errorf("entered wrong repository name '%s', expected '%s'", enteredRepoSlug, repoSlug)
}
}
_, err = client.Repositories.DeleteRepo(requestCtx, owner, repoName)
if err != nil {
return err
}
fmt.Printf("Successfully deleted %s/%s\n", owner, repoName)
return nil
}
+111
View File
@@ -0,0 +1,111 @@
// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repos
import (
stdctx "context"
"strings"
"gitea.dev/sdk"
"gitea.dev/tea/cmd/flags"
"gitea.dev/tea/modules/context"
"gitea.dev/tea/modules/print"
"github.com/urfave/cli/v3"
)
// CmdRepoEdit represents a sub command of repos to edit one
var CmdRepoEdit = cli.Command{
Name: "edit",
Aliases: []string{"e"},
Usage: "Edit repository properties",
Description: "Edit repository properties",
ArgsUsage: " ", // command does not accept arguments
Action: runRepoEdit,
Flags: append([]cli.Flag{
&cli.StringFlag{
Name: "name",
Usage: "New name of the repository",
},
&cli.StringFlag{
Name: "description",
Aliases: []string{"desc"},
Usage: "New description of the repository",
},
&cli.StringFlag{
Name: "website",
Usage: "New website URL of the repository",
},
&cli.StringFlag{
Name: "private",
Usage: "Set private [true/false]",
DefaultText: "true",
},
&cli.StringFlag{
Name: "template",
Usage: "Set template [true/false]",
DefaultText: "true",
},
&cli.StringFlag{
Name: "archived",
Usage: "Set archived [true/false]",
DefaultText: "true",
},
&cli.StringFlag{
Name: "default-branch",
Usage: "Set default branch",
},
}, flags.AllDefaultFlags...),
}
func runRepoEdit(requestCtx stdctx.Context, cmd *cli.Command) error {
ctx, err := context.InitCommand(cmd)
if err != nil {
return err
}
if err := ctx.Ensure(context.CtxRequirement{RemoteRepo: true}); err != nil {
return err
}
client := ctx.Login.Client()
opts := gitea.EditRepoOption{}
if ctx.IsSet("name") {
val := ctx.String("name")
opts.Name = &val
}
if ctx.IsSet("description") {
val := ctx.String("description")
opts.Description = &val
}
if ctx.IsSet("website") {
val := ctx.String("website")
opts.Website = &val
}
if ctx.IsSet("default-branch") {
val := ctx.String("default-branch")
opts.DefaultBranch = &val
}
if ctx.IsSet("private") {
opts.Private = gitea.OptionalBool(strings.ToLower(ctx.String("private"))[:1] == "t")
}
if ctx.IsSet("template") {
opts.Template = gitea.OptionalBool(strings.ToLower(ctx.String("template"))[:1] == "t")
}
if ctx.IsSet("archived") {
opts.Archived = gitea.OptionalBool(strings.ToLower(ctx.String("archived"))[:1] == "t")
}
repo, _, err := client.Repositories.EditRepo(requestCtx, ctx.Owner, ctx.Repo, opts)
if err != nil {
return err
}
topics, _, err := client.Repositories.ListRepoTopics(requestCtx, repo.Owner.UserName, repo.Name, gitea.ListRepoTopicsOptions{})
if err != nil {
return err
}
print.RepoDetails(repo, topics)
return nil
}
+36
View File
@@ -0,0 +1,36 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repos
import (
"fmt"
"gitea.dev/sdk"
"github.com/urfave/cli/v3"
)
var typeFilterFlag = cli.StringFlag{
Name: "type",
Aliases: []string{"T"},
Required: false,
Usage: "Filter by type: fork, mirror, source",
}
func getTypeFilter(cmd *cli.Command) (filter gitea.RepoType, err error) {
t := cmd.String("type")
filter = gitea.RepoTypeNone
switch t {
case "":
filter = gitea.RepoTypeNone
case "fork":
filter = gitea.RepoTypeFork
case "mirror":
filter = gitea.RepoTypeMirror
case "source":
filter = gitea.RepoTypeSource
default:
err = fmt.Errorf("invalid repo type '%s'. valid: fork, mirror, source", t)
}
return
}
+64
View File
@@ -0,0 +1,64 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repos
import (
stdctx "context"
"fmt"
"gitea.dev/sdk"
"gitea.dev/tea/cmd/flags"
"gitea.dev/tea/modules/context"
"gitea.dev/tea/modules/print"
"github.com/urfave/cli/v3"
)
// CmdRepoFork represents a sub command of repos to fork an existing repo
var CmdRepoFork = cli.Command{
Name: "fork",
Aliases: []string{"f"},
Usage: "Fork an existing repository",
Description: "Create a repository from an existing repo",
ArgsUsage: " ", // command does not accept arguments
Action: runRepoFork,
Flags: append([]cli.Flag{
&cli.StringFlag{
Name: "owner",
Aliases: []string{"O"},
Usage: "name of fork's owner, defaults to current user",
},
}, flags.LoginRepoFlags...),
}
func runRepoFork(requestCtx stdctx.Context, cmd *cli.Command) error {
ctx, err := context.InitCommand(cmd)
if err != nil {
return err
}
if err := ctx.Ensure(context.CtxRequirement{RemoteRepo: true}); err != nil {
return err
}
client := ctx.Login.Client()
opts := gitea.CreateForkOption{}
if ctx.IsSet("owner") {
owner := ctx.String("owner")
opts.Organization = &owner
}
repo, _, err := client.Repositories.CreateFork(requestCtx, ctx.Owner, ctx.Repo, opts)
if err != nil {
return err
}
topics, _, err := client.Repositories.ListRepoTopics(requestCtx, repo.Owner.UserName, repo.Name, gitea.ListRepoTopicsOptions{})
if err != nil {
return err
}
print.RepoDetails(repo, topics)
fmt.Printf("%s\n", repo.HTMLURL)
return nil
}
+187
View File
@@ -0,0 +1,187 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repos
import (
stdctx "context"
"fmt"
"net/http"
"gitea.dev/sdk"
"gitea.dev/tea/cmd/flags"
"gitea.dev/tea/modules/context"
"gitea.dev/tea/modules/print"
"github.com/urfave/cli/v3"
)
var repoFieldsFlag = flags.FieldsFlag(print.RepoFields, []string{
"owner", "name", "type", "ssh",
})
// CmdReposListFlags contains all flags needed for repo listing
var CmdReposListFlags = append([]cli.Flag{
&cli.BoolFlag{
Name: "watched",
Aliases: []string{"w"},
Required: false,
Usage: "List your watched repos instead",
},
&cli.BoolFlag{
Name: "starred",
Aliases: []string{"s"},
Required: false,
Usage: "List your starred repos instead",
},
&cli.StringFlag{
Name: "owner",
Aliases: []string{"O"},
Required: false,
Usage: "List repos of a specific owner (org or user)",
},
repoFieldsFlag,
&typeFilterFlag,
&flags.PaginationPageFlag,
&flags.PaginationLimitFlag,
}, flags.LoginOutputFlags...)
// CmdReposList represents a sub command of repos to list them
var CmdReposList = cli.Command{
Name: "list",
Aliases: []string{"ls"},
Usage: "List repositories you have access to",
Description: "List repositories you have access to",
Action: RunReposList,
Flags: CmdReposListFlags,
}
// RunReposList list repositories
func RunReposList(requestCtx stdctx.Context, cmd *cli.Command) error {
teaCmd, err := context.InitCommand(cmd)
if err != nil {
return err
}
client := teaCmd.Login.Client()
typeFilter, err := getTypeFilter(cmd)
if err != nil {
return err
}
var rps []*gitea.Repository
if owner := teaCmd.String("owner"); owner != "" {
var err error
_, resp, orgErr := client.Organizations.GetOrg(requestCtx, owner)
if orgErr != nil {
if resp == nil || resp.StatusCode != http.StatusNotFound {
return fmt.Errorf("could not find owner: %w", orgErr)
}
// not an org, treat as user
rps, _, err = client.Repositories.ListUserRepos(requestCtx, owner, gitea.ListReposOptions{
ListOptions: flags.GetListOptions(cmd),
})
} else {
rps, _, err = client.Repositories.ListOrgRepos(requestCtx, owner, gitea.ListOrgReposOptions{
ListOptions: flags.GetListOptions(cmd),
})
}
if err != nil {
return err
}
} else if teaCmd.Bool("starred") {
user, _, err := client.Users.GetMyUserInfo(requestCtx)
if err != nil {
return err
}
rps, _, err = client.Repositories.SearchRepos(requestCtx, gitea.SearchRepoOptions{
ListOptions: flags.GetListOptions(cmd),
StarredByUserID: user.ID,
})
if err != nil {
return err
}
} else if teaCmd.Bool("watched") {
// GetMyWatchedRepos doesn't expose server-side pagination,
// so we implement client-side pagination as a workaround
allRepos, _, err := client.Repositories.GetMyWatchedRepos(requestCtx)
if err != nil {
return err
}
rps = paginateRepos(allRepos, flags.GetListOptions(cmd))
} else {
var err error
rps, _, err = client.Repositories.ListMyRepos(requestCtx, gitea.ListReposOptions{
ListOptions: flags.GetListOptions(cmd),
})
if err != nil {
return err
}
}
reposFiltered := rps
if typeFilter != gitea.RepoTypeNone {
reposFiltered = filterReposByType(rps, typeFilter)
}
fields, err := repoFieldsFlag.GetValues(cmd)
if err != nil {
return err
}
return print.ReposList(reposFiltered, teaCmd.Output, fields)
}
func filterReposByType(repos []*gitea.Repository, t gitea.RepoType) []*gitea.Repository {
var filtered []*gitea.Repository
for _, r := range repos {
switch t {
case gitea.RepoTypeFork:
if !r.Fork {
continue
}
case gitea.RepoTypeMirror:
if !r.Mirror {
continue
}
case gitea.RepoTypeSource:
if r.Fork || r.Mirror {
continue
}
}
filtered = append(filtered, r)
}
return filtered
}
// paginateRepos implements client-side pagination for repositories.
// This is a workaround for API endpoints that don't support server-side pagination.
func paginateRepos(repos []*gitea.Repository, opts gitea.ListOptions) []*gitea.Repository {
if len(repos) == 0 {
return repos
}
pageSize := opts.PageSize
if pageSize <= 0 {
pageSize = flags.PaginationLimitFlag.Value
}
page := opts.Page
if page < 1 {
page = 1
}
start := (page - 1) * pageSize
end := start + pageSize
if start >= len(repos) {
return []*gitea.Repository{}
}
if end > len(repos) {
end = len(repos)
}
return repos[start:end]
}
+175
View File
@@ -0,0 +1,175 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repos
import (
"fmt"
stdctx "context"
"gitea.dev/sdk"
"github.com/urfave/cli/v3"
"gitea.dev/tea/cmd/flags"
"gitea.dev/tea/modules/context"
"gitea.dev/tea/modules/print"
)
// CmdRepoMigrate represents a sub command of repos to migrate one
var CmdRepoMigrate = cli.Command{
Name: "migrate",
Aliases: []string{"m"},
Usage: "Migrate a repository",
Description: "Migrate a repository and or mirror it.",
ArgsUsage: " ", // command does not accept arguments
Action: runRepoMigrate,
Flags: append([]cli.Flag{
&cli.StringFlag{
Name: "name",
Usage: "Name of the repository",
Required: true,
},
&cli.StringFlag{
Name: "owner",
Usage: "Owner of the repository",
Required: true,
},
&cli.StringFlag{
Name: "clone-url",
Usage: "Clone URL of the repository",
Required: true,
},
&cli.StringFlag{
Name: "service",
Usage: string("Service to migrate from. Supported services are: " + gitea.GitServicePlain +
", " + gitea.GitServiceGitea + ", " + gitea.GitServiceGitlab + ", " + gitea.GitServiceGogs),
Required: true,
},
&cli.BoolFlag{
Name: "mirror",
Usage: "Mirror the repository",
},
&cli.BoolFlag{
Name: "private",
Usage: "Make the repository private",
},
&cli.BoolFlag{
Name: "template",
Usage: "Make the repository a template",
},
&cli.BoolFlag{
Name: "wiki",
Usage: "Copy the wiki",
},
&cli.BoolFlag{
Name: "issues",
Usage: "Copy the issues",
},
&cli.BoolFlag{
Name: "labels",
Usage: "Copy the lables",
},
&cli.BoolFlag{
Name: "pull-requests",
Usage: "Copy the pull requests",
},
&cli.BoolFlag{
Name: "releases",
Usage: "Copy the releases",
},
&cli.BoolFlag{
Name: "milestones",
Usage: "Copy the milestones",
},
&cli.StringFlag{
Name: "mirror-interval",
Usage: "Interval to mirror the repository.",
},
&cli.BoolFlag{
Name: "lfs",
Usage: "Copy the LFS objects",
},
&cli.StringFlag{
Name: "lfs-endpoint",
Usage: "LFS endpoint to use",
},
&cli.StringFlag{
Name: "auth-user",
Usage: "Username to use for authentication.",
},
&cli.StringFlag{
Name: "auth-password",
Usage: "Password to use for authentication.",
},
&cli.StringFlag{
Name: "auth-token",
Usage: "Token to use for authentication.",
},
}, flags.LoginOutputFlags...),
}
func runRepoMigrate(requestCtx stdctx.Context, cmd *cli.Command) error {
ctx, err := context.InitCommand(cmd)
if err != nil {
return err
}
client := ctx.Login.Client()
var (
repo *gitea.Repository
service gitea.GitServiceType
)
if ctx.IsSet("service") {
switch ctx.String("service") {
case "git":
service = gitea.GitServicePlain
case "gitea":
service = gitea.GitServiceGitea
case "gitlab":
service = gitea.GitServiceGitlab
case "gogs":
service = gitea.GitServiceGogs
case "github":
service = gitea.GitServiceGithub
default:
return fmt.Errorf("unknown git service type '%s'", ctx.String("service"))
}
}
opts := gitea.MigrateRepoOption{
RepoName: ctx.String("name"),
RepoOwner: ctx.String("owner"),
CloneAddr: ctx.String("clone-url"),
Service: service,
AuthUsername: ctx.String("auth-user"),
AuthPassword: ctx.String("auth-password"),
AuthToken: ctx.String("auth-token"),
Mirror: ctx.Bool("mirror"),
Private: ctx.Bool("private"),
Description: ctx.String("description"),
Wiki: ctx.Bool("wiki"),
Milestones: ctx.Bool("milestones"),
Labels: ctx.Bool("labels"),
Issues: ctx.Bool("issues"),
PullRequests: ctx.Bool("pull-requests"),
Releases: ctx.Bool("releases"),
MirrorInterval: ctx.String("mirror-interval"),
LFS: ctx.Bool("lfs"),
LFSEndpoint: ctx.String("lfs-endpoint"),
}
repo, _, err = client.Repositories.MigrateRepo(requestCtx, opts)
if err != nil {
return err
}
topics, _, err := client.Repositories.ListRepoTopics(requestCtx, repo.Owner.UserName, repo.Name, gitea.ListRepoTopicsOptions{})
if err != nil {
return err
}
print.RepoDetails(repo, topics)
fmt.Printf("%s\n", repo.HTMLURL)
return nil
}
+134
View File
@@ -0,0 +1,134 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package repos
import (
stdctx "context"
"fmt"
"net/http"
"strings"
"gitea.dev/sdk"
"gitea.dev/tea/cmd/flags"
"gitea.dev/tea/modules/context"
"gitea.dev/tea/modules/print"
"github.com/urfave/cli/v3"
)
// CmdReposSearch represents a sub command of repos to find them
var CmdReposSearch = cli.Command{
Name: "search",
Aliases: []string{"s"},
Usage: "Find any repo on an Gitea instance",
Description: "Find any repo on an Gitea instance",
ArgsUsage: "[<search term>]",
Action: runReposSearch,
Flags: append([]cli.Flag{
&cli.BoolFlag{
// TODO: it might be nice to search for topics as an ADDITIONAL filter.
// for that, we'd probably need to make multiple queries and UNION the results.
Name: "topic",
Aliases: []string{"t"},
Required: false,
Usage: "Search for term in repo topics instead of name",
},
&typeFilterFlag,
&cli.StringFlag{
Name: "owner",
Aliases: []string{"O"},
Required: false,
Usage: "Filter by owner",
},
&cli.StringFlag{
Name: "private",
Required: false,
Usage: "Filter private repos (true|false)",
},
&cli.StringFlag{
Name: "archived",
Required: false,
Usage: "Filter archived repos (true|false)",
},
repoFieldsFlag,
&flags.PaginationPageFlag,
&flags.PaginationLimitFlag,
}, flags.LoginOutputFlags...),
}
func runReposSearch(requestCtx stdctx.Context, cmd *cli.Command) error {
teaCmd, err := context.InitCommand(cmd)
if err != nil {
return err
}
client := teaCmd.Login.Client()
var ownerID int64
if teaCmd.IsSet("owner") {
// test if owner is an organization
org, resp, err := client.Organizations.GetOrg(requestCtx, teaCmd.String("owner"))
if err != nil {
if resp == nil || resp.StatusCode != http.StatusNotFound {
return fmt.Errorf("could not find owner: %w", err)
}
// if owner is no org, its a user
user, _, err := client.Users.GetUserInfo(requestCtx, teaCmd.String("owner"))
if err != nil {
return err
}
ownerID = user.ID
} else {
ownerID = org.ID
}
}
var isArchived *bool
if teaCmd.IsSet("archived") {
archived := strings.ToLower(teaCmd.String("archived"))[:1] == "t"
isArchived = &archived
}
var isPrivate *bool
if teaCmd.IsSet("private") {
private := strings.ToLower(teaCmd.String("private"))[:1] == "t"
isPrivate = &private
}
mode, err := getTypeFilter(cmd)
if err != nil {
return err
}
var keyword string
if teaCmd.Args().Present() {
keyword = strings.Join(teaCmd.Args().Slice(), " ")
}
user, _, err := client.Users.GetMyUserInfo(requestCtx)
if err != nil {
return err
}
rps, _, err := client.Repositories.SearchRepos(requestCtx, gitea.SearchRepoOptions{
ListOptions: flags.GetListOptions(cmd),
OwnerID: ownerID,
IsPrivate: isPrivate,
IsArchived: isArchived,
Type: mode,
Keyword: keyword,
KeywordInDescription: true,
KeywordIsTopic: teaCmd.Bool("topic"),
PrioritizedByOwnerID: user.ID,
})
if err != nil {
return err
}
fields, err := repoFieldsFlag.GetValues(cmd)
if err != nil {
return err
}
return print.ReposList(rps, teaCmd.Output, fields)
}