Add Repo Create subcomand & enhancements (#173)
repos ls: use owner filter and remove org&user one better desc refactor rm local filter, let us fix upstream split user org add archive and private filters use SearchRepos migrate to sdk v0.13.0 print URL add CmdRepoCreate, Add RepoDetails ListRepos: better desc, add aliases, add note for sdk-release Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/173 Reviewed-by: Andrew Thornton <art27@cantab.net> Reviewed-by: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
parent
eacf1be066
commit
2e701ee8a2
277
cmd/repos.go
277
cmd/repos.go
|
@ -5,26 +5,32 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/tea/modules/utils"
|
||||||
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdRepos represents to login a gitea server.
|
// CmdRepos represents to login a gitea server.
|
||||||
var CmdRepos = cli.Command{
|
var CmdRepos = cli.Command{
|
||||||
Name: "repos",
|
Name: "repos",
|
||||||
Usage: "Operate with repositories",
|
Usage: "Show repositories details",
|
||||||
Description: `Operate with repositories`,
|
Description: "Show repositories details",
|
||||||
Action: runReposList,
|
ArgsUsage: "[<repo owner>/<repo name>]",
|
||||||
|
Action: runRepos,
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
&CmdReposList,
|
&CmdReposList,
|
||||||
|
&CmdRepoCreate,
|
||||||
},
|
},
|
||||||
Flags: LoginOutputFlags,
|
Flags: LoginOutputFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
// CmdReposList represents a sub command of issues to list issues
|
// CmdReposList represents a sub command of repos to list them
|
||||||
var CmdReposList = cli.Command{
|
var CmdReposList = cli.Command{
|
||||||
Name: "ls",
|
Name: "ls",
|
||||||
Usage: "List available repositories",
|
Usage: "List available repositories",
|
||||||
|
@ -33,65 +39,163 @@ var CmdReposList = cli.Command{
|
||||||
Flags: append([]cli.Flag{
|
Flags: append([]cli.Flag{
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "mode",
|
Name: "mode",
|
||||||
Usage: "Filter listed repositories based on mode, optional - fork, mirror, source",
|
Aliases: []string{"m"},
|
||||||
|
Required: false,
|
||||||
|
Usage: "Filter by mode: fork, mirror, source",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "org",
|
Name: "owner",
|
||||||
Usage: "Filter listed repositories based on organization, optional",
|
Aliases: []string{"O"},
|
||||||
|
Required: false,
|
||||||
|
Usage: "Filter by owner",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "user",
|
Name: "private",
|
||||||
Usage: "Filter listed repositories absed on user, optional",
|
Required: false,
|
||||||
|
Usage: "Filter private repos (true|false)",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "archived",
|
||||||
|
Required: false,
|
||||||
|
Usage: "Filter archived repos (true|false)",
|
||||||
},
|
},
|
||||||
}, LoginOutputFlags...),
|
}, LoginOutputFlags...),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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",
|
||||||
|
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)",
|
||||||
|
},
|
||||||
|
}, LoginOutputFlags...),
|
||||||
|
}
|
||||||
|
|
||||||
|
func runRepos(ctx *cli.Context) error {
|
||||||
|
if ctx.Args().Len() == 1 {
|
||||||
|
return runRepoDetail(ctx, ctx.Args().First())
|
||||||
|
}
|
||||||
|
return runReposList(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
// runReposList list repositories
|
// runReposList list repositories
|
||||||
func runReposList(ctx *cli.Context) error {
|
func runReposList(ctx *cli.Context) error {
|
||||||
login := initCommandLoginOnly()
|
login := initCommandLoginOnly()
|
||||||
|
client := login.Client()
|
||||||
|
|
||||||
mode := ctx.String("mode")
|
var ownerID int64
|
||||||
org := ctx.String("org")
|
if ctx.IsSet("owner") {
|
||||||
user := ctx.String("user")
|
// test if owner is a organisation
|
||||||
|
org, resp, err := client.GetOrg(ctx.String("owner"))
|
||||||
var rps []*gitea.Repository
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if org != "" {
|
|
||||||
rps, _, err = login.Client().ListOrgRepos(org, gitea.ListOrgReposOptions{})
|
|
||||||
} else if user != "" {
|
|
||||||
rps, _, err = login.Client().ListUserRepos(user, gitea.ListReposOptions{})
|
|
||||||
} else {
|
|
||||||
rps, _, err = login.Client().ListMyRepos(gitea.ListReposOptions{})
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
if resp == nil || resp.StatusCode != http.StatusNotFound {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
// if owner is no org, its a user
|
||||||
var repos []*gitea.Repository
|
user, _, err := client.GetUserInfo(ctx.String("owner"))
|
||||||
if mode == "" {
|
if err != nil {
|
||||||
repos = rps
|
return err
|
||||||
} else if mode == "fork" {
|
|
||||||
for _, rp := range rps {
|
|
||||||
if rp.Fork == true {
|
|
||||||
repos = append(repos, rp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if mode == "mirror" {
|
|
||||||
for _, rp := range rps {
|
|
||||||
if rp.Mirror == true {
|
|
||||||
repos = append(repos, rp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if mode == "source" {
|
|
||||||
for _, rp := range rps {
|
|
||||||
if rp.Mirror != true && rp.Fork != true {
|
|
||||||
repos = append(repos, rp)
|
|
||||||
}
|
}
|
||||||
|
ownerID = user.ID
|
||||||
|
} else {
|
||||||
|
ownerID = org.ID
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Fatal("Unknown mode: ", mode, "\nUse one of the following:\n- fork\n- mirror\n- source\n")
|
me, _, err := client.GetMyUserInfo()
|
||||||
return nil
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ownerID = me.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
var isArchived *bool
|
||||||
|
if ctx.IsSet("archived") {
|
||||||
|
archived := strings.ToLower(ctx.String("archived"))[:1] == "t"
|
||||||
|
isArchived = &archived
|
||||||
|
}
|
||||||
|
|
||||||
|
var isPrivate *bool
|
||||||
|
if ctx.IsSet("private") {
|
||||||
|
private := strings.ToLower(ctx.String("private"))[:1] == "t"
|
||||||
|
isArchived = &private
|
||||||
|
}
|
||||||
|
|
||||||
|
mode := gitea.RepoTypeNone
|
||||||
|
switch ctx.String("mode") {
|
||||||
|
case "fork":
|
||||||
|
mode = gitea.RepoTypeFork
|
||||||
|
case "mirror":
|
||||||
|
mode = gitea.RepoTypeMirror
|
||||||
|
case "source":
|
||||||
|
mode = gitea.RepoTypeSource
|
||||||
|
}
|
||||||
|
|
||||||
|
rps, _, err := client.SearchRepos(gitea.SearchRepoOptions{
|
||||||
|
OwnerID: ownerID,
|
||||||
|
IsPrivate: isPrivate,
|
||||||
|
IsArchived: isArchived,
|
||||||
|
Type: mode,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rps) == 0 {
|
if len(rps) == 0 {
|
||||||
|
@ -107,7 +211,7 @@ func runReposList(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
var values [][]string
|
var values [][]string
|
||||||
|
|
||||||
for _, rp := range repos {
|
for _, rp := range rps {
|
||||||
var mode = "source"
|
var mode = "source"
|
||||||
if rp.Fork {
|
if rp.Fork {
|
||||||
mode = "fork"
|
mode = "fork"
|
||||||
|
@ -130,3 +234,80 @@ func runReposList(ctx *cli.Context) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func runRepoDetail(_ *cli.Context, path string) error {
|
||||||
|
login := initCommandLoginOnly()
|
||||||
|
client := login.Client()
|
||||||
|
repoOwner, repoName := getOwnerAndRepo(path, login.User)
|
||||||
|
repo, _, err := client.GetRepo(repoOwner, repoName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
topics, _, err := client.ListRepoTopics(repo.Owner.UserName, repo.Name, gitea.ListRepoTopicsOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
output := repo.FullName
|
||||||
|
if repo.Mirror {
|
||||||
|
output += " (mirror)"
|
||||||
|
}
|
||||||
|
if repo.Fork {
|
||||||
|
output += " (fork)"
|
||||||
|
}
|
||||||
|
if repo.Archived {
|
||||||
|
output += " (archived)"
|
||||||
|
}
|
||||||
|
if repo.Empty {
|
||||||
|
output += " (empty)"
|
||||||
|
}
|
||||||
|
output += "\n"
|
||||||
|
if len(topics) != 0 {
|
||||||
|
output += "Topics: " + strings.Join(topics, ", ") + "\n"
|
||||||
|
}
|
||||||
|
output += "\n"
|
||||||
|
output += repo.Description + "\n\n"
|
||||||
|
output += fmt.Sprintf(
|
||||||
|
"Open Issues: %d, Stars: %d, Forks: %d, Size: %s\n\n",
|
||||||
|
repo.OpenIssues,
|
||||||
|
repo.Stars,
|
||||||
|
repo.Forks,
|
||||||
|
utils.FormatSize(int64(repo.Size)),
|
||||||
|
)
|
||||||
|
|
||||||
|
fmt.Print(output)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runRepoCreate(ctx *cli.Context) error {
|
||||||
|
login := initCommandLoginOnly()
|
||||||
|
client := login.Client()
|
||||||
|
var (
|
||||||
|
repo *gitea.Repository
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
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"),
|
||||||
|
}
|
||||||
|
if len(ctx.String("owner")) != 0 {
|
||||||
|
repo, _, err = client.CreateOrgRepo(ctx.String("owner"), opts)
|
||||||
|
} else {
|
||||||
|
repo, _, err = client.CreateRepo(opts)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = runRepoDetail(ctx, repo.FullName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", repo.HTMLURL)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Copyright 2020 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 utils
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// FormatSize get kb in int and return string
|
||||||
|
func FormatSize(kb int64) string {
|
||||||
|
if kb < 1024 {
|
||||||
|
return fmt.Sprintf("%d Kb", kb)
|
||||||
|
}
|
||||||
|
mb := kb / 1024
|
||||||
|
if mb < 1024 {
|
||||||
|
return fmt.Sprintf("%d Mb", mb)
|
||||||
|
}
|
||||||
|
gb := mb / 1024
|
||||||
|
if gb < 1024 {
|
||||||
|
return fmt.Sprintf("%d Gb", gb)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d Tb", gb/1024)
|
||||||
|
}
|
Loading…
Reference in New Issue