Commit 99ec0bbcaf
Verified · cmc
internal/control/build.go +55 −19
| @@ -22,37 +22,64 @@ import ( | ||
| 22 | 22 | func init() { |
| 23 | 23 | register(Command{Path: []string{"build", "list"}, |
| 24 | 24 | Summary: "list recent builds", |
| 25 | Usage: "build list <owner/name> [--ref <branch>] [--status <state>] [--job <name>] [--limit <n>] [--cursor <c>]", ReadOnly: true, Run: runBuildList}) | |
| 25 | Usage: "build list <owner/name> [--ref <branch>] [--status <state>] [--job <name>] [--limit <n>] [--cursor <c>]", | |
| 26 | Flags: []Flag{ | |
| 27 | {"--ref", "<branch>", "only builds on this branch", ""}, | |
| 28 | {"--status", "<state>", "only builds in this state", ""}, | |
| 29 | {"--job", "<name>", "only this job", ""}, | |
| 30 | {"--limit", "<n>", "rows per page", "50"}, | |
| 31 | {"--cursor", "<c>", "continue from the previous page", ""}, | |
| 32 | }, | |
| 33 | Examples: []string{"build list krz/gitbay --status failure"}, | |
| 34 | ReadOnly: true, Run: runBuildList}) | |
| 26 | 35 | register(Command{Path: []string{"build", "show"}, |
| 27 | Summary: "show one build", | |
| 28 | Usage: "build show <owner/name> <n>", ReadOnly: true, Run: runBuildShow}) | |
| 36 | Summary: "show one build", | |
| 37 | Usage: "build show <owner/name> <n>", | |
| 38 | Examples: []string{"build show krz/gitbay 431"}, | |
| 39 | ReadOnly: true, Run: runBuildShow}) | |
| 29 | 40 | register(Command{Path: []string{"build", "log"}, |
| 30 | 41 | Summary: "print a build's log, or follow it until the build ends", |
| 31 | Usage: "build log <owner/name> <n> [--follow]", ReadOnly: true, Run: runBuildLog}) | |
| 42 | Usage: "build log <owner/name> <n> [--follow]", | |
| 43 | Flags: []Flag{ | |
| 44 | {"--follow", "", "stream the log until the build ends", ""}, | |
| 45 | }, | |
| 46 | Examples: []string{"build log krz/gitbay 431 --follow"}, | |
| 47 | ReadOnly: true, Run: runBuildLog}) | |
| 32 | 48 | |
| 33 | 49 | register(Command{Path: []string{"build", "jobs"}, |
| 34 | Summary: "list the jobs a trigger can name", | |
| 35 | Usage: "build jobs <owner/name>", ReadOnly: true, Run: runBuildJobs}) | |
| 50 | Summary: "list the jobs a trigger can name", | |
| 51 | Usage: "build jobs <owner/name>", | |
| 52 | Examples: []string{"build jobs krz/gitbay"}, | |
| 53 | ReadOnly: true, Run: runBuildJobs}) | |
| 36 | 54 | |
| 37 | 55 | register(Command{Path: []string{"build", "cancel"}, |
| 38 | Summary: "withdraw a queued build before a runner claims it", | |
| 39 | Usage: "build cancel <owner/name> <n>", Run: runBuildCancel}) | |
| 56 | Summary: "withdraw a queued build before a runner claims it", | |
| 57 | Usage: "build cancel <owner/name> <n>", | |
| 58 | Examples: []string{"build cancel krz/gitbay 431"}, | |
| 59 | Run: runBuildCancel}) | |
| 40 | 60 | register(Command{Path: []string{"build", "trigger"}, |
| 41 | Summary: "queue a job now (scheduled or not)", | |
| 42 | Usage: "build trigger <owner/name> <job>", Run: runBuildTrigger}) | |
| 61 | Summary: "queue a job now (scheduled or not)", | |
| 62 | Usage: "build trigger <owner/name> <job>", | |
| 63 | Examples: []string{"build trigger krz/gitbay vuln"}, | |
| 64 | Run: runBuildTrigger}) | |
| 43 | 65 | // Secrets: set over stdin, listed by name only, injected into the |
| 44 | 66 | // repo's builds as environment variables. Same discipline as mirror |
| 45 | 67 | // tokens — the value never appears in argv, logs, or output. |
| 46 | 68 | register(Command{Path: []string{"repo", "secret", "set"}, |
| 47 | 69 | Summary: "set a build secret", |
| 48 | 70 | Usage: "repo secret set <owner/name> <NAME> (value on stdin)", |
| 71 | Examples: []string{"repo secret set krz/gitbay DEPLOY_TOKEN"}, | |
| 49 | 72 | ReadsStdin: true, Run: runSecretSet}) |
| 50 | 73 | register(Command{Path: []string{"repo", "secret", "remove"}, |
| 51 | Summary: "remove a build secret", | |
| 52 | Usage: "repo secret remove <owner/name> <NAME>", Run: runSecretRemove}) | |
| 74 | Summary: "remove a build secret", | |
| 75 | Usage: "repo secret remove <owner/name> <NAME>", | |
| 76 | Examples: []string{"repo secret remove krz/gitbay DEPLOY_TOKEN"}, | |
| 77 | Run: runSecretRemove}) | |
| 53 | 78 | register(Command{Path: []string{"repo", "secret", "list"}, |
| 54 | Summary: "list build secret names", | |
| 55 | Usage: "repo secret list <owner/name>", ReadOnly: true, Run: runSecretList}) | |
| 79 | Summary: "list build secret names", | |
| 80 | Usage: "repo secret list <owner/name>", | |
| 81 | Examples: []string{"repo secret list krz/gitbay"}, | |
| 82 | ReadOnly: true, Run: runSecretList}) | |
| 56 | 83 | |
| 57 | 84 | // Runner commands: the claim/report loop for gitbay-runner. A runner |
| 58 | 85 | // executes arbitrary repo code, so handing out jobs is the instance |
| @@ -61,13 +88,22 @@ func init() { | ||
| 61 | 88 | // an admin key, which a runner host should not hold (#92). |
| 62 | 89 | register(Command{Path: []string{"runner", "next"}, |
| 63 | 90 | Summary: "claim the oldest pending build this key may run (runner protocol)", |
| 64 | Usage: "runner next [--untrusted] [<owner/name>...]", Run: runRunnerNext}) | |
| 91 | Usage: "runner next [--untrusted] [<owner/name>...]", | |
| 92 | Flags: []Flag{ | |
| 93 | {"--untrusted", "", "this runner may build a fork's merge request head", ""}, | |
| 94 | }, | |
| 95 | Examples: []string{"runner next krz/gitbay"}, | |
| 96 | Run: runRunnerNext}) | |
| 65 | 97 | register(Command{Path: []string{"runner", "log"}, |
| 66 | Summary: "append a build's log from stdin", | |
| 67 | Usage: "runner log <build-id>", ReadsStdin: true, Run: runRunnerLog}) | |
| 98 | Summary: "append a build's log from stdin", | |
| 99 | Usage: "runner log <build-id>", | |
| 100 | Examples: []string{"runner log 431"}, | |
| 101 | ReadsStdin: true, Run: runRunnerLog}) | |
| 68 | 102 | register(Command{Path: []string{"runner", "done"}, |
| 69 | Summary: "finish a build", | |
| 70 | Usage: "runner done <build-id> success|failure", Run: runRunnerDone}) | |
| 103 | Summary: "finish a build", | |
| 104 | Usage: "runner done <build-id> success|failure", | |
| 105 | Examples: []string{"runner done 431 success"}, | |
| 106 | Run: runRunnerDone}) | |
| 71 | 107 | } |
| 72 | 108 | |
| 73 | 109 | type BuildOut struct { |
internal/control/commitfile.go +8
| @@ -17,6 +17,14 @@ func init() { | ||
| 17 | 17 | Summary: "write a file and commit it", |
| 18 | 18 | Usage: "repo commit-file <owner/name> <path> " + |
| 19 | 19 | "--ref <branch> [--message <m>] [--file -]", |
| 20 | Flags: []Flag{ | |
| 21 | {"--ref", "<branch>", "branch to commit to", ""}, | |
| 22 | {"--message", "<m>", "the commit message", ""}, | |
| 23 | {"--file", "-", "read the new content from stdin", ""}, | |
| 24 | }, | |
| 25 | Examples: []string{ | |
| 26 | `repo commit-file krz/gitbay CHANGELOG.org --ref main --message "note the release" --file - '< CHANGELOG.org'`, | |
| 27 | }, | |
| 20 | 28 | ReadsStdin: true, |
| 21 | 29 | Run: runCommitFile, |
| 22 | 30 | }) |
internal/control/control.go +10
| @@ -68,6 +68,14 @@ func (c *Ctx) usageWith(msg string) int { | ||
| 68 | 68 | return c.fail(protocol.ExitUsage, "%s\nusage: %s", msg, c.Cmd.Usage) |
| 69 | 69 | } |
| 70 | 70 | |
| 71 | // Flag is one flag in a command's help. | |
| 72 | type Flag struct { | |
| 73 | Name string // "--state" | |
| 74 | Arg string // "open|closed|all"; empty for a switch | |
| 75 | Desc string // what it does, lower case, no full stop | |
| 76 | Default string // empty for none | |
| 77 | } | |
| 78 | ||
| 71 | 79 | type Command struct { |
| 72 | 80 | Path []string // e.g. ["keys", "add"] |
| 73 | 81 | // Summary is one line of prose: what the command does, no argument |
| @@ -75,6 +83,8 @@ type Command struct { | ||
| 75 | 83 | // help renders them separately, so neither may carry the other's job. |
| 76 | 84 | Summary string |
| 77 | 85 | Usage string |
| 86 | Flags []Flag | |
| 87 | Examples []string // full argv after the program, repository named | |
| 78 | 88 | ReadsStdin bool |
| 79 | 89 | ReadOnly bool // safe for read-scoped API tokens |
| 80 | 90 | Run func(c *Ctx, args []string) int |
internal/control/dashboard.go +8 −2
| @@ -18,10 +18,16 @@ func init() { | ||
| 18 | 18 | register(Command{Path: []string{"dashboard"}, |
| 19 | 19 | Summary: "one read for the account dashboard: review queue, assigned and open work, pins, activity, builds", |
| 20 | 20 | Usage: "dashboard", |
| 21 | Examples: []string{"dashboard"}, | |
| 21 | 22 | ReadOnly: true, Run: runDashboard}) |
| 22 | 23 | register(Command{Path: []string{"feed"}, |
| 23 | Summary: "activity on repositories you can reach", | |
| 24 | Usage: "feed [--limit <n>] [--cursor <c>]", | |
| 24 | Summary: "activity on repositories you can reach", | |
| 25 | Usage: "feed [--limit <n>] [--cursor <c>]", | |
| 26 | Flags: []Flag{ | |
| 27 | {"--limit", "<n>", "rows per page", ""}, | |
| 28 | {"--cursor", "<c>", "continue from the previous page", ""}, | |
| 29 | }, | |
| 30 | Examples: []string{"feed --limit 20"}, | |
| 25 | 31 | ReadOnly: true, Run: runFeed}) |
| 26 | 32 | } |
| 27 | 33 | |
internal/control/deploykey.go +14 −6
| @@ -14,15 +14,23 @@ import ( | ||
| 14 | 14 | |
| 15 | 15 | func init() { |
| 16 | 16 | register(Command{Path: []string{"repo", "deploy-key", "add"}, |
| 17 | Summary: "bind a read-only (or --rw) key to one repository", | |
| 18 | Usage: "repo deploy-key add <owner/name> [--rw] < key.pub", | |
| 17 | Summary: "bind a read-only (or --rw) key to one repository", | |
| 18 | Usage: "repo deploy-key add <owner/name> [--rw] < key.pub", | |
| 19 | Flags: []Flag{ | |
| 20 | {"--rw", "", "the key may push, not just fetch", ""}, | |
| 21 | }, | |
| 22 | Examples: []string{"repo deploy-key add krz/gitbay '< key.pub'"}, | |
| 19 | 23 | ReadsStdin: true, Run: runDeployKeyAdd}) |
| 20 | 24 | register(Command{Path: []string{"repo", "deploy-key", "list"}, |
| 21 | Summary: "list deploy keys", | |
| 22 | Usage: "repo deploy-key list <owner/name>", ReadOnly: true, Run: runDeployKeyList}) | |
| 25 | Summary: "list deploy keys", | |
| 26 | Usage: "repo deploy-key list <owner/name>", | |
| 27 | Examples: []string{"repo deploy-key list krz/gitbay"}, | |
| 28 | ReadOnly: true, Run: runDeployKeyList}) | |
| 23 | 29 | register(Command{Path: []string{"repo", "deploy-key", "remove"}, |
| 24 | Summary: "remove a deploy key", | |
| 25 | Usage: "repo deploy-key remove <owner/name> <fingerprint>", Run: runDeployKeyRemove}) | |
| 30 | Summary: "remove a deploy key", | |
| 31 | Usage: "repo deploy-key remove <owner/name> <fingerprint>", | |
| 32 | Examples: []string{"repo deploy-key remove krz/gitbay SHA256:abcd1234"}, | |
| 33 | Run: runDeployKeyRemove}) | |
| 26 | 34 | } |
| 27 | 35 | |
| 28 | 36 | func runDeployKeyAdd(c *Ctx, args []string) int { |
internal/control/deps.go +12 −6
| @@ -15,14 +15,20 @@ func init() { | ||
| 15 | 15 | // public registry what the repository depends on, which is the owner's |
| 16 | 16 | // disclosure to make, not the instance's. |
| 17 | 17 | register(Command{Path: []string{"repo", "deps", "enable"}, |
| 18 | Summary: "check dependencies for updates", | |
| 19 | Usage: "repo deps enable <owner/name>", Run: runDepsEnable}) | |
| 18 | Summary: "check dependencies for updates", | |
| 19 | Usage: "repo deps enable <owner/name>", | |
| 20 | Examples: []string{"repo deps enable krz/gitbay"}, | |
| 21 | Run: runDepsEnable}) | |
| 20 | 22 | register(Command{Path: []string{"repo", "deps", "disable"}, |
| 21 | Summary: "stop checking dependencies", | |
| 22 | Usage: "repo deps disable <owner/name>", Run: runDepsDisable}) | |
| 23 | Summary: "stop checking dependencies", | |
| 24 | Usage: "repo deps disable <owner/name>", | |
| 25 | Examples: []string{"repo deps disable krz/gitbay"}, | |
| 26 | Run: runDepsDisable}) | |
| 23 | 27 | register(Command{Path: []string{"repo", "deps", "status"}, |
| 24 | Summary: "show dependency check state", | |
| 25 | Usage: "repo deps status <owner/name>", ReadOnly: true, Run: runDepsStatus}) | |
| 28 | Summary: "show dependency check state", | |
| 29 | Usage: "repo deps status <owner/name>", | |
| 30 | Examples: []string{"repo deps status krz/gitbay"}, | |
| 31 | ReadOnly: true, Run: runDepsStatus}) | |
| 26 | 32 | } |
| 27 | 33 | |
| 28 | 34 | // DepsOut is what `repo deps status` emits: the check's state and what |
internal/control/diffcomment.go +27 −8
| @@ -16,18 +16,37 @@ import ( | ||
| 16 | 16 | |
| 17 | 17 | func init() { |
| 18 | 18 | register(Command{Path: []string{"mr", "diff-comment"}, |
| 19 | Summary: "comment on a diff line", | |
| 20 | Usage: "mr diff-comment <owner/name> <n> --path <file> --line <l> [--old] [--pending] [--reply <id>] [--message <m> | --file -]", | |
| 19 | Summary: "comment on a diff line", | |
| 20 | Usage: "mr diff-comment <owner/name> <n> --path <file> --line <l> [--old] [--pending] [--reply <id>] [--message <m> | --file -]", | |
| 21 | Flags: []Flag{ | |
| 22 | {"--path", "<file>", "the file the comment is on", ""}, | |
| 23 | {"--line", "<l>", "the line the comment is on", ""}, | |
| 24 | {"--old", "", "the line is on the old side of the diff", ""}, | |
| 25 | {"--pending", "", "hold the comment for `mr review --comment`", ""}, | |
| 26 | {"--reply", "<id>", "reply to this thread instead of opening one", ""}, | |
| 27 | {"--message", "<m>", "the comment's text", ""}, | |
| 28 | {"--file", "-", "read the comment from stdin", ""}, | |
| 29 | }, | |
| 30 | Examples: []string{ | |
| 31 | `mr diff-comment krz/gitbay 431 --path internal/control/build.go --line 42 --message "why is this a switch"`, | |
| 32 | "mr diff-comment krz/gitbay 431 --reply 12 --file - '< notes.md'", | |
| 33 | }, | |
| 21 | 34 | ReadsStdin: true, Run: runDiffComment}) |
| 22 | 35 | register(Command{Path: []string{"mr", "threads"}, |
| 23 | Summary: "review threads on an MR", | |
| 24 | Usage: "mr threads <owner/name> <n>", ReadOnly: true, Run: runMRThreads}) | |
| 36 | Summary: "review threads on an MR", | |
| 37 | Usage: "mr threads <owner/name> <n>", | |
| 38 | Examples: []string{"mr threads krz/gitbay 431"}, | |
| 39 | ReadOnly: true, Run: runMRThreads}) | |
| 25 | 40 | register(Command{Path: []string{"mr", "resolve"}, |
| 26 | Summary: "resolve a review thread", | |
| 27 | Usage: "mr resolve <owner/name> <n> <thread-id>", Run: runMRResolve}) | |
| 41 | Summary: "resolve a review thread", | |
| 42 | Usage: "mr resolve <owner/name> <n> <thread-id>", | |
| 43 | Examples: []string{"mr resolve krz/gitbay 431 12"}, | |
| 44 | Run: runMRResolve}) | |
| 28 | 45 | register(Command{Path: []string{"mr", "unresolve"}, |
| 29 | Summary: "reopen a review thread", | |
| 30 | Usage: "mr unresolve <owner/name> <n> <thread-id>", Run: runMRUnresolve}) | |
| 46 | Summary: "reopen a review thread", | |
| 47 | Usage: "mr unresolve <owner/name> <n> <thread-id>", | |
| 48 | Examples: []string{"mr unresolve krz/gitbay 431 12"}, | |
| 49 | Run: runMRUnresolve}) | |
| 31 | 50 | } |
| 32 | 51 | |
| 33 | 52 | func runDiffComment(c *Ctx, args []string) int { |
internal/control/explore.go +14 −5
| @@ -11,9 +11,14 @@ import ( | ||
| 11 | 11 | |
| 12 | 12 | func init() { |
| 13 | 13 | register(Command{ |
| 14 | Path: []string{"explore"}, | |
| 15 | Summary: "list public repositories", | |
| 16 | Usage: "explore [--limit <n>] [--cursor <c>]", | |
| 14 | Path: []string{"explore"}, | |
| 15 | Summary: "list public repositories", | |
| 16 | Usage: "explore [--limit <n>] [--cursor <c>]", | |
| 17 | Flags: []Flag{ | |
| 18 | {"--limit", "<n>", "rows per page", ""}, | |
| 19 | {"--cursor", "<c>", "continue from the previous page", ""}, | |
| 20 | }, | |
| 21 | Examples: []string{"explore --limit 20"}, | |
| 17 | 22 | ReadOnly: true, |
| 18 | 23 | Run: runExplore, |
| 19 | 24 | }) |
| @@ -21,8 +26,12 @@ func init() { | ||
| 21 | 26 | Path: []string{"repo", "download"}, |
| 22 | 27 | // Not "repo archive": that name is taken by the read-only flag, |
| 23 | 28 | // and renaming it would break every script that sets it. |
| 24 | Summary: "write a tar.gz of a ref to stdout", | |
| 25 | Usage: "repo download <owner/name> [--ref <r>] > repo.tar.gz", | |
| 29 | Summary: "write a tar.gz of a ref to stdout", | |
| 30 | Usage: "repo download <owner/name> [--ref <r>] > repo.tar.gz", | |
| 31 | Flags: []Flag{ | |
| 32 | {"--ref", "<r>", "branch, tag or commit to archive", ""}, | |
| 33 | }, | |
| 34 | Examples: []string{"repo download krz/gitbay --ref main '> gitbay.tar.gz'"}, | |
| 26 | 35 | ReadOnly: true, |
| 27 | 36 | Run: runRepoDownload, |
| 28 | 37 | }) |
internal/control/ghimport.go +8 −2
| @@ -23,8 +23,14 @@ import ( | ||
| 23 | 23 | |
| 24 | 24 | func init() { |
| 25 | 25 | register(Command{Path: []string{"repo", "import-issues"}, |
| 26 | Summary: "import issue and PR history from GitHub or Forgejo", | |
| 27 | Usage: "repo import-issues <owner/name> --from <owner/repo> [--token-stdin] [--api-base <url>]", | |
| 26 | Summary: "import issue and PR history from GitHub or Forgejo", | |
| 27 | Usage: "repo import-issues <owner/name> --from <owner/repo> [--token-stdin] [--api-base <url>]", | |
| 28 | Flags: []Flag{ | |
| 29 | {"--from", "<owner/repo>", "the source repository", ""}, | |
| 30 | {"--token-stdin", "", "read an API token from stdin", ""}, | |
| 31 | {"--api-base", "<url>", "the API's base URL, for Forgejo", ""}, | |
| 32 | }, | |
| 33 | Examples: []string{"repo import-issues krz/gitbay --from krz/gitbay-old"}, | |
| 28 | 34 | ReadsStdin: true, Run: runImportIssues}) |
| 29 | 35 | } |
| 30 | 36 | |
internal/control/help_test.go added +80
| @@ -0,0 +1,80 @@ | ||
| 1 | package control | |
| 2 | ||
| 3 | import ( | |
| 4 | "regexp" | |
| 5 | "slices" | |
| 6 | "strings" | |
| 7 | "testing" | |
| 8 | ||
| 9 | "gitbay.org/gitbay/internal/protocol" | |
| 10 | ) | |
| 11 | ||
| 12 | var usageFlag = regexp.MustCompile(`--[a-z][a-z0-9-]*`) | |
| 13 | ||
| 14 | // helpCovered restricts TestHelpIsComplete to the path prefixes whose help | |
| 15 | // text this commit filled in. Task 4.3 fills the rest and removes this set. | |
| 16 | // "org label" and "org milestone" name the two prefixes under "org" this | |
| 17 | // commit covers; the rest of "org" (teams, members, profile) is not. | |
| 18 | // widened to every command in the next commit | |
| 19 | var helpCovered = []string{ | |
| 20 | "issue", "mr", "build", "release", "milestone", "label", "search", | |
| 21 | "dashboard", "feed", "status", "wiki", "snippet", "repo", | |
| 22 | "org label", "org milestone", | |
| 23 | } | |
| 24 | ||
| 25 | func isHelpCovered(path []string) bool { | |
| 26 | joined := strings.Join(path, " ") | |
| 27 | for _, prefix := range helpCovered { | |
| 28 | if joined == prefix || strings.HasPrefix(joined, prefix+" ") { | |
| 29 | return true | |
| 30 | } | |
| 31 | } | |
| 32 | return false | |
| 33 | } | |
| 34 | ||
| 35 | // Help is written once, in the registry. Every flag in a usage line has | |
| 36 | // a description, every description names a flag in the usage line, and | |
| 37 | // every command has an example that runs it. | |
| 38 | func TestHelpIsComplete(t *testing.T) { | |
| 39 | for _, cmd := range Commands() { | |
| 40 | if !isHelpCovered(cmd.Path) { | |
| 41 | continue | |
| 42 | } | |
| 43 | path := strings.Join(cmd.Path, " ") | |
| 44 | inUsage := map[string]bool{} | |
| 45 | for _, f := range usageFlag.FindAllString(cmd.Usage, -1) { | |
| 46 | if f != "--json" { | |
| 47 | inUsage[f] = true | |
| 48 | } | |
| 49 | } | |
| 50 | described := map[string]bool{} | |
| 51 | for _, f := range cmd.Flags { | |
| 52 | described[f.Name] = true | |
| 53 | if f.Desc == "" { | |
| 54 | t.Errorf("%s: %s has no description", path, f.Name) | |
| 55 | } | |
| 56 | if !inUsage[f.Name] { | |
| 57 | t.Errorf("%s: %s is described but not in the usage", path, f.Name) | |
| 58 | } | |
| 59 | } | |
| 60 | for f := range inUsage { | |
| 61 | if !described[f] { | |
| 62 | t.Errorf("%s: %s is in the usage with no description", path, f) | |
| 63 | } | |
| 64 | } | |
| 65 | if len(cmd.Examples) == 0 { | |
| 66 | t.Errorf("%s: no example", path) | |
| 67 | } | |
| 68 | for _, ex := range cmd.Examples { | |
| 69 | argv, err := protocol.Tokenize(ex) | |
| 70 | if err != nil { | |
| 71 | t.Errorf("%s: example %q: %v", path, ex, err) | |
| 72 | continue | |
| 73 | } | |
| 74 | got, _, ok := Lookup(argv) | |
| 75 | if !ok || !slices.Equal(got.Path, cmd.Path) { | |
| 76 | t.Errorf("%s: example %q runs %v", path, ex, got.Path) | |
| 77 | } | |
| 78 | } | |
| 79 | } | |
| 80 | } | |
internal/control/import.go +8 −2
| @@ -17,8 +17,14 @@ import ( | ||
| 17 | 17 | |
| 18 | 18 | func init() { |
| 19 | 19 | register(Command{Path: []string{"repo", "import"}, |
| 20 | Summary: "server-side mirror of a foreign repository", | |
| 21 | Usage: "repo import <owner/name> --from <url> [--private] [--token-stdin]", | |
| 20 | Summary: "server-side mirror of a foreign repository", | |
| 21 | Usage: "repo import <owner/name> --from <url> [--private] [--token-stdin]", | |
| 22 | Flags: []Flag{ | |
| 23 | {"--from", "<url>", "the repository to import", ""}, | |
| 24 | {"--private", "", "create it private", ""}, | |
| 25 | {"--token-stdin", "", "read a credential token from stdin", ""}, | |
| 26 | }, | |
| 27 | Examples: []string{"repo import krz/imported --from https://github.com/krz/old.git"}, | |
| 22 | 28 | ReadsStdin: true, Run: runRepoImport}) |
| 23 | 29 | } |
| 24 | 30 | |
internal/control/issue.go +77 −15
| @@ -16,35 +16,97 @@ const maxBodyBytes = 64 << 10 | ||
| 16 | 16 | |
| 17 | 17 | func init() { |
| 18 | 18 | register(Command{Path: []string{"issue", "create"}, |
| 19 | Summary: "open an issue", | |
| 20 | Usage: "issue create <owner/name> --title <t> [--body <b> | --file -] [--format md|org]", | |
| 19 | Summary: "open an issue", | |
| 20 | Usage: "issue create <owner/name> --title <t> [--body <b> | --file -] [--format md|org]", | |
| 21 | Flags: []Flag{ | |
| 22 | {"--title", "<t>", "the issue's title", ""}, | |
| 23 | {"--body", "<b>", "the issue's body", ""}, | |
| 24 | {"--file", "-", "read the body from stdin", ""}, | |
| 25 | {"--format", "md|org", "the body's markup", "md"}, | |
| 26 | }, | |
| 27 | Examples: []string{ | |
| 28 | `issue create krz/gitbay --title "crash on empty repo" --body "steps to reproduce..."`, | |
| 29 | "issue create krz/gitbay --title notes --file - '< notes.md'", | |
| 30 | }, | |
| 21 | 31 | ReadsStdin: true, Run: runIssueCreate}) |
| 22 | 32 | register(Command{Path: []string{"issue", "list"}, |
| 23 | 33 | Summary: "list issues", |
| 24 | Usage: "issue list <owner/name> [--state open|closed|all] [--label <l>] [--assignee <user>] [--author <user>] [--milestone <title>|none] [--search <text>] [--limit <n>] [--cursor <c>]", ReadOnly: true, Run: runIssueList}) | |
| 34 | Usage: "issue list <owner/name> [--state open|closed|all] [--label <l>] [--assignee <user>] [--author <user>] [--milestone <title>|none] [--search <text>] [--limit <n>] [--cursor <c>]", | |
| 35 | Flags: []Flag{ | |
| 36 | {"--state", "open|closed|all", "which issues", "open"}, | |
| 37 | {"--label", "<l>", "only issues carrying this label", ""}, | |
| 38 | {"--assignee", "<user>", "only issues assigned to this user", ""}, | |
| 39 | {"--author", "<user>", "only issues opened by this user", ""}, | |
| 40 | {"--milestone", "<title>|none", "only issues in this milestone, or in none", ""}, | |
| 41 | {"--search", "<text>", "match title and body", ""}, | |
| 42 | {"--limit", "<n>", "rows per page", ""}, | |
| 43 | {"--cursor", "<c>", "continue from the previous page", ""}, | |
| 44 | }, | |
| 45 | Examples: []string{ | |
| 46 | "issue list krz/gitbay --label bug --state all", | |
| 47 | "issue list krz/gitbay --assignee cmc", | |
| 48 | }, | |
| 49 | ReadOnly: true, Run: runIssueList}) | |
| 25 | 50 | register(Command{Path: []string{"issue", "show"}, |
| 26 | Summary: "show an issue with comments", | |
| 27 | Usage: "issue show <owner/name> <n>", ReadOnly: true, Run: runIssueShow}) | |
| 51 | Summary: "show an issue with comments", | |
| 52 | Usage: "issue show <owner/name> <n>", | |
| 53 | Examples: []string{"issue show krz/gitbay 42"}, | |
| 54 | ReadOnly: true, Run: runIssueShow}) | |
| 28 | 55 | register(Command{Path: []string{"issue", "edit"}, |
| 29 | Summary: "edit title or body", | |
| 30 | Usage: "issue edit <owner/name> <n> [--title <t>] [--body <b> | --file -] [--format md|org]", | |
| 56 | Summary: "edit title or body", | |
| 57 | Usage: "issue edit <owner/name> <n> [--title <t>] [--body <b> | --file -] [--format md|org]", | |
| 58 | Flags: []Flag{ | |
| 59 | {"--title", "<t>", "the issue's new title", ""}, | |
| 60 | {"--body", "<b>", "the issue's new body", ""}, | |
| 61 | {"--file", "-", "read the new body from stdin", ""}, | |
| 62 | {"--format", "md|org", "the body's markup", ""}, | |
| 63 | }, | |
| 64 | Examples: []string{ | |
| 65 | `issue edit krz/gitbay 42 --title "crash on empty repo, take two"`, | |
| 66 | "issue edit krz/gitbay 42 --file - '< notes.md'", | |
| 67 | }, | |
| 31 | 68 | ReadsStdin: true, Run: runIssueEdit}) |
| 32 | 69 | register(Command{Path: []string{"issue", "comment"}, |
| 33 | Summary: "comment", | |
| 34 | Usage: "issue comment <owner/name> <n> [--message <m> | --file -] [--format md|org]", | |
| 70 | Summary: "comment", | |
| 71 | Usage: "issue comment <owner/name> <n> [--message <m> | --file -] [--format md|org]", | |
| 72 | Flags: []Flag{ | |
| 73 | {"--message", "<m>", "the comment's text", ""}, | |
| 74 | {"--file", "-", "read the comment from stdin", ""}, | |
| 75 | {"--format", "md|org", "the comment's markup", "md"}, | |
| 76 | }, | |
| 77 | Examples: []string{ | |
| 78 | `issue comment krz/gitbay 42 --message "can't reproduce on main"`, | |
| 79 | "issue comment krz/gitbay 42 --file - '< notes.md'", | |
| 80 | }, | |
| 35 | 81 | ReadsStdin: true, Run: runIssueComment}) |
| 36 | 82 | register(Command{Path: []string{"issue", "close"}, |
| 37 | Summary: "close an issue", | |
| 38 | Usage: "issue close <owner/name> <n>", Run: runIssueClose}) | |
| 83 | Summary: "close an issue", | |
| 84 | Usage: "issue close <owner/name> <n>", | |
| 85 | Examples: []string{"issue close krz/gitbay 42"}, | |
| 86 | Run: runIssueClose}) | |
| 39 | 87 | register(Command{Path: []string{"issue", "reopen"}, |
| 40 | Summary: "reopen an issue", | |
| 41 | Usage: "issue reopen <owner/name> <n>", Run: runIssueReopen}) | |
| 88 | Summary: "reopen an issue", | |
| 89 | Usage: "issue reopen <owner/name> <n>", | |
| 90 | Examples: []string{"issue reopen krz/gitbay 42"}, | |
| 91 | Run: runIssueReopen}) | |
| 42 | 92 | register(Command{Path: []string{"issue", "label"}, |
| 43 | 93 | Summary: "labels", |
| 44 | Usage: "issue label <owner/name> <n> [--add <l>]... [--remove <l>]...", Run: runIssueLabel}) | |
| 94 | Usage: "issue label <owner/name> <n> [--add <l>]... [--remove <l>]...", | |
| 95 | Flags: []Flag{ | |
| 96 | {"--add", "<l>", "label to add, may repeat", ""}, | |
| 97 | {"--remove", "<l>", "label to remove, may repeat", ""}, | |
| 98 | }, | |
| 99 | Examples: []string{"issue label krz/gitbay 42 --add bug --remove needs-triage"}, | |
| 100 | Run: runIssueLabel}) | |
| 45 | 101 | register(Command{Path: []string{"issue", "assign"}, |
| 46 | 102 | Summary: "assignees", |
| 47 | Usage: "issue assign <owner/name> <n> [--add <user>]... [--remove <user>]...", Run: runIssueAssign}) | |
| 103 | Usage: "issue assign <owner/name> <n> [--add <user>]... [--remove <user>]...", | |
| 104 | Flags: []Flag{ | |
| 105 | {"--add", "<user>", "user to assign, may repeat", ""}, | |
| 106 | {"--remove", "<user>", "user to unassign, may repeat", ""}, | |
| 107 | }, | |
| 108 | Examples: []string{"issue assign krz/gitbay 42 --add cmc"}, | |
| 109 | Run: runIssueAssign}) | |
| 48 | 110 | } |
| 49 | 111 | |
| 50 | 112 | // issueArgs parses "<owner/name> <n>" plus flags handled by the caller. |
internal/control/label.go +14 −5
| @@ -14,14 +14,23 @@ import ( | ||
| 14 | 14 | |
| 15 | 15 | func init() { |
| 16 | 16 | register(Command{Path: []string{"label", "list"}, |
| 17 | Summary: "list a repository's labels with colour and use", | |
| 18 | Usage: "label list <owner/name>", ReadOnly: true, Run: runLabelList}) | |
| 17 | Summary: "list a repository's labels with colour and use", | |
| 18 | Usage: "label list <owner/name>", | |
| 19 | Examples: []string{"label list krz/gitbay"}, | |
| 20 | ReadOnly: true, Run: runLabelList}) | |
| 19 | 21 | register(Command{Path: []string{"label", "set"}, |
| 20 | 22 | Summary: "create a label or set its colour", |
| 21 | Usage: "label set <owner/name> <label> [--color rrggbb|'']", Run: runLabelSet}) | |
| 23 | Usage: "label set <owner/name> <label> [--color rrggbb|'']", | |
| 24 | Flags: []Flag{ | |
| 25 | {"--color", "rrggbb|''", "the label's colour, or '' to clear it", ""}, | |
| 26 | }, | |
| 27 | Examples: []string{"label set krz/gitbay bug --color d73a4a"}, | |
| 28 | Run: runLabelSet}) | |
| 22 | 29 | register(Command{Path: []string{"label", "remove"}, |
| 23 | Summary: "remove a label from the repository and from every issue and merge request", | |
| 24 | Usage: "label remove <owner/name> <label>", Run: runLabelRemove}) | |
| 30 | Summary: "remove a label from the repository and from every issue and merge request", | |
| 31 | Usage: "label remove <owner/name> <label>", | |
| 32 | Examples: []string{"label remove krz/gitbay wontfix"}, | |
| 33 | Run: runLabelRemove}) | |
| 25 | 34 | } |
| 26 | 35 | |
| 27 | 36 | // A colour is six hex digits, with or without the hash: over bare ssh a |
internal/control/milestone.go +33 −12
| @@ -17,25 +17,46 @@ import ( | ||
| 17 | 17 | func init() { |
| 18 | 18 | register(Command{Path: []string{"milestone", "create"}, |
| 19 | 19 | Summary: "create a milestone", |
| 20 | Usage: "milestone create <owner/name> <title> [--description <d>] [--due YYYY-MM-DD]", Run: runMilestoneCreate}) | |
| 20 | Usage: "milestone create <owner/name> <title> [--description <d>] [--due YYYY-MM-DD]", | |
| 21 | Flags: []Flag{ | |
| 22 | {"--description", "<d>", "what the milestone covers", ""}, | |
| 23 | {"--due", "YYYY-MM-DD", "target date", ""}, | |
| 24 | }, | |
| 25 | Examples: []string{`milestone create krz/gitbay v1.31.0 --due 2026-10-01`}, | |
| 26 | Run: runMilestoneCreate}) | |
| 21 | 27 | register(Command{Path: []string{"milestone", "list"}, |
| 22 | 28 | Summary: "list milestones with progress", |
| 23 | Usage: "milestone list <owner/name> [--state open|closed|all]", ReadOnly: true, Run: runMilestoneList}) | |
| 29 | Usage: "milestone list <owner/name> [--state open|closed|all]", | |
| 30 | Flags: []Flag{ | |
| 31 | {"--state", "open|closed|all", "which milestones", "open"}, | |
| 32 | }, | |
| 33 | Examples: []string{"milestone list krz/gitbay --state all"}, | |
| 34 | ReadOnly: true, Run: runMilestoneList}) | |
| 24 | 35 | register(Command{Path: []string{"milestone", "close"}, |
| 25 | Summary: "close a milestone", | |
| 26 | Usage: "milestone close <owner/name> <title>", Run: runMilestoneClose}) | |
| 36 | Summary: "close a milestone", | |
| 37 | Usage: "milestone close <owner/name> <title>", | |
| 38 | Examples: []string{"milestone close krz/gitbay v1.30.0"}, | |
| 39 | Run: runMilestoneClose}) | |
| 27 | 40 | register(Command{Path: []string{"milestone", "reopen"}, |
| 28 | Summary: "reopen a milestone", | |
| 29 | Usage: "milestone reopen <owner/name> <title>", Run: runMilestoneReopen}) | |
| 41 | Summary: "reopen a milestone", | |
| 42 | Usage: "milestone reopen <owner/name> <title>", | |
| 43 | Examples: []string{"milestone reopen krz/gitbay v1.30.0"}, | |
| 44 | Run: runMilestoneReopen}) | |
| 30 | 45 | register(Command{Path: []string{"issue", "milestone"}, |
| 31 | Summary: "set or clear an issue's milestone", | |
| 32 | Usage: "issue milestone <owner/name> <n> <title|none>", Run: runIssueMilestone}) | |
| 46 | Summary: "set or clear an issue's milestone", | |
| 47 | Usage: "issue milestone <owner/name> <n> <title|none>", | |
| 48 | Examples: []string{"issue milestone krz/gitbay 42 v1.31.0"}, | |
| 49 | Run: runIssueMilestone}) | |
| 33 | 50 | register(Command{Path: []string{"mr", "milestone"}, |
| 34 | Summary: "set or clear an MR's milestone", | |
| 35 | Usage: "mr milestone <owner/name> <n> <title|none>", Run: runMRMilestone}) | |
| 51 | Summary: "set or clear an MR's milestone", | |
| 52 | Usage: "mr milestone <owner/name> <n> <title|none>", | |
| 53 | Examples: []string{"mr milestone krz/gitbay 431 v1.31.0"}, | |
| 54 | Run: runMRMilestone}) | |
| 36 | 55 | register(Command{Path: []string{"issue", "templates"}, |
| 37 | Summary: "list issue templates (.gitbay/issue-template*.md)", | |
| 38 | Usage: "issue templates <owner/name>", ReadOnly: true, Run: runIssueTemplates}) | |
| 56 | Summary: "list issue templates (.gitbay/issue-template*.md)", | |
| 57 | Usage: "issue templates <owner/name>", | |
| 58 | Examples: []string{"issue templates krz/gitbay"}, | |
| 59 | ReadOnly: true, Run: runIssueTemplates}) | |
| 39 | 60 | } |
| 40 | 61 | |
| 41 | 62 | var duePat = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`) |
internal/control/mirrorcmd.go +20 −8
| @@ -16,18 +16,30 @@ import ( | ||
| 16 | 16 | |
| 17 | 17 | func init() { |
| 18 | 18 | register(Command{Path: []string{"repo", "mirror", "add"}, |
| 19 | Summary: "mirror to or from a remote", | |
| 20 | Usage: "repo mirror add <owner/name> <https-url> --direction push|pull [--username <u>] [--token-stdin]", | |
| 19 | Summary: "mirror to or from a remote", | |
| 20 | Usage: "repo mirror add <owner/name> <https-url> --direction push|pull [--username <u>] [--token-stdin]", | |
| 21 | Flags: []Flag{ | |
| 22 | {"--direction", "push|pull", "which way the mirror syncs", ""}, | |
| 23 | {"--username", "<u>", "the remote's username", ""}, | |
| 24 | {"--token-stdin", "", "read a credential token from stdin", ""}, | |
| 25 | }, | |
| 26 | Examples: []string{"repo mirror add krz/gitbay https://github.com/krazywarez/gitbay.git --direction push"}, | |
| 21 | 27 | ReadsStdin: true, Run: runMirrorAdd}) |
| 22 | 28 | register(Command{Path: []string{"repo", "mirror", "list"}, |
| 23 | Summary: "list mirrors with sync status", | |
| 24 | Usage: "repo mirror list <owner/name>", ReadOnly: true, Run: runMirrorList}) | |
| 29 | Summary: "list mirrors with sync status", | |
| 30 | Usage: "repo mirror list <owner/name>", | |
| 31 | Examples: []string{"repo mirror list krz/gitbay"}, | |
| 32 | ReadOnly: true, Run: runMirrorList}) | |
| 25 | 33 | register(Command{Path: []string{"repo", "mirror", "remove"}, |
| 26 | Summary: "remove a mirror", | |
| 27 | Usage: "repo mirror remove <owner/name> <id>", Run: runMirrorRemove}) | |
| 34 | Summary: "remove a mirror", | |
| 35 | Usage: "repo mirror remove <owner/name> <id>", | |
| 36 | Examples: []string{"repo mirror remove krz/gitbay 3"}, | |
| 37 | Run: runMirrorRemove}) | |
| 28 | 38 | register(Command{Path: []string{"repo", "mirror", "sync"}, |
| 29 | Summary: "schedule an immediate sync", | |
| 30 | Usage: "repo mirror sync <owner/name>", Run: runMirrorSync}) | |
| 39 | Summary: "schedule an immediate sync", | |
| 40 | Usage: "repo mirror sync <owner/name>", | |
| 41 | Examples: []string{"repo mirror sync krz/gitbay"}, | |
| 42 | Run: runMirrorSync}) | |
| 31 | 43 | } |
| 32 | 44 | |
| 33 | 45 | func runMirrorAdd(c *Ctx, args []string) int { |
internal/control/mr.go +142 −37
| @@ -20,78 +20,183 @@ import ( | ||
| 20 | 20 | func init() { |
| 21 | 21 | register(Command{Path: []string{"repo", "fork"}, |
| 22 | 22 | Summary: "fork a repository under your account", |
| 23 | Usage: "repo fork <owner/name> [--owner <o>] [--name <n>]", Run: runRepoFork}) | |
| 23 | Usage: "repo fork <owner/name> [--owner <o>] [--name <n>]", | |
| 24 | Flags: []Flag{ | |
| 25 | {"--owner", "<o>", "fork under this user or org, default your account", ""}, | |
| 26 | {"--name", "<n>", "name the fork", "the source's name"}, | |
| 27 | }, | |
| 28 | Examples: []string{"repo fork krz/gitbay"}, | |
| 29 | Run: runRepoFork}) | |
| 24 | 30 | register(Command{Path: []string{"repo", "settings", "require-approvals"}, |
| 25 | Summary: "require N fresh approvals to merge", | |
| 26 | Usage: "repo settings require-approvals <owner/name> <n> (0 = off)", Run: runRequireApprovals}) | |
| 31 | Summary: "require N fresh approvals to merge", | |
| 32 | Usage: "repo settings require-approvals <owner/name> <n> (0 = off)", | |
| 33 | Examples: []string{"repo settings require-approvals krz/gitbay 1"}, | |
| 34 | Run: runRequireApprovals}) | |
| 27 | 35 | register(Command{Path: []string{"repo", "settings", "require-resolved"}, |
| 28 | Summary: "require all review threads resolved to merge", | |
| 29 | Usage: "repo settings require-resolved <owner/name> on|off", Run: runRequireResolved}) | |
| 36 | Summary: "require all review threads resolved to merge", | |
| 37 | Usage: "repo settings require-resolved <owner/name> on|off", | |
| 38 | Examples: []string{"repo settings require-resolved krz/gitbay on"}, | |
| 39 | Run: runRequireResolved}) | |
| 30 | 40 | register(Command{Path: []string{"repo", "settings", "require-codeowners"}, |
| 31 | Summary: "require an owner's approval for every file CODEOWNERS covers", | |
| 32 | Usage: "repo settings require-codeowners <owner/name> on|off", Run: runRequireCodeowners}) | |
| 41 | Summary: "require an owner's approval for every file CODEOWNERS covers", | |
| 42 | Usage: "repo settings require-codeowners <owner/name> on|off", | |
| 43 | Examples: []string{"repo settings require-codeowners krz/gitbay on"}, | |
| 44 | Run: runRequireCodeowners}) | |
| 33 | 45 | register(Command{Path: []string{"repo", "settings", "require-checks"}, |
| 34 | Summary: "gate merges on green statuses", | |
| 35 | Usage: "repo settings require-checks <owner/name> on|off", Run: runRequireChecks}) | |
| 46 | Summary: "gate merges on green statuses", | |
| 47 | Usage: "repo settings require-checks <owner/name> on|off", | |
| 48 | Examples: []string{"repo settings require-checks krz/gitbay on"}, | |
| 49 | Run: runRequireChecks}) | |
| 36 | 50 | register(Command{Path: []string{"repo", "settings", "require-mr"}, |
| 37 | Summary: "protected branches take changes through merge requests only", | |
| 38 | Usage: "repo settings require-mr <owner/name> on|off", Run: runRequireMR}) | |
| 51 | Summary: "protected branches take changes through merge requests only", | |
| 52 | Usage: "repo settings require-mr <owner/name> on|off", | |
| 53 | Examples: []string{"repo settings require-mr krz/gitbay on"}, | |
| 54 | Run: runRequireMR}) | |
| 39 | 55 | register(Command{Path: []string{"repo", "settings", "require-signed"}, |
| 40 | Summary: "require verified commit signatures", | |
| 41 | Usage: "repo settings require-signed <owner/name> on|off", Run: runRequireSigned}) | |
| 56 | Summary: "require verified commit signatures", | |
| 57 | Usage: "repo settings require-signed <owner/name> on|off", | |
| 58 | Examples: []string{"repo settings require-signed krz/gitbay on"}, | |
| 59 | Run: runRequireSigned}) | |
| 42 | 60 | register(Command{Path: []string{"mr", "create"}, |
| 43 | Summary: "open a merge request", | |
| 44 | Usage: "mr create <target owner/name> --source [owner/name:]<branch> --target <branch> --title <t> [--body <b> | --file -] [--format md|org] [--draft]", | |
| 61 | Summary: "open a merge request", | |
| 62 | Usage: "mr create <target owner/name> --source [owner/name:]<branch> --target <branch> --title <t> [--body <b> | --file -] [--format md|org] [--draft]", | |
| 63 | Flags: []Flag{ | |
| 64 | {"--source", "[owner/name:]<branch>", "the branch to merge, from a fork with owner/name:", ""}, | |
| 65 | {"--target", "<branch>", "the branch to merge into", ""}, | |
| 66 | {"--title", "<t>", "the merge request's title", ""}, | |
| 67 | {"--body", "<b>", "the merge request's body", ""}, | |
| 68 | {"--file", "-", "read the body from stdin", ""}, | |
| 69 | {"--format", "md|org", "the body's markup", "md"}, | |
| 70 | {"--draft", "", "open it as work in progress", ""}, | |
| 71 | }, | |
| 72 | Examples: []string{ | |
| 73 | `mr create krz/gitbay --source cli-output-help --target main --title "control: flag help"`, | |
| 74 | "mr create krz/gitbay --source cli-output-help --target main --title notes --file - '< notes.md'", | |
| 75 | }, | |
| 45 | 76 | ReadsStdin: true, Run: runMRCreate}) |
| 46 | 77 | register(Command{Path: []string{"mr", "range-diff"}, |
| 47 | Summary: "what changed between two revisions of a merge request", | |
| 48 | Usage: "mr range-diff <owner/name> <n> [--from <sha>] [--to <sha>]", | |
| 78 | Summary: "what changed between two revisions of a merge request", | |
| 79 | Usage: "mr range-diff <owner/name> <n> [--from <sha>] [--to <sha>]", | |
| 80 | Flags: []Flag{ | |
| 81 | {"--from", "<sha>", "earlier revision, default the one before --to", ""}, | |
| 82 | {"--to", "<sha>", "later revision, default the head", ""}, | |
| 83 | }, | |
| 84 | Examples: []string{"mr range-diff krz/gitbay 431"}, | |
| 49 | 85 | ReadOnly: true, Run: runMRRangeDiff}) |
| 50 | 86 | register(Command{Path: []string{"mr", "revisions"}, |
| 51 | 87 | Summary: "the heads a merge request has had", |
| 52 | 88 | Usage: "mr revisions <owner/name> <n>", |
| 89 | Examples: []string{"mr revisions krz/gitbay 431"}, | |
| 53 | 90 | ReadOnly: true, Run: runMRRevisions}) |
| 54 | 91 | register(Command{Path: []string{"mr", "draft"}, |
| 55 | Summary: "mark a merge request as work in progress", | |
| 56 | Usage: "mr draft <owner/name> <n>", Run: runMRDraft}) | |
| 92 | Summary: "mark a merge request as work in progress", | |
| 93 | Usage: "mr draft <owner/name> <n>", | |
| 94 | Examples: []string{"mr draft krz/gitbay 431"}, | |
| 95 | Run: runMRDraft}) | |
| 57 | 96 | register(Command{Path: []string{"mr", "ready"}, |
| 58 | Summary: "take the draft mark off, so it can merge", | |
| 59 | Usage: "mr ready <owner/name> <n>", Run: runMRReady}) | |
| 97 | Summary: "take the draft mark off, so it can merge", | |
| 98 | Usage: "mr ready <owner/name> <n>", | |
| 99 | Examples: []string{"mr ready krz/gitbay 431"}, | |
| 100 | Run: runMRReady}) | |
| 60 | 101 | register(Command{Path: []string{"mr", "list"}, |
| 61 | 102 | Summary: "list merge requests", |
| 62 | Usage: "mr list <owner/name> [--state open|merged|closed|source_gone|all] [--label <l>] [--author <user>] [--milestone <title>|none] [--search <text>] [--limit <n>] [--cursor <c>]", ReadOnly: true, Run: runMRList}) | |
| 103 | Usage: "mr list <owner/name> [--state open|merged|closed|source_gone|all] [--label <l>] [--author <user>] [--milestone <title>|none] [--search <text>] [--limit <n>] [--cursor <c>]", | |
| 104 | Flags: []Flag{ | |
| 105 | {"--state", "open|merged|closed|source_gone|all", "which merge requests", "open"}, | |
| 106 | {"--label", "<l>", "only MRs carrying this label", ""}, | |
| 107 | {"--author", "<user>", "only MRs opened by this user", ""}, | |
| 108 | {"--milestone", "<title>|none", "only MRs in this milestone, or in none", ""}, | |
| 109 | {"--search", "<text>", "match title and body", ""}, | |
| 110 | {"--limit", "<n>", "rows per page", ""}, | |
| 111 | {"--cursor", "<c>", "continue from the previous page", ""}, | |
| 112 | }, | |
| 113 | Examples: []string{ | |
| 114 | "mr list krz/gitbay --state open", | |
| 115 | "mr list krz/gitbay --author cmc --state all", | |
| 116 | }, | |
| 117 | ReadOnly: true, Run: runMRList}) | |
| 63 | 118 | register(Command{Path: []string{"mr", "show"}, |
| 64 | Summary: "show a merge request", | |
| 65 | Usage: "mr show <owner/name> <n>", ReadOnly: true, Run: runMRShow}) | |
| 119 | Summary: "show a merge request", | |
| 120 | Usage: "mr show <owner/name> <n>", | |
| 121 | Examples: []string{"mr show krz/gitbay 431"}, | |
| 122 | ReadOnly: true, Run: runMRShow}) | |
| 66 | 123 | register(Command{Path: []string{"mr", "diff"}, |
| 67 | Summary: "show the diff", | |
| 68 | Usage: "mr diff <owner/name> <n>", ReadOnly: true, Run: runMRDiff}) | |
| 124 | Summary: "show the diff", | |
| 125 | Usage: "mr diff <owner/name> <n>", | |
| 126 | Examples: []string{"mr diff krz/gitbay 431"}, | |
| 127 | ReadOnly: true, Run: runMRDiff}) | |
| 69 | 128 | register(Command{Path: []string{"mr", "edit"}, |
| 70 | Summary: "edit title or body", | |
| 71 | Usage: "mr edit <owner/name> <n> [--title <t>] [--body <b> | --file -] [--format md|org] [--superseded-by <m>|none]", | |
| 129 | Summary: "edit title or body", | |
| 130 | Usage: "mr edit <owner/name> <n> [--title <t>] [--body <b> | --file -] [--format md|org] [--superseded-by <m>|none]", | |
| 131 | Flags: []Flag{ | |
| 132 | {"--title", "<t>", "the merge request's new title", ""}, | |
| 133 | {"--body", "<b>", "the merge request's new body", ""}, | |
| 134 | {"--file", "-", "read the new body from stdin", ""}, | |
| 135 | {"--format", "md|org", "the body's markup", ""}, | |
| 136 | {"--superseded-by", "<m>|none", "the MR that replaces this closed one, or none to clear", ""}, | |
| 137 | }, | |
| 138 | Examples: []string{`mr edit krz/gitbay 431 --title "control: flag help, take two"`}, | |
| 72 | 139 | ReadsStdin: true, Run: runMREdit}) |
| 73 | 140 | register(Command{Path: []string{"mr", "retarget"}, |
| 74 | Summary: "retarget onto another branch", | |
| 75 | Usage: "mr retarget <owner/name> <n> <branch>", Run: runMRRetarget}) | |
| 141 | Summary: "retarget onto another branch", | |
| 142 | Usage: "mr retarget <owner/name> <n> <branch>", | |
| 143 | Examples: []string{"mr retarget krz/gitbay 431 main"}, | |
| 144 | Run: runMRRetarget}) | |
| 76 | 145 | register(Command{Path: []string{"mr", "comment"}, |
| 77 | Summary: "comment", | |
| 78 | Usage: "mr comment <owner/name> <n> [--message <m> | --file -] [--format md|org]", | |
| 146 | Summary: "comment", | |
| 147 | Usage: "mr comment <owner/name> <n> [--message <m> | --file -] [--format md|org]", | |
| 148 | Flags: []Flag{ | |
| 149 | {"--message", "<m>", "the comment's text", ""}, | |
| 150 | {"--file", "-", "read the comment from stdin", ""}, | |
| 151 | {"--format", "md|org", "the comment's markup", "md"}, | |
| 152 | }, | |
| 153 | Examples: []string{`mr comment krz/gitbay 431 --message "looks good"`}, | |
| 79 | 154 | ReadsStdin: true, Run: runMRComment}) |
| 80 | 155 | register(Command{Path: []string{"mr", "review"}, |
| 81 | 156 | Summary: "review", |
| 82 | Usage: "mr review <owner/name> <n> --approve|--request-changes|--comment|--discard", Run: runMRReview}) | |
| 157 | Usage: "mr review <owner/name> <n> --approve|--request-changes|--comment|--discard", | |
| 158 | Flags: []Flag{ | |
| 159 | {"--approve", "", "approve the merge request", ""}, | |
| 160 | {"--request-changes", "", "ask for changes", ""}, | |
| 161 | {"--comment", "", "submit pending diff comments without a verdict", ""}, | |
| 162 | {"--discard", "", "throw away pending diff comments", ""}, | |
| 163 | }, | |
| 164 | Examples: []string{"mr review krz/gitbay 431 --approve"}, | |
| 165 | Run: runMRReview}) | |
| 83 | 166 | register(Command{Path: []string{"mr", "review", "request"}, |
| 84 | 167 | Summary: "ask specific people for a review", |
| 85 | Usage: "mr review request <owner/name> <n> [--add <user>]... [--remove <user>]...", Run: runMRReviewRequest}) | |
| 168 | Usage: "mr review request <owner/name> <n> [--add <user>]... [--remove <user>]...", | |
| 169 | Flags: []Flag{ | |
| 170 | {"--add", "<user>", "reviewer to add, may repeat", ""}, | |
| 171 | {"--remove", "<user>", "reviewer to remove, may repeat", ""}, | |
| 172 | }, | |
| 173 | Examples: []string{"mr review request krz/gitbay 431 --add cmc"}, | |
| 174 | Run: runMRReviewRequest}) | |
| 86 | 175 | register(Command{Path: []string{"mr", "label"}, |
| 87 | 176 | Summary: "labels", |
| 88 | Usage: "mr label <owner/name> <n> [--add <l>]... [--remove <l>]...", Run: runMRLabel}) | |
| 177 | Usage: "mr label <owner/name> <n> [--add <l>]... [--remove <l>]...", | |
| 178 | Flags: []Flag{ | |
| 179 | {"--add", "<l>", "label to add, may repeat", ""}, | |
| 180 | {"--remove", "<l>", "label to remove, may repeat", ""}, | |
| 181 | }, | |
| 182 | Examples: []string{"mr label krz/gitbay 431 --add needs-review"}, | |
| 183 | Run: runMRLabel}) | |
| 89 | 184 | register(Command{Path: []string{"mr", "merge"}, |
| 90 | 185 | Summary: "merge", |
| 91 | Usage: "mr merge <owner/name> <n> [--strategy ff|merge|squash|rebase]", Run: runMRMerge}) | |
| 186 | Usage: "mr merge <owner/name> <n> [--strategy ff|merge|squash|rebase]", | |
| 187 | Flags: []Flag{ | |
| 188 | {"--strategy", "ff|merge|squash|rebase", "how to merge", ""}, | |
| 189 | }, | |
| 190 | Examples: []string{"mr merge krz/gitbay 431 --strategy ff"}, | |
| 191 | Run: runMRMerge}) | |
| 92 | 192 | register(Command{Path: []string{"mr", "close"}, |
| 93 | 193 | Summary: "close without merging", |
| 94 | Usage: "mr close <owner/name> <n> [--by <m>]", Run: runMRClose}) | |
| 194 | Usage: "mr close <owner/name> <n> [--by <m>]", | |
| 195 | Flags: []Flag{ | |
| 196 | {"--by", "<m>", "the MR that supersedes this one", ""}, | |
| 197 | }, | |
| 198 | Examples: []string{"mr close krz/gitbay 431"}, | |
| 199 | Run: runMRClose}) | |
| 95 | 200 | } |
| 96 | 201 | |
| 97 | 202 | // ForkOut is what `repo fork` emits: where the fork landed, and what it |
internal/control/notifications.go +12 −6
| @@ -48,14 +48,20 @@ func init() { | ||
| 48 | 48 | Summary: "activity on your registered devices as well as the inbox", |
| 49 | 49 | Usage: "notifications settings push on|off", Run: runNotificationsSettingsPush}) |
| 50 | 50 | register(Command{Path: []string{"repo", "watch"}, |
| 51 | Summary: "hear about all activity on a repository", | |
| 52 | Usage: "repo watch <owner/name>", Run: runRepoWatch}) | |
| 51 | Summary: "hear about all activity on a repository", | |
| 52 | Usage: "repo watch <owner/name>", | |
| 53 | Examples: []string{"repo watch krz/gitbay"}, | |
| 54 | Run: runRepoWatch}) | |
| 53 | 55 | register(Command{Path: []string{"repo", "unwatch"}, |
| 54 | Summary: "back to the default: only work you are part of", | |
| 55 | Usage: "repo unwatch <owner/name>", Run: runRepoUnwatch}) | |
| 56 | Summary: "back to the default: only work you are part of", | |
| 57 | Usage: "repo unwatch <owner/name>", | |
| 58 | Examples: []string{"repo unwatch krz/gitbay"}, | |
| 59 | Run: runRepoUnwatch}) | |
| 56 | 60 | register(Command{Path: []string{"repo", "mute"}, |
| 57 | Summary: "mute a repository, including work you are part of", | |
| 58 | Usage: "repo mute <owner/name>", Run: runRepoMute}) | |
| 61 | Summary: "mute a repository, including work you are part of", | |
| 62 | Usage: "repo mute <owner/name>", | |
| 63 | Examples: []string{"repo mute krz/gitbay"}, | |
| 64 | Run: runRepoMute}) | |
| 59 | 65 | } |
| 60 | 66 | |
| 61 | 67 | // notice is one thing that happened, in the shape both delivery routes |
internal/control/orglabel.go +35 −11
| @@ -13,25 +13,49 @@ import ( | ||
| 13 | 13 | func init() { |
| 14 | 14 | register(Command{Path: []string{"org", "label", "set"}, |
| 15 | 15 | Summary: "create an org label every org repository sees, or set its colour; folds in same-named repo labels", |
| 16 | Usage: "org label set <org> <label> [--color rrggbb|'']", Run: runOrgLabelSet}) | |
| 16 | Usage: "org label set <org> <label> [--color rrggbb|'']", | |
| 17 | Flags: []Flag{ | |
| 18 | {"--color", "rrggbb|''", "the label's colour, or '' to clear it", ""}, | |
| 19 | }, | |
| 20 | Examples: []string{"org label set krz bug --color d73a4a"}, | |
| 21 | Run: runOrgLabelSet}) | |
| 17 | 22 | register(Command{Path: []string{"org", "label", "list"}, |
| 18 | Summary: "list an org's labels with use across the repositories you can read", | |
| 19 | Usage: "org label list <org>", ReadOnly: true, Run: runOrgLabelList}) | |
| 23 | Summary: "list an org's labels with use across the repositories you can read", | |
| 24 | Usage: "org label list <org>", | |
| 25 | Examples: []string{"org label list krz"}, | |
| 26 | ReadOnly: true, Run: runOrgLabelList}) | |
| 20 | 27 | register(Command{Path: []string{"org", "label", "remove"}, |
| 21 | Summary: "remove an org label from the org and from every issue under it", | |
| 22 | Usage: "org label remove <org> <label>", Run: runOrgLabelRemove}) | |
| 28 | Summary: "remove an org label from the org and from every issue under it", | |
| 29 | Usage: "org label remove <org> <label>", | |
| 30 | Examples: []string{"org label remove krz wontfix"}, | |
| 31 | Run: runOrgLabelRemove}) | |
| 23 | 32 | register(Command{Path: []string{"org", "milestone", "create"}, |
| 24 | 33 | Summary: "create an org milestone spanning every org repository; folds in same-titled repo milestones", |
| 25 | Usage: "org milestone create <org> <title> [--description <d>] [--due YYYY-MM-DD]", Run: runOrgMilestoneCreate}) | |
| 34 | Usage: "org milestone create <org> <title> [--description <d>] [--due YYYY-MM-DD]", | |
| 35 | Flags: []Flag{ | |
| 36 | {"--description", "<d>", "what the milestone covers", ""}, | |
| 37 | {"--due", "YYYY-MM-DD", "target date", ""}, | |
| 38 | }, | |
| 39 | Examples: []string{"org milestone create krz mobile --due 2026-12-01"}, | |
| 40 | Run: runOrgMilestoneCreate}) | |
| 26 | 41 | register(Command{Path: []string{"org", "milestone", "list"}, |
| 27 | 42 | Summary: "list an org's milestones with progress across the repositories you can read", |
| 28 | Usage: "org milestone list <org> [--state open|closed|all]", ReadOnly: true, Run: runOrgMilestoneList}) | |
| 43 | Usage: "org milestone list <org> [--state open|closed|all]", | |
| 44 | Flags: []Flag{ | |
| 45 | {"--state", "open|closed|all", "which milestones", "open"}, | |
| 46 | }, | |
| 47 | Examples: []string{"org milestone list krz --state all"}, | |
| 48 | ReadOnly: true, Run: runOrgMilestoneList}) | |
| 29 | 49 | register(Command{Path: []string{"org", "milestone", "close"}, |
| 30 | Summary: "close an org milestone", | |
| 31 | Usage: "org milestone close <org> <title>", Run: runOrgMilestoneClose}) | |
| 50 | Summary: "close an org milestone", | |
| 51 | Usage: "org milestone close <org> <title>", | |
| 52 | Examples: []string{"org milestone close krz mobile"}, | |
| 53 | Run: runOrgMilestoneClose}) | |
| 32 | 54 | register(Command{Path: []string{"org", "milestone", "reopen"}, |
| 33 | Summary: "reopen an org milestone", | |
| 34 | Usage: "org milestone reopen <org> <title>", Run: runOrgMilestoneReopen}) | |
| 55 | Summary: "reopen an org milestone", | |
| 56 | Usage: "org milestone reopen <org> <title>", | |
| 57 | Examples: []string{"org milestone reopen krz mobile"}, | |
| 58 | Run: runOrgMilestoneReopen}) | |
| 35 | 59 | } |
| 36 | 60 | |
| 37 | 61 | // orgReader resolves an org for a read of its labels or milestones. |
internal/control/pagescmd.go +16 −8
| @@ -20,17 +20,25 @@ import ( | ||
| 20 | 20 | |
| 21 | 21 | func init() { |
| 22 | 22 | register(Command{Path: []string{"repo", "domain", "add"}, |
| 23 | Summary: "claim a custom pages domain (verify with a DNS TXT record)", | |
| 24 | Usage: "repo domain add <owner/name> <domain>", Run: runDomainAdd}) | |
| 23 | Summary: "claim a custom pages domain (verify with a DNS TXT record)", | |
| 24 | Usage: "repo domain add <owner/name> <domain>", | |
| 25 | Examples: []string{"repo domain add krz/gitbay gitbay.org"}, | |
| 26 | Run: runDomainAdd}) | |
| 25 | 27 | register(Command{Path: []string{"repo", "domain", "verify"}, |
| 26 | Summary: "check the DNS challenge and activate a claim", | |
| 27 | Usage: "repo domain verify <owner/name> <domain>", Run: runDomainVerify}) | |
| 28 | Summary: "check the DNS challenge and activate a claim", | |
| 29 | Usage: "repo domain verify <owner/name> <domain>", | |
| 30 | Examples: []string{"repo domain verify krz/gitbay gitbay.org"}, | |
| 31 | Run: runDomainVerify}) | |
| 28 | 32 | register(Command{Path: []string{"repo", "domain", "remove"}, |
| 29 | Summary: "remove a custom pages domain", | |
| 30 | Usage: "repo domain remove <owner/name> <domain>", Run: runDomainRemove}) | |
| 33 | Summary: "remove a custom pages domain", | |
| 34 | Usage: "repo domain remove <owner/name> <domain>", | |
| 35 | Examples: []string{"repo domain remove krz/gitbay gitbay.org"}, | |
| 36 | Run: runDomainRemove}) | |
| 31 | 37 | register(Command{Path: []string{"repo", "domain", "list"}, |
| 32 | Summary: "list custom pages domains", | |
| 33 | Usage: "repo domain list <owner/name>", ReadOnly: true, Run: runDomainList}) | |
| 38 | Summary: "list custom pages domains", | |
| 39 | Usage: "repo domain list <owner/name>", | |
| 40 | Examples: []string{"repo domain list krz/gitbay"}, | |
| 41 | ReadOnly: true, Run: runDomainList}) | |
| 34 | 42 | } |
| 35 | 43 | |
| 36 | 44 | // challengeLabel prefixes the domain for the ownership TXT record. |
internal/control/read.go +24 −9
| @@ -17,23 +17,37 @@ import ( | ||
| 17 | 17 | |
| 18 | 18 | func init() { |
| 19 | 19 | register(Command{ |
| 20 | Path: []string{"repo", "tree"}, | |
| 21 | Summary: "list a directory", | |
| 22 | Usage: "repo tree <owner/name> [<path>] [--ref <ref>]", | |
| 20 | Path: []string{"repo", "tree"}, | |
| 21 | Summary: "list a directory", | |
| 22 | Usage: "repo tree <owner/name> [<path>] [--ref <ref>]", | |
| 23 | Flags: []Flag{ | |
| 24 | {"--ref", "<ref>", "branch, tag or commit to read", "the default branch"}, | |
| 25 | }, | |
| 26 | Examples: []string{"repo tree krz/gitbay internal/control"}, | |
| 23 | 27 | ReadOnly: true, |
| 24 | 28 | Run: runRepoTree, |
| 25 | 29 | }) |
| 26 | 30 | register(Command{ |
| 27 | Path: []string{"repo", "cat"}, | |
| 28 | Summary: "read a file", | |
| 29 | Usage: "repo cat <owner/name> <path> [--ref <ref>]", | |
| 31 | Path: []string{"repo", "cat"}, | |
| 32 | Summary: "read a file", | |
| 33 | Usage: "repo cat <owner/name> <path> [--ref <ref>]", | |
| 34 | Flags: []Flag{ | |
| 35 | {"--ref", "<ref>", "branch, tag or commit to read", "the default branch"}, | |
| 36 | }, | |
| 37 | Examples: []string{"repo cat krz/gitbay internal/control/control.go"}, | |
| 30 | 38 | ReadOnly: true, |
| 31 | 39 | Run: runRepoCat, |
| 32 | 40 | }) |
| 33 | 41 | register(Command{ |
| 34 | Path: []string{"repo", "blame"}, | |
| 35 | Summary: "attribute lines to commits", | |
| 36 | Usage: "repo blame <owner/name> <path> [--ref <ref>] [--from <n>] [--to <n>]", | |
| 42 | Path: []string{"repo", "blame"}, | |
| 43 | Summary: "attribute lines to commits", | |
| 44 | Usage: "repo blame <owner/name> <path> [--ref <ref>] [--from <n>] [--to <n>]", | |
| 45 | Flags: []Flag{ | |
| 46 | {"--ref", "<ref>", "branch, tag or commit to read", "the default branch"}, | |
| 47 | {"--from", "<n>", "first line to attribute", "1"}, | |
| 48 | {"--to", "<n>", "last line to attribute", "the file's last line"}, | |
| 49 | }, | |
| 50 | Examples: []string{"repo blame krz/gitbay internal/control/control.go --from 1 --to 40"}, | |
| 37 | 51 | ReadOnly: true, |
| 38 | 52 | Run: runRepoBlame, |
| 39 | 53 | }) |
| @@ -41,6 +55,7 @@ func init() { | ||
| 41 | 55 | Path: []string{"repo", "refs"}, |
| 42 | 56 | Summary: "list branches and tags", |
| 43 | 57 | Usage: "repo refs <owner/name>", |
| 58 | Examples: []string{"repo refs krz/gitbay"}, | |
| 44 | 59 | ReadOnly: true, |
| 45 | 60 | Run: runRepoRefs, |
| 46 | 61 | }) |
internal/control/release.go +44 −10
| @@ -20,33 +20,67 @@ import ( | ||
| 20 | 20 | |
| 21 | 21 | func init() { |
| 22 | 22 | register(Command{Path: []string{"release", "create"}, |
| 23 | Summary: "create a release on a tag", | |
| 24 | Usage: "release create <owner/name> <tag> [--title <t>] [--notes <n> | --file -] [--format md|org]", | |
| 23 | Summary: "create a release on a tag", | |
| 24 | Usage: "release create <owner/name> <tag> [--title <t>] [--notes <n> | --file -] [--format md|org]", | |
| 25 | Flags: []Flag{ | |
| 26 | {"--title", "<t>", "the release's title", "the tag"}, | |
| 27 | {"--notes", "<n>", "the release notes", ""}, | |
| 28 | {"--file", "-", "read the release notes from stdin", ""}, | |
| 29 | {"--format", "md|org", "the notes' markup", "md"}, | |
| 30 | }, | |
| 31 | Examples: []string{ | |
| 32 | `release create krz/gitbay v1.31.0 --title "v1.31.0" --notes "flag help"`, | |
| 33 | "release create krz/gitbay v1.31.0 --file - '< notes.md'", | |
| 34 | }, | |
| 25 | 35 | ReadsStdin: true, Run: runReleaseCreate}) |
| 26 | 36 | register(Command{Path: []string{"release", "edit"}, |
| 27 | Summary: "update a release's title and notes", | |
| 28 | Usage: "release edit <owner/name> <tag> [--title <t>] [--notes <n> | --file -] [--format md|org]", | |
| 37 | Summary: "update a release's title and notes", | |
| 38 | Usage: "release edit <owner/name> <tag> [--title <t>] [--notes <n> | --file -] [--format md|org]", | |
| 39 | Flags: []Flag{ | |
| 40 | {"--title", "<t>", "the release's new title", ""}, | |
| 41 | {"--notes", "<n>", "the release's new notes", ""}, | |
| 42 | {"--file", "-", "read the new release notes from stdin", ""}, | |
| 43 | {"--format", "md|org", "the notes' markup", ""}, | |
| 44 | }, | |
| 45 | Examples: []string{`release edit krz/gitbay v1.31.0 --title "v1.31.0"`}, | |
| 29 | 46 | ReadsStdin: true, Run: runReleaseEdit}) |
| 30 | 47 | register(Command{Path: []string{"release", "list"}, |
| 31 | 48 | Summary: "list releases", |
| 32 | Usage: "release list <owner/name> [--limit <n>] [--cursor <c>]", ReadOnly: true, Run: runReleaseList}) | |
| 49 | Usage: "release list <owner/name> [--limit <n>] [--cursor <c>]", | |
| 50 | Flags: []Flag{ | |
| 51 | {"--limit", "<n>", "rows per page", ""}, | |
| 52 | {"--cursor", "<c>", "continue from the previous page", ""}, | |
| 53 | }, | |
| 54 | Examples: []string{"release list krz/gitbay --limit 10"}, | |
| 55 | ReadOnly: true, Run: runReleaseList}) | |
| 33 | 56 | register(Command{Path: []string{"release", "show"}, |
| 34 | Summary: "show a release with assets", | |
| 35 | Usage: "release show <owner/name> <tag>", ReadOnly: true, Run: runReleaseShow}) | |
| 57 | Summary: "show a release with assets", | |
| 58 | Usage: "release show <owner/name> <tag>", | |
| 59 | Examples: []string{"release show krz/gitbay v1.30.0"}, | |
| 60 | ReadOnly: true, Run: runReleaseShow}) | |
| 36 | 61 | register(Command{Path: []string{"release", "delete"}, |
| 37 | 62 | Summary: "delete a release and its assets", |
| 38 | Usage: "release delete <owner/name> <tag> --yes", Run: runReleaseDelete}) | |
| 63 | Usage: "release delete <owner/name> <tag> --yes", | |
| 64 | Flags: []Flag{ | |
| 65 | {"--yes", "", "confirm the permanent delete", ""}, | |
| 66 | }, | |
| 67 | Examples: []string{"release delete krz/gitbay v1.30.0 --yes"}, | |
| 68 | Run: runReleaseDelete}) | |
| 39 | 69 | register(Command{Path: []string{"release", "asset", "add"}, |
| 40 | 70 | Summary: "upload an asset from stdin", |
| 41 | 71 | Usage: "release asset add <owner/name> <tag> <filename> < file", |
| 72 | Examples: []string{"release asset add krz/gitbay v1.30.0 gitbay-darwin-arm64 '< gitbay-darwin-arm64'"}, | |
| 42 | 73 | ReadsStdin: true, Run: runAssetAdd}) |
| 43 | 74 | register(Command{Path: []string{"release", "asset", "get"}, |
| 44 | 75 | Summary: "write an asset to stdout", |
| 45 | 76 | Usage: "release asset get <owner/name> <tag> <filename> > file", |
| 77 | Examples: []string{"release asset get krz/gitbay v1.30.0 gitbay-darwin-arm64 '> gitbay-darwin-arm64'"}, | |
| 46 | 78 | ReadOnly: true, Run: runAssetGet}) |
| 47 | 79 | register(Command{Path: []string{"release", "asset", "remove"}, |
| 48 | Summary: "remove an asset", | |
| 49 | Usage: "release asset remove <owner/name> <tag> <filename>", Run: runAssetRemove}) | |
| 80 | Summary: "remove an asset", | |
| 81 | Usage: "release asset remove <owner/name> <tag> <filename>", | |
| 82 | Examples: []string{"release asset remove krz/gitbay v1.30.0 gitbay-darwin-arm64"}, | |
| 83 | Run: runAssetRemove}) | |
| 50 | 84 | } |
| 51 | 85 | |
| 52 | 86 | var assetNamePat = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9._+-]{0,199}$`) |
internal/control/repo.go +137 −60
| @@ -28,100 +28,177 @@ func HooksDir(root string) string { return filepath.Join(root, "hooks") } | ||
| 28 | 28 | func init() { |
| 29 | 29 | register(Command{Path: []string{"repo", "create"}, |
| 30 | 30 | Summary: "create a repository", |
| 31 | Usage: "repo create <owner/name> [--private]", Run: runRepoCreate}) | |
| 31 | Usage: "repo create <owner/name> [--private]", | |
| 32 | Flags: []Flag{ | |
| 33 | {"--private", "", "create it private", ""}, | |
| 34 | }, | |
| 35 | Examples: []string{"repo create krz/newthing --private"}, | |
| 36 | Run: runRepoCreate}) | |
| 32 | 37 | register(Command{Path: []string{"repo", "list"}, |
| 33 | 38 | Summary: "list repositories you own or can access", |
| 34 | Usage: "repo list [--limit <n>] [--cursor <c>]", ReadOnly: true, Run: runRepoList}) | |
| 39 | Usage: "repo list [--limit <n>] [--cursor <c>]", | |
| 40 | Flags: []Flag{ | |
| 41 | {"--limit", "<n>", "rows per page", ""}, | |
| 42 | {"--cursor", "<c>", "continue from the previous page", ""}, | |
| 43 | }, | |
| 44 | Examples: []string{"repo list --limit 20"}, | |
| 45 | ReadOnly: true, Run: runRepoList}) | |
| 35 | 46 | register(Command{Path: []string{"repo", "show"}, |
| 36 | Summary: "show repository details", | |
| 37 | Usage: "repo show <owner/name>", ReadOnly: true, Run: runRepoShow}) | |
| 47 | Summary: "show repository details", | |
| 48 | Usage: "repo show <owner/name>", | |
| 49 | Examples: []string{"repo show krz/gitbay"}, | |
| 50 | ReadOnly: true, Run: runRepoShow}) | |
| 38 | 51 | register(Command{Path: []string{"repo", "transfer"}, |
| 39 | Summary: "move a repository to another owner", | |
| 40 | Usage: "repo transfer <owner/name> <new-owner> (clone URLs change)", Run: runRepoTransfer}) | |
| 52 | Summary: "move a repository to another owner", | |
| 53 | Usage: "repo transfer <owner/name> <new-owner> (clone URLs change)", | |
| 54 | Examples: []string{"repo transfer krz/gitbay krazywarez"}, | |
| 55 | Run: runRepoTransfer}) | |
| 41 | 56 | register(Command{Path: []string{"repo", "rename"}, |
| 42 | Summary: "rename a repository", | |
| 43 | Usage: "repo rename <owner/name> <new-name> (clone URLs change)", Run: runRepoRename}) | |
| 57 | Summary: "rename a repository", | |
| 58 | Usage: "repo rename <owner/name> <new-name> (clone URLs change)", | |
| 59 | Examples: []string{"repo rename krz/gitbay forge"}, | |
| 60 | Run: runRepoRename}) | |
| 44 | 61 | register(Command{Path: []string{"repo", "delete"}, |
| 45 | 62 | Summary: "delete a repository", |
| 46 | Usage: "repo delete <owner/name> --yes", Run: runRepoDelete}) | |
| 63 | Usage: "repo delete <owner/name> --yes", | |
| 64 | Flags: []Flag{ | |
| 65 | {"--yes", "", "confirm the permanent delete", ""}, | |
| 66 | }, | |
| 67 | Examples: []string{"repo delete cmc/scratch --yes"}, | |
| 68 | Run: runRepoDelete}) | |
| 47 | 69 | register(Command{Path: []string{"repo", "access", "grant"}, |
| 48 | Summary: "grant access", | |
| 49 | Usage: "repo access grant <owner/name> <user> read|write|admin", Run: runAccessGrant}) | |
| 70 | Summary: "grant access", | |
| 71 | Usage: "repo access grant <owner/name> <user> read|write|admin", | |
| 72 | Examples: []string{"repo access grant krz/gitbay cmc write"}, | |
| 73 | Run: runAccessGrant}) | |
| 50 | 74 | register(Command{Path: []string{"repo", "access", "revoke"}, |
| 51 | Summary: "revoke access", | |
| 52 | Usage: "repo access revoke <owner/name> <user>", Run: runAccessRevoke}) | |
| 75 | Summary: "revoke access", | |
| 76 | Usage: "repo access revoke <owner/name> <user>", | |
| 77 | Examples: []string{"repo access revoke krz/gitbay cmc"}, | |
| 78 | Run: runAccessRevoke}) | |
| 53 | 79 | register(Command{Path: []string{"repo", "access", "list"}, |
| 54 | Summary: "list who can reach the repository, with the role and where it comes from", | |
| 55 | Usage: "repo access list <owner/name>", ReadOnly: true, Run: runAccessList}) | |
| 80 | Summary: "list who can reach the repository, with the role and where it comes from", | |
| 81 | Usage: "repo access list <owner/name>", | |
| 82 | Examples: []string{"repo access list krz/gitbay"}, | |
| 83 | ReadOnly: true, Run: runAccessList}) | |
| 56 | 84 | register(Command{Path: []string{"repo", "settings", "show"}, |
| 57 | Summary: "show settings", | |
| 58 | Usage: "repo settings show <owner/name>", ReadOnly: true, Run: runSettingsShow}) | |
| 85 | Summary: "show settings", | |
| 86 | Usage: "repo settings show <owner/name>", | |
| 87 | Examples: []string{"repo settings show krz/gitbay"}, | |
| 88 | ReadOnly: true, Run: runSettingsShow}) | |
| 59 | 89 | register(Command{Path: []string{"repo", "settings", "protect"}, |
| 60 | Summary: "protect a branch", | |
| 61 | Usage: "repo settings protect <owner/name> <branch>", Run: runProtect}) | |
| 90 | Summary: "protect a branch", | |
| 91 | Usage: "repo settings protect <owner/name> <branch>", | |
| 92 | Examples: []string{"repo settings protect krz/gitbay main"}, | |
| 93 | Run: runProtect}) | |
| 62 | 94 | register(Command{Path: []string{"repo", "settings", "unprotect"}, |
| 63 | Summary: "unprotect a branch", | |
| 64 | Usage: "repo settings unprotect <owner/name> <branch>", Run: runUnprotect}) | |
| 95 | Summary: "unprotect a branch", | |
| 96 | Usage: "repo settings unprotect <owner/name> <branch>", | |
| 97 | Examples: []string{"repo settings unprotect krz/gitbay main"}, | |
| 98 | Run: runUnprotect}) | |
| 65 | 99 | register(Command{Path: []string{"repo", "settings", "protect-tag"}, |
| 66 | Summary: "protect tags matching a glob (created once, never moved or deleted)", | |
| 67 | Usage: "repo settings protect-tag <owner/name> <glob>", Run: runProtectTag}) | |
| 100 | Summary: "protect tags matching a glob (created once, never moved or deleted)", | |
| 101 | Usage: "repo settings protect-tag <owner/name> <glob>", | |
| 102 | Examples: []string{"repo settings protect-tag krz/gitbay 'v*'"}, | |
| 103 | Run: runProtectTag}) | |
| 68 | 104 | register(Command{Path: []string{"repo", "settings", "unprotect-tag"}, |
| 69 | Summary: "drop a protected-tag glob", | |
| 70 | Usage: "repo settings unprotect-tag <owner/name> <glob>", Run: runUnprotectTag}) | |
| 105 | Summary: "drop a protected-tag glob", | |
| 106 | Usage: "repo settings unprotect-tag <owner/name> <glob>", | |
| 107 | Examples: []string{"repo settings unprotect-tag krz/gitbay 'v*'"}, | |
| 108 | Run: runUnprotectTag}) | |
| 71 | 109 | register(Command{Path: []string{"repo", "settings", "description"}, |
| 72 | Summary: "set the repository description", | |
| 73 | Usage: "repo settings description <owner/name> <text> ('' clears)", Run: runSetDescription}) | |
| 110 | Summary: "set the repository description", | |
| 111 | Usage: "repo settings description <owner/name> <text> ('' clears)", | |
| 112 | Examples: []string{`repo settings description krz/gitbay "a CLI-first git forge"`}, | |
| 113 | Run: runSetDescription}) | |
| 74 | 114 | register(Command{Path: []string{"repo", "settings", "visibility"}, |
| 75 | Summary: "set repository visibility", | |
| 76 | Usage: "repo settings visibility <owner/name> public|private", Run: runSetVisibility}) | |
| 115 | Summary: "set repository visibility", | |
| 116 | Usage: "repo settings visibility <owner/name> public|private", | |
| 117 | Examples: []string{"repo settings visibility krz/gitbay public"}, | |
| 118 | Run: runSetVisibility}) | |
| 77 | 119 | register(Command{Path: []string{"repo", "settings", "website"}, |
| 78 | Summary: "set the repository website", | |
| 79 | Usage: "repo settings website <owner/name> <url> ('' clears)", Run: runSetWebsite}) | |
| 120 | Summary: "set the repository website", | |
| 121 | Usage: "repo settings website <owner/name> <url> ('' clears)", | |
| 122 | Examples: []string{"repo settings website krz/gitbay https://gitbay.org"}, | |
| 123 | Run: runSetWebsite}) | |
| 80 | 124 | register(Command{Path: []string{"repo", "settings", "default-branch"}, |
| 81 | Summary: "set the default branch", | |
| 82 | Usage: "repo settings default-branch <owner/name> <branch>", Run: runSetDefaultBranch}) | |
| 125 | Summary: "set the default branch", | |
| 126 | Usage: "repo settings default-branch <owner/name> <branch>", | |
| 127 | Examples: []string{"repo settings default-branch krz/gitbay main"}, | |
| 128 | Run: runSetDefaultBranch}) | |
| 83 | 129 | register(Command{Path: []string{"repo", "settings", "git-daemon"}, |
| 84 | Summary: "expose over git://", | |
| 85 | Usage: "repo settings git-daemon <owner/name> on|off", Run: runGitDaemon}) | |
| 130 | Summary: "expose over git://", | |
| 131 | Usage: "repo settings git-daemon <owner/name> on|off", | |
| 132 | Examples: []string{"repo settings git-daemon krz/gitbay on"}, | |
| 133 | Run: runGitDaemon}) | |
| 86 | 134 | register(Command{Path: []string{"repo", "archive"}, |
| 87 | Summary: "archive a repository (read-only: pushes and issue/MR writes refused)", | |
| 88 | Usage: "repo archive <owner/name>", Run: runArchive}) | |
| 135 | Summary: "archive a repository (read-only: pushes and issue/MR writes refused)", | |
| 136 | Usage: "repo archive <owner/name>", | |
| 137 | Examples: []string{"repo archive krz/gitbay"}, | |
| 138 | Run: runArchive}) | |
| 89 | 139 | register(Command{Path: []string{"repo", "unarchive"}, |
| 90 | Summary: "unarchive a repository", | |
| 91 | Usage: "repo unarchive <owner/name>", Run: runUnarchive}) | |
| 140 | Summary: "unarchive a repository", | |
| 141 | Usage: "repo unarchive <owner/name>", | |
| 142 | Examples: []string{"repo unarchive krz/gitbay"}, | |
| 143 | Run: runUnarchive}) | |
| 92 | 144 | register(Command{Path: []string{"repo", "topics"}, |
| 93 | Summary: "list topics", | |
| 94 | Usage: "repo topics <owner/name>", ReadOnly: true, Run: runTopicsList}) | |
| 145 | Summary: "list topics", | |
| 146 | Usage: "repo topics <owner/name>", | |
| 147 | Examples: []string{"repo topics krz/gitbay"}, | |
| 148 | ReadOnly: true, Run: runTopicsList}) | |
| 95 | 149 | register(Command{Path: []string{"repo", "topics", "add"}, |
| 96 | Summary: "add topics", | |
| 97 | Usage: "repo topics add <owner/name> <topic>...", Run: runTopicsAdd}) | |
| 150 | Summary: "add topics", | |
| 151 | Usage: "repo topics add <owner/name> <topic>...", | |
| 152 | Examples: []string{"repo topics add krz/gitbay git forge cli"}, | |
| 153 | Run: runTopicsAdd}) | |
| 98 | 154 | register(Command{Path: []string{"repo", "topics", "remove"}, |
| 99 | Summary: "remove topics", | |
| 100 | Usage: "repo topics remove <owner/name> <topic>...", Run: runTopicsRemove}) | |
| 155 | Summary: "remove topics", | |
| 156 | Usage: "repo topics remove <owner/name> <topic>...", | |
| 157 | Examples: []string{"repo topics remove krz/gitbay cli"}, | |
| 158 | Run: runTopicsRemove}) | |
| 101 | 159 | register(Command{Path: []string{"repo", "search"}, |
| 102 | Summary: "find repositories by name, description, or topic", | |
| 103 | Usage: "repo search <query>", ReadOnly: true, Run: runRepoSearch}) | |
| 160 | Summary: "find repositories by name, description, or topic", | |
| 161 | Usage: "repo search <query>", | |
| 162 | Examples: []string{"repo search forge"}, | |
| 163 | ReadOnly: true, Run: runRepoSearch}) | |
| 104 | 164 | register(Command{Path: []string{"repo", "grep"}, |
| 105 | 165 | Summary: "search file contents", |
| 106 | Usage: "repo grep <owner/name> <query> [--ref <ref>]", ReadOnly: true, Run: runRepoGrep}) | |
| 166 | Usage: "repo grep <owner/name> <query> [--ref <ref>]", | |
| 167 | Flags: []Flag{ | |
| 168 | {"--ref", "<ref>", "branch, tag or commit to search", "the default branch"}, | |
| 169 | }, | |
| 170 | Examples: []string{"repo grep krz/gitbay TODO"}, | |
| 171 | ReadOnly: true, Run: runRepoGrep}) | |
| 107 | 172 | register(Command{Path: []string{"repo", "diff"}, |
| 108 | Summary: "the patch between two refs, from their merge base", | |
| 109 | Usage: "repo diff <owner/name> <base> <head>", ReadOnly: true, Run: runRepoDiff}) | |
| 173 | Summary: "the patch between two refs, from their merge base", | |
| 174 | Usage: "repo diff <owner/name> <base> <head>", | |
| 175 | Examples: []string{"repo diff krz/gitbay main cli-output-help"}, | |
| 176 | ReadOnly: true, Run: runRepoDiff}) | |
| 110 | 177 | register(Command{Path: []string{"repo", "pin"}, |
| 111 | Summary: "pin a repository to your dashboard", | |
| 112 | Usage: "repo pin <owner/name>", Run: runRepoPin}) | |
| 178 | Summary: "pin a repository to your dashboard", | |
| 179 | Usage: "repo pin <owner/name>", | |
| 180 | Examples: []string{"repo pin krz/gitbay"}, | |
| 181 | Run: runRepoPin}) | |
| 113 | 182 | register(Command{Path: []string{"repo", "unpin"}, |
| 114 | Summary: "unpin a repository", | |
| 115 | Usage: "repo unpin <owner/name>", Run: runRepoUnpin}) | |
| 183 | Summary: "unpin a repository", | |
| 184 | Usage: "repo unpin <owner/name>", | |
| 185 | Examples: []string{"repo unpin krz/gitbay"}, | |
| 186 | Run: runRepoUnpin}) | |
| 116 | 187 | register(Command{Path: []string{"repo", "bookmark"}, |
| 117 | Summary: "bookmark a repository to come back to", | |
| 118 | Usage: "repo bookmark <owner/name>", Run: runRepoBookmark}) | |
| 188 | Summary: "bookmark a repository to come back to", | |
| 189 | Usage: "repo bookmark <owner/name>", | |
| 190 | Examples: []string{"repo bookmark krz/gitbay"}, | |
| 191 | Run: runRepoBookmark}) | |
| 119 | 192 | register(Command{Path: []string{"repo", "unbookmark"}, |
| 120 | Summary: "remove a bookmark", | |
| 121 | Usage: "repo unbookmark <owner/name>", Run: runRepoUnbookmark}) | |
| 193 | Summary: "remove a bookmark", | |
| 194 | Usage: "repo unbookmark <owner/name>", | |
| 195 | Examples: []string{"repo unbookmark krz/gitbay"}, | |
| 196 | Run: runRepoUnbookmark}) | |
| 122 | 197 | register(Command{Path: []string{"repo", "bookmarks"}, |
| 123 | Summary: "list the repositories you have bookmarked", | |
| 124 | Usage: "repo bookmarks", ReadOnly: true, Run: runRepoBookmarks}) | |
| 198 | Summary: "list the repositories you have bookmarked", | |
| 199 | Usage: "repo bookmarks", | |
| 200 | Examples: []string{"repo bookmarks"}, | |
| 201 | ReadOnly: true, Run: runRepoBookmarks}) | |
| 125 | 202 | } |
| 126 | 203 | |
| 127 | 204 | const ( |
internal/control/runnerrepo.go +9 −4
| @@ -21,13 +21,18 @@ func init() { | ||
| 21 | 21 | register(Command{Path: []string{"repo", "runner", "add"}, |
| 22 | 22 | Summary: "attach a runner's public key to a repository", |
| 23 | 23 | Usage: "repo runner add <owner/name> < key.pub", |
| 24 | Examples: []string{"repo runner add krz/gitbay '< key.pub'"}, | |
| 24 | 25 | ReadsStdin: true, Run: runRepoRunnerAdd}) |
| 25 | 26 | register(Command{Path: []string{"repo", "runner", "list"}, |
| 26 | Summary: "list the runners attached to a repository", | |
| 27 | Usage: "repo runner list <owner/name>", ReadOnly: true, Run: runRepoRunnerList}) | |
| 27 | Summary: "list the runners attached to a repository", | |
| 28 | Usage: "repo runner list <owner/name>", | |
| 29 | Examples: []string{"repo runner list krz/gitbay"}, | |
| 30 | ReadOnly: true, Run: runRepoRunnerList}) | |
| 28 | 31 | register(Command{Path: []string{"repo", "runner", "remove"}, |
| 29 | Summary: "detach a runner from a repository", | |
| 30 | Usage: "repo runner remove <owner/name> <fingerprint>", Run: runRepoRunnerRemove}) | |
| 32 | Summary: "detach a runner from a repository", | |
| 33 | Usage: "repo runner remove <owner/name> <fingerprint>", | |
| 34 | Examples: []string{"repo runner remove krz/gitbay SHA256:abcd1234"}, | |
| 35 | Run: runRepoRunnerRemove}) | |
| 31 | 36 | } |
| 32 | 37 | |
| 33 | 38 | func runRepoRunnerAdd(c *Ctx, args []string) int { |
internal/control/search.go +9 −2
| @@ -12,8 +12,15 @@ import ( | ||
| 12 | 12 | |
| 13 | 13 | func init() { |
| 14 | 14 | register(Command{Path: []string{"search"}, |
| 15 | Summary: "find repositories, issues and merge requests across the instance", | |
| 16 | Usage: "search <query> [--kind repo|issue|mr]", | |
| 15 | Summary: "find repositories, issues and merge requests across the instance", | |
| 16 | Usage: "search <query> [--kind repo|issue|mr]", | |
| 17 | Flags: []Flag{ | |
| 18 | {"--kind", "repo|issue|mr", "only this kind of result, may repeat", ""}, | |
| 19 | }, | |
| 20 | Examples: []string{ | |
| 21 | "search auth bug", | |
| 22 | "search auth bug --kind issue", | |
| 23 | }, | |
| 17 | 24 | ReadOnly: true, Run: runSearch}) |
| 18 | 25 | } |
| 19 | 26 | |
internal/control/sig.go +9 −1
| @@ -29,10 +29,18 @@ func init() { | ||
| 29 | 29 | register(Command{Path: []string{"repo", "commit"}, |
| 30 | 30 | Summary: "show one commit with its patch", |
| 31 | 31 | Usage: "repo commit <owner/name> <sha>", |
| 32 | Examples: []string{"repo commit krz/gitbay a1b2c3d"}, | |
| 32 | 33 | ReadOnly: true, Run: runRepoCommit}) |
| 33 | 34 | register(Command{Path: []string{"repo", "log"}, |
| 34 | 35 | Summary: "commit log with signature states", |
| 35 | Usage: "repo log <owner/name> [--ref <r>] [--limit n] [--path <file>]", ReadOnly: true, Run: runRepoLog}) | |
| 36 | Usage: "repo log <owner/name> [--ref <r>] [--limit n] [--path <file>]", | |
| 37 | Flags: []Flag{ | |
| 38 | {"--ref", "<r>", "branch, tag or commit to start from", "the default branch"}, | |
| 39 | {"--limit", "n", "rows to show", "30"}, | |
| 40 | {"--path", "<file>", "only commits touching this path", ""}, | |
| 41 | }, | |
| 42 | Examples: []string{"repo log krz/gitbay --limit 10"}, | |
| 43 | ReadOnly: true, Run: runRepoLog}) | |
| 36 | 44 | } |
| 37 | 45 | |
| 38 | 46 | func runPGPAdd(c *Ctx, args []string) int { |
internal/control/snippet.go +38 −12
| @@ -19,31 +19,57 @@ const maxSnippetFiles = 64 | ||
| 19 | 19 | |
| 20 | 20 | func init() { |
| 21 | 21 | register(Command{Path: []string{"snippet", "create"}, |
| 22 | Summary: "create a snippet from one file on stdin", | |
| 23 | Usage: "snippet create <filename> [--description <d>] [--visibility public|unlisted|private] < file", | |
| 22 | Summary: "create a snippet from one file on stdin", | |
| 23 | Usage: "snippet create <filename> [--description <d>] [--visibility public|unlisted|private] < file", | |
| 24 | Flags: []Flag{ | |
| 25 | {"--description", "<d>", "one line about the snippet", ""}, | |
| 26 | {"--visibility", "public|unlisted|private", "who can find it", "unlisted"}, | |
| 27 | }, | |
| 28 | Examples: []string{"snippet create notes.md --visibility private '< notes.md'"}, | |
| 24 | 29 | ReadsStdin: true, Run: runSnippetCreate}) |
| 25 | 30 | register(Command{Path: []string{"snippet", "show"}, |
| 26 | Summary: "show a snippet's metadata and files", | |
| 27 | Usage: "snippet show <id>", ReadOnly: true, Run: runSnippetShow}) | |
| 31 | Summary: "show a snippet's metadata and files", | |
| 32 | Usage: "snippet show <id>", | |
| 33 | Examples: []string{"snippet show a1b2c3"}, | |
| 34 | ReadOnly: true, Run: runSnippetShow}) | |
| 28 | 35 | register(Command{Path: []string{"snippet", "list"}, |
| 29 | 36 | Summary: "list your snippets, or an owner's public ones", |
| 30 | Usage: "snippet list [<owner>] [--limit n] [--cursor c]", ReadOnly: true, Run: runSnippetList}) | |
| 37 | Usage: "snippet list [<owner>] [--limit n] [--cursor c]", | |
| 38 | Flags: []Flag{ | |
| 39 | {"--limit", "n", "rows per page", ""}, | |
| 40 | {"--cursor", "c", "continue from the previous page", ""}, | |
| 41 | }, | |
| 42 | Examples: []string{"snippet list cmc"}, | |
| 43 | ReadOnly: true, Run: runSnippetList}) | |
| 31 | 44 | register(Command{Path: []string{"snippet", "edit"}, |
| 32 | 45 | Summary: "change a snippet's description or visibility", |
| 33 | Usage: "snippet edit <id> [--description <d>] [--visibility public|unlisted|private]", Run: runSnippetEdit}) | |
| 46 | Usage: "snippet edit <id> [--description <d>] [--visibility public|unlisted|private]", | |
| 47 | Flags: []Flag{ | |
| 48 | {"--description", "<d>", "one line about the snippet", ""}, | |
| 49 | {"--visibility", "public|unlisted|private", "who can find it", ""}, | |
| 50 | }, | |
| 51 | Examples: []string{"snippet edit a1b2c3 --visibility public"}, | |
| 52 | Run: runSnippetEdit}) | |
| 34 | 53 | register(Command{Path: []string{"snippet", "delete"}, |
| 35 | Summary: "delete a snippet and its files", | |
| 36 | Usage: "snippet delete <id>", Run: runSnippetDelete}) | |
| 54 | Summary: "delete a snippet and its files", | |
| 55 | Usage: "snippet delete <id>", | |
| 56 | Examples: []string{"snippet delete a1b2c3"}, | |
| 57 | Run: runSnippetDelete}) | |
| 37 | 58 | register(Command{Path: []string{"snippet", "file", "set"}, |
| 38 | 59 | Summary: "add a file to a snippet, or replace one, from stdin", |
| 39 | 60 | Usage: "snippet file set <id> <filename> < file", |
| 61 | Examples: []string{"snippet file set a1b2c3 notes.md '< notes.md'"}, | |
| 40 | 62 | ReadsStdin: true, Run: runSnippetFileSet}) |
| 41 | 63 | register(Command{Path: []string{"snippet", "file", "get"}, |
| 42 | Summary: "write a snippet file to stdout", | |
| 43 | Usage: "snippet file get <id> <filename> > file", ReadOnly: true, Run: runSnippetFileGet}) | |
| 64 | Summary: "write a snippet file to stdout", | |
| 65 | Usage: "snippet file get <id> <filename> > file", | |
| 66 | Examples: []string{"snippet file get a1b2c3 notes.md '> notes.md'"}, | |
| 67 | ReadOnly: true, Run: runSnippetFileGet}) | |
| 44 | 68 | register(Command{Path: []string{"snippet", "file", "remove"}, |
| 45 | Summary: "remove a file from a snippet", | |
| 46 | Usage: "snippet file remove <id> <filename>", Run: runSnippetFileRemove}) | |
| 69 | Summary: "remove a file from a snippet", | |
| 70 | Usage: "snippet file remove <id> <filename>", | |
| 71 | Examples: []string{"snippet file remove a1b2c3 notes.md"}, | |
| 72 | Run: runSnippetFileRemove}) | |
| 47 | 73 | } |
| 48 | 74 | |
| 49 | 75 | type SnippetFileOut struct { |
internal/control/status.go +14 −3
| @@ -15,10 +15,21 @@ func init() { | ||
| 15 | 15 | register(Command{Path: []string{"status", "set"}, |
| 16 | 16 | Summary: "report a commit status (CI)", |
| 17 | 17 | Usage: "status set <owner/name> <sha> --context <c> --state pending|success|failure|error [--description <d>] [--url <u>]", |
| 18 | Run: runStatusSet}) | |
| 18 | Flags: []Flag{ | |
| 19 | {"--context", "<c>", "the check this status reports for", ""}, | |
| 20 | {"--state", "pending|success|failure|error", "the check's outcome", ""}, | |
| 21 | {"--description", "<d>", "short text shown beside the state", ""}, | |
| 22 | {"--url", "<u>", "link to the check's own output", ""}, | |
| 23 | }, | |
| 24 | Examples: []string{ | |
| 25 | "status set krz/gitbay a1b2c3d --context ci/build --state success", | |
| 26 | }, | |
| 27 | Run: runStatusSet}) | |
| 19 | 28 | register(Command{Path: []string{"status", "list"}, |
| 20 | Summary: "statuses on a commit", | |
| 21 | Usage: "status list <owner/name> <sha>", ReadOnly: true, Run: runStatusList}) | |
| 29 | Summary: "statuses on a commit", | |
| 30 | Usage: "status list <owner/name> <sha>", | |
| 31 | Examples: []string{"status list krz/gitbay a1b2c3d"}, | |
| 32 | ReadOnly: true, Run: runStatusList}) | |
| 22 | 33 | } |
| 23 | 34 | |
| 24 | 35 | var validStatusState = map[string]bool{"pending": true, "success": true, "failure": true, "error": true} |
internal/control/wiki.go +2
| @@ -18,6 +18,7 @@ func init() { | ||
| 18 | 18 | Path: []string{"wiki", "list"}, |
| 19 | 19 | Summary: "list a repository's wiki pages", |
| 20 | 20 | Usage: "wiki list <owner/name>", |
| 21 | Examples: []string{"wiki list krz/gitbay"}, | |
| 21 | 22 | ReadOnly: true, |
| 22 | 23 | Run: runWikiList, |
| 23 | 24 | }) |
| @@ -25,6 +26,7 @@ func init() { | ||
| 25 | 26 | Path: []string{"wiki", "show"}, |
| 26 | 27 | Summary: "print a wiki page", |
| 27 | 28 | Usage: "wiki show <owner/name> [<page>]", |
| 29 | Examples: []string{"wiki show krz/gitbay Quickstart"}, | |
| 28 | 30 | ReadOnly: true, |
| 29 | 31 | Run: runWikiShow, |
| 30 | 32 | }) |