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:
6543 2020-09-23 19:49:59 +00:00
parent eacf1be066
commit 2e701ee8a2
2 changed files with 255 additions and 51 deletions

View File

@ -5,26 +5,32 @@
package cmd
import (
"fmt"
"log"
"net/http"
"strings"
"code.gitea.io/tea/modules/utils"
"code.gitea.io/sdk/gitea"
"github.com/urfave/cli/v2"
)
// CmdRepos represents to login a gitea server.
var CmdRepos = cli.Command{
Name: "repos",
Usage: "Operate with repositories",
Description: `Operate with repositories`,
Action: runReposList,
Usage: "Show repositories details",
Description: "Show repositories details",
ArgsUsage: "[<repo owner>/<repo name>]",
Action: runRepos,
Subcommands: []*cli.Command{
&CmdReposList,
&CmdRepoCreate,
},
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{
Name: "ls",
Usage: "List available repositories",
@ -32,66 +38,164 @@ var CmdReposList = cli.Command{
Action: runReposList,
Flags: append([]cli.Flag{
&cli.StringFlag{
Name: "mode",
Usage: "Filter listed repositories based on mode, optional - fork, mirror, source",
Name: "mode",
Aliases: []string{"m"},
Required: false,
Usage: "Filter by mode: fork, mirror, source",
},
&cli.StringFlag{
Name: "org",
Usage: "Filter listed repositories based on organization, optional",
Name: "owner",
Aliases: []string{"O"},
Required: false,
Usage: "Filter by owner",
},
&cli.StringFlag{
Name: "user",
Usage: "Filter listed repositories absed on user, optional",
Name: "private",
Required: false,
Usage: "Filter private repos (true|false)",
},
&cli.StringFlag{
Name: "archived",
Required: false,
Usage: "Filter archived repos (true|false)",
},
}, 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
func runReposList(ctx *cli.Context) error {
login := initCommandLoginOnly()
client := login.Client()
mode := ctx.String("mode")
org := ctx.String("org")
user := ctx.String("user")
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{})
var ownerID int64
if ctx.IsSet("owner") {
// test if owner is a organisation
org, resp, err := client.GetOrg(ctx.String("owner"))
if err != nil {
if resp == nil || resp.StatusCode != http.StatusNotFound {
return err
}
// if owner is no org, its a user
user, _, err := client.GetUserInfo(ctx.String("owner"))
if err != nil {
return err
}
ownerID = user.ID
} else {
ownerID = org.ID
}
} else {
rps, _, err = login.Client().ListMyRepos(gitea.ListReposOptions{})
me, _, err := client.GetMyUserInfo()
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 {
log.Fatal(err)
}
var repos []*gitea.Repository
if mode == "" {
repos = rps
} 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)
}
}
} else {
log.Fatal("Unknown mode: ", mode, "\nUse one of the following:\n- fork\n- mirror\n- source\n")
return nil
return err
}
if len(rps) == 0 {
@ -107,7 +211,7 @@ func runReposList(ctx *cli.Context) error {
}
var values [][]string
for _, rp := range repos {
for _, rp := range rps {
var mode = "source"
if rp.Fork {
mode = "fork"
@ -130,3 +234,80 @@ func runReposList(ctx *cli.Context) error {
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
}

23
modules/utils/format.go Normal file
View File

@ -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)
}