Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions cli/cmd_releases.go

This file was deleted.

40 changes: 0 additions & 40 deletions cli/cmd_repo.go

This file was deleted.

29 changes: 0 additions & 29 deletions cli/cmd_search.go

This file was deleted.

28 changes: 0 additions & 28 deletions cli/cmd_trending.go

This file was deleted.

35 changes: 0 additions & 35 deletions cli/cmd_user.go

This file was deleted.

11 changes: 0 additions & 11 deletions cli/errors.go

This file was deleted.

25 changes: 0 additions & 25 deletions cli/output.go

This file was deleted.

150 changes: 11 additions & 139 deletions cli/root.go
Original file line number Diff line number Diff line change
@@ -1,152 +1,24 @@
// Package cli builds the gitee command tree on top of the gitee library.
// Package cli assembles the gitee command tree from the gitee domain on top of
// the any-cli/kit framework.
package cli

import (
"fmt"
"os"

"github.com/mattn/go-isatty"
"github.com/spf13/cobra"
"github.com/tamnd/any-cli/kit"
"github.com/tamnd/gitee-cli/gitee"
)

// Build metadata, injected via -ldflags at release time.
// Build metadata, set via -ldflags at release time.
var (
Version = "dev"
Commit = "none"
Date = "unknown"
)

// exit codes.
const (
exitError = 1
exitUsage = 2
exitNoData = 3
)

// ExitError carries a process exit code up to main.
type ExitError struct {
Code int
Err error
}

func (e *ExitError) Error() string {
if e.Err != nil {
return e.Err.Error()
}
return fmt.Sprintf("exit %d", e.Code)
}

func (e *ExitError) Unwrap() error { return e.Err }

func codeError(code int, err error) error { return &ExitError{Code: code, Err: err} }

// App holds shared state threaded through every command.
type App struct {
client *gitee.Client
cfg gitee.Config

output string
fields []string
noHeader bool
template string
limit int
quiet bool
}

// Root builds the root command and its subtree.
func Root() *cobra.Command {
app := &App{cfg: gitee.DefaultConfig()}

root := &cobra.Command{
Use: "gitee",
Short: "Browse Gitee repositories and users",
Long: `gitee reads Gitee — China's largest Git hosting platform — through its
official public REST API. No authentication token is required. It returns
records as table, JSON, JSONL, CSV, TSV, or URLs.

gitee is an independent tool and is not affiliated with Gitee or Oschina.`,
SilenceUsage: true,
SilenceErrors: true,
PersistentPreRunE: func(cmd *cobra.Command, _ []string) error {
return app.setup()
},
}

pf := root.PersistentFlags()
pf.StringVarP(&app.output, "output", "o", "auto", "output: table|json|jsonl|csv|tsv|url|raw (auto=table on TTY, jsonl piped)")
pf.StringSliceVar(&app.fields, "fields", nil, "comma-separated columns to include")
pf.BoolVar(&app.noHeader, "no-header", false, "omit the header row in table/csv/tsv")
pf.StringVar(&app.template, "template", "", "Go text/template applied per record")
pf.IntVarP(&app.limit, "limit", "n", 0, "limit number of records (0 = command default)")
pf.BoolVarP(&app.quiet, "quiet", "q", false, "suppress progress on stderr")

pf.DurationVar(&app.cfg.Rate, "delay", app.cfg.Rate, "minimum spacing between requests")
pf.DurationVar(&app.cfg.Timeout, "timeout", app.cfg.Timeout, "per-request timeout")
pf.IntVar(&app.cfg.Retries, "retries", app.cfg.Retries, "retry attempts on 429/5xx")
pf.StringVar(&app.cfg.UserAgent, "user-agent", app.cfg.UserAgent, "User-Agent sent with each request")

root.AddCommand(
app.searchCmd(),
app.repoCmd(),
app.trendingCmd(),
app.userCmd(),
app.releasesCmd(),
newVersionCmd(),
)
return root
}

func (a *App) setup() error {
if a.output == "" || a.output == "auto" {
if isatty.IsTerminal(os.Stdout.Fd()) {
a.output = string(FormatTable)
} else {
a.output = string(FormatJSONL)
}
}
if !Format(a.output).Valid() {
return codeError(exitUsage, fmt.Errorf("unknown output format %q", a.output))
}
a.client = gitee.NewClient(a.cfg)
return nil
}

func (a *App) render(records any) error {
r := NewRenderer(os.Stdout, Format(a.output), a.fields, a.noHeader, a.template)
return r.Render(records)
}

func (a *App) renderOrEmpty(records any, n int) error {
if err := a.render(records); err != nil {
return err
}
if n == 0 {
return codeError(exitNoData, nil)
}
return nil
}

func (a *App) progressf(format string, args ...any) {
if a.quiet {
return
}
_, _ = fmt.Fprintf(os.Stderr, format+"\n", args...)
}

func mapFetchErr(err error) error {
if err == nil {
return nil
}
if isNotFound(err) {
return codeError(exitNoData, err)
}
return codeError(exitError, err)
}

func (a *App) effectiveLimit(def int) int {
if a.limit > 0 {
return a.limit
}
return def
// NewApp assembles the kit application from the gitee domain.
func NewApp() *kit.App {
id := gitee.BaseIdentity()
id.Version = Version
app := kit.New(id, kit.WithDefaults(gitee.Defaults))
gitee.Register(app)
return app
}
27 changes: 0 additions & 27 deletions cli/version.go

This file was deleted.

Loading