mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-01-02 05:38:43 +00:00
fix merge conflicts
This commit is contained in:
commit
3f45889ead
79 changed files with 1131 additions and 2638 deletions
15
.drone.yml
15
.drone.yml
|
@ -28,24 +28,11 @@ pipeline:
|
||||||
|
|
||||||
build:
|
build:
|
||||||
image: golang:1.8
|
image: golang:1.8
|
||||||
commands:
|
commands: sh .drone.sh
|
||||||
- ./ci.sh
|
|
||||||
- ./dist.sh
|
|
||||||
secrets: [ ssh_key ]
|
secrets: [ ssh_key ]
|
||||||
when:
|
when:
|
||||||
event: [ push, tag ]
|
event: [ push, tag ]
|
||||||
|
|
||||||
archive:
|
|
||||||
image: plugins/s3
|
|
||||||
acl: public-read
|
|
||||||
bucket: downloads.drone.io
|
|
||||||
source: release/**/*.*
|
|
||||||
target: /0.6.0/
|
|
||||||
secrets: [ aws_access_key_id, aws_secret_access_key ]
|
|
||||||
when:
|
|
||||||
event: push
|
|
||||||
branch: master
|
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
image: plugins/docker
|
image: plugins/docker
|
||||||
repo: drone/drone
|
repo: drone/drone
|
||||||
|
|
21
dist.sh
21
dist.sh
|
@ -1,21 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
set -e
|
|
||||||
set -v
|
|
||||||
|
|
||||||
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-X github.com/drone/drone/version.VersionDev=build.${DRONE_BUILD_NUMBER}" -o release/linux/amd64/drone github.com/drone/drone/drone
|
|
||||||
GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -ldflags "-X github.com/drone/drone/version.VersionDev=build.${DRONE_BUILD_NUMBER}" -o release/linux/arm64/drone github.com/drone/drone/drone
|
|
||||||
GOOS=linux GOARCH=arm CGO_ENABLED=0 go build -ldflags "-X github.com/drone/drone/version.VersionDev=build.${DRONE_BUILD_NUMBER}" -o release/linux/arm/drone github.com/drone/drone/drone
|
|
||||||
GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-X github.com/drone/drone/version.VersionDev=build.${DRONE_BUILD_NUMBER}" -o release/windows/amd64/drone github.com/drone/drone/drone
|
|
||||||
GOOS=darwin GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-X github.com/drone/drone/version.VersionDev=build.${DRONE_BUILD_NUMBER}" -o release/darwin/amd64/drone github.com/drone/drone/drone
|
|
||||||
|
|
||||||
tar -cvzf release/linux/amd64/drone.tar.gz -C release/linux/amd64 drone
|
|
||||||
tar -cvzf release/linux/arm64/drone.tar.gz -C release/linux/arm64 drone
|
|
||||||
tar -cvzf release/linux/arm/drone.tar.gz -C release/linux/arm drone
|
|
||||||
tar -cvzf release/windows/amd64/drone.tar.gz -C release/windows/amd64 drone
|
|
||||||
tar -cvzf release/darwin/amd64/drone.tar.gz -C release/darwin/amd64 drone
|
|
||||||
|
|
||||||
sha256sum release/linux/amd64/drone.tar.gz > release/linux/amd64/drone.sha256
|
|
||||||
sha256sum release/linux/arm64/drone.tar.gz > release/linux/arm64/drone.sha256
|
|
||||||
sha256sum release/linux/arm/drone.tar.gz > release/linux/arm/drone.sha256
|
|
||||||
sha256sum release/windows/amd64/drone.tar.gz > release/windows/amd64/drone.sha256
|
|
||||||
sha256sum release/darwin/amd64/drone.tar.gz > release/darwin/amd64/drone.sha256
|
|
|
@ -1,20 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import "github.com/urfave/cli"
|
|
||||||
|
|
||||||
// Command exports the build command set.
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "build",
|
|
||||||
Usage: "manage builds",
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
buildListCmd,
|
|
||||||
buildLastCmd,
|
|
||||||
buildLogsCmd,
|
|
||||||
buildInfoCmd,
|
|
||||||
buildStopCmd,
|
|
||||||
buildStartCmd,
|
|
||||||
buildApproveCmd,
|
|
||||||
buildDeclineCmd,
|
|
||||||
buildQueueCmd,
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var buildApproveCmd = cli.Command{
|
|
||||||
Name: "approve",
|
|
||||||
Usage: "approve a build",
|
|
||||||
Action: buildApprove,
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildApprove(c *cli.Context) (err error) {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
number, err := strconv.Atoi(c.Args().Get(1))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = client.BuildApprove(owner, name, number)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Approving build %s/%s#%d\n", owner, name, number)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var buildDeclineCmd = cli.Command{
|
|
||||||
Name: "decline",
|
|
||||||
Usage: "decline a build",
|
|
||||||
Action: buildDecline,
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildDecline(c *cli.Context) (err error) {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
number, err := strconv.Atoi(c.Args().Get(1))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = client.BuildDecline(owner, name, number)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Declining build %s/%s#%d\n", owner, name, number)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var buildInfoCmd = cli.Command{
|
|
||||||
Name: "info",
|
|
||||||
Usage: "show build details",
|
|
||||||
Action: buildInfo,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplBuildInfo,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildInfo(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
buildArg := c.Args().Get(1)
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var number int
|
|
||||||
if buildArg == "last" {
|
|
||||||
// Fetch the build number from the last build
|
|
||||||
build, err := client.BuildLast(owner, name, "")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
number = build.Number
|
|
||||||
} else {
|
|
||||||
number, err = strconv.Atoi(buildArg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
build, err := client.Build(owner, name, number)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return tmpl.Execute(os.Stdout, build)
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for build information
|
|
||||||
var tmplBuildInfo = `Number: {{ .Number }}
|
|
||||||
Status: {{ .Status }}
|
|
||||||
Event: {{ .Event }}
|
|
||||||
Commit: {{ .Commit }}
|
|
||||||
Branch: {{ .Branch }}
|
|
||||||
Ref: {{ .Ref }}
|
|
||||||
Message: {{ .Message }}
|
|
||||||
Author: {{ .Author }}
|
|
||||||
`
|
|
|
@ -1,51 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var buildLastCmd = cli.Command{
|
|
||||||
Name: "last",
|
|
||||||
Usage: "show latest build details",
|
|
||||||
Action: buildLast,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplBuildInfo,
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "branch",
|
|
||||||
Usage: "branch name",
|
|
||||||
Value: "master",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildLast(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
build, err := client.BuildLast(owner, name, c.String("branch"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return tmpl.Execute(os.Stdout, build)
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var buildListCmd = cli.Command{
|
|
||||||
Name: "list",
|
|
||||||
Usage: "show build history",
|
|
||||||
Action: buildList,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplBuildList,
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "branch",
|
|
||||||
Usage: "branch filter",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "event",
|
|
||||||
Usage: "event filter",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "status",
|
|
||||||
Usage: "status filter",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "limit",
|
|
||||||
Usage: "limit the list size",
|
|
||||||
Value: 25,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildList(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
builds, err := client.BuildList(owner, name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format") + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
branch := c.String("branch")
|
|
||||||
event := c.String("event")
|
|
||||||
status := c.String("status")
|
|
||||||
limit := c.Int("limit")
|
|
||||||
|
|
||||||
var count int
|
|
||||||
for _, build := range builds {
|
|
||||||
if count >= limit {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if branch != "" && build.Branch != branch {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if event != "" && build.Event != event {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if status != "" && build.Status != status {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tmpl.Execute(os.Stdout, build)
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for build list information
|
|
||||||
var tmplBuildList = "\x1b[33mBuild #{{ .Number }} \x1b[0m" + `
|
|
||||||
Status: {{ .Status }}
|
|
||||||
Event: {{ .Event }}
|
|
||||||
Commit: {{ .Commit }}
|
|
||||||
Branch: {{ .Branch }}
|
|
||||||
Ref: {{ .Ref }}
|
|
||||||
Author: {{ .Author }} {{ if .Email }}<{{.Email}}>{{ end }}
|
|
||||||
Message: {{ .Message }}
|
|
||||||
`
|
|
|
@ -1,84 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/cncd/pipeline/pipeline/rpc"
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var buildLogsCmd = cli.Command{
|
|
||||||
Name: "logs",
|
|
||||||
Usage: "show build logs",
|
|
||||||
Action: buildLogsDisabled,
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildLogsDisabled(c *cli.Context) error {
|
|
||||||
return fmt.Errorf("Command temporarily disabled. See https://github.com/drone/drone/issues/2005")
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildLogs(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
buildArg := c.Args().Get(1)
|
|
||||||
var number int
|
|
||||||
if buildArg == "" {
|
|
||||||
// Fetch the build number from the last build
|
|
||||||
build, err := client.BuildLast(owner, name, "")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
number = build.Number
|
|
||||||
} else {
|
|
||||||
number, err = strconv.Atoi(buildArg)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("Error: Invalid number or missing job number. eg 100")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
job, _ := strconv.Atoi(c.Args().Get(2))
|
|
||||||
if job == 0 {
|
|
||||||
job = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := client.BuildLogs(owner, name, number, job)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer r.Close()
|
|
||||||
|
|
||||||
dec := json.NewDecoder(r)
|
|
||||||
fmt.Printf("Logs for build %s/%s#%d.%d\n", owner, name, number, job)
|
|
||||||
var line rpc.Line
|
|
||||||
|
|
||||||
_, err = dec.Token()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for dec.More() {
|
|
||||||
if err = dec.Decode(&line); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("%s", line.Out)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = dec.Token()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var buildQueueCmd = cli.Command{
|
|
||||||
Name: "queue",
|
|
||||||
Usage: "show build queue",
|
|
||||||
Action: buildQueue,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplBuildQueue,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildQueue(c *cli.Context) error {
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
builds, err := client.BuildQueue()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(builds) == 0 {
|
|
||||||
fmt.Println("there are no pending or running builds")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format") + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, build := range builds {
|
|
||||||
tmpl.Execute(os.Stdout, build)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for build list information
|
|
||||||
var tmplBuildQueue = "\x1b[33m{{ .FullName }} #{{ .Number }} \x1b[0m" + `
|
|
||||||
Status: {{ .Status }}
|
|
||||||
Event: {{ .Event }}
|
|
||||||
Commit: {{ .Commit }}
|
|
||||||
Branch: {{ .Branch }}
|
|
||||||
Ref: {{ .Ref }}
|
|
||||||
Author: {{ .Author }} {{ if .Email }}<{{.Email}}>{{ end }}
|
|
||||||
Message: {{ .Message }}
|
|
||||||
`
|
|
|
@ -1,70 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var buildStartCmd = cli.Command{
|
|
||||||
Name: "start",
|
|
||||||
Usage: "start a build",
|
|
||||||
Action: buildStart,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "fork",
|
|
||||||
Usage: "fork the build",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "param, p",
|
|
||||||
Usage: "custom parameters to be injected into the job environment. Format: KEY=value",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildStart(c *cli.Context) (err error) {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
buildArg := c.Args().Get(1)
|
|
||||||
var number int
|
|
||||||
if buildArg == "last" {
|
|
||||||
// Fetch the build number from the last build
|
|
||||||
build, err := client.BuildLast(owner, name, "")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
number = build.Number
|
|
||||||
} else {
|
|
||||||
number, err = strconv.Atoi(buildArg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
params := internal.ParseKeyPair(c.StringSlice("param"))
|
|
||||||
|
|
||||||
var build *model.Build
|
|
||||||
if c.Bool("fork") {
|
|
||||||
build, err = client.BuildFork(owner, name, number, params)
|
|
||||||
} else {
|
|
||||||
build, err = client.BuildStart(owner, name, number, params)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Starting build %s/%s#%d\n", owner, name, build.Number)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
package build
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var buildStopCmd = cli.Command{
|
|
||||||
Name: "stop",
|
|
||||||
Usage: "stop a build",
|
|
||||||
Action: buildStop,
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildStop(c *cli.Context) (err error) {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
number, err := strconv.Atoi(c.Args().Get(1))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
job, _ := strconv.Atoi(c.Args().Get(2))
|
|
||||||
if job == 0 {
|
|
||||||
job = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = client.BuildStop(owner, name, number, job)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Stopping build %s/%s#%d.%d\n", owner, name, number, job)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,124 +0,0 @@
|
||||||
package deploy
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"html/template"
|
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command exports the deploy command.
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "deploy",
|
|
||||||
Usage: "deploy code",
|
|
||||||
Action: deploy,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplDeployInfo,
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "branch",
|
|
||||||
Usage: "branch filter",
|
|
||||||
Value: "master",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "event",
|
|
||||||
Usage: "event filter",
|
|
||||||
Value: model.EventPush,
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "status",
|
|
||||||
Usage: "status filter",
|
|
||||||
Value: model.StatusSuccess,
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "param, p",
|
|
||||||
Usage: "custom parameters to be injected into the job environment. Format: KEY=value",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func deploy(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
branch := c.String("branch")
|
|
||||||
event := c.String("event")
|
|
||||||
status := c.String("status")
|
|
||||||
|
|
||||||
buildArg := c.Args().Get(1)
|
|
||||||
var number int
|
|
||||||
if buildArg == "last" {
|
|
||||||
// Fetch the build number from the last build
|
|
||||||
builds, berr := client.BuildList(owner, name)
|
|
||||||
if berr != nil {
|
|
||||||
return berr
|
|
||||||
}
|
|
||||||
for _, build := range builds {
|
|
||||||
if branch != "" && build.Branch != branch {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if event != "" && build.Event != event {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if status != "" && build.Status != status {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if build.Number > number {
|
|
||||||
number = build.Number
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if number == 0 {
|
|
||||||
return fmt.Errorf("Cannot deploy failure build")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
number, err = strconv.Atoi(buildArg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env := c.Args().Get(2)
|
|
||||||
if env == "" {
|
|
||||||
return fmt.Errorf("Please specify the target environment (ie production)")
|
|
||||||
}
|
|
||||||
|
|
||||||
params := internal.ParseKeyPair(c.StringSlice("param"))
|
|
||||||
|
|
||||||
deploy, err := client.Deploy(owner, name, number, env, params)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return tmpl.Execute(os.Stdout, deploy)
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for deployment information
|
|
||||||
var tmplDeployInfo = `Number: {{ .Number }}
|
|
||||||
Status: {{ .Status }}
|
|
||||||
Commit: {{ .Commit }}
|
|
||||||
Branch: {{ .Branch }}
|
|
||||||
Ref: {{ .Ref }}
|
|
||||||
Message: {{ .Message }}
|
|
||||||
Author: {{ .Author }}
|
|
||||||
Target: {{ .Deploy }}
|
|
||||||
`
|
|
|
@ -1,456 +0,0 @@
|
||||||
package exec
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/cncd/pipeline/pipeline"
|
|
||||||
"github.com/cncd/pipeline/pipeline/backend"
|
|
||||||
"github.com/cncd/pipeline/pipeline/backend/docker"
|
|
||||||
"github.com/cncd/pipeline/pipeline/frontend"
|
|
||||||
"github.com/cncd/pipeline/pipeline/frontend/yaml"
|
|
||||||
"github.com/cncd/pipeline/pipeline/frontend/yaml/compiler"
|
|
||||||
"github.com/cncd/pipeline/pipeline/frontend/yaml/linter"
|
|
||||||
"github.com/cncd/pipeline/pipeline/interrupt"
|
|
||||||
"github.com/cncd/pipeline/pipeline/multipart"
|
|
||||||
"github.com/drone/envsubst"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command exports the exec command.
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "exec",
|
|
||||||
Usage: "execute a local build",
|
|
||||||
Action: func(c *cli.Context) {
|
|
||||||
if err := exec(c); err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolTFlag{
|
|
||||||
Name: "local",
|
|
||||||
Usage: "build from local directory",
|
|
||||||
EnvVar: "DRONE_LOCAL",
|
|
||||||
},
|
|
||||||
cli.DurationFlag{
|
|
||||||
Name: "timeout",
|
|
||||||
Usage: "build timeout",
|
|
||||||
Value: time.Hour,
|
|
||||||
EnvVar: "DRONE_TIMEOUT",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "volumes",
|
|
||||||
Usage: "build volumes",
|
|
||||||
EnvVar: "DRONE_VOLUMES",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "network",
|
|
||||||
Usage: "external networks",
|
|
||||||
EnvVar: "DRONE_NETWORKS",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prefix",
|
|
||||||
Value: "drone",
|
|
||||||
Usage: "prefix containers created by drone",
|
|
||||||
EnvVar: "DRONE_DOCKER_PREFIX",
|
|
||||||
Hidden: true,
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "privileged",
|
|
||||||
Usage: "privileged plugins",
|
|
||||||
Value: &cli.StringSlice{
|
|
||||||
"plugins/docker",
|
|
||||||
"plugins/gcr",
|
|
||||||
"plugins/ecr",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
//
|
|
||||||
// Please note the below flags are mirrored in the pipec and
|
|
||||||
// should be kept synchronized. Do not edit directly
|
|
||||||
// https://github.com/cncd/pipeline/pipec
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// workspace default
|
|
||||||
//
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "workspace-base",
|
|
||||||
Value: "/pipeline",
|
|
||||||
EnvVar: "DRONE_WORKSPACE_BASE",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "workspace-path",
|
|
||||||
Value: "src",
|
|
||||||
EnvVar: "DRONE_WORKSPACE_PATH",
|
|
||||||
},
|
|
||||||
//
|
|
||||||
// netrc parameters
|
|
||||||
//
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "netrc-username",
|
|
||||||
EnvVar: "DRONE_NETRC_USERNAME",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "netrc-password",
|
|
||||||
EnvVar: "DRONE_NETRC_PASSWORD",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "netrc-machine",
|
|
||||||
EnvVar: "DRONE_NETRC_MACHINE",
|
|
||||||
},
|
|
||||||
//
|
|
||||||
// metadata parameters
|
|
||||||
//
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "system-arch",
|
|
||||||
Value: "linux/amd64",
|
|
||||||
EnvVar: "DRONE_SYSTEM_ARCH",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "system-name",
|
|
||||||
Value: "pipec",
|
|
||||||
EnvVar: "DRONE_SYSTEM_NAME",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "system-link",
|
|
||||||
Value: "https://github.com/cncd/pipec",
|
|
||||||
EnvVar: "DRONE_SYSTEM_LINK",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo-name",
|
|
||||||
EnvVar: "DRONE_REPO_NAME",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo-link",
|
|
||||||
EnvVar: "DRONE_REPO_LINK",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo-remote-url",
|
|
||||||
EnvVar: "DRONE_REPO_REMOTE",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repo-private",
|
|
||||||
EnvVar: "DRONE_REPO_PRIVATE",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "build-number",
|
|
||||||
EnvVar: "DRONE_BUILD_NUMBER",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "parent-build-number",
|
|
||||||
EnvVar: "DRONE_PARENT_BUILD_NUMBER",
|
|
||||||
},
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "build-created",
|
|
||||||
EnvVar: "DRONE_BUILD_CREATED",
|
|
||||||
},
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "build-started",
|
|
||||||
EnvVar: "DRONE_BUILD_STARTED",
|
|
||||||
},
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "build-finished",
|
|
||||||
EnvVar: "DRONE_BUILD_FINISHED",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "build-status",
|
|
||||||
EnvVar: "DRONE_BUILD_STATUS",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "build-event",
|
|
||||||
EnvVar: "DRONE_BUILD_EVENT",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "build-link",
|
|
||||||
EnvVar: "DRONE_BUILD_LINK",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "build-target",
|
|
||||||
EnvVar: "DRONE_BUILD_TARGET",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "commit-sha",
|
|
||||||
EnvVar: "DRONE_COMMIT_SHA",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "commit-ref",
|
|
||||||
EnvVar: "DRONE_COMMIT_REF",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "commit-refspec",
|
|
||||||
EnvVar: "DRONE_COMMIT_REFSPEC",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "commit-branch",
|
|
||||||
EnvVar: "DRONE_COMMIT_BRANCH",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "commit-message",
|
|
||||||
EnvVar: "DRONE_COMMIT_MESSAGE",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "commit-author-name",
|
|
||||||
EnvVar: "DRONE_COMMIT_AUTHOR_NAME",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "commit-author-avatar",
|
|
||||||
EnvVar: "DRONE_COMMIT_AUTHOR_AVATAR",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "commit-author-email",
|
|
||||||
EnvVar: "DRONE_COMMIT_AUTHOR_EMAIL",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "prev-build-number",
|
|
||||||
EnvVar: "DRONE_PREV_BUILD_NUMBER",
|
|
||||||
},
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "prev-build-created",
|
|
||||||
EnvVar: "DRONE_PREV_BUILD_CREATED",
|
|
||||||
},
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "prev-build-started",
|
|
||||||
EnvVar: "DRONE_PREV_BUILD_STARTED",
|
|
||||||
},
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "prev-build-finished",
|
|
||||||
EnvVar: "DRONE_PREV_BUILD_FINISHED",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-build-status",
|
|
||||||
EnvVar: "DRONE_PREV_BUILD_STATUS",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-build-event",
|
|
||||||
EnvVar: "DRONE_PREV_BUILD_EVENT",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-build-link",
|
|
||||||
EnvVar: "DRONE_PREV_BUILD_LINK",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-commit-sha",
|
|
||||||
EnvVar: "DRONE_PREV_COMMIT_SHA",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-commit-ref",
|
|
||||||
EnvVar: "DRONE_PREV_COMMIT_REF",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-commit-refspec",
|
|
||||||
EnvVar: "DRONE_PREV_COMMIT_REFSPEC",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-commit-branch",
|
|
||||||
EnvVar: "DRONE_PREV_COMMIT_BRANCH",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-commit-message",
|
|
||||||
EnvVar: "DRONE_PREV_COMMIT_MESSAGE",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-commit-author-name",
|
|
||||||
EnvVar: "DRONE_PREV_COMMIT_AUTHOR_NAME",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-commit-author-avatar",
|
|
||||||
EnvVar: "DRONE_PREV_COMMIT_AUTHOR_AVATAR",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prev-commit-author-email",
|
|
||||||
EnvVar: "DRONE_PREV_COMMIT_AUTHOR_EMAIL",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "job-number",
|
|
||||||
EnvVar: "DRONE_JOB_NUMBER",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func exec(c *cli.Context) error {
|
|
||||||
file := c.Args().First()
|
|
||||||
if file == "" {
|
|
||||||
file = ".drone.yml"
|
|
||||||
}
|
|
||||||
|
|
||||||
metadata := metadataFromContext(c)
|
|
||||||
environ := metadata.Environ()
|
|
||||||
secrets := []compiler.Secret{}
|
|
||||||
for k, v := range metadata.EnvironDrone() {
|
|
||||||
environ[k] = v
|
|
||||||
}
|
|
||||||
for _, env := range os.Environ() {
|
|
||||||
k := strings.Split(env, "=")[0]
|
|
||||||
v := strings.Split(env, "=")[1]
|
|
||||||
environ[k] = v
|
|
||||||
secrets = append(secrets, compiler.Secret{
|
|
||||||
Name: k,
|
|
||||||
Value: v,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := envsubst.ParseFile(file)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
confstr, err := tmpl.Execute(func(name string) string {
|
|
||||||
return environ[name]
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
conf, err := yaml.ParseString(confstr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// configure volumes for local execution
|
|
||||||
volumes := c.StringSlice("volumes")
|
|
||||||
if c.Bool("local") {
|
|
||||||
var (
|
|
||||||
workspaceBase = conf.Workspace.Base
|
|
||||||
workspacePath = conf.Workspace.Path
|
|
||||||
)
|
|
||||||
if workspaceBase == "" {
|
|
||||||
workspaceBase = c.String("workspace-base")
|
|
||||||
}
|
|
||||||
if workspacePath == "" {
|
|
||||||
workspacePath = c.String("workspace-path")
|
|
||||||
}
|
|
||||||
dir, _ := filepath.Abs(filepath.Dir(file))
|
|
||||||
volumes = append(volumes, dir+":"+path.Join(workspaceBase, workspacePath))
|
|
||||||
}
|
|
||||||
|
|
||||||
// lint the yaml file
|
|
||||||
if lerr := linter.New(linter.WithTrusted(true)).Lint(conf); lerr != nil {
|
|
||||||
return lerr
|
|
||||||
}
|
|
||||||
|
|
||||||
// compiles the yaml file
|
|
||||||
compiled := compiler.New(
|
|
||||||
compiler.WithEscalated(
|
|
||||||
c.StringSlice("privileged")...,
|
|
||||||
),
|
|
||||||
compiler.WithVolumes(volumes...),
|
|
||||||
compiler.WithWorkspace(
|
|
||||||
c.String("workspace-base"),
|
|
||||||
c.String("workspace-path"),
|
|
||||||
),
|
|
||||||
compiler.WithNetworks(
|
|
||||||
c.StringSlice("network")...,
|
|
||||||
),
|
|
||||||
compiler.WithPrefix(
|
|
||||||
c.String("prefix"),
|
|
||||||
),
|
|
||||||
compiler.WithProxy(),
|
|
||||||
compiler.WithLocal(
|
|
||||||
c.Bool("local"),
|
|
||||||
),
|
|
||||||
compiler.WithNetrc(
|
|
||||||
c.String("netrc-username"),
|
|
||||||
c.String("netrc-password"),
|
|
||||||
c.String("netrc-machine"),
|
|
||||||
),
|
|
||||||
compiler.WithMetadata(metadata),
|
|
||||||
compiler.WithSecret(secrets...),
|
|
||||||
).Compile(conf)
|
|
||||||
|
|
||||||
engine, err := docker.NewEnv()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), c.Duration("timeout"))
|
|
||||||
defer cancel()
|
|
||||||
ctx = interrupt.WithContext(ctx)
|
|
||||||
|
|
||||||
return pipeline.New(compiled,
|
|
||||||
pipeline.WithContext(ctx),
|
|
||||||
pipeline.WithLogger(defaultLogger),
|
|
||||||
pipeline.WithTracer(pipeline.DefaultTracer),
|
|
||||||
pipeline.WithLogger(defaultLogger),
|
|
||||||
pipeline.WithEngine(engine),
|
|
||||||
).Run()
|
|
||||||
}
|
|
||||||
|
|
||||||
// return the metadata from the cli context.
|
|
||||||
func metadataFromContext(c *cli.Context) frontend.Metadata {
|
|
||||||
return frontend.Metadata{
|
|
||||||
Repo: frontend.Repo{
|
|
||||||
Name: c.String("repo-name"),
|
|
||||||
Link: c.String("repo-link"),
|
|
||||||
Remote: c.String("repo-remote-url"),
|
|
||||||
Private: c.Bool("repo-private"),
|
|
||||||
},
|
|
||||||
Curr: frontend.Build{
|
|
||||||
Number: c.Int("build-number"),
|
|
||||||
Parent: c.Int("parent-build-number"),
|
|
||||||
Created: c.Int64("build-created"),
|
|
||||||
Started: c.Int64("build-started"),
|
|
||||||
Finished: c.Int64("build-finished"),
|
|
||||||
Status: c.String("build-status"),
|
|
||||||
Event: c.String("build-event"),
|
|
||||||
Link: c.String("build-link"),
|
|
||||||
Target: c.String("build-target"),
|
|
||||||
Commit: frontend.Commit{
|
|
||||||
Sha: c.String("commit-sha"),
|
|
||||||
Ref: c.String("commit-ref"),
|
|
||||||
Refspec: c.String("commit-refspec"),
|
|
||||||
Branch: c.String("commit-branch"),
|
|
||||||
Message: c.String("commit-message"),
|
|
||||||
Author: frontend.Author{
|
|
||||||
Name: c.String("commit-author-name"),
|
|
||||||
Email: c.String("commit-author-email"),
|
|
||||||
Avatar: c.String("commit-author-avatar"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Prev: frontend.Build{
|
|
||||||
Number: c.Int("prev-build-number"),
|
|
||||||
Created: c.Int64("prev-build-created"),
|
|
||||||
Started: c.Int64("prev-build-started"),
|
|
||||||
Finished: c.Int64("prev-build-finished"),
|
|
||||||
Status: c.String("prev-build-status"),
|
|
||||||
Event: c.String("prev-build-event"),
|
|
||||||
Link: c.String("prev-build-link"),
|
|
||||||
Commit: frontend.Commit{
|
|
||||||
Sha: c.String("prev-commit-sha"),
|
|
||||||
Ref: c.String("prev-commit-ref"),
|
|
||||||
Refspec: c.String("prev-commit-refspec"),
|
|
||||||
Branch: c.String("prev-commit-branch"),
|
|
||||||
Message: c.String("prev-commit-message"),
|
|
||||||
Author: frontend.Author{
|
|
||||||
Name: c.String("prev-commit-author-name"),
|
|
||||||
Email: c.String("prev-commit-author-email"),
|
|
||||||
Avatar: c.String("prev-commit-author-avatar"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Job: frontend.Job{
|
|
||||||
Number: c.Int("job-number"),
|
|
||||||
},
|
|
||||||
Sys: frontend.System{
|
|
||||||
Name: c.String("system-name"),
|
|
||||||
Link: c.String("system-link"),
|
|
||||||
Arch: c.String("system-arch"),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultLogger = pipeline.LogFunc(func(proc *backend.Step, rc multipart.Reader) error {
|
|
||||||
part, err := rc.NextPart()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
io.Copy(os.Stderr, part)
|
|
||||||
return nil
|
|
||||||
})
|
|
|
@ -1,48 +0,0 @@
|
||||||
package info
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command exports the info command.
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "info",
|
|
||||||
Usage: "show information about the current user",
|
|
||||||
Action: info,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplInfo,
|
|
||||||
Hidden: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func info(c *cli.Context) error {
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := client.Self()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format") + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tmpl.Execute(os.Stdout, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for user information
|
|
||||||
var tmplInfo = `User: {{ .Login }}
|
|
||||||
Email: {{ .Email }}`
|
|
|
@ -1,78 +0,0 @@
|
||||||
package internal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/drone/drone/client"
|
|
||||||
|
|
||||||
"github.com/jackspirou/syscerts"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewClient returns a new client from the CLI context.
|
|
||||||
func NewClient(c *cli.Context) (client.Client, error) {
|
|
||||||
var token = c.GlobalString("token")
|
|
||||||
var server = strings.TrimRight(c.GlobalString("server"), "/")
|
|
||||||
|
|
||||||
// if no server url is provided we can default
|
|
||||||
// to the hosted Drone service.
|
|
||||||
if len(server) == 0 {
|
|
||||||
return nil, fmt.Errorf("Error: you must provide the Drone server address.")
|
|
||||||
}
|
|
||||||
if len(token) == 0 {
|
|
||||||
return nil, fmt.Errorf("Error: you must provide your Drone access token.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// attempt to find system CA certs
|
|
||||||
certs := syscerts.SystemRootsPool()
|
|
||||||
tlsConfig := &tls.Config{RootCAs: certs}
|
|
||||||
|
|
||||||
// create the drone client with TLS options
|
|
||||||
return client.NewClientTokenTLS(server, token, tlsConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseRepo parses the repository owner and name from a string.
|
|
||||||
func ParseRepo(str string) (user, repo string, err error) {
|
|
||||||
var parts = strings.Split(str, "/")
|
|
||||||
if len(parts) != 2 {
|
|
||||||
err = fmt.Errorf("Error: Invalid or missing repository. eg octocat/hello-world.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user = parts[0]
|
|
||||||
repo = parts[1]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func readInput(in string) ([]byte, error) {
|
|
||||||
if in == "-" {
|
|
||||||
return ioutil.ReadAll(os.Stdin)
|
|
||||||
}
|
|
||||||
return ioutil.ReadFile(in)
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringInSlice(a string, list []string) bool {
|
|
||||||
for _, b := range list {
|
|
||||||
if b == a {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseKeyPair parses a key=value pair.
|
|
||||||
func ParseKeyPair(p []string) map[string]string {
|
|
||||||
params := map[string]string{}
|
|
||||||
for _, i := range p {
|
|
||||||
parts := strings.Split(i, "=")
|
|
||||||
if len(parts) != 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
params[parts[0]] = parts[1]
|
|
||||||
}
|
|
||||||
return params
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
package internal
|
|
||||||
|
|
||||||
import "testing"
|
|
||||||
|
|
||||||
func TestParseKeyPair(t *testing.T) {
|
|
||||||
s := []string{"FOO=bar", "BAR=", "INVALID"}
|
|
||||||
p := ParseKeyPair(s)
|
|
||||||
if p["FOO"] != "bar" {
|
|
||||||
t.Errorf("Wanted %q, got %q.", "bar", p["FOO"])
|
|
||||||
}
|
|
||||||
if _, exists := p["BAR"]; !exists {
|
|
||||||
t.Error("Missing a key with no value. Keys with empty values are also valid.")
|
|
||||||
}
|
|
||||||
if _, exists := p["INVALID"]; exists {
|
|
||||||
t.Error("Keys without an equal sign suffix are invalid.")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,15 +7,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/drone/drone/drone/agent"
|
"github.com/drone/drone/drone/agent"
|
||||||
"github.com/drone/drone/drone/build"
|
|
||||||
"github.com/drone/drone/drone/deploy"
|
|
||||||
"github.com/drone/drone/drone/exec"
|
|
||||||
"github.com/drone/drone/drone/info"
|
|
||||||
"github.com/drone/drone/drone/registry"
|
|
||||||
"github.com/drone/drone/drone/repo"
|
|
||||||
"github.com/drone/drone/drone/secret"
|
|
||||||
"github.com/drone/drone/drone/server"
|
"github.com/drone/drone/drone/server"
|
||||||
"github.com/drone/drone/drone/user"
|
|
||||||
"github.com/drone/drone/version"
|
"github.com/drone/drone/version"
|
||||||
|
|
||||||
"github.com/ianschenck/envflag"
|
"github.com/ianschenck/envflag"
|
||||||
|
@ -44,15 +36,7 @@ func main() {
|
||||||
}
|
}
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []cli.Command{
|
||||||
agent.Command,
|
agent.Command,
|
||||||
build.Command,
|
|
||||||
deploy.Command,
|
|
||||||
exec.Command,
|
|
||||||
info.Command,
|
|
||||||
registry.Command,
|
|
||||||
secret.Command,
|
|
||||||
server.Command,
|
server.Command,
|
||||||
repo.Command,
|
|
||||||
user.Command,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := app.Run(os.Args); err != nil {
|
||||||
|
|
|
@ -7,14 +7,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/drone/drone/drone/agent"
|
"github.com/drone/drone/drone/agent"
|
||||||
"github.com/drone/drone/drone/build"
|
|
||||||
"github.com/drone/drone/drone/deploy"
|
|
||||||
"github.com/drone/drone/drone/exec"
|
|
||||||
"github.com/drone/drone/drone/info"
|
|
||||||
"github.com/drone/drone/drone/registry"
|
|
||||||
"github.com/drone/drone/drone/repo"
|
|
||||||
"github.com/drone/drone/drone/secret"
|
|
||||||
"github.com/drone/drone/drone/user"
|
|
||||||
"github.com/drone/drone/version"
|
"github.com/drone/drone/version"
|
||||||
|
|
||||||
"github.com/drone/drone/extras/cmd/drone/server"
|
"github.com/drone/drone/extras/cmd/drone/server"
|
||||||
|
@ -45,15 +37,7 @@ func main() {
|
||||||
}
|
}
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []cli.Command{
|
||||||
agent.Command,
|
agent.Command,
|
||||||
build.Command,
|
|
||||||
deploy.Command,
|
|
||||||
exec.Command,
|
|
||||||
info.Command,
|
|
||||||
registry.Command,
|
|
||||||
secret.Command,
|
|
||||||
server.Command,
|
server.Command,
|
||||||
repo.Command,
|
|
||||||
user.Command,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := app.Run(os.Args); err != nil {
|
if err := app.Run(os.Args); err != nil {
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
package registry
|
|
||||||
|
|
||||||
import "github.com/urfave/cli"
|
|
||||||
|
|
||||||
// Command exports the registry command set.
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "registry",
|
|
||||||
Usage: "manage registries",
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
registryCreateCmd,
|
|
||||||
registryDeleteCmd,
|
|
||||||
registryUpdateCmd,
|
|
||||||
registryInfoCmd,
|
|
||||||
registryListCmd,
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
package registry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var registryCreateCmd = cli.Command{
|
|
||||||
Name: "add",
|
|
||||||
Usage: "adds a registry",
|
|
||||||
Action: registryCreate,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "hostname",
|
|
||||||
Usage: "registry hostname",
|
|
||||||
Value: "docker.io",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "username",
|
|
||||||
Usage: "registry username",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "password",
|
|
||||||
Usage: "registry password",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func registryCreate(c *cli.Context) error {
|
|
||||||
var (
|
|
||||||
hostname = c.String("hostname")
|
|
||||||
username = c.String("username")
|
|
||||||
password = c.String("password")
|
|
||||||
reponame = c.String("repository")
|
|
||||||
)
|
|
||||||
if reponame == "" {
|
|
||||||
reponame = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(reponame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
registry := &model.Registry{
|
|
||||||
Address: hostname,
|
|
||||||
Username: username,
|
|
||||||
Password: password,
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(registry.Password, "@") {
|
|
||||||
path := strings.TrimPrefix(registry.Password, "@")
|
|
||||||
out, ferr := ioutil.ReadFile(path)
|
|
||||||
if ferr != nil {
|
|
||||||
return ferr
|
|
||||||
}
|
|
||||||
registry.Password = string(out)
|
|
||||||
}
|
|
||||||
_, err = client.RegistryCreate(owner, name, registry)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
package registry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"html/template"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var registryInfoCmd = cli.Command{
|
|
||||||
Name: "info",
|
|
||||||
Usage: "display registry info",
|
|
||||||
Action: registryInfo,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "hostname",
|
|
||||||
Usage: "registry hostname",
|
|
||||||
Value: "docker.io",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplRegistryList,
|
|
||||||
Hidden: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func registryInfo(c *cli.Context) error {
|
|
||||||
var (
|
|
||||||
hostname = c.String("hostname")
|
|
||||||
reponame = c.String("repository")
|
|
||||||
format = c.String("format") + "\n"
|
|
||||||
)
|
|
||||||
if reponame == "" {
|
|
||||||
reponame = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(reponame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
registry, err := client.Registry(owner, name, hostname)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tmpl, err := template.New("_").Parse(format)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return tmpl.Execute(os.Stdout, registry)
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
package registry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"html/template"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
var registryListCmd = cli.Command{
|
|
||||||
Name: "ls",
|
|
||||||
Usage: "list regitries",
|
|
||||||
Action: registryList,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplRegistryList,
|
|
||||||
Hidden: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func registryList(c *cli.Context) error {
|
|
||||||
var (
|
|
||||||
format = c.String("format") + "\n"
|
|
||||||
reponame = c.String("repository")
|
|
||||||
)
|
|
||||||
if reponame == "" {
|
|
||||||
reponame = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(reponame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
list, err := client.RegistryList(owner, name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tmpl, err := template.New("_").Parse(format)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, registry := range list {
|
|
||||||
tmpl.Execute(os.Stdout, registry)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for build list information
|
|
||||||
var tmplRegistryList = "\x1b[33m{{ .Address }} \x1b[0m" + `
|
|
||||||
Username: {{ .Username }}
|
|
||||||
Email: {{ .Email }}
|
|
||||||
`
|
|
|
@ -1,43 +0,0 @@
|
||||||
package registry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var registryDeleteCmd = cli.Command{
|
|
||||||
Name: "rm",
|
|
||||||
Usage: "remove a registry",
|
|
||||||
Action: registryDelete,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "hostname",
|
|
||||||
Usage: "registry hostname",
|
|
||||||
Value: "docker.io",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func registryDelete(c *cli.Context) error {
|
|
||||||
var (
|
|
||||||
hostname = c.String("hostname")
|
|
||||||
reponame = c.String("repository")
|
|
||||||
)
|
|
||||||
if reponame == "" {
|
|
||||||
reponame = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(reponame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return client.RegistryDelete(owner, name, hostname)
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
package registry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var registryUpdateCmd = cli.Command{
|
|
||||||
Name: "update",
|
|
||||||
Usage: "update a registry",
|
|
||||||
Action: registryUpdate,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "hostname",
|
|
||||||
Usage: "registry hostname",
|
|
||||||
Value: "docker.io",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "username",
|
|
||||||
Usage: "registry username",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "password",
|
|
||||||
Usage: "registry password",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func registryUpdate(c *cli.Context) error {
|
|
||||||
var (
|
|
||||||
hostname = c.String("hostname")
|
|
||||||
username = c.String("username")
|
|
||||||
password = c.String("password")
|
|
||||||
reponame = c.String("repository")
|
|
||||||
)
|
|
||||||
if reponame == "" {
|
|
||||||
reponame = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(reponame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
registry := &model.Registry{
|
|
||||||
Address: hostname,
|
|
||||||
Username: username,
|
|
||||||
Password: password,
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(registry.Password, "@") {
|
|
||||||
path := strings.TrimPrefix(registry.Password, "@")
|
|
||||||
out, ferr := ioutil.ReadFile(path)
|
|
||||||
if ferr != nil {
|
|
||||||
return ferr
|
|
||||||
}
|
|
||||||
registry.Password = string(out)
|
|
||||||
}
|
|
||||||
_, err = client.RegistryUpdate(owner, name, registry)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
package repo
|
|
||||||
|
|
||||||
import "github.com/urfave/cli"
|
|
||||||
|
|
||||||
// Command exports the repository command.
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "repo",
|
|
||||||
Usage: "manage repositories",
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
repoListCmd,
|
|
||||||
repoInfoCmd,
|
|
||||||
repoAddCmd,
|
|
||||||
repoUpdateCmd,
|
|
||||||
repoRemoveCmd,
|
|
||||||
repoRepairCmd,
|
|
||||||
repoChownCmd,
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var repoAddCmd = cli.Command{
|
|
||||||
Name: "add",
|
|
||||||
Usage: "add a repository",
|
|
||||||
Action: repoAdd,
|
|
||||||
}
|
|
||||||
|
|
||||||
func repoAdd(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := client.RepoPost(owner, name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("Successfully activated repository %s/%s\n", owner, name)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var repoChownCmd = cli.Command{
|
|
||||||
Name: "chown",
|
|
||||||
Usage: "assume ownership of a repository",
|
|
||||||
Action: repoChown,
|
|
||||||
}
|
|
||||||
|
|
||||||
func repoChown(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := client.RepoChown(owner, name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("Successfully assumed ownership of repository %s/%s\n", owner, name)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var repoInfoCmd = cli.Command{
|
|
||||||
Name: "info",
|
|
||||||
Usage: "show repository details",
|
|
||||||
Action: repoInfo,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplRepoInfo,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func repoInfo(c *cli.Context) error {
|
|
||||||
arg := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(arg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
repo, err := client.Repo(owner, name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return tmpl.Execute(os.Stdout, repo)
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for repo information
|
|
||||||
var tmplRepoInfo = `Owner: {{ .Owner }}
|
|
||||||
Repo: {{ .Name }}
|
|
||||||
Type: {{ .Kind }}
|
|
||||||
Config: {{ .Config }}
|
|
||||||
Private: {{ .IsPrivate }}
|
|
||||||
Trusted: {{ .IsTrusted }}
|
|
||||||
Gated: {{ .IsGated }}
|
|
||||||
Remote: {{ .Clone }}
|
|
||||||
`
|
|
|
@ -1,55 +0,0 @@
|
||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var repoListCmd = cli.Command{
|
|
||||||
Name: "ls",
|
|
||||||
Usage: "list all repos",
|
|
||||||
Action: repoList,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplRepoList,
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "org",
|
|
||||||
Usage: "filter by organization",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func repoList(c *cli.Context) error {
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
repos, err := client.RepoList()
|
|
||||||
if err != nil || len(repos) == 0 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format") + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
org := c.String("org")
|
|
||||||
for _, repo := range repos {
|
|
||||||
if org != "" && org != repo.Owner {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tmpl.Execute(os.Stdout, repo)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for repository list items
|
|
||||||
var tmplRepoList = `{{ .FullName }}`
|
|
|
@ -1,25 +0,0 @@
|
||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var repoRepairCmd = cli.Command{
|
|
||||||
Name: "repair",
|
|
||||||
Usage: "repair repository webhooks",
|
|
||||||
Action: repoRepair,
|
|
||||||
}
|
|
||||||
|
|
||||||
func repoRepair(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return client.RepoRepair(owner, name)
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var repoRemoveCmd = cli.Command{
|
|
||||||
Name: "rm",
|
|
||||||
Usage: "remove a repository",
|
|
||||||
Action: repoRemove,
|
|
||||||
}
|
|
||||||
|
|
||||||
func repoRemove(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := client.RepoDel(owner, name); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("Successfully removed repository %s/%s\n", owner, name)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
package repo
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var repoUpdateCmd = cli.Command{
|
|
||||||
Name: "update",
|
|
||||||
Usage: "update a repository",
|
|
||||||
Action: repoUpdate,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "trusted",
|
|
||||||
Usage: "repository is trusted",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "gated",
|
|
||||||
Usage: "repository is gated",
|
|
||||||
},
|
|
||||||
cli.DurationFlag{
|
|
||||||
Name: "timeout",
|
|
||||||
Usage: "repository timeout",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config",
|
|
||||||
Usage: "repository configuration path (e.g. .drone.yml)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func repoUpdate(c *cli.Context) error {
|
|
||||||
repo := c.Args().First()
|
|
||||||
owner, name, err := internal.ParseRepo(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
config = c.String("config")
|
|
||||||
timeout = c.Duration("timeout")
|
|
||||||
trusted = c.Bool("trusted")
|
|
||||||
gated = c.Bool("gated")
|
|
||||||
)
|
|
||||||
|
|
||||||
patch := new(model.RepoPatch)
|
|
||||||
if c.IsSet("trusted") {
|
|
||||||
patch.IsTrusted = &trusted
|
|
||||||
}
|
|
||||||
if c.IsSet("gated") {
|
|
||||||
patch.IsGated = &gated
|
|
||||||
}
|
|
||||||
if c.IsSet("timeout") {
|
|
||||||
v := int64(timeout / time.Minute)
|
|
||||||
patch.Timeout = &v
|
|
||||||
}
|
|
||||||
if c.IsSet("config") {
|
|
||||||
patch.Config = &config
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := client.RepoPatch(owner, name, patch); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("Successfully updated repository %s/%s\n", owner, name)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package secret
|
|
||||||
|
|
||||||
import "github.com/urfave/cli"
|
|
||||||
|
|
||||||
// Command exports the secret command.
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "secret",
|
|
||||||
Usage: "manage secrets",
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
secretCreateCmd,
|
|
||||||
secretDeleteCmd,
|
|
||||||
secretUpdateCmd,
|
|
||||||
secretInfoCmd,
|
|
||||||
secretListCmd,
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
package secret
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var secretCreateCmd = cli.Command{
|
|
||||||
Name: "add",
|
|
||||||
Usage: "adds a secret",
|
|
||||||
Action: secretCreate,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "name",
|
|
||||||
Usage: "secret name",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "value",
|
|
||||||
Usage: "secret value",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "event",
|
|
||||||
Usage: "secret limited to these events",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "image",
|
|
||||||
Usage: "secret limited to these images",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func secretCreate(c *cli.Context) error {
|
|
||||||
reponame := c.String("repository")
|
|
||||||
if reponame == "" {
|
|
||||||
reponame = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(reponame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
secret := &model.Secret{
|
|
||||||
Name: c.String("name"),
|
|
||||||
Value: c.String("value"),
|
|
||||||
Images: c.StringSlice("image"),
|
|
||||||
Events: c.StringSlice("event"),
|
|
||||||
}
|
|
||||||
if len(secret.Events) == 0 {
|
|
||||||
secret.Events = defaultSecretEvents
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(secret.Value, "@") {
|
|
||||||
path := strings.TrimPrefix(secret.Value, "@")
|
|
||||||
out, ferr := ioutil.ReadFile(path)
|
|
||||||
if ferr != nil {
|
|
||||||
return ferr
|
|
||||||
}
|
|
||||||
secret.Value = string(out)
|
|
||||||
}
|
|
||||||
_, err = client.SecretCreate(owner, name, secret)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultSecretEvents = []string{
|
|
||||||
model.EventPush,
|
|
||||||
model.EventTag,
|
|
||||||
model.EventDeploy,
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
package secret
|
|
||||||
|
|
||||||
import (
|
|
||||||
"html/template"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
var secretInfoCmd = cli.Command{
|
|
||||||
Name: "info",
|
|
||||||
Usage: "display secret info",
|
|
||||||
Action: secretInfo,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "name",
|
|
||||||
Usage: "secret name",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplSecretList,
|
|
||||||
Hidden: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func secretInfo(c *cli.Context) error {
|
|
||||||
var (
|
|
||||||
secretName = c.String("name")
|
|
||||||
repoName = c.String("repository")
|
|
||||||
format = c.String("format") + "\n"
|
|
||||||
)
|
|
||||||
if repoName == "" {
|
|
||||||
repoName = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(repoName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
secret, err := client.Secret(owner, name, secretName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tmpl, err := template.New("_").Funcs(secretFuncMap).Parse(format)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return tmpl.Execute(os.Stdout, secret)
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
package secret
|
|
||||||
|
|
||||||
import (
|
|
||||||
"html/template"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
var secretListCmd = cli.Command{
|
|
||||||
Name: "ls",
|
|
||||||
Usage: "list secrets",
|
|
||||||
Action: secretList,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplSecretList,
|
|
||||||
Hidden: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func secretList(c *cli.Context) error {
|
|
||||||
var (
|
|
||||||
format = c.String("format") + "\n"
|
|
||||||
reponame = c.String("repository")
|
|
||||||
)
|
|
||||||
if reponame == "" {
|
|
||||||
reponame = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(reponame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
list, err := client.SecretList(owner, name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tmpl, err := template.New("_").Funcs(secretFuncMap).Parse(format)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, registry := range list {
|
|
||||||
tmpl.Execute(os.Stdout, registry)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for secret list items
|
|
||||||
var tmplSecretList = "\x1b[33m{{ .Name }} \x1b[0m" + `
|
|
||||||
Events: {{ list .Events }}
|
|
||||||
{{- if .Images }}
|
|
||||||
Images: {{ list .Images }}
|
|
||||||
{{- else }}
|
|
||||||
Images: <any>
|
|
||||||
{{- end }}
|
|
||||||
`
|
|
||||||
|
|
||||||
var secretFuncMap = template.FuncMap{
|
|
||||||
"list": func(s []string) string {
|
|
||||||
return strings.Join(s, ", ")
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
package secret
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
var secretDeleteCmd = cli.Command{
|
|
||||||
Name: "rm",
|
|
||||||
Usage: "remove a secret",
|
|
||||||
Action: secretDelete,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "name",
|
|
||||||
Usage: "secret name",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func secretDelete(c *cli.Context) error {
|
|
||||||
var (
|
|
||||||
secret = c.String("name")
|
|
||||||
reponame = c.String("repository")
|
|
||||||
)
|
|
||||||
if reponame == "" {
|
|
||||||
reponame = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(reponame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return client.SecretDelete(owner, name, secret)
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
package secret
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var secretUpdateCmd = cli.Command{
|
|
||||||
Name: "update",
|
|
||||||
Usage: "update a secret",
|
|
||||||
Action: secretUpdate,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "repository",
|
|
||||||
Usage: "repository name (e.g. octocat/hello-world)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "name",
|
|
||||||
Usage: "secret name",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "value",
|
|
||||||
Usage: "secret value",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "event",
|
|
||||||
Usage: "secret limited to these events",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "image",
|
|
||||||
Usage: "secret limited to these images",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func secretUpdate(c *cli.Context) error {
|
|
||||||
reponame := c.String("repository")
|
|
||||||
if reponame == "" {
|
|
||||||
reponame = c.Args().First()
|
|
||||||
}
|
|
||||||
owner, name, err := internal.ParseRepo(reponame)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
secret := &model.Secret{
|
|
||||||
Name: c.String("name"),
|
|
||||||
Value: c.String("value"),
|
|
||||||
Images: c.StringSlice("image"),
|
|
||||||
Events: c.StringSlice("events"),
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(secret.Value, "@") {
|
|
||||||
path := strings.TrimPrefix(secret.Value, "@")
|
|
||||||
out, ferr := ioutil.ReadFile(path)
|
|
||||||
if ferr != nil {
|
|
||||||
return ferr
|
|
||||||
}
|
|
||||||
secret.Value = string(out)
|
|
||||||
}
|
|
||||||
_, err = client.SecretUpdate(owner, name, secret)
|
|
||||||
return err
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package user
|
|
||||||
|
|
||||||
import "github.com/urfave/cli"
|
|
||||||
|
|
||||||
// Command exports the user command set.
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "user",
|
|
||||||
Usage: "manage users",
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
userListCmd,
|
|
||||||
userInfoCmd,
|
|
||||||
userAddCmd,
|
|
||||||
userRemoveCmd,
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
package user
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
var userAddCmd = cli.Command{
|
|
||||||
Name: "add",
|
|
||||||
Usage: "adds a user",
|
|
||||||
Action: userAdd,
|
|
||||||
}
|
|
||||||
|
|
||||||
func userAdd(c *cli.Context) error {
|
|
||||||
login := c.Args().First()
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := client.UserPost(&model.User{Login: login})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("Successfully added user %s\n", user.Login)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
package user
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
var userInfoCmd = cli.Command{
|
|
||||||
Name: "info",
|
|
||||||
Usage: "show user details",
|
|
||||||
Action: userInfo,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplUserInfo,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func userInfo(c *cli.Context) error {
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
login := c.Args().First()
|
|
||||||
if len(login) == 0 {
|
|
||||||
return fmt.Errorf("Missing or invalid user login")
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := client.User(login)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format") + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return tmpl.Execute(os.Stdout, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for user information
|
|
||||||
var tmplUserInfo = `User: {{ .Login }}
|
|
||||||
Email: {{ .Email }}`
|
|
|
@ -1,47 +0,0 @@
|
||||||
package user
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"text/template"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
var userListCmd = cli.Command{
|
|
||||||
Name: "ls",
|
|
||||||
Usage: "list all users",
|
|
||||||
Action: userList,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "format",
|
|
||||||
Usage: "format output",
|
|
||||||
Value: tmplUserList,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func userList(c *cli.Context) error {
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
users, err := client.UserList()
|
|
||||||
if err != nil || len(users) == 0 {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpl, err := template.New("_").Parse(c.String("format") + "\n")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
for _, user := range users {
|
|
||||||
tmpl.Execute(os.Stdout, user)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// template for user list items
|
|
||||||
var tmplUserList = `{{ .Login }}`
|
|
|
@ -1,30 +0,0 @@
|
||||||
package user
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
"github.com/drone/drone/drone/internal"
|
|
||||||
)
|
|
||||||
|
|
||||||
var userRemoveCmd = cli.Command{
|
|
||||||
Name: "rm",
|
|
||||||
Usage: "remove a user",
|
|
||||||
Action: userRemove,
|
|
||||||
}
|
|
||||||
|
|
||||||
func userRemove(c *cli.Context) error {
|
|
||||||
login := c.Args().First()
|
|
||||||
|
|
||||||
client, err := internal.NewClient(c)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := client.UserDel(login); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("Successfully removed user %s\n", login)
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -25,3 +25,9 @@ const (
|
||||||
RepoFossil = "fossil"
|
RepoFossil = "fossil"
|
||||||
RepoPerforce = "perforce"
|
RepoPerforce = "perforce"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
VisibilityPublic = "public"
|
||||||
|
VisibilityPrivate = "private"
|
||||||
|
VisibilityInternal = "internal"
|
||||||
|
)
|
||||||
|
|
|
@ -22,6 +22,7 @@ type Repo struct {
|
||||||
Clone string `json:"clone_url,omitempty" meddler:"repo_clone"`
|
Clone string `json:"clone_url,omitempty" meddler:"repo_clone"`
|
||||||
Branch string `json:"default_branch,omitempty" meddler:"repo_branch"`
|
Branch string `json:"default_branch,omitempty" meddler:"repo_branch"`
|
||||||
Timeout int64 `json:"timeout,omitempty" meddler:"repo_timeout"`
|
Timeout int64 `json:"timeout,omitempty" meddler:"repo_timeout"`
|
||||||
|
Visibility string `json:"visibility" meddler:"repo_visibility"`
|
||||||
IsPrivate bool `json:"private,omitempty" meddler:"repo_private"`
|
IsPrivate bool `json:"private,omitempty" meddler:"repo_private"`
|
||||||
IsTrusted bool `json:"trusted" meddler:"repo_trusted"`
|
IsTrusted bool `json:"trusted" meddler:"repo_trusted"`
|
||||||
IsStarred bool `json:"starred,omitempty" meddler:"-"`
|
IsStarred bool `json:"starred,omitempty" meddler:"-"`
|
||||||
|
@ -41,6 +42,7 @@ type RepoPatch struct {
|
||||||
IsTrusted *bool `json:"trusted,omitempty"`
|
IsTrusted *bool `json:"trusted,omitempty"`
|
||||||
IsGated *bool `json:"gated,omitempty"`
|
IsGated *bool `json:"gated,omitempty"`
|
||||||
Timeout *int64 `json:"timeout,omitempty"`
|
Timeout *int64 `json:"timeout,omitempty"`
|
||||||
|
Visibility *string `json:"visibility,omitempty"`
|
||||||
AllowPull *bool `json:"allow_pr,omitempty"`
|
AllowPull *bool `json:"allow_pr,omitempty"`
|
||||||
AllowPush *bool `json:"allow_push,omitempty"`
|
AllowPush *bool `json:"allow_push,omitempty"`
|
||||||
AllowDeploy *bool `json:"allow_deploy,omitempty"`
|
AllowDeploy *bool `json:"allow_deploy,omitempty"`
|
||||||
|
|
|
@ -44,6 +44,9 @@ type Secret struct {
|
||||||
|
|
||||||
// Match returns true if an image and event match the restricted list.
|
// Match returns true if an image and event match the restricted list.
|
||||||
func (s *Secret) Match(event string) bool {
|
func (s *Secret) Match(event string) bool {
|
||||||
|
if len(s.Events) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
for _, pattern := range s.Events {
|
for _, pattern := range s.Events {
|
||||||
if match, _ := filepath.Match(pattern, event); match {
|
if match, _ := filepath.Match(pattern, event); match {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -21,6 +21,10 @@ func TestSecret(t *testing.T) {
|
||||||
secret.Events = []string{"pull_request"}
|
secret.Events = []string{"pull_request"}
|
||||||
g.Assert(secret.Match("push")).IsFalse()
|
g.Assert(secret.Match("push")).IsFalse()
|
||||||
})
|
})
|
||||||
|
g.It("should match when no event filters defined", func() {
|
||||||
|
secret := Secret{}
|
||||||
|
g.Assert(secret.Match("pull_request")).IsTrue()
|
||||||
|
})
|
||||||
g.It("should pass validation")
|
g.It("should pass validation")
|
||||||
g.Describe("should fail validation", func() {
|
g.Describe("should fail validation", func() {
|
||||||
g.It("when no image")
|
g.It("when no image")
|
||||||
|
|
|
@ -2,7 +2,6 @@ package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/drone/drone/cache"
|
"github.com/drone/drone/cache"
|
||||||
"github.com/drone/drone/model"
|
"github.com/drone/drone/model"
|
||||||
|
@ -79,7 +78,6 @@ func Perm(c *gin.Context) *model.Perm {
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetPerm() gin.HandlerFunc {
|
func SetPerm() gin.HandlerFunc {
|
||||||
PUBLIC_MODE := os.Getenv("PUBLIC_MODE")
|
|
||||||
|
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
user := User(c)
|
user := User(c)
|
||||||
|
@ -87,49 +85,24 @@ func SetPerm() gin.HandlerFunc {
|
||||||
perm := &model.Perm{}
|
perm := &model.Perm{}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
// if the user is not authenticated, and the
|
case user != nil && user.Admin:
|
||||||
// repository is private, the user has NO permission
|
|
||||||
// to view the repository.
|
|
||||||
case user == nil && repo.IsPrivate == true:
|
|
||||||
perm.Pull = false
|
|
||||||
perm.Push = false
|
|
||||||
perm.Admin = false
|
|
||||||
|
|
||||||
// if the user is not authenticated, but the repository
|
|
||||||
// is public, the user has pull-rights only.
|
|
||||||
case user == nil && repo.IsPrivate == false:
|
|
||||||
perm.Pull = true
|
|
||||||
perm.Push = false
|
|
||||||
perm.Admin = false
|
|
||||||
|
|
||||||
case user.Admin:
|
|
||||||
perm.Pull = true
|
perm.Pull = true
|
||||||
perm.Push = true
|
perm.Push = true
|
||||||
perm.Admin = true
|
perm.Admin = true
|
||||||
|
|
||||||
// otherwise if the user is authenticated we should
|
case user != nil:
|
||||||
// check the remote system to get the users permissiosn.
|
|
||||||
default:
|
|
||||||
var err error
|
var err error
|
||||||
perm, err = cache.GetPerms(c, user, repo.Owner, repo.Name)
|
perm, err = cache.GetPerms(c, user, repo.Owner, repo.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
perm.Pull = false
|
|
||||||
perm.Push = false
|
|
||||||
perm.Admin = false
|
|
||||||
|
|
||||||
// debug
|
|
||||||
log.Errorf("Error fetching permission for %s %s",
|
log.Errorf("Error fetching permission for %s %s",
|
||||||
user.Login, repo.FullName)
|
user.Login, repo.FullName)
|
||||||
}
|
}
|
||||||
// if we couldn't fetch permissions, but the repository
|
|
||||||
// is public, we should grant the user pull access.
|
|
||||||
if err != nil && repo.IsPrivate == false {
|
|
||||||
perm.Pull = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// all build logs are visible in public mode
|
switch {
|
||||||
if PUBLIC_MODE != "" {
|
case repo.Visibility == model.VisibilityPublic:
|
||||||
|
perm.Pull = true
|
||||||
|
case repo.Visibility == model.VisibilityInternal && user != nil:
|
||||||
perm.Pull = true
|
perm.Pull = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,44 +1,9 @@
|
||||||
package session
|
package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/drone/drone/model"
|
|
||||||
"github.com/franela/goblin"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSetPerm(t *testing.T) {
|
func TestSetPerm(t *testing.T) {
|
||||||
g := goblin.Goblin(t)
|
|
||||||
g.Describe("SetPerm", func() {
|
|
||||||
g.BeforeEach(func() {
|
|
||||||
os.Unsetenv("PUBLIC_MODE")
|
|
||||||
})
|
|
||||||
g.It("Should set pull to false (private repo, user not logged in)", func() {
|
|
||||||
c := gin.Context{}
|
|
||||||
c.Set("repo", &model.Repo{
|
|
||||||
IsPrivate: true,
|
|
||||||
})
|
|
||||||
SetPerm()(&c)
|
|
||||||
v, ok := c.Get("perm")
|
|
||||||
g.Assert(ok).IsTrue("perm was not set")
|
|
||||||
p, ok := v.(*model.Perm)
|
|
||||||
g.Assert(ok).IsTrue("perm was the wrong type")
|
|
||||||
g.Assert(p.Pull).IsFalse("pull should be false")
|
|
||||||
})
|
|
||||||
g.It("Should set pull to true (private repo, user not logged in, public mode)", func() {
|
|
||||||
os.Setenv("PUBLIC_MODE", "true")
|
|
||||||
c := gin.Context{}
|
|
||||||
c.Set("repo", &model.Repo{
|
|
||||||
IsPrivate: true,
|
|
||||||
})
|
|
||||||
SetPerm()(&c)
|
|
||||||
v, ok := c.Get("perm")
|
|
||||||
g.Assert(ok).IsTrue("perm was not set")
|
|
||||||
p, ok := v.(*model.Perm)
|
|
||||||
g.Assert(ok).IsTrue("perm was the wrong type")
|
|
||||||
g.Assert(p.Pull).IsTrue("pull should be true")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,7 @@ func PostApproval(c *gin.Context) {
|
||||||
// get the previous build so that we can send
|
// get the previous build so that we can send
|
||||||
// on status change notifications
|
// on status change notifications
|
||||||
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
||||||
secs, err := Config.Services.Secrets.SecretList(repo)
|
secs, err := Config.Services.Secrets.SecretListBuild(repo, build)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Debugf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
logrus.Debugf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
||||||
}
|
}
|
||||||
|
@ -476,7 +476,7 @@ func PostBuild(c *gin.Context) {
|
||||||
// get the previous build so that we can send
|
// get the previous build so that we can send
|
||||||
// on status change notifications
|
// on status change notifications
|
||||||
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
||||||
secs, err := Config.Services.Secrets.SecretList(repo)
|
secs, err := Config.Services.Secrets.SecretListBuild(repo, build)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Debugf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
logrus.Debugf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,16 +175,6 @@ func PostHook(c *gin.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
secs, err := Config.Services.Secrets.SecretList(repo)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Debugf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
regs, err := Config.Services.Registries.RegistryList(repo)
|
|
||||||
if err != nil {
|
|
||||||
logrus.Debugf("Error getting registry credentials for %s#%d. %s", repo.FullName, build.Number, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// update some build fields
|
// update some build fields
|
||||||
build.RepoID = repo.ID
|
build.RepoID = repo.ID
|
||||||
build.Verified = true
|
build.Verified = true
|
||||||
|
@ -211,6 +201,16 @@ func PostHook(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secs, err := Config.Services.Secrets.SecretListBuild(repo, build)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Debugf("Error getting secrets for %s#%d. %s", repo.FullName, build.Number, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
regs, err := Config.Services.Registries.RegistryList(repo)
|
||||||
|
if err != nil {
|
||||||
|
logrus.Debugf("Error getting registry credentials for %s#%d. %s", repo.FullName, build.Number, err)
|
||||||
|
}
|
||||||
|
|
||||||
// get the previous build so that we can send
|
// get the previous build so that we can send
|
||||||
// on status change notifications
|
// on status change notifications
|
||||||
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
||||||
|
|
|
@ -55,11 +55,15 @@ func PostRepo(c *gin.Context) {
|
||||||
r.UserID = user.ID
|
r.UserID = user.ID
|
||||||
r.AllowPush = true
|
r.AllowPush = true
|
||||||
r.AllowPull = true
|
r.AllowPull = true
|
||||||
|
r.Visibility = model.VisibilityPublic
|
||||||
r.Config = ".drone.yml"
|
r.Config = ".drone.yml"
|
||||||
r.Timeout = 60 // 1 hour default build time
|
r.Timeout = 60 // 1 hour default build time
|
||||||
r.Hash = base32.StdEncoding.EncodeToString(
|
r.Hash = base32.StdEncoding.EncodeToString(
|
||||||
securecookie.GenerateRandomKey(32),
|
securecookie.GenerateRandomKey(32),
|
||||||
)
|
)
|
||||||
|
if r.IsPrivate {
|
||||||
|
r.Visibility = model.VisibilityPrivate
|
||||||
|
}
|
||||||
|
|
||||||
// crates the jwt token used to verify the repository
|
// crates the jwt token used to verify the repository
|
||||||
t := token.New(token.HookToken, r.FullName)
|
t := token.New(token.HookToken, r.FullName)
|
||||||
|
@ -132,6 +136,15 @@ func PatchRepo(c *gin.Context) {
|
||||||
if in.Config != nil {
|
if in.Config != nil {
|
||||||
repo.Config = *in.Config
|
repo.Config = *in.Config
|
||||||
}
|
}
|
||||||
|
if in.Visibility != nil {
|
||||||
|
switch *in.Visibility {
|
||||||
|
case model.VisibilityInternal, model.VisibilityPrivate, model.VisibilityPublic:
|
||||||
|
repo.Visibility = *in.Visibility
|
||||||
|
default:
|
||||||
|
c.String(400, "Invalid visibility type")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err := store.UpdateRepo(c, repo)
|
err := store.UpdateRepo(c, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -99,7 +99,7 @@ INSERT IGNORE INTO migrations (name) VALUES
|
||||||
|
|
||||||
var createMigrationsTable = `
|
var createMigrationsTable = `
|
||||||
CREATE TABLE IF NOT EXISTS migrations (
|
CREATE TABLE IF NOT EXISTS migrations (
|
||||||
name VARCHAR(512)
|
name VARCHAR(255)
|
||||||
,UNIQUE(name)
|
,UNIQUE(name)
|
||||||
)
|
)
|
||||||
`
|
`
|
||||||
|
|
|
@ -88,6 +88,14 @@ var migrations = []struct {
|
||||||
name: "create-index-sender-repos",
|
name: "create-index-sender-repos",
|
||||||
stmt: createIndexSenderRepos,
|
stmt: createIndexSenderRepos,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "alter-table-add-repo-visibility",
|
||||||
|
stmt: alterTableAddRepoVisibility,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update-table-set-repo-visibility",
|
||||||
|
stmt: updateTableSetRepoVisibility,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "alter-table-add-repo-seq",
|
name: "alter-table-add-repo-seq",
|
||||||
stmt: alterTableAddRepoSeq,
|
stmt: alterTableAddRepoSeq,
|
||||||
|
@ -376,7 +384,7 @@ CREATE TABLE IF NOT EXISTS registry (
|
||||||
,registry_addr VARCHAR(250)
|
,registry_addr VARCHAR(250)
|
||||||
,registry_email VARCHAR(500)
|
,registry_email VARCHAR(500)
|
||||||
,registry_username VARCHAR(2000)
|
,registry_username VARCHAR(2000)
|
||||||
,registry_password VARCHAR(2000)
|
,registry_password VARCHAR(8000)
|
||||||
,registry_token VARCHAR(2000)
|
,registry_token VARCHAR(2000)
|
||||||
|
|
||||||
,UNIQUE(registry_addr, registry_repo_id)
|
,UNIQUE(registry_addr, registry_repo_id)
|
||||||
|
@ -451,6 +459,22 @@ var createIndexSenderRepos = `
|
||||||
CREATE INDEX sender_repo_ix ON senders (sender_repo_id);
|
CREATE INDEX sender_repo_ix ON senders (sender_repo_id);
|
||||||
`
|
`
|
||||||
|
|
||||||
|
//
|
||||||
|
// 013_add_column_repo_visibility.sql
|
||||||
|
//
|
||||||
|
|
||||||
|
var alterTableAddRepoVisibility = `
|
||||||
|
ALTER TABLE repos ADD COLUMN repo_visibility VARCHAR(50)
|
||||||
|
`
|
||||||
|
|
||||||
|
var updateTableSetRepoVisibility = `
|
||||||
|
UPDATE repos
|
||||||
|
SET repo_visibility = CASE
|
||||||
|
WHEN repo_private = 0 THEN 'public'
|
||||||
|
ELSE 'private'
|
||||||
|
END
|
||||||
|
`
|
||||||
|
|
||||||
//
|
//
|
||||||
// 014_add_column_repo_seq.sql
|
// 014_add_column_repo_seq.sql
|
||||||
//
|
//
|
||||||
|
|
|
@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS registry (
|
||||||
,registry_addr VARCHAR(250)
|
,registry_addr VARCHAR(250)
|
||||||
,registry_email VARCHAR(500)
|
,registry_email VARCHAR(500)
|
||||||
,registry_username VARCHAR(2000)
|
,registry_username VARCHAR(2000)
|
||||||
,registry_password VARCHAR(2000)
|
,registry_password VARCHAR(8000)
|
||||||
,registry_token VARCHAR(2000)
|
,registry_token VARCHAR(2000)
|
||||||
|
|
||||||
,UNIQUE(registry_addr, registry_repo_id)
|
,UNIQUE(registry_addr, registry_repo_id)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
-- name: alter-table-add-repo-visibility
|
||||||
|
|
||||||
|
ALTER TABLE repos ADD COLUMN repo_visibility VARCHAR(50)
|
||||||
|
|
||||||
|
-- name: update-table-set-repo-visibility
|
||||||
|
|
||||||
|
UPDATE repos
|
||||||
|
SET repo_visibility = CASE
|
||||||
|
WHEN repo_private = 0 THEN 'public'
|
||||||
|
ELSE 'private'
|
||||||
|
END
|
|
@ -88,6 +88,14 @@ var migrations = []struct {
|
||||||
name: "create-index-sender-repos",
|
name: "create-index-sender-repos",
|
||||||
stmt: createIndexSenderRepos,
|
stmt: createIndexSenderRepos,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "alter-table-add-repo-visibility",
|
||||||
|
stmt: alterTableAddRepoVisibility,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update-table-set-repo-visibility",
|
||||||
|
stmt: updateTableSetRepoVisibility,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "alter-table-add-repo-seq",
|
name: "alter-table-add-repo-seq",
|
||||||
stmt: alterTableAddRepoSeq,
|
stmt: alterTableAddRepoSeq,
|
||||||
|
@ -376,7 +384,7 @@ CREATE TABLE IF NOT EXISTS registry (
|
||||||
,registry_addr VARCHAR(250)
|
,registry_addr VARCHAR(250)
|
||||||
,registry_email VARCHAR(500)
|
,registry_email VARCHAR(500)
|
||||||
,registry_username VARCHAR(2000)
|
,registry_username VARCHAR(2000)
|
||||||
,registry_password VARCHAR(2000)
|
,registry_password VARCHAR(8000)
|
||||||
,registry_token VARCHAR(2000)
|
,registry_token VARCHAR(2000)
|
||||||
|
|
||||||
,UNIQUE(registry_addr, registry_repo_id)
|
,UNIQUE(registry_addr, registry_repo_id)
|
||||||
|
@ -451,6 +459,22 @@ var createIndexSenderRepos = `
|
||||||
CREATE INDEX IF NOT EXISTS sender_repo_ix ON senders (sender_repo_id);
|
CREATE INDEX IF NOT EXISTS sender_repo_ix ON senders (sender_repo_id);
|
||||||
`
|
`
|
||||||
|
|
||||||
|
//
|
||||||
|
// 013_add_column_repo_visibility.sql
|
||||||
|
//
|
||||||
|
|
||||||
|
var alterTableAddRepoVisibility = `
|
||||||
|
ALTER TABLE repos ADD COLUMN repo_visibility VARCHAR(50)
|
||||||
|
`
|
||||||
|
|
||||||
|
var updateTableSetRepoVisibility = `
|
||||||
|
UPDATE repos
|
||||||
|
SET repo_visibility = (CASE
|
||||||
|
WHEN repo_private = true THEN 'public'
|
||||||
|
ELSE 'private'
|
||||||
|
END)
|
||||||
|
`
|
||||||
|
|
||||||
//
|
//
|
||||||
// 014_add_column_repo_seq.sql
|
// 014_add_column_repo_seq.sql
|
||||||
//
|
//
|
||||||
|
|
|
@ -6,7 +6,7 @@ CREATE TABLE IF NOT EXISTS registry (
|
||||||
,registry_addr VARCHAR(250)
|
,registry_addr VARCHAR(250)
|
||||||
,registry_email VARCHAR(500)
|
,registry_email VARCHAR(500)
|
||||||
,registry_username VARCHAR(2000)
|
,registry_username VARCHAR(2000)
|
||||||
,registry_password VARCHAR(2000)
|
,registry_password VARCHAR(8000)
|
||||||
,registry_token VARCHAR(2000)
|
,registry_token VARCHAR(2000)
|
||||||
|
|
||||||
,UNIQUE(registry_addr, registry_repo_id)
|
,UNIQUE(registry_addr, registry_repo_id)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
-- name: alter-table-add-repo-visibility
|
||||||
|
|
||||||
|
ALTER TABLE repos ADD COLUMN repo_visibility VARCHAR(50)
|
||||||
|
|
||||||
|
-- name: update-table-set-repo-visibility
|
||||||
|
|
||||||
|
UPDATE repos
|
||||||
|
SET repo_visibility = (CASE
|
||||||
|
WHEN repo_private = true THEN 'public'
|
||||||
|
ELSE 'private'
|
||||||
|
END)
|
|
@ -92,6 +92,14 @@ var migrations = []struct {
|
||||||
name: "create-index-sender-repos",
|
name: "create-index-sender-repos",
|
||||||
stmt: createIndexSenderRepos,
|
stmt: createIndexSenderRepos,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "alter-table-add-repo-visibility",
|
||||||
|
stmt: alterTableAddRepoVisibility,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update-table-set-repo-visibility",
|
||||||
|
stmt: updateTableSetRepoVisibility,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "alter-table-add-repo-seq",
|
name: "alter-table-add-repo-seq",
|
||||||
stmt: alterTableAddRepoSeq,
|
stmt: alterTableAddRepoSeq,
|
||||||
|
@ -452,6 +460,22 @@ var createIndexSenderRepos = `
|
||||||
CREATE INDEX IF NOT EXISTS sender_repo_ix ON senders (sender_repo_id);
|
CREATE INDEX IF NOT EXISTS sender_repo_ix ON senders (sender_repo_id);
|
||||||
`
|
`
|
||||||
|
|
||||||
|
//
|
||||||
|
// 013_add_column_repo_visibility.sql
|
||||||
|
//
|
||||||
|
|
||||||
|
var alterTableAddRepoVisibility = `
|
||||||
|
ALTER TABLE repos ADD COLUMN repo_visibility TEXT
|
||||||
|
`
|
||||||
|
|
||||||
|
var updateTableSetRepoVisibility = `
|
||||||
|
UPDATE repos
|
||||||
|
SET repo_visibility = CASE
|
||||||
|
WHEN repo_private = 0 THEN 'public'
|
||||||
|
ELSE 'private'
|
||||||
|
END
|
||||||
|
`
|
||||||
|
|
||||||
//
|
//
|
||||||
// 014_add_column_repo_seq.sql
|
// 014_add_column_repo_seq.sql
|
||||||
//
|
//
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
-- name: alter-table-add-repo-visibility
|
||||||
|
|
||||||
|
ALTER TABLE repos ADD COLUMN repo_visibility TEXT
|
||||||
|
|
||||||
|
-- name: update-table-set-repo-visibility
|
||||||
|
|
||||||
|
UPDATE repos
|
||||||
|
SET repo_visibility = CASE
|
||||||
|
WHEN repo_private = 0 THEN 'public'
|
||||||
|
ELSE 'private'
|
||||||
|
END
|
|
@ -37,7 +37,7 @@ SELECT
|
||||||
,proc_environ
|
,proc_environ
|
||||||
FROM procs
|
FROM procs
|
||||||
WHERE proc_build_id = $1
|
WHERE proc_build_id = $1
|
||||||
ORDER BY proc_pid ASC
|
ORDER BY proc_id ASC
|
||||||
|
|
||||||
-- name: procs-find-build-pid
|
-- name: procs-find-build-pid
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ SELECT
|
||||||
,proc_environ
|
,proc_environ
|
||||||
FROM procs
|
FROM procs
|
||||||
WHERE proc_build_id = $1
|
WHERE proc_build_id = $1
|
||||||
ORDER BY proc_pid ASC
|
ORDER BY proc_id ASC
|
||||||
`
|
`
|
||||||
|
|
||||||
var procsFindBuildPid = `
|
var procsFindBuildPid = `
|
||||||
|
|
|
@ -37,6 +37,7 @@ SELECT
|
||||||
,proc_environ
|
,proc_environ
|
||||||
FROM procs
|
FROM procs
|
||||||
WHERE proc_build_id = ?
|
WHERE proc_build_id = ?
|
||||||
|
ORDER BY proc_id ASC
|
||||||
|
|
||||||
-- name: procs-find-build-pid
|
-- name: procs-find-build-pid
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,7 @@ SELECT
|
||||||
,proc_environ
|
,proc_environ
|
||||||
FROM procs
|
FROM procs
|
||||||
WHERE proc_build_id = ?
|
WHERE proc_build_id = ?
|
||||||
|
ORDER BY proc_id ASC
|
||||||
`
|
`
|
||||||
|
|
||||||
var procsFindBuildPid = `
|
var procsFindBuildPid = `
|
||||||
|
|
21
vendor/github.com/kr/pretty/License
generated
vendored
Normal file
21
vendor/github.com/kr/pretty/License
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright 2012 Keith Rarick
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
9
vendor/github.com/kr/pretty/Readme
generated
vendored
Normal file
9
vendor/github.com/kr/pretty/Readme
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package pretty
|
||||||
|
|
||||||
|
import "github.com/kr/pretty"
|
||||||
|
|
||||||
|
Package pretty provides pretty-printing for Go values.
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
|
||||||
|
http://godoc.org/github.com/kr/pretty
|
265
vendor/github.com/kr/pretty/diff.go
generated
vendored
Normal file
265
vendor/github.com/kr/pretty/diff.go
generated
vendored
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
package pretty
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sbuf []string
|
||||||
|
|
||||||
|
func (p *sbuf) Printf(format string, a ...interface{}) {
|
||||||
|
s := fmt.Sprintf(format, a...)
|
||||||
|
*p = append(*p, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff returns a slice where each element describes
|
||||||
|
// a difference between a and b.
|
||||||
|
func Diff(a, b interface{}) (desc []string) {
|
||||||
|
Pdiff((*sbuf)(&desc), a, b)
|
||||||
|
return desc
|
||||||
|
}
|
||||||
|
|
||||||
|
// wprintfer calls Fprintf on w for each Printf call
|
||||||
|
// with a trailing newline.
|
||||||
|
type wprintfer struct{ w io.Writer }
|
||||||
|
|
||||||
|
func (p *wprintfer) Printf(format string, a ...interface{}) {
|
||||||
|
fmt.Fprintf(p.w, format+"\n", a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fdiff writes to w a description of the differences between a and b.
|
||||||
|
func Fdiff(w io.Writer, a, b interface{}) {
|
||||||
|
Pdiff(&wprintfer{w}, a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Printfer interface {
|
||||||
|
Printf(format string, a ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pdiff prints to p a description of the differences between a and b.
|
||||||
|
// It calls Printf once for each difference, with no trailing newline.
|
||||||
|
// The standard library log.Logger is a Printfer.
|
||||||
|
func Pdiff(p Printfer, a, b interface{}) {
|
||||||
|
diffPrinter{w: p}.diff(reflect.ValueOf(a), reflect.ValueOf(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Logfer interface {
|
||||||
|
Logf(format string, a ...interface{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// logprintfer calls Fprintf on w for each Printf call
|
||||||
|
// with a trailing newline.
|
||||||
|
type logprintfer struct{ l Logfer }
|
||||||
|
|
||||||
|
func (p *logprintfer) Printf(format string, a ...interface{}) {
|
||||||
|
p.l.Logf(format, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ldiff prints to l a description of the differences between a and b.
|
||||||
|
// It calls Logf once for each difference, with no trailing newline.
|
||||||
|
// The standard library testing.T and testing.B are Logfers.
|
||||||
|
func Ldiff(l Logfer, a, b interface{}) {
|
||||||
|
Pdiff(&logprintfer{l}, a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
type diffPrinter struct {
|
||||||
|
w Printfer
|
||||||
|
l string // label
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w diffPrinter) printf(f string, a ...interface{}) {
|
||||||
|
var l string
|
||||||
|
if w.l != "" {
|
||||||
|
l = w.l + ": "
|
||||||
|
}
|
||||||
|
w.w.Printf(l+f, a...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w diffPrinter) diff(av, bv reflect.Value) {
|
||||||
|
if !av.IsValid() && bv.IsValid() {
|
||||||
|
w.printf("nil != %# v", formatter{v: bv, quote: true})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if av.IsValid() && !bv.IsValid() {
|
||||||
|
w.printf("%# v != nil", formatter{v: av, quote: true})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !av.IsValid() && !bv.IsValid() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
at := av.Type()
|
||||||
|
bt := bv.Type()
|
||||||
|
if at != bt {
|
||||||
|
w.printf("%v != %v", at, bt)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch kind := at.Kind(); kind {
|
||||||
|
case reflect.Bool:
|
||||||
|
if a, b := av.Bool(), bv.Bool(); a != b {
|
||||||
|
w.printf("%v != %v", a, b)
|
||||||
|
}
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
if a, b := av.Int(), bv.Int(); a != b {
|
||||||
|
w.printf("%d != %d", a, b)
|
||||||
|
}
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
if a, b := av.Uint(), bv.Uint(); a != b {
|
||||||
|
w.printf("%d != %d", a, b)
|
||||||
|
}
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
if a, b := av.Float(), bv.Float(); a != b {
|
||||||
|
w.printf("%v != %v", a, b)
|
||||||
|
}
|
||||||
|
case reflect.Complex64, reflect.Complex128:
|
||||||
|
if a, b := av.Complex(), bv.Complex(); a != b {
|
||||||
|
w.printf("%v != %v", a, b)
|
||||||
|
}
|
||||||
|
case reflect.Array:
|
||||||
|
n := av.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i))
|
||||||
|
}
|
||||||
|
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
|
||||||
|
if a, b := av.Pointer(), bv.Pointer(); a != b {
|
||||||
|
w.printf("%#x != %#x", a, b)
|
||||||
|
}
|
||||||
|
case reflect.Interface:
|
||||||
|
w.diff(av.Elem(), bv.Elem())
|
||||||
|
case reflect.Map:
|
||||||
|
ak, both, bk := keyDiff(av.MapKeys(), bv.MapKeys())
|
||||||
|
for _, k := range ak {
|
||||||
|
w := w.relabel(fmt.Sprintf("[%#v]", k))
|
||||||
|
w.printf("%q != (missing)", av.MapIndex(k))
|
||||||
|
}
|
||||||
|
for _, k := range both {
|
||||||
|
w := w.relabel(fmt.Sprintf("[%#v]", k))
|
||||||
|
w.diff(av.MapIndex(k), bv.MapIndex(k))
|
||||||
|
}
|
||||||
|
for _, k := range bk {
|
||||||
|
w := w.relabel(fmt.Sprintf("[%#v]", k))
|
||||||
|
w.printf("(missing) != %q", bv.MapIndex(k))
|
||||||
|
}
|
||||||
|
case reflect.Ptr:
|
||||||
|
switch {
|
||||||
|
case av.IsNil() && !bv.IsNil():
|
||||||
|
w.printf("nil != %# v", formatter{v: bv, quote: true})
|
||||||
|
case !av.IsNil() && bv.IsNil():
|
||||||
|
w.printf("%# v != nil", formatter{v: av, quote: true})
|
||||||
|
case !av.IsNil() && !bv.IsNil():
|
||||||
|
w.diff(av.Elem(), bv.Elem())
|
||||||
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
lenA := av.Len()
|
||||||
|
lenB := bv.Len()
|
||||||
|
if lenA != lenB {
|
||||||
|
w.printf("%s[%d] != %s[%d]", av.Type(), lenA, bv.Type(), lenB)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for i := 0; i < lenA; i++ {
|
||||||
|
w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i))
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
if a, b := av.String(), bv.String(); a != b {
|
||||||
|
w.printf("%q != %q", a, b)
|
||||||
|
}
|
||||||
|
case reflect.Struct:
|
||||||
|
for i := 0; i < av.NumField(); i++ {
|
||||||
|
w.relabel(at.Field(i).Name).diff(av.Field(i), bv.Field(i))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unknown reflect Kind: " + kind.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d diffPrinter) relabel(name string) (d1 diffPrinter) {
|
||||||
|
d1 = d
|
||||||
|
if d.l != "" && name[0] != '[' {
|
||||||
|
d1.l += "."
|
||||||
|
}
|
||||||
|
d1.l += name
|
||||||
|
return d1
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyEqual compares a and b for equality.
|
||||||
|
// Both a and b must be valid map keys.
|
||||||
|
func keyEqual(av, bv reflect.Value) bool {
|
||||||
|
if !av.IsValid() && !bv.IsValid() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if !av.IsValid() || !bv.IsValid() || av.Type() != bv.Type() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch kind := av.Kind(); kind {
|
||||||
|
case reflect.Bool:
|
||||||
|
a, b := av.Bool(), bv.Bool()
|
||||||
|
return a == b
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
a, b := av.Int(), bv.Int()
|
||||||
|
return a == b
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
a, b := av.Uint(), bv.Uint()
|
||||||
|
return a == b
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
a, b := av.Float(), bv.Float()
|
||||||
|
return a == b
|
||||||
|
case reflect.Complex64, reflect.Complex128:
|
||||||
|
a, b := av.Complex(), bv.Complex()
|
||||||
|
return a == b
|
||||||
|
case reflect.Array:
|
||||||
|
for i := 0; i < av.Len(); i++ {
|
||||||
|
if !keyEqual(av.Index(i), bv.Index(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
case reflect.Chan, reflect.UnsafePointer, reflect.Ptr:
|
||||||
|
a, b := av.Pointer(), bv.Pointer()
|
||||||
|
return a == b
|
||||||
|
case reflect.Interface:
|
||||||
|
return keyEqual(av.Elem(), bv.Elem())
|
||||||
|
case reflect.String:
|
||||||
|
a, b := av.String(), bv.String()
|
||||||
|
return a == b
|
||||||
|
case reflect.Struct:
|
||||||
|
for i := 0; i < av.NumField(); i++ {
|
||||||
|
if !keyEqual(av.Field(i), bv.Field(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
panic("invalid map key type " + av.Type().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func keyDiff(a, b []reflect.Value) (ak, both, bk []reflect.Value) {
|
||||||
|
for _, av := range a {
|
||||||
|
inBoth := false
|
||||||
|
for _, bv := range b {
|
||||||
|
if keyEqual(av, bv) {
|
||||||
|
inBoth = true
|
||||||
|
both = append(both, av)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !inBoth {
|
||||||
|
ak = append(ak, av)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, bv := range b {
|
||||||
|
inBoth := false
|
||||||
|
for _, av := range a {
|
||||||
|
if keyEqual(av, bv) {
|
||||||
|
inBoth = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !inBoth {
|
||||||
|
bk = append(bk, bv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
328
vendor/github.com/kr/pretty/formatter.go
generated
vendored
Normal file
328
vendor/github.com/kr/pretty/formatter.go
generated
vendored
Normal file
|
@ -0,0 +1,328 @@
|
||||||
|
package pretty
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"reflect"
|
||||||
|
"strconv"
|
||||||
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/kr/text"
|
||||||
|
)
|
||||||
|
|
||||||
|
type formatter struct {
|
||||||
|
v reflect.Value
|
||||||
|
force bool
|
||||||
|
quote bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formatter makes a wrapper, f, that will format x as go source with line
|
||||||
|
// breaks and tabs. Object f responds to the "%v" formatting verb when both the
|
||||||
|
// "#" and " " (space) flags are set, for example:
|
||||||
|
//
|
||||||
|
// fmt.Sprintf("%# v", Formatter(x))
|
||||||
|
//
|
||||||
|
// If one of these two flags is not set, or any other verb is used, f will
|
||||||
|
// format x according to the usual rules of package fmt.
|
||||||
|
// In particular, if x satisfies fmt.Formatter, then x.Format will be called.
|
||||||
|
func Formatter(x interface{}) (f fmt.Formatter) {
|
||||||
|
return formatter{v: reflect.ValueOf(x), quote: true}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fo formatter) String() string {
|
||||||
|
return fmt.Sprint(fo.v) // unwrap it
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fo formatter) passThrough(f fmt.State, c rune) {
|
||||||
|
s := "%"
|
||||||
|
for i := 0; i < 128; i++ {
|
||||||
|
if f.Flag(i) {
|
||||||
|
s += string(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if w, ok := f.Width(); ok {
|
||||||
|
s += fmt.Sprintf("%d", w)
|
||||||
|
}
|
||||||
|
if p, ok := f.Precision(); ok {
|
||||||
|
s += fmt.Sprintf(".%d", p)
|
||||||
|
}
|
||||||
|
s += string(c)
|
||||||
|
fmt.Fprintf(f, s, fo.v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fo formatter) Format(f fmt.State, c rune) {
|
||||||
|
if fo.force || c == 'v' && f.Flag('#') && f.Flag(' ') {
|
||||||
|
w := tabwriter.NewWriter(f, 4, 4, 1, ' ', 0)
|
||||||
|
p := &printer{tw: w, Writer: w, visited: make(map[visit]int)}
|
||||||
|
p.printValue(fo.v, true, fo.quote)
|
||||||
|
w.Flush()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fo.passThrough(f, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
type printer struct {
|
||||||
|
io.Writer
|
||||||
|
tw *tabwriter.Writer
|
||||||
|
visited map[visit]int
|
||||||
|
depth int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *printer) indent() *printer {
|
||||||
|
q := *p
|
||||||
|
q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0)
|
||||||
|
q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'})
|
||||||
|
return &q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *printer) printInline(v reflect.Value, x interface{}, showType bool) {
|
||||||
|
if showType {
|
||||||
|
io.WriteString(p, v.Type().String())
|
||||||
|
fmt.Fprintf(p, "(%#v)", x)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(p, "%#v", x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// printValue must keep track of already-printed pointer values to avoid
|
||||||
|
// infinite recursion.
|
||||||
|
type visit struct {
|
||||||
|
v uintptr
|
||||||
|
typ reflect.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *printer) printValue(v reflect.Value, showType, quote bool) {
|
||||||
|
if p.depth > 10 {
|
||||||
|
io.WriteString(p, "!%v(DEPTH EXCEEDED)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
p.printInline(v, v.Bool(), showType)
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
p.printInline(v, v.Int(), showType)
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
p.printInline(v, v.Uint(), showType)
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
p.printInline(v, v.Float(), showType)
|
||||||
|
case reflect.Complex64, reflect.Complex128:
|
||||||
|
fmt.Fprintf(p, "%#v", v.Complex())
|
||||||
|
case reflect.String:
|
||||||
|
p.fmtString(v.String(), quote)
|
||||||
|
case reflect.Map:
|
||||||
|
t := v.Type()
|
||||||
|
if showType {
|
||||||
|
io.WriteString(p, t.String())
|
||||||
|
}
|
||||||
|
writeByte(p, '{')
|
||||||
|
if nonzero(v) {
|
||||||
|
expand := !canInline(v.Type())
|
||||||
|
pp := p
|
||||||
|
if expand {
|
||||||
|
writeByte(p, '\n')
|
||||||
|
pp = p.indent()
|
||||||
|
}
|
||||||
|
keys := v.MapKeys()
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
showTypeInStruct := true
|
||||||
|
k := keys[i]
|
||||||
|
mv := v.MapIndex(k)
|
||||||
|
pp.printValue(k, false, true)
|
||||||
|
writeByte(pp, ':')
|
||||||
|
if expand {
|
||||||
|
writeByte(pp, '\t')
|
||||||
|
}
|
||||||
|
showTypeInStruct = t.Elem().Kind() == reflect.Interface
|
||||||
|
pp.printValue(mv, showTypeInStruct, true)
|
||||||
|
if expand {
|
||||||
|
io.WriteString(pp, ",\n")
|
||||||
|
} else if i < v.Len()-1 {
|
||||||
|
io.WriteString(pp, ", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expand {
|
||||||
|
pp.tw.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeByte(p, '}')
|
||||||
|
case reflect.Struct:
|
||||||
|
t := v.Type()
|
||||||
|
if v.CanAddr() {
|
||||||
|
addr := v.UnsafeAddr()
|
||||||
|
vis := visit{addr, t}
|
||||||
|
if vd, ok := p.visited[vis]; ok && vd < p.depth {
|
||||||
|
p.fmtString(t.String()+"{(CYCLIC REFERENCE)}", false)
|
||||||
|
break // don't print v again
|
||||||
|
}
|
||||||
|
p.visited[vis] = p.depth
|
||||||
|
}
|
||||||
|
|
||||||
|
if showType {
|
||||||
|
io.WriteString(p, t.String())
|
||||||
|
}
|
||||||
|
writeByte(p, '{')
|
||||||
|
if nonzero(v) {
|
||||||
|
expand := !canInline(v.Type())
|
||||||
|
pp := p
|
||||||
|
if expand {
|
||||||
|
writeByte(p, '\n')
|
||||||
|
pp = p.indent()
|
||||||
|
}
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
showTypeInStruct := true
|
||||||
|
if f := t.Field(i); f.Name != "" {
|
||||||
|
io.WriteString(pp, f.Name)
|
||||||
|
writeByte(pp, ':')
|
||||||
|
if expand {
|
||||||
|
writeByte(pp, '\t')
|
||||||
|
}
|
||||||
|
showTypeInStruct = labelType(f.Type)
|
||||||
|
}
|
||||||
|
pp.printValue(getField(v, i), showTypeInStruct, true)
|
||||||
|
if expand {
|
||||||
|
io.WriteString(pp, ",\n")
|
||||||
|
} else if i < v.NumField()-1 {
|
||||||
|
io.WriteString(pp, ", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expand {
|
||||||
|
pp.tw.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeByte(p, '}')
|
||||||
|
case reflect.Interface:
|
||||||
|
switch e := v.Elem(); {
|
||||||
|
case e.Kind() == reflect.Invalid:
|
||||||
|
io.WriteString(p, "nil")
|
||||||
|
case e.IsValid():
|
||||||
|
pp := *p
|
||||||
|
pp.depth++
|
||||||
|
pp.printValue(e, showType, true)
|
||||||
|
default:
|
||||||
|
io.WriteString(p, v.Type().String())
|
||||||
|
io.WriteString(p, "(nil)")
|
||||||
|
}
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
t := v.Type()
|
||||||
|
if showType {
|
||||||
|
io.WriteString(p, t.String())
|
||||||
|
}
|
||||||
|
if v.Kind() == reflect.Slice && v.IsNil() && showType {
|
||||||
|
io.WriteString(p, "(nil)")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if v.Kind() == reflect.Slice && v.IsNil() {
|
||||||
|
io.WriteString(p, "nil")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
writeByte(p, '{')
|
||||||
|
expand := !canInline(v.Type())
|
||||||
|
pp := p
|
||||||
|
if expand {
|
||||||
|
writeByte(p, '\n')
|
||||||
|
pp = p.indent()
|
||||||
|
}
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
showTypeInSlice := t.Elem().Kind() == reflect.Interface
|
||||||
|
pp.printValue(v.Index(i), showTypeInSlice, true)
|
||||||
|
if expand {
|
||||||
|
io.WriteString(pp, ",\n")
|
||||||
|
} else if i < v.Len()-1 {
|
||||||
|
io.WriteString(pp, ", ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expand {
|
||||||
|
pp.tw.Flush()
|
||||||
|
}
|
||||||
|
writeByte(p, '}')
|
||||||
|
case reflect.Ptr:
|
||||||
|
e := v.Elem()
|
||||||
|
if !e.IsValid() {
|
||||||
|
writeByte(p, '(')
|
||||||
|
io.WriteString(p, v.Type().String())
|
||||||
|
io.WriteString(p, ")(nil)")
|
||||||
|
} else {
|
||||||
|
pp := *p
|
||||||
|
pp.depth++
|
||||||
|
writeByte(pp, '&')
|
||||||
|
pp.printValue(e, true, true)
|
||||||
|
}
|
||||||
|
case reflect.Chan:
|
||||||
|
x := v.Pointer()
|
||||||
|
if showType {
|
||||||
|
writeByte(p, '(')
|
||||||
|
io.WriteString(p, v.Type().String())
|
||||||
|
fmt.Fprintf(p, ")(%#v)", x)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(p, "%#v", x)
|
||||||
|
}
|
||||||
|
case reflect.Func:
|
||||||
|
io.WriteString(p, v.Type().String())
|
||||||
|
io.WriteString(p, " {...}")
|
||||||
|
case reflect.UnsafePointer:
|
||||||
|
p.printInline(v, v.Pointer(), showType)
|
||||||
|
case reflect.Invalid:
|
||||||
|
io.WriteString(p, "nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func canInline(t reflect.Type) bool {
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Map:
|
||||||
|
return !canExpand(t.Elem())
|
||||||
|
case reflect.Struct:
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
if canExpand(t.Field(i).Type) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
case reflect.Interface:
|
||||||
|
return false
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
return !canExpand(t.Elem())
|
||||||
|
case reflect.Ptr:
|
||||||
|
return false
|
||||||
|
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func canExpand(t reflect.Type) bool {
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Map, reflect.Struct,
|
||||||
|
reflect.Interface, reflect.Array, reflect.Slice,
|
||||||
|
reflect.Ptr:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func labelType(t reflect.Type) bool {
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Interface, reflect.Struct:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *printer) fmtString(s string, quote bool) {
|
||||||
|
if quote {
|
||||||
|
s = strconv.Quote(s)
|
||||||
|
}
|
||||||
|
io.WriteString(p, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeByte(w io.Writer, b byte) {
|
||||||
|
w.Write([]byte{b})
|
||||||
|
}
|
||||||
|
|
||||||
|
func getField(v reflect.Value, i int) reflect.Value {
|
||||||
|
val := v.Field(i)
|
||||||
|
if val.Kind() == reflect.Interface && !val.IsNil() {
|
||||||
|
val = val.Elem()
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
108
vendor/github.com/kr/pretty/pretty.go
generated
vendored
Normal file
108
vendor/github.com/kr/pretty/pretty.go
generated
vendored
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
// Package pretty provides pretty-printing for Go values. This is
|
||||||
|
// useful during debugging, to avoid wrapping long output lines in
|
||||||
|
// the terminal.
|
||||||
|
//
|
||||||
|
// It provides a function, Formatter, that can be used with any
|
||||||
|
// function that accepts a format string. It also provides
|
||||||
|
// convenience wrappers for functions in packages fmt and log.
|
||||||
|
package pretty
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Errorf is a convenience wrapper for fmt.Errorf.
|
||||||
|
//
|
||||||
|
// Calling Errorf(f, x, y) is equivalent to
|
||||||
|
// fmt.Errorf(f, Formatter(x), Formatter(y)).
|
||||||
|
func Errorf(format string, a ...interface{}) error {
|
||||||
|
return fmt.Errorf(format, wrap(a, false)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fprintf is a convenience wrapper for fmt.Fprintf.
|
||||||
|
//
|
||||||
|
// Calling Fprintf(w, f, x, y) is equivalent to
|
||||||
|
// fmt.Fprintf(w, f, Formatter(x), Formatter(y)).
|
||||||
|
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, error error) {
|
||||||
|
return fmt.Fprintf(w, format, wrap(a, false)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log is a convenience wrapper for log.Printf.
|
||||||
|
//
|
||||||
|
// Calling Log(x, y) is equivalent to
|
||||||
|
// log.Print(Formatter(x), Formatter(y)), but each operand is
|
||||||
|
// formatted with "%# v".
|
||||||
|
func Log(a ...interface{}) {
|
||||||
|
log.Print(wrap(a, true)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logf is a convenience wrapper for log.Printf.
|
||||||
|
//
|
||||||
|
// Calling Logf(f, x, y) is equivalent to
|
||||||
|
// log.Printf(f, Formatter(x), Formatter(y)).
|
||||||
|
func Logf(format string, a ...interface{}) {
|
||||||
|
log.Printf(format, wrap(a, false)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logln is a convenience wrapper for log.Printf.
|
||||||
|
//
|
||||||
|
// Calling Logln(x, y) is equivalent to
|
||||||
|
// log.Println(Formatter(x), Formatter(y)), but each operand is
|
||||||
|
// formatted with "%# v".
|
||||||
|
func Logln(a ...interface{}) {
|
||||||
|
log.Println(wrap(a, true)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print pretty-prints its operands and writes to standard output.
|
||||||
|
//
|
||||||
|
// Calling Print(x, y) is equivalent to
|
||||||
|
// fmt.Print(Formatter(x), Formatter(y)), but each operand is
|
||||||
|
// formatted with "%# v".
|
||||||
|
func Print(a ...interface{}) (n int, errno error) {
|
||||||
|
return fmt.Print(wrap(a, true)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printf is a convenience wrapper for fmt.Printf.
|
||||||
|
//
|
||||||
|
// Calling Printf(f, x, y) is equivalent to
|
||||||
|
// fmt.Printf(f, Formatter(x), Formatter(y)).
|
||||||
|
func Printf(format string, a ...interface{}) (n int, errno error) {
|
||||||
|
return fmt.Printf(format, wrap(a, false)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Println pretty-prints its operands and writes to standard output.
|
||||||
|
//
|
||||||
|
// Calling Print(x, y) is equivalent to
|
||||||
|
// fmt.Println(Formatter(x), Formatter(y)), but each operand is
|
||||||
|
// formatted with "%# v".
|
||||||
|
func Println(a ...interface{}) (n int, errno error) {
|
||||||
|
return fmt.Println(wrap(a, true)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprint is a convenience wrapper for fmt.Sprintf.
|
||||||
|
//
|
||||||
|
// Calling Sprint(x, y) is equivalent to
|
||||||
|
// fmt.Sprint(Formatter(x), Formatter(y)), but each operand is
|
||||||
|
// formatted with "%# v".
|
||||||
|
func Sprint(a ...interface{}) string {
|
||||||
|
return fmt.Sprint(wrap(a, true)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprintf is a convenience wrapper for fmt.Sprintf.
|
||||||
|
//
|
||||||
|
// Calling Sprintf(f, x, y) is equivalent to
|
||||||
|
// fmt.Sprintf(f, Formatter(x), Formatter(y)).
|
||||||
|
func Sprintf(format string, a ...interface{}) string {
|
||||||
|
return fmt.Sprintf(format, wrap(a, false)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrap(a []interface{}, force bool) []interface{} {
|
||||||
|
w := make([]interface{}, len(a))
|
||||||
|
for i, x := range a {
|
||||||
|
w[i] = formatter{v: reflect.ValueOf(x), force: force}
|
||||||
|
}
|
||||||
|
return w
|
||||||
|
}
|
41
vendor/github.com/kr/pretty/zero.go
generated
vendored
Normal file
41
vendor/github.com/kr/pretty/zero.go
generated
vendored
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package pretty
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
)
|
||||||
|
|
||||||
|
func nonzero(v reflect.Value) bool {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
return v.Bool()
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return v.Int() != 0
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return v.Uint() != 0
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return v.Float() != 0
|
||||||
|
case reflect.Complex64, reflect.Complex128:
|
||||||
|
return v.Complex() != complex(0, 0)
|
||||||
|
case reflect.String:
|
||||||
|
return v.String() != ""
|
||||||
|
case reflect.Struct:
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
if nonzero(getField(v, i)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
case reflect.Array:
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
if nonzero(v.Index(i)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
case reflect.Map, reflect.Interface, reflect.Slice, reflect.Ptr, reflect.Chan, reflect.Func:
|
||||||
|
return !v.IsNil()
|
||||||
|
case reflect.UnsafePointer:
|
||||||
|
return v.Pointer() != 0
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
19
vendor/github.com/kr/text/License
generated
vendored
Normal file
19
vendor/github.com/kr/text/License
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
Copyright 2012 Keith Rarick
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
3
vendor/github.com/kr/text/Readme
generated
vendored
Normal file
3
vendor/github.com/kr/text/Readme
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
This is a Go package for manipulating paragraphs of text.
|
||||||
|
|
||||||
|
See http://go.pkgdoc.org/github.com/kr/text for full documentation.
|
3
vendor/github.com/kr/text/doc.go
generated
vendored
Normal file
3
vendor/github.com/kr/text/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
// Package text provides rudimentary functions for manipulating text in
|
||||||
|
// paragraphs.
|
||||||
|
package text
|
74
vendor/github.com/kr/text/indent.go
generated
vendored
Normal file
74
vendor/github.com/kr/text/indent.go
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
package text
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Indent inserts prefix at the beginning of each non-empty line of s. The
|
||||||
|
// end-of-line marker is NL.
|
||||||
|
func Indent(s, prefix string) string {
|
||||||
|
return string(IndentBytes([]byte(s), []byte(prefix)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IndentBytes inserts prefix at the beginning of each non-empty line of b.
|
||||||
|
// The end-of-line marker is NL.
|
||||||
|
func IndentBytes(b, prefix []byte) []byte {
|
||||||
|
var res []byte
|
||||||
|
bol := true
|
||||||
|
for _, c := range b {
|
||||||
|
if bol && c != '\n' {
|
||||||
|
res = append(res, prefix...)
|
||||||
|
}
|
||||||
|
res = append(res, c)
|
||||||
|
bol = c == '\n'
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// Writer indents each line of its input.
|
||||||
|
type indentWriter struct {
|
||||||
|
w io.Writer
|
||||||
|
bol bool
|
||||||
|
pre [][]byte
|
||||||
|
sel int
|
||||||
|
off int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewIndentWriter makes a new write filter that indents the input
|
||||||
|
// lines. Each line is prefixed in order with the corresponding
|
||||||
|
// element of pre. If there are more lines than elements, the last
|
||||||
|
// element of pre is repeated for each subsequent line.
|
||||||
|
func NewIndentWriter(w io.Writer, pre ...[]byte) io.Writer {
|
||||||
|
return &indentWriter{
|
||||||
|
w: w,
|
||||||
|
pre: pre,
|
||||||
|
bol: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The only errors returned are from the underlying indentWriter.
|
||||||
|
func (w *indentWriter) Write(p []byte) (n int, err error) {
|
||||||
|
for _, c := range p {
|
||||||
|
if w.bol {
|
||||||
|
var i int
|
||||||
|
i, err = w.w.Write(w.pre[w.sel][w.off:])
|
||||||
|
w.off += i
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = w.w.Write([]byte{c})
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
n++
|
||||||
|
w.bol = c == '\n'
|
||||||
|
if w.bol {
|
||||||
|
w.off = 0
|
||||||
|
if w.sel < len(w.pre)-1 {
|
||||||
|
w.sel++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
86
vendor/github.com/kr/text/wrap.go
generated
vendored
Normal file
86
vendor/github.com/kr/text/wrap.go
generated
vendored
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
package text
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
nl = []byte{'\n'}
|
||||||
|
sp = []byte{' '}
|
||||||
|
)
|
||||||
|
|
||||||
|
const defaultPenalty = 1e5
|
||||||
|
|
||||||
|
// Wrap wraps s into a paragraph of lines of length lim, with minimal
|
||||||
|
// raggedness.
|
||||||
|
func Wrap(s string, lim int) string {
|
||||||
|
return string(WrapBytes([]byte(s), lim))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapBytes wraps b into a paragraph of lines of length lim, with minimal
|
||||||
|
// raggedness.
|
||||||
|
func WrapBytes(b []byte, lim int) []byte {
|
||||||
|
words := bytes.Split(bytes.Replace(bytes.TrimSpace(b), nl, sp, -1), sp)
|
||||||
|
var lines [][]byte
|
||||||
|
for _, line := range WrapWords(words, 1, lim, defaultPenalty) {
|
||||||
|
lines = append(lines, bytes.Join(line, sp))
|
||||||
|
}
|
||||||
|
return bytes.Join(lines, nl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WrapWords is the low-level line-breaking algorithm, useful if you need more
|
||||||
|
// control over the details of the text wrapping process. For most uses, either
|
||||||
|
// Wrap or WrapBytes will be sufficient and more convenient.
|
||||||
|
//
|
||||||
|
// WrapWords splits a list of words into lines with minimal "raggedness",
|
||||||
|
// treating each byte as one unit, accounting for spc units between adjacent
|
||||||
|
// words on each line, and attempting to limit lines to lim units. Raggedness
|
||||||
|
// is the total error over all lines, where error is the square of the
|
||||||
|
// difference of the length of the line and lim. Too-long lines (which only
|
||||||
|
// happen when a single word is longer than lim units) have pen penalty units
|
||||||
|
// added to the error.
|
||||||
|
func WrapWords(words [][]byte, spc, lim, pen int) [][][]byte {
|
||||||
|
n := len(words)
|
||||||
|
|
||||||
|
length := make([][]int, n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
length[i] = make([]int, n)
|
||||||
|
length[i][i] = len(words[i])
|
||||||
|
for j := i + 1; j < n; j++ {
|
||||||
|
length[i][j] = length[i][j-1] + spc + len(words[j])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nbrk := make([]int, n)
|
||||||
|
cost := make([]int, n)
|
||||||
|
for i := range cost {
|
||||||
|
cost[i] = math.MaxInt32
|
||||||
|
}
|
||||||
|
for i := n - 1; i >= 0; i-- {
|
||||||
|
if length[i][n-1] <= lim || i == n-1 {
|
||||||
|
cost[i] = 0
|
||||||
|
nbrk[i] = n
|
||||||
|
} else {
|
||||||
|
for j := i + 1; j < n; j++ {
|
||||||
|
d := lim - length[i][j-1]
|
||||||
|
c := d*d + cost[j]
|
||||||
|
if length[i][j-1] > lim {
|
||||||
|
c += pen // too-long lines get a worse penalty
|
||||||
|
}
|
||||||
|
if c < cost[i] {
|
||||||
|
cost[i] = c
|
||||||
|
nbrk[i] = j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var lines [][][]byte
|
||||||
|
i := 0
|
||||||
|
for i < n {
|
||||||
|
lines = append(lines, words[i:nbrk[i]])
|
||||||
|
i = nbrk[i]
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}
|
12
vendor/vendor.json
vendored
12
vendor/vendor.json
vendored
|
@ -516,6 +516,18 @@
|
||||||
"revision": "487fc0ca06f9aa1a02d796f5510784b47d5afae2",
|
"revision": "487fc0ca06f9aa1a02d796f5510784b47d5afae2",
|
||||||
"revisionTime": "2014-09-12T11:56:02+03:00"
|
"revisionTime": "2014-09-12T11:56:02+03:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "vbjzNeqTEIPV1W6wT5PB3OwN9Ns=",
|
||||||
|
"path": "github.com/kr/pretty",
|
||||||
|
"revision": "737b74a46c4bf788349f72cb256fed10aea4d0ac",
|
||||||
|
"revisionTime": "2016-07-08T21:57:48Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"checksumSHA1": "uulQHQ7IsRKqDudBC8Go9J0gtAc=",
|
||||||
|
"path": "github.com/kr/text",
|
||||||
|
"revision": "7cafcd837844e784b526369c9bce262804aebc60",
|
||||||
|
"revisionTime": "2016-05-04T02:26:26Z"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "github.com/lib/pq",
|
"path": "github.com/lib/pq",
|
||||||
"revision": "83c4f410d0aed80a0f44bac6a576a7f2435791f3",
|
"revision": "83c4f410d0aed80a0f44bac6a576a7f2435791f3",
|
||||||
|
|
Loading…
Reference in a new issue