Implement notification subcommands #389
16
.drone.yml
16
.drone.yml
|
@ -9,7 +9,7 @@ platform:
|
|||
steps:
|
||||
- name: build
|
||||
pull: always
|
||||
image: golang:1.15
|
||||
image: golang:1.16
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
|
@ -27,7 +27,7 @@ steps:
|
|||
- pull_request
|
||||
|
||||
- name: unit-test
|
||||
image: golang:1.15
|
||||
image: golang:1.16
|
||||
commands:
|
||||
- make unit-test-coverage
|
||||
settings:
|
||||
|
@ -40,7 +40,7 @@ steps:
|
|||
- pull_request
|
||||
|
||||
- name: release-test
|
||||
image: golang:1.15
|
||||
image: golang:1.16
|
||||
commands:
|
||||
- make test
|
||||
settings:
|
||||
|
@ -54,7 +54,7 @@ steps:
|
|||
|
||||
- name: tag-test
|
||||
pull: always
|
||||
image: golang:1.15
|
||||
image: golang:1.16
|
||||
commands:
|
||||
- make test
|
||||
settings:
|
||||
|
@ -64,7 +64,7 @@ steps:
|
|||
- tag
|
||||
|
||||
- name: static
|
||||
image: golang:1.15
|
||||
image: golang:1.16
|
||||
environment:
|
||||
GOPROXY: https://goproxy.cn
|
||||
commands:
|
||||
|
@ -99,7 +99,7 @@ steps:
|
|||
image: plugins/s3:1
|
||||
settings:
|
||||
acl: public-read
|
||||
bucket: releases
|
||||
bucket: gitea-artifacts
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
source: "dist/release/*"
|
||||
|
@ -119,7 +119,7 @@ steps:
|
|||
image: plugins/s3:1
|
||||
settings:
|
||||
acl: public-read
|
||||
bucket: releases
|
||||
bucket: gitea-artifacts
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
source: "dist/release/*"
|
||||
|
@ -141,7 +141,7 @@ steps:
|
|||
image: plugins/s3:1
|
||||
settings:
|
||||
acl: public-read
|
||||
bucket: releases
|
||||
bucket: gitea-artifacts
|
||||
endpoint: https://storage.gitea.io
|
||||
path_style: true
|
||||
source: "dist/release/*"
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,3 +4,5 @@ tea
|
|||
.idea/
|
||||
.history/
|
||||
dist/
|
||||
|
||||
.vscode/
|
||||
|
|
29
CHANGELOG.md
29
CHANGELOG.md
|
@ -1,5 +1,34 @@
|
|||
# Changelog
|
||||
|
||||
## [v0.7.0](https://gitea.com/gitea/tea/releases/tag/v0.7.0) - 2021-03-12
|
||||
|
||||
* BREAKING
|
||||
* `tea issue create`: move `-b` flag to `-d` (#331)
|
||||
* Drop `tea notif` shorthand in favor of `tea n` (#307)
|
||||
* FEATURES
|
||||
* Add commands for reviews (#315)
|
||||
* Add `tea comment` and show comments of issues/pulls (#313)
|
||||
* Add interactive mode for `tea milestone create` (#310)
|
||||
* Add command to install shell completion (#309)
|
||||
* Implement PR closing and reopening (#304)
|
||||
* Add interactive mode for `tea issue create` (#302)
|
||||
* BUGFIXES
|
||||
* Introduce workaround for missing pull head sha (#340)
|
||||
* Don't exit if we can't find a local repo with a remote matching to a login (#336)
|
||||
* Don't push before creating a pull (#334)
|
||||
* InitCommand() robustness (#327)
|
||||
* `tea comment`: handle piped stdin (#322)
|
||||
* ENHANCEMENTS
|
||||
* Allow checking out PRs with deleted head branch (#341)
|
||||
* Markdown renderer: detect terminal width, resolve relative URLs (#332)
|
||||
* Add more issue / pr creation parameters (#331)
|
||||
* Improve `tea time` (#319)
|
||||
* `tea pr checkout`: dont create local branches (#314)
|
||||
* Add `tea issues --fields`, allow printing labels (#312)
|
||||
* Add more command shorthands (#307)
|
||||
* Show PR CI status (#306)
|
||||
* Make PR workflow helpers more robust (#300)
|
||||
|
||||
## [v0.6.0](https://gitea.com/gitea/tea/releases/tag/v0.6.0) - 2020-12-11
|
||||
|
||||
* BREAKING
|
||||
|
|
25
Dockerfile
Normal file
25
Dockerfile
Normal file
|
@ -0,0 +1,25 @@
|
|||
ARG GOVERSION="1.16.2"
|
||||
|
||||
FROM golang:${GOVERSION}-alpine AS buildenv
|
||||
|
||||
ARG CGO_ENABLED="0"
|
||||
ARG GOOS="linux"
|
||||
|
||||
COPY . $GOPATH/src/
|
||||
WORKDIR $GOPATH/src
|
||||
|
||||
RUN apk add --quiet --no-cache \
|
||||
make \
|
||||
git && \
|
||||
make build
|
||||
|
||||
FROM scratch
|
||||
ARG VERSION="0.7.0"
|
||||
LABEL org.opencontainers.image.title="tea - CLI for Gitea - git with a cup of tea"
|
||||
LABEL org.opencontainers.image.description="A command line tool to interact with Gitea servers"
|
||||
LABEL org.opencontainers.image.version="${VERSION}"
|
||||
LABEL org.opencontainers.image.authors="Tamás Gérczei <tamas@gerczei.eu>"
|
||||
LABEL org.opencontainers.image.vendor="The Gitea Authors"
|
||||
COPY --from=buildenv /go/src/tea /
|
||||
ENV HOME="/app"
|
||||
ENTRYPOINT ["/tea"]
|
8
Makefile
8
Makefile
|
@ -38,6 +38,8 @@ else
|
|||
TEA_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||
endif
|
||||
|
||||
TEA_VERSION_TAG ?= $(shell sed 's/+/_/' <<< $(TEA_VERSION))
|
||||
|
||||
LDFLAGS := -X "main.Version=$(TEA_VERSION)" -X "main.Tags=$(TAGS)"
|
||||
|
||||
PACKAGES ?= $(shell $(GO) list ./... | grep -v /vendor/)
|
||||
|
@ -139,6 +141,10 @@ build: $(EXECUTABLE)
|
|||
$(EXECUTABLE): $(SOURCES)
|
||||
$(GO) build -mod=vendor $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||
|
||||
.PHONY: build-image
|
||||
build-image:
|
||||
docker build --build-arg VERSION=$(TEA_VERSION) -t gitea/tea:$(TEA_VERSION_TAG) .
|
||||
|
||||
.PHONY: release
|
||||
release: release-dirs release-os release-compress release-check
|
||||
|
||||
|
@ -151,7 +157,7 @@ release-os:
|
|||
@hash gox > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
|
||||
cd /tmp && $(GO) get -u github.com/mitchellh/gox; \
|
||||
fi
|
||||
CGO_ENABLED=0 gox -verbose -cgo=false -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -osarch='!darwin/386 !darwin/arm64 !darwin/arm' -os="windows linux darwin" -arch="386 amd64 arm arm64" -output="$(DIST)/release/tea-$(VERSION)-{{.OS}}-{{.Arch}}"
|
||||
CGO_ENABLED=0 gox -verbose -cgo=false -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -osarch='!darwin/386 !darwin/arm' -os="windows linux darwin" -arch="386 amd64 arm arm64" -output="$(DIST)/release/tea-$(VERSION)-{{.OS}}-{{.Arch}}"
|
||||
|
||||
.PHONY: release-compress
|
||||
release-compress:
|
||||
|
|
130
README.md
130
README.md
|
@ -2,67 +2,95 @@
|
|||
|
||||
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Release](https://raster.shields.io/badge/dynamic/json.svg?label=release&url=https://gitea.com/api/v1/repos/gitea/tea/releases&query=$[0].tag_name)](https://gitea.com/gitea/tea/releases) [![Build Status](https://drone.gitea.com/api/badges/gitea/tea/status.svg)](https://drone.gitea.com/gitea/tea) [![Join the chat at https://img.shields.io/discord/322538954119184384.svg](https://img.shields.io/discord/322538954119184384.svg)](https://discord.gg/Gitea) [![Go Report Card](https://goreportcard.com/badge/code.gitea.io/tea)](https://goreportcard.com/report/code.gitea.io/tea) [![GoDoc](https://godoc.org/code.gitea.io/tea?status.svg)](https://godoc.org/code.gitea.io/tea)
|
||||
|
||||
## The official CLI interface for gitea
|
||||
### The official CLI for Gitea
|
||||
|
||||
Tea is a command line tool for interacting on one or more Gitea instances.
|
||||
It uses [code.gitea.io/sdk](https://code.gitea.io/sdk) and interacts with the Gitea API
|
||||
![demo gif](./demo.gif)
|
||||
|
||||
![demo gif](https://dl.gitea.io/screenshots/tea_demo.gif)
|
||||
```
|
||||
tea - command line tool to interact with Gitea
|
||||
version 0.7.0-preview
|
||||
|
||||
For a feature comparison with other git forge CLIs see [here](./FEATURE-COMPARISON.md).
|
||||
USAGE
|
||||
tea command [subcommand] [command options] [arguments...]
|
||||
|
||||
DESCRIPTION
|
||||
tea is a productivity helper for Gitea. It can be used to manage most entities on one
|
||||
or multiple Gitea instances and provides local helpers like 'tea pull checkout'.
|
||||
tea makes use of context provided by the repository in $PWD if available, but is still
|
||||
usable independently of $PWD. Configuration is persisted in $XDG_CONFIG_HOME/tea.
|
||||
|
||||
COMMANDS
|
||||
help, h Shows a list of commands or help for one command
|
||||
ENTITIES:
|
||||
issues, issue, i List, create and update issues
|
||||
pulls, pull, pr Manage and checkout pull requests
|
||||
labels, label Manage issue labels
|
||||
milestones, milestone, ms List and create milestones
|
||||
releases, release, r Manage releases
|
||||
times, time, t Operate on tracked times of a repository's issues & pulls
|
||||
organizations, organization, org List, create, delete organizations
|
||||
repos, repo Show repository details
|
||||
HELPERS:
|
||||
open, o Open something of the repository in web browser
|
||||
notifications, notification, n Show notifications
|
||||
SETUP:
|
||||
logins, login Log in to a Gitea server
|
||||
logout Log out from a Gitea server
|
||||
shellcompletion, autocomplete Install shell completion for tea
|
||||
|
||||
OPTIONS
|
||||
--help, -h show help (default: false)
|
||||
--version, -v print the version (default: false)
|
||||
|
||||
EXAMPLES
|
||||
tea login add # add a login once to get started
|
||||
|
||||
tea pulls # list open pulls for the repo in $PWD
|
||||
tea pulls --repo $HOME/foo # list open pulls for the repo in $HOME/foo
|
||||
tea pulls --remote upstream # list open pulls for the repo pointed at by
|
||||
# your local "upstream" git remote
|
||||
# list open pulls for any gitea repo at the given login instance
|
||||
tea pulls --repo gitea/tea --login gitea.com
|
||||
|
||||
tea milestone issues 0.7.0 # view open issues for milestone '0.7.0'
|
||||
tea issue 189 # view contents of issue 189
|
||||
tea open 189 # open web ui for issue 189
|
||||
tea open milestones # open web ui for milestones
|
||||
|
||||
# send gitea desktop notifications every 5 minutes (bash + libnotify)
|
||||
while :; do tea notifications --all -o simple | xargs -i notify-send {}; sleep 300; done
|
||||
|
||||
ABOUT
|
||||
Written & maintained by The Gitea Authors.
|
||||
If you find a bug or want to contribute, we'll welcome you at https://gitea.com/gitea/tea.
|
||||
More info about Gitea itself on https://gitea.io.
|
||||
```
|
||||
|
||||
- [Compare features with other git forge CLIs](./FEATURE-COMPARISON.md)
|
||||
- tea uses [code.gitea.io/sdk](https://code.gitea.io/sdk) and interacts with the Gitea API.
|
||||
|
||||
## Installation
|
||||
|
||||
You can use the prebuilt binaries from [dl.gitea.io](https://dl.gitea.io/tea/)
|
||||
There are different ways to get `tea`:
|
||||
|
||||
To install from source, go 1.13 or newer is required:
|
||||
1. Install via your system package manager:
|
||||
- macOS via `brew` (gitea-maintained):
|
||||
```sh
|
||||
brew tap gitea/tap https://gitea.com/gitea/homebrew-gitea
|
||||
brew install tea
|
||||
```
|
||||
- arch linux ([gitea-tea](https://aur.archlinux.org/packages/gitea-tea), thirdparty)
|
||||
- alpine linux ([tea](https://pkgs.alpinelinux.org/packages?name=tea&branch=edge), thirdparty)
|
||||
|
||||
```sh
|
||||
go get code.gitea.io/tea
|
||||
go install code.gitea.io/tea
|
||||
```
|
||||
2. Use the prebuilt binaries from [dl.gitea.io](https://dl.gitea.io/tea/)
|
||||
|
||||
If you have `brew` installed, you can install `tea` via:
|
||||
3. Install from source (go 1.13 or newer is required):
|
||||
```sh
|
||||
go get code.gitea.io/tea
|
||||
go install code.gitea.io/tea
|
||||
```
|
||||
|
||||
```sh
|
||||
brew tap gitea/tap https://gitea.com/gitea/homebrew-gitea
|
||||
brew install tea
|
||||
```
|
||||
|
||||
Distribution packages exist for: **alpinelinux ([tea](https://pkgs.alpinelinux.org/packages?name=tea&branch=edge))** and **archlinux ([gitea-tea](https://aur.archlinux.org/packages/gitea-tea))**
|
||||
|
||||
|
||||
Shell completion can be added via `tea autocomplete --install`.
|
||||
|
||||
## Usage
|
||||
|
||||
First of all, you have to create a token on your `personal settings -> application` page of your gitea instance.
|
||||
Use this token to login with `tea`:
|
||||
|
||||
```sh
|
||||
tea login add --name=try --url=https://try.gitea.io --token=xxxxxx
|
||||
```
|
||||
|
||||
Now you can use the following `tea` subcommands.
|
||||
Detailed usage information is available via `tea <command> --help`.
|
||||
|
||||
```none
|
||||
login Log in to a Gitea server
|
||||
logout Log out from a Gitea server
|
||||
issues List, create and update issues
|
||||
pulls List, create, checkout and clean pull requests
|
||||
releases List, create, update and delete releases
|
||||
repos Operate with repositories
|
||||
labels Manage issue labels
|
||||
times Operate on tracked times of a repositorys issues and pulls
|
||||
open Open something of the repository on web browser
|
||||
notifications Show notifications
|
||||
milestones List and create milestones
|
||||
organizations List, create, delete organizations
|
||||
help, h Shows a list of commands or help for one command
|
||||
```
|
||||
|
||||
To fetch issues from different repos, use the `--remote` flag (when inside a gitea repository directory) or `--login` & `--repo` flags.
|
||||
4. Docker (thirdparty): [tgerczei/tea](https://hub.docker.com/r/tgerczei/tea)
|
||||
|
||||
## Compilation
|
||||
|
||||
|
|
|
@ -19,9 +19,10 @@ import (
|
|||
var CmdAutocomplete = cli.Command{
|
||||
Name: "shellcompletion",
|
||||
Aliases: []string{"autocomplete"},
|
||||
Category: catSetup,
|
||||
Usage: "Install shell completion for tea",
|
||||
Description: "Install shell completion for tea",
|
||||
ArgsUsage: "<shell type> (bash, zsh, powershell)",
|
||||
ArgsUsage: "<shell type> (bash, zsh, powershell, fish)",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "install",
|
||||
|
@ -39,20 +40,26 @@ func runAutocompleteAdd(ctx *cli.Context) error {
|
|||
case "zsh":
|
||||
remoteFile = "contrib/autocomplete.zsh"
|
||||
localFile = "autocomplete.zsh"
|
||||
cmds = "echo 'PROG=tea _CLI_ZSH_AUTOCOMPLETE_HACK=1 source %s' >> ~/.zshrc && source ~/.zshrc"
|
||||
cmds = "echo 'PROG=tea _CLI_ZSH_AUTOCOMPLETE_HACK=1 source \"%s\"' >> ~/.zshrc && source ~/.zshrc"
|
||||
|
||||
case "bash":
|
||||
remoteFile = "contrib/autocomplete.sh"
|
||||
localFile = "autocomplete.sh"
|
||||
cmds = "echo 'PROG=tea source %s' >> ~/.bashrc && source ~/.bashrc"
|
||||
cmds = "echo 'PROG=tea source \"%s\"' >> ~/.bashrc && source ~/.bashrc"
|
||||
|
||||
case "powershell":
|
||||
remoteFile = "contrib/autocomplete.ps1"
|
||||
localFile = "tea.ps1"
|
||||
cmds = "\"& %s\" >> $profile"
|
||||
|
||||
case "fish":
|
||||
// fish is different, in that urfave/cli provides a generator for the shell script needed.
|
||||
// this also means that the fish completion can become out of sync with the tea binary!
|
||||
// writing to this directory suffices, as fish reads files there on startup, no cmds needed.
|
||||
return writeFishAutoCompleteFile(ctx)
|
||||
|
||||
default:
|
||||
return fmt.Errorf("Must specify valid shell type")
|
||||
return fmt.Errorf("Must specify valid %s", ctx.Command.ArgsUsage)
|
||||
}
|
||||
|
||||
localPath, err := xdg.ConfigFile("tea/" + localFile)
|
||||
|
@ -61,8 +68,7 @@ func runAutocompleteAdd(ctx *cli.Context) error {
|
|||
}
|
||||
|
||||
cmds = fmt.Sprintf(cmds, localPath)
|
||||
|
||||
if err := saveAutoCompleteFile(remoteFile, localPath); err != nil {
|
||||
if err = writeRemoteAutoCompleteFile(remoteFile, localPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -84,7 +90,7 @@ func runAutocompleteAdd(ctx *cli.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func saveAutoCompleteFile(file, destPath string) error {
|
||||
func writeRemoteAutoCompleteFile(file, destPath string) error {
|
||||
url := fmt.Sprintf("https://gitea.com/gitea/tea/raw/branch/master/%s", file)
|
||||
fmt.Println("Fetching " + url)
|
||||
|
||||
|
@ -103,3 +109,30 @@ func saveAutoCompleteFile(file, destPath string) error {
|
|||
_, err = io.Copy(writer, res.Body)
|
||||
return err
|
||||
}
|
||||
|
||||
func writeFishAutoCompleteFile(ctx *cli.Context) error {
|
||||
// NOTE: to make sure this file is in sync with tea commands, we'd need to
|
||||
// - check if the file exists
|
||||
// - if it does, check if the tea version that wrote it is the currently running version
|
||||
// - if not, rewrite the file
|
||||
// on each application run
|
||||
// NOTE: this generates a completion that also suggests file names, which looks kinda messy..
|
||||
script, err := ctx.App.ToFishCompletion()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
localPath, err := xdg.ConfigFile("fish/conf.d/tea_completion.fish")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
writer, err := os.Create(localPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = io.WriteString(writer, script); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Installed tab completion to %s\n", localPath)
|
||||
return nil
|
||||
}
|
||||
|
|
11
cmd/categories.go
Normal file
11
cmd/categories.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cmd
|
||||
|
||||
var (
|
||||
catSetup = "SETUP"
|
||||
catEntities = "ENTITIES"
|
||||
catHelpers = "HELPERS"
|
||||
)
|
77
cmd/comment.go
Normal file
77
cmd/comment.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/tea/modules/interact"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// CmdAddComment is the main command to operate with notifications
|
||||
var CmdAddComment = cli.Command{
|
||||
Name: "comment",
|
||||
Aliases: []string{"c"},
|
||||
Category: catEntities,
|
||||
Usage: "Add a comment to an issue / pr",
|
||||
Description: "Add a comment to an issue / pr",
|
||||
ArgsUsage: "<issue / pr index> [<comment body>]",
|
||||
Action: runAddComment,
|
||||
Flags: flags.AllDefaultFlags,
|
||||
}
|
||||
|
||||
func runAddComment(cmd *cli.Context) error {
|
||||
ctx := context.InitCommand(cmd)
|
||||
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
|
||||
|
||||
args := ctx.Args()
|
||||
if args.Len() == 0 {
|
||||
return fmt.Errorf("Please specify issue / pr index")
|
||||
}
|
||||
|
||||
idx, err := utils.ArgToIndex(ctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
body := strings.Join(ctx.Args().Tail(), " ")
|
||||
if interact.IsStdinPiped() {
|
||||
// custom solution until https://github.com/AlecAivazis/survey/issues/328 is fixed
|
||||
if bodyStdin, err := ioutil.ReadAll(ctx.App.Reader); err != nil {
|
||||
return err
|
||||
} else if len(bodyStdin) != 0 {
|
||||
body = strings.Join([]string{body, string(bodyStdin)}, "\n\n")
|
||||
}
|
||||
} else if len(body) == 0 {
|
||||
if body, err = interact.PromptMultiline("Content"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if len(body) == 0 {
|
||||
return fmt.Errorf("No comment body provided")
|
||||
}
|
||||
|
||||
client := ctx.Login.Client()
|
||||
comment, _, err := client.CreateIssueComment(ctx.Owner, ctx.Repo, idx, gitea.CreateIssueCommentOption{
|
||||
Body: body,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
print.Comment(comment)
|
||||
|
||||
return nil
|
||||
}
|
|
@ -5,6 +5,15 @@
|
|||
package flags
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
"github.com/araddon/dateparse"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
@ -102,3 +111,106 @@ var NotificationFlags = append([]cli.Flag{
|
|||
&PaginationPageFlag,
|
||||
&PaginationLimitFlag,
|
||||
}, AllDefaultFlags...)
|
||||
|
||||
// IssuePREditFlags defines flags for properties of issues and PRs
|
||||
var IssuePREditFlags = append([]cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "title",
|
||||
Aliases: []string{"t"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "description",
|
||||
Aliases: []string{"d"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "assignees",
|
||||
Aliases: []string{"a"},
|
||||
Usage: "Comma-separated list of usernames to assign",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "labels",
|
||||
Aliases: []string{"L"},
|
||||
Usage: "Comma-separated list of labels to assign",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "deadline",
|
||||
Aliases: []string{"D"},
|
||||
Usage: "Deadline timestamp to assign",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "milestone",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Milestone to assign",
|
||||
},
|
||||
}, LoginRepoFlags...)
|
||||
|
||||
// GetIssuePREditFlags parses all IssuePREditFlags
|
||||
func GetIssuePREditFlags(ctx *context.TeaContext) (*gitea.CreateIssueOption, error) {
|
||||
opts := gitea.CreateIssueOption{
|
||||
Title: ctx.String("title"),
|
||||
Body: ctx.String("description"),
|
||||
Assignees: strings.Split(ctx.String("assignees"), ","),
|
||||
}
|
||||
var err error
|
||||
|
||||
date := ctx.String("deadline")
|
||||
if date != "" {
|
||||
t, err := dateparse.ParseAny(date)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
opts.Deadline = &t
|
||||
}
|
||||
|
||||
client := ctx.Login.Client()
|
||||
|
||||
labelNames := strings.Split(ctx.String("labels"), ",")
|
||||
if len(labelNames) != 0 {
|
||||
if client == nil {
|
||||
client = ctx.Login.Client()
|
||||
}
|
||||
if opts.Labels, err = task.ResolveLabelNames(client, ctx.Owner, ctx.Repo, labelNames); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if milestoneName := ctx.String("milestone"); len(milestoneName) != 0 {
|
||||
if client == nil {
|
||||
client = ctx.Login.Client()
|
||||
}
|
||||
ms, _, err := client.GetMilestoneByName(ctx.Owner, ctx.Repo, milestoneName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Milestone '%s' not found", milestoneName)
|
||||
}
|
||||
opts.Milestone = ms.ID
|
||||
}
|
||||
|
||||
return &opts, nil
|
||||
}
|
||||
|
||||
// FieldsFlag generates a flag selecting printable fields.
|
||||
// To retrieve the value, use GetFields()
|
||||
func FieldsFlag(availableFields, defaultFields []string) *cli.StringFlag {
|
||||
return &cli.StringFlag{
|
||||
Name: "fields",
|
||||
Aliases: []string{"f"},
|
||||
Usage: fmt.Sprintf(`Comma-separated list of fields to print. Available values:
|
||||
%s
|
||||
`, strings.Join(availableFields, ",")),
|
||||
Value: strings.Join(defaultFields, ","),
|
||||
}
|
||||
}
|
||||
|
||||
// GetFields parses the values provided in a fields flag, and
|
||||
// optionally validates against valid values.
|
||||
func GetFields(ctx *cli.Context, validFields []string) ([]string, error) {
|
||||
selection := strings.Split(ctx.String("fields"), ",")
|
||||
if validFields != nil {
|
||||
for _, field := range selection {
|
||||
if !utils.Contains(validFields, field) {
|
||||
return nil, fmt.Errorf("Invalid field '%s'", field)
|
||||
}
|
||||
}
|
||||
}
|
||||
return selection, nil
|
||||
}
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/tea/cmd/issues"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/interact"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
|
@ -18,8 +20,9 @@ import (
|
|||
var CmdIssues = cli.Command{
|
||||
Name: "issues",
|
||||
Aliases: []string{"issue", "i"},
|
||||
Category: catEntities,
|
||||
Usage: "List, create and update issues",
|
||||
Description: "List, create and update issues",
|
||||
Description: `Lists issues when called without argument. If issue index is provided, will show it in detail.`,
|
||||
ArgsUsage: "[<issue index>]",
|
||||
Action: runIssues,
|
||||
Subcommands: []*cli.Command{
|
||||
|
@ -28,7 +31,12 @@ var CmdIssues = cli.Command{
|
|||
&issues.CmdIssuesReopen,
|
||||
&issues.CmdIssuesClose,
|
||||
},
|
||||
Flags: flags.IssuePRFlags,
|
||||
Flags: append([]cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "comments",
|
||||
Usage: "Wether to display comments (will prompt if not provided & run interactively)",
|
||||
},
|
||||
}, issues.CmdIssuesList.Flags...),
|
||||
}
|
||||
|
||||
func runIssues(ctx *cli.Context) error {
|
||||
|
@ -51,5 +59,13 @@ func runIssueDetail(cmd *cli.Context, index string) error {
|
|||
return err
|
||||
}
|
||||
print.IssueDetails(issue)
|
||||
|
||||
if issue.Comments > 0 {
|
||||
err = interact.ShowCommentsMaybeInteractive(ctx, idx, issue.Comments)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading comments: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -20,18 +20,7 @@ var CmdIssuesCreate = cli.Command{
|
|||
Usage: "Create an issue on repository",
|
||||
Description: `Create an issue on repository`,
|
||||
Action: runIssuesCreate,
|
||||
Flags: append([]cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "title",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "issue title to create",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "body",
|
||||
Aliases: []string{"b"},
|
||||
Usage: "issue body to create",
|
||||
},
|
||||
}, flags.LoginRepoFlags...),
|
||||
Flags: flags.IssuePREditFlags,
|
||||
}
|
||||
|
||||
func runIssuesCreate(cmd *cli.Context) error {
|
||||
|
@ -42,11 +31,15 @@ func runIssuesCreate(cmd *cli.Context) error {
|
|||
return interact.CreateIssue(ctx.Login, ctx.Owner, ctx.Repo)
|
||||
}
|
||||
|
||||
opts, err := flags.GetIssuePREditFlags(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.CreateIssue(
|
||||
ctx.Login,
|
||||
ctx.Owner,
|
||||
ctx.Repo,
|
||||
ctx.String("title"),
|
||||
ctx.String("body"),
|
||||
*opts,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,7 +20,11 @@ var CmdIssuesList = cli.Command{
|
|||
Usage: "List issues of the repository",
|
||||
Description: `List issues of the repository`,
|
||||
Action: RunIssuesList,
|
||||
Flags: flags.IssuePRFlags,
|
||||
Flags: append([]cli.Flag{
|
||||
flags.FieldsFlag(print.IssueFields, []string{
|
||||
"index", "title", "state", "author", "milestone", "labels",
|
||||
}),
|
||||
}, flags.IssuePRFlags...),
|
||||
}
|
||||
|
||||
// RunIssuesList list issues
|
||||
|
@ -48,6 +52,11 @@ func RunIssuesList(cmd *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
print.IssuesList(issues, ctx.Output)
|
||||
fields, err := flags.GetFields(cmd, print.IssueFields)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
print.IssuesPullsList(issues, ctx.Output, fields)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
var CmdLabels = cli.Command{
|
||||
Name: "labels",
|
||||
Aliases: []string{"label"},
|
||||
Category: catEntities,
|
||||
Usage: "Manage issue labels",
|
||||
Description: `Manage issue labels`,
|
||||
Action: runLabels,
|
||||
|
@ -24,6 +25,7 @@ var CmdLabels = cli.Command{
|
|||
&labels.CmdLabelUpdate,
|
||||
&labels.CmdLabelDelete,
|
||||
},
|
||||
Flags: labels.CmdLabelsList.Flags,
|
||||
}
|
||||
|
||||
func runLabels(ctx *cli.Context) error {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"os"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
|
@ -23,7 +24,7 @@ var CmdLabelCreate = cli.Command{
|
|||
Usage: "Create a label",
|
||||
Description: `Create a label`,
|
||||
Action: runLabelCreate,
|
||||
Flags: []cli.Flag{
|
||||
Flags: append([]cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "name",
|
||||
Usage: "label name",
|
||||
|
@ -40,7 +41,7 @@ var CmdLabelCreate = cli.Command{
|
|||
Name: "file",
|
||||
Usage: "indicate a label file",
|
||||
},
|
||||
},
|
||||
}, flags.AllDefaultFlags...),
|
||||
}
|
||||
|
||||
func runLabelCreate(cmd *cli.Context) error {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package labels
|
||||
|
||||
import (
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
|
@ -17,12 +18,12 @@ var CmdLabelDelete = cli.Command{
|
|||
Usage: "Delete a label",
|
||||
Description: `Delete a label`,
|
||||
Action: runLabelDelete,
|
||||
Flags: []cli.Flag{
|
||||
Flags: append([]cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "id",
|
||||
Usage: "label id",
|
||||
},
|
||||
},
|
||||
}, flags.AllDefaultFlags...),
|
||||
}
|
||||
|
||||
func runLabelDelete(cmd *cli.Context) error {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package labels
|
||||
|
||||
import (
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
|
@ -17,7 +18,7 @@ var CmdLabelUpdate = cli.Command{
|
|||
Usage: "Update a label",
|
||||
Description: `Update a label`,
|
||||
Action: runLabelUpdate,
|
||||
Flags: []cli.Flag{
|
||||
Flags: append([]cli.Flag{
|
||||
&cli.IntFlag{
|
||||
Name: "id",
|
||||
Usage: "label id",
|
||||
|
@ -34,7 +35,7 @@ var CmdLabelUpdate = cli.Command{
|
|||
Name: "description",
|
||||
Usage: "label description",
|
||||
},
|
||||
},
|
||||
}, flags.AllDefaultFlags...),
|
||||
}
|
||||
|
||||
func runLabelUpdate(cmd *cli.Context) error {
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
var CmdLogin = cli.Command{
|
||||
Name: "logins",
|
||||
Aliases: []string{"login"},
|
||||
Category: catSetup,
|
||||
Usage: "Log in to a Gitea server",
|
||||
Description: `Log in to a Gitea server`,
|
||||
ArgsUsage: "[<login name>]",
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
// CmdLogout represents to logout a gitea server.
|
||||
var CmdLogout = cli.Command{
|
||||
Name: "logout",
|
||||
Category: catSetup,
|
||||
Usage: "Log out from a Gitea server",
|
||||
Description: `Log out from a Gitea server`,
|
||||
ArgsUsage: "<login name>",
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/cmd/milestones"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
|
@ -17,6 +16,7 @@ import (
|
|||
var CmdMilestones = cli.Command{
|
||||
Name: "milestones",
|
||||
Aliases: []string{"milestone", "ms"},
|
||||
Category: catEntities,
|
||||
Usage: "List and create milestones",
|
||||
Description: `List and create milestones`,
|
||||
ArgsUsage: "[<milestone name>]",
|
||||
|
@ -29,7 +29,7 @@ var CmdMilestones = cli.Command{
|
|||
&milestones.CmdMilestonesReopen,
|
||||
&milestones.CmdMilestonesIssues,
|
||||
},
|
||||
Flags: flags.AllDefaultFlags,
|
||||
Flags: milestones.CmdMilestonesList.Flags,
|
||||
}
|
||||
|
||||
func runMilestones(ctx *cli.Context) error {
|
||||
|
|
|
@ -5,13 +5,15 @@
|
|||
package milestones
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
"code.gitea.io/tea/modules/interact"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/araddon/dateparse"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
|
@ -33,6 +35,11 @@ var CmdMilestonesCreate = cli.Command{
|
|||
Aliases: []string{"d"},
|
||||
Usage: "milestone description to create",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "deadline",
|
||||
Aliases: []string{"expires", "x"},
|
||||
Usage: "set milestone deadline (default is no due date)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "state",
|
||||
Usage: "set milestone state (default is open)",
|
||||
|
@ -43,12 +50,15 @@ var CmdMilestonesCreate = cli.Command{
|
|||
|
||||
func runMilestonesCreate(cmd *cli.Context) error {
|
||||
ctx := context.InitCommand(cmd)
|
||||
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
|
||||
|
||||
title := ctx.String("title")
|
||||
if len(title) == 0 {
|
||||
fmt.Printf("Title is required\n")
|
||||
return nil
|
||||
date := ctx.String("deadline")
|
||||
deadline := &time.Time{}
|
||||
if date != "" {
|
||||
t, err := dateparse.ParseAny(date)
|
||||
if err == nil {
|
||||
return err
|
||||
}
|
||||
deadline = &t
|
||||
}
|
||||
|
||||
state := gitea.StateOpen
|
||||
|
@ -56,15 +66,17 @@ func runMilestonesCreate(cmd *cli.Context) error {
|
|||
state = gitea.StateClosed
|
||||
}
|
||||
|
||||
mile, _, err := ctx.Login.Client().CreateMilestone(ctx.Owner, ctx.Repo, gitea.CreateMilestoneOption{
|
||||
Title: title,
|
||||
Description: ctx.String("description"),
|
||||
State: state,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
if ctx.NumFlags() == 0 {
|
||||
return interact.CreateMilestone(ctx.Login, ctx.Owner, ctx.Repo)
|
||||
}
|
||||
|
||||
print.MilestoneDetails(mile)
|
||||
return nil
|
||||
return task.CreateMilestone(
|
||||
ctx.Login,
|
||||
ctx.Owner,
|
||||
ctx.Repo,
|
||||
ctx.String("title"),
|
||||
ctx.String("description"),
|
||||
deadline,
|
||||
state,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@ var CmdMilestonesIssues = cli.Command{
|
|||
},
|
||||
&flags.PaginationPageFlag,
|
||||
&flags.PaginationLimitFlag,
|
||||
flags.FieldsFlag(print.IssueFields, []string{
|
||||
"index", "kind", "title", "state", "updated", "labels",
|
||||
}),
|
||||
}, flags.AllDefaultFlags...),
|
||||
}
|
||||
|
||||
|
@ -107,7 +110,11 @@ func runMilestoneIssueList(cmd *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
print.IssuesPullsList(issues, ctx.Output)
|
||||
fields, err := flags.GetFields(cmd, print.IssueFields)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
print.IssuesPullsList(issues, ctx.Output, fields)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
var CmdNotifications = cli.Command{
|
||||
Name: "notifications",
|
||||
Aliases: []string{"notification", "n"},
|
||||
Category: catHelpers,
|
||||
Usage: "Show notifications",
|
||||
Description: "Show notifications, by default based of the current repo",
|
||||
Action: runNotifications,
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
package notifications
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/config"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
|
@ -17,30 +15,28 @@ import (
|
|||
)
|
||||
|
||||
//listNotifications will get the notifications based on status
|
||||
func listNotifications(ctx *cli.Context, status []gitea.NotifyStatus) error {
|
||||
func listNotifications(cmd *cli.Context, status []gitea.NotifyStatus) error {
|
||||
var news []*gitea.NotificationThread
|
||||
var err error
|
||||
|
||||
ctx := context.InitCommand(cmd)
|
||||
client := ctx.Login.Client()
|
||||
all := ctx.Bool("all")
|
||||
|
||||
//This enforces pagination.
|
||||
listOpts := flags.GetListOptions(ctx)
|
||||
listOpts := ctx.GetListOptions()
|
||||
if listOpts.Page == 0 {
|
||||
listOpts.Page = 1
|
||||
}
|
||||
|
||||
var news []*gitea.NotificationThread
|
||||
var err error
|
||||
|
||||
var allRelated = ctx.Bool("all")
|
||||
fmt.Printf("allRelated: %t\n", allRelated)
|
||||
|
||||
login, owner, repo := config.InitCommand(flags.GlobalRepoValue, flags.GlobalLoginValue, flags.GlobalRemoteValue)
|
||||
if allRelated {
|
||||
fmt.Printf("login: %s owner: %s repo:%s\n", login.Name, owner, repo)
|
||||
news, _, err = login.Client().ListNotifications(gitea.ListNotificationOptions{
|
||||
if all {
|
||||
news, _, err = client.ListNotifications(gitea.ListNotificationOptions{
|
||||
ListOptions: listOpts,
|
||||
Status: status,
|
||||
})
|
||||
} else {
|
||||
fmt.Printf("login: %s owner: %s repo:%s\n", login.Name, owner, repo)
|
||||
news, _, err = login.Client().ListRepoNotifications(owner, repo, gitea.ListNotificationOptions{
|
||||
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
|
||||
news, _, err = client.ListRepoNotifications(ctx.Owner, ctx.Repo, gitea.ListNotificationOptions{
|
||||
ListOptions: listOpts,
|
||||
Status: status,
|
||||
})
|
||||
|
@ -49,6 +45,6 @@ func listNotifications(ctx *cli.Context, status []gitea.NotifyStatus) error {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
print.NotificationsList(news, flags.GlobalOutputValue, allRelated)
|
||||
print.NotificationsList(news, ctx.Output, all)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
var CmdOpen = cli.Command{
|
||||
Name: "open",
|
||||
Aliases: []string{"o"},
|
||||
Category: catHelpers,
|
||||
Usage: "Open something of the repository in web browser",
|
||||
Description: `Open something of the repository in web browser`,
|
||||
Action: runOpen,
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
var CmdOrgs = cli.Command{
|
||||
Name: "organizations",
|
||||
Aliases: []string{"organization", "org"},
|
||||
Category: catEntities,
|
||||
Usage: "List, create, delete organizations",
|
||||
Description: "Show organization details",
|
||||
ArgsUsage: "[<organization>]",
|
||||
|
@ -24,6 +25,7 @@ var CmdOrgs = cli.Command{
|
|||
&organizations.CmdOrganizationList,
|
||||
&organizations.CmdOrganizationDelete,
|
||||
},
|
||||
Flags: organizations.CmdOrganizationList.Flags,
|
||||
}
|
||||
|
||||
func runOrganizations(ctx *cli.Context) error {
|
||||
|
|
|
@ -7,6 +7,7 @@ package organizations
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
@ -19,6 +20,10 @@ var CmdOrganizationDelete = cli.Command{
|
|||
Description: "Delete users organizations",
|
||||
ArgsUsage: "<organization name>",
|
||||
Action: RunOrganizationDelete,
|
||||
Flags: []cli.Flag{
|
||||
&flags.LoginFlag,
|
||||
&flags.RemoteFlag,
|
||||
},
|
||||
}
|
||||
|
||||
// RunOrganizationDelete delete user organization
|
||||
|
|
32
cmd/pulls.go
32
cmd/pulls.go
|
@ -7,11 +7,12 @@ package cmd
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/cmd/pulls"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/interact"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
"code.gitea.io/tea/modules/workaround"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
@ -21,16 +22,28 @@ import (
|
|||
var CmdPulls = cli.Command{
|
||||
Name: "pulls",
|
||||
Aliases: []string{"pull", "pr"},
|
||||
Usage: "List, create, checkout and clean pull requests",
|
||||
Description: `List, create, checkout and clean pull requests`,
|
||||
Category: catEntities,
|
||||
Usage: "Manage and checkout pull requests",
|
||||
Description: `Lists PRs when called without argument. If PR index is provided, will show it in detail.`,
|
||||
ArgsUsage: "[<pull index>]",
|
||||
Action: runPulls,
|
||||
Flags: flags.IssuePRFlags,
|
||||
Flags: append([]cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "comments",
|
||||
Usage: "Wether to display comments (will prompt if not provided & run interactively)",
|
||||
},
|
||||
}, pulls.CmdPullsList.Flags...),
|
||||
Subcommands: []*cli.Command{
|
||||
&pulls.CmdPullsList,
|
||||
&pulls.CmdPullsCheckout,
|
||||
&pulls.CmdPullsClean,
|
||||
&pulls.CmdPullsCreate,
|
||||
&pulls.CmdPullsClose,
|
||||
&pulls.CmdPullsReopen,
|
||||
&pulls.CmdPullsReview,
|
||||
&pulls.CmdPullsApprove,
|
||||
&pulls.CmdPullsReject,
|
||||
&pulls.CmdPullsMerge,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -54,6 +67,9 @@ func runPullDetail(cmd *cli.Context, index string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := workaround.FixPullHeadSha(client, pr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
reviews, _, err := client.ListPullReviews(ctx.Owner, ctx.Repo, idx, gitea.ListPullReviewsOptions{})
|
||||
if err != nil {
|
||||
|
@ -66,5 +82,13 @@ func runPullDetail(cmd *cli.Context, index string) error {
|
|||
}
|
||||
|
||||
print.PullDetails(pr, reviews, ci)
|
||||
|
||||
if pr.Comments > 0 {
|
||||
err = interact.ShowCommentsMaybeInteractive(ctx, idx, pr.Comments)
|
||||
if err != nil {
|
||||
fmt.Printf("error loading comments: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
45
cmd/pulls/approve.go
Normal file
45
cmd/pulls/approve.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pulls
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// CmdPullsApprove approves a PR
|
||||
var CmdPullsApprove = cli.Command{
|
||||
Name: "approve",
|
||||
Aliases: []string{"lgtm", "a"},
|
||||
Usage: "Approve a pull request",
|
||||
Description: "Approve a pull request",
|
||||
ArgsUsage: "<pull index> [<comment>]",
|
||||
Action: func(cmd *cli.Context) error {
|
||||
ctx := context.InitCommand(cmd)
|
||||
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
|
||||
|
||||
if ctx.Args().Len() == 0 {
|
||||
return fmt.Errorf("Must specify a PR index")
|
||||
}
|
||||
|
||||
idx, err := utils.ArgToIndex(ctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
comment := strings.Join(ctx.Args().Tail(), " ")
|
||||
|
||||
return task.CreatePullReview(ctx, idx, gitea.ReviewStateApproved, comment, nil)
|
||||
},
|
||||
Flags: flags.AllDefaultFlags,
|
||||
}
|
|
@ -24,7 +24,13 @@ var CmdPullsCheckout = cli.Command{
|
|||
Description: `Locally check out the given PR`,
|
||||
Action: runPullsCheckout,
|
||||
ArgsUsage: "<pull index>",
|
||||
Flags: flags.AllDefaultFlags,
|
||||
Flags: append([]cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "branch",
|
||||
Aliases: []string{"b"},
|
||||
Usage: "Create a local branch if it doesn't exist yet",
|
||||
},
|
||||
}, flags.AllDefaultFlags...),
|
||||
}
|
||||
|
||||
func runPullsCheckout(cmd *cli.Context) error {
|
||||
|
@ -38,5 +44,5 @@ func runPullsCheckout(cmd *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return task.PullCheckout(ctx.Login, ctx.Owner, ctx.Repo, idx, interact.PromptPassword)
|
||||
return task.PullCheckout(ctx.Login, ctx.Owner, ctx.Repo, ctx.Bool("branch"), idx, interact.PromptPassword)
|
||||
}
|
||||
|
|
25
cmd/pulls/close.go
Normal file
25
cmd/pulls/close.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pulls
|
||||
|
||||
import (
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// CmdPullsClose closes a given open pull request
|
||||
var CmdPullsClose = cli.Command{
|
||||
Name: "close",
|
||||
Usage: "Change state of a pull request to 'closed'",
|
||||
Description: `Change state of a pull request to 'closed'`,
|
||||
ArgsUsage: "<pull index>",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
var s = gitea.StateClosed
|
||||
return editPullState(ctx, gitea.EditPullRequestOption{State: &s})
|
||||
},
|
||||
Flags: flags.AllDefaultFlags,
|
||||
}
|
|
@ -30,17 +30,7 @@ var CmdPullsCreate = cli.Command{
|
|||
Aliases: []string{"b"},
|
||||
Usage: "Set base branch (default is default branch)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "title",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "Set title of pull (default is head branch name)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "description",
|
||||
Aliases: []string{"d"},
|
||||
Usage: "Set body of new pull",
|
||||
},
|
||||
}, flags.AllDefaultFlags...),
|
||||
}, flags.IssuePREditFlags...),
|
||||
}
|
||||
|
||||
func runPullsCreate(cmd *cli.Context) error {
|
||||
|
@ -53,13 +43,17 @@ func runPullsCreate(cmd *cli.Context) error {
|
|||
}
|
||||
|
||||
// else use args to create PR
|
||||
opts, err := flags.GetIssuePREditFlags(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.CreatePull(
|
||||
ctx.Login,
|
||||
ctx.Owner,
|
||||
ctx.Repo,
|
||||
ctx.String("base"),
|
||||
ctx.String("head"),
|
||||
ctx.String("title"),
|
||||
ctx.String("description"),
|
||||
opts,
|
||||
)
|
||||
}
|
||||
|
|
38
cmd/pulls/edit.go
Normal file
38
cmd/pulls/edit.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pulls
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// editPullState abstracts the arg parsing to edit the given pull request
|
||||
func editPullState(cmd *cli.Context, opts gitea.EditPullRequestOption) error {
|
||||
ctx := context.InitCommand(cmd)
|
||||
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
|
||||
if ctx.Args().Len() == 0 {
|
||||
return fmt.Errorf("Please provide a Pull Request index")
|
||||
}
|
||||
|
||||
index, err := utils.ArgToIndex(ctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pr, _, err := ctx.Login.Client().EditPullRequest(ctx.Owner, ctx.Repo, index, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
print.PullDetails(pr, nil, nil)
|
||||
return nil
|
||||
}
|
70
cmd/pulls/merge.go
Normal file
70
cmd/pulls/merge.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pulls
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// CmdPullsMerge merges a PR
|
||||
var CmdPullsMerge = cli.Command{
|
||||
Name: "merge",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Merge a pull request",
|
||||
Description: "Merge a pull request",
|
||||
ArgsUsage: "<pull index>",
|
||||
Flags: append([]cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "style",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "Kind of merge to perform: merge, rebase, squash, rebase-merge",
|
||||
Value: "merge",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "title",
|
||||
Aliases: []string{"t"},
|
||||
Usage: "Merge commit title",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "message",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Merge commit message",
|
||||
},
|
||||
}, flags.AllDefaultFlags...),
|
||||
Action: func(cmd *cli.Context) error {
|
||||
ctx := context.InitCommand(cmd)
|
||||
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
|
||||
|
||||
if ctx.Args().Len() != 1 {
|
||||
return fmt.Errorf("Must specify a PR index")
|
||||
}
|
||||
|
||||
idx, err := utils.ArgToIndex(ctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
success, _, err := ctx.Login.Client().MergePullRequest(ctx.Owner, ctx.Repo, idx, gitea.MergePullRequestOption{
|
||||
Style: gitea.MergeStyle(ctx.String("style")),
|
||||
Title: ctx.String("title"),
|
||||
Message: ctx.String("message"),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !success {
|
||||
return fmt.Errorf("Failed to merge PR. Is it still open?")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
44
cmd/pulls/reject.go
Normal file
44
cmd/pulls/reject.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pulls
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// CmdPullsReject requests changes to a PR
|
||||
var CmdPullsReject = cli.Command{
|
||||
Name: "reject",
|
||||
Usage: "Request changes to a pull request",
|
||||
Description: "Request changes to a pull request",
|
||||
ArgsUsage: "<pull index> <reason>",
|
||||
Action: func(cmd *cli.Context) error {
|
||||
ctx := context.InitCommand(cmd)
|
||||
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
|
||||
|
||||
if ctx.Args().Len() < 2 {
|
||||
return fmt.Errorf("Must specify a PR index and comment")
|
||||
}
|
||||
|
||||
idx, err := utils.ArgToIndex(ctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
comment := strings.Join(ctx.Args().Tail(), " ")
|
||||
|
||||
return task.CreatePullReview(ctx, idx, gitea.ReviewStateRequestChanges, comment, nil)
|
||||
},
|
||||
Flags: flags.AllDefaultFlags,
|
||||
}
|
26
cmd/pulls/reopen.go
Normal file
26
cmd/pulls/reopen.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pulls
|
||||
|
||||
import (
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// CmdPullsReopen reopens a given closed pull request
|
||||
var CmdPullsReopen = cli.Command{
|
||||
Name: "reopen",
|
||||
Aliases: []string{"open"},
|
||||
Usage: "Change state of a pull request to 'open'",
|
||||
Description: `Change state of a pull request to 'open'`,
|
||||
ArgsUsage: "<pull index>",
|
||||
Action: func(ctx *cli.Context) error {
|
||||
var s = gitea.StateOpen
|
||||
return editPullState(ctx, gitea.EditPullRequestOption{State: &s})
|
||||
},
|
||||
Flags: flags.AllDefaultFlags,
|
||||
}
|
40
cmd/pulls/review.go
Normal file
40
cmd/pulls/review.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package pulls
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/tea/cmd/flags"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/interact"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// CmdPullsReview starts an interactive review session
|
||||
var CmdPullsReview = cli.Command{
|
||||
Name: "review",
|
||||
Usage: "Interactively review a pull request",
|
||||
Description: "Interactively review a pull request",
|
||||
ArgsUsage: "<pull index>",
|
||||
Action: func(cmd *cli.Context) error {
|
||||
ctx := context.InitCommand(cmd)
|
||||
ctx.Ensure(context.CtxRequirement{RemoteRepo: true})
|
||||
|
||||
if ctx.Args().Len() != 1 {
|
||||
return fmt.Errorf("Must specify a PR index")
|
||||
}
|
||||
|
||||
idx, err := utils.ArgToIndex(ctx.Args().First())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return interact.ReviewPull(ctx, idx)
|
||||
},
|
||||
Flags: flags.AllDefaultFlags,
|
||||
}
|
|
@ -16,6 +16,7 @@ import (
|
|||
var CmdReleases = cli.Command{
|
||||
Name: "releases",
|
||||
Aliases: []string{"release", "r"},
|
||||
Category: catEntities,
|
||||
Usage: "Manage releases",
|
||||
Description: "Manage releases",
|
||||
Action: releases.RunReleasesList,
|
||||
|
|
|
@ -64,7 +64,7 @@ func runReleaseDelete(cmd *cli.Context) error {
|
|||
}
|
||||
|
||||
if ctx.Bool("delete-tag") {
|
||||
_, err = client.DeleteReleaseTag(ctx.Owner, ctx.Repo, tag)
|
||||
_, err = client.DeleteTag(ctx.Owner, ctx.Repo, tag)
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import (
|
|||
var CmdRepos = cli.Command{
|
||||
Name: "repos",
|
||||
Aliases: []string{"repo"},
|
||||
Category: catEntities,
|
||||
Usage: "Show repository details",
|
||||
Description: "Show repository details",
|
||||
ArgsUsage: "[<repo owner>/<repo name>]",
|
||||
|
|
|
@ -6,28 +6,11 @@ package repos
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/tea/modules/print"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
// printFieldsFlag provides a selection of fields to print
|
||||
var printFieldsFlag = cli.StringFlag{
|
||||
Name: "fields",
|
||||
Aliases: []string{"f"},
|
||||
Usage: fmt.Sprintf(`Comma-separated list of fields to print. Available values:
|
||||
%s
|
||||
`, strings.Join(print.RepoFields, ",")),
|
||||
Value: "owner,name,type,ssh",
|
||||
}
|
||||
|
||||
func getFields(ctx *cli.Context) []string {
|
||||
return strings.Split(ctx.String("fields"), ",")
|
||||
}
|
||||
|
||||
var typeFilterFlag = cli.StringFlag{
|
||||
Name: "type",
|
||||
Aliases: []string{"T"},
|
||||
|
|
|
@ -27,7 +27,9 @@ var CmdReposListFlags = append([]cli.Flag{
|
|||
Required: false,
|
||||
Usage: "List your starred repos instead",
|
||||
},
|
||||
&printFieldsFlag,
|
||||
flags.FieldsFlag(print.RepoFields, []string{
|
||||
"owner", "name", "type", "ssh",
|
||||
}),
|
||||
&typeFilterFlag,
|
||||
&flags.PaginationPageFlag,
|
||||
&flags.PaginationLimitFlag,
|
||||
|
@ -80,7 +82,12 @@ func RunReposList(cmd *cli.Context) error {
|
|||
reposFiltered = filterReposByType(rps, typeFilter)
|
||||
}
|
||||
|
||||
print.ReposList(reposFiltered, ctx.Output, getFields(cmd))
|
||||
fields, err := flags.GetFields(cmd, print.RepoFields)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
print.ReposList(reposFiltered, ctx.Output, fields)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,9 @@ var CmdReposSearch = cli.Command{
|
|||
Required: false,
|
||||
Usage: "Filter archived repos (true|false)",
|
||||
},
|
||||
&printFieldsFlag,
|
||||
flags.FieldsFlag(print.RepoFields, []string{
|
||||
"owner", "name", "type", "ssh",
|
||||
}),
|
||||
&flags.PaginationPageFlag,
|
||||
&flags.PaginationLimitFlag,
|
||||
}, flags.LoginOutputFlags...),
|
||||
|
@ -123,6 +125,10 @@ func runReposSearch(cmd *cli.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
print.ReposList(rps, ctx.Output, getFields(cmd))
|
||||
fields, err := flags.GetFields(cmd, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
print.ReposList(rps, ctx.Output, fields)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -11,9 +11,10 @@ import (
|
|||
|
||||
// CmdTrackedTimes represents the command to operate repositories' times.
|
||||
var CmdTrackedTimes = cli.Command{
|
||||
Name: "times",
|
||||
Aliases: []string{"time", "t"},
|
||||
Usage: "Operate on tracked times of a repository's issues & pulls",
|
||||
Name: "times",
|
||||
Aliases: []string{"time", "t"},
|
||||
Category: catEntities,
|
||||
Usage: "Operate on tracked times of a repository's issues & pulls",
|
||||
Description: `Operate on tracked times of a repository's issues & pulls.
|
||||
Depending on your permissions on the repository, only your own tracked
|
||||
times might be listed.`,
|
||||
|
@ -25,4 +26,5 @@ var CmdTrackedTimes = cli.Command{
|
|||
×.CmdTrackedTimesReset,
|
||||
×.CmdTrackedTimesList,
|
||||
},
|
||||
Flags: times.CmdTrackedTimesList.Flags,
|
||||
}
|
||||
|
|
|
@ -24,10 +24,12 @@ var CmdTrackedTimesList = cli.Command{
|
|||
Name: "list",
|
||||
Aliases: []string{"ls"},
|
||||
Action: RunTimesList,
|
||||
Usage: "Operate on tracked times of a repository's issues & pulls",
|
||||
Description: `Operate on tracked times of a repository's issues & pulls.
|
||||
Depending on your permissions on the repository, only your own tracked
|
||||
times might be listed.`,
|
||||
Usage: "List tracked times on issues & pulls",
|
||||
Description: `List tracked times, across repos, or on a single repo or issue:
|
||||
- given a username all times on a repo by that user are shown,
|
||||
- given a issue index with '#' prefix, all times on that issue are listed,
|
||||
- given --mine, your times are listed across all repositories.
|
||||
Depending on your permissions on the repository, only your own tracked times might be listed.`,
|
||||
ArgsUsage: "[username | #issue]",
|
||||
|
||||
Flags: append([]cli.Flag{
|
||||
|
@ -46,6 +48,17 @@ var CmdTrackedTimesList = cli.Command{
|
|||
Aliases: []string{"t"},
|
||||
Usage: "Print the total duration at the end",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "mine",
|
||||
Aliases: []string{"m"},
|
||||
Usage: "Show all times tracked by you across all repositories (overrides command arguments)",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "fields",
|
||||
Usage: fmt.Sprintf(`Comma-separated list of fields to print. Available values:
|
||||
%s
|
||||
`, strings.Join(print.TrackedTimeFields, ",")),
|
||||
},
|
||||
}, flags.AllDefaultFlags...),
|
||||
}
|
||||
|
||||
|
@ -57,42 +70,57 @@ func RunTimesList(cmd *cli.Context) error {
|
|||
|
||||
var times []*gitea.TrackedTime
|
||||
var err error
|
||||
|
||||
user := ctx.Args().First()
|
||||
fmt.Println(ctx.Command.ArgsUsage)
|
||||
if user == "" {
|
||||
// get all tracked times on the repo
|
||||
times, _, err = client.GetRepoTrackedTimes(ctx.Owner, ctx.Repo)
|
||||
} else if strings.HasPrefix(user, "#") {
|
||||
// get all tracked times on the specified issue
|
||||
issue, err := utils.ArgToIndex(user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
times, _, err = client.ListTrackedTimes(ctx.Owner, ctx.Repo, issue, gitea.ListTrackedTimesOptions{})
|
||||
} else {
|
||||
// get all tracked times by the specified user
|
||||
times, _, err = client.GetUserTrackedTimes(ctx.Owner, ctx.Repo, user)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var from, until time.Time
|
||||
if ctx.String("from") != "" {
|
||||
var fields []string
|
||||
|
||||
if ctx.IsSet("from") {
|
||||
from, err = dateparse.ParseLocal(ctx.String("from"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if ctx.String("until") != "" {
|
||||
if ctx.IsSet("until") {
|
||||
until, err = dateparse.ParseLocal(ctx.String("until"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
print.TrackedTimesList(times, ctx.Output, from, until, ctx.Bool("total"))
|
||||
opts := gitea.ListTrackedTimesOptions{Since: from, Before: until}
|
||||
|
||||
user := ctx.Args().First()
|
||||
if ctx.Bool("mine") {
|
||||
times, _, err = client.GetMyTrackedTimes()
|
||||
fields = []string{"created", "repo", "issue", "duration"}
|
||||
} else if user == "" {
|
||||
// get all tracked times on the repo
|
||||
times, _, err = client.ListRepoTrackedTimes(ctx.Owner, ctx.Repo, opts)
|
||||
fields = []string{"created", "issue", "user", "duration"}
|
||||
} else if strings.HasPrefix(user, "#") {
|
||||
// get all tracked times on the specified issue
|
||||
issue, err := utils.ArgToIndex(user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
times, _, err = client.ListIssueTrackedTimes(ctx.Owner, ctx.Repo, issue, opts)
|
||||
fields = []string{"created", "user", "duration"}
|
||||
} else {
|
||||
// get all tracked times by the specified user
|
||||
opts.User = user
|
||||
times, _, err = client.ListRepoTrackedTimes(ctx.Owner, ctx.Repo, opts)
|
||||
fields = []string{"created", "issue", "duration"}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if ctx.IsSet("fields") {
|
||||
if fields, err = flags.GetFields(cmd, print.TrackedTimeFields); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
print.TrackedTimesList(times, ctx.Output, fields, ctx.Bool("total"))
|
||||
return nil
|
||||
}
|
||||
|
|
BIN
demo.gif
Normal file
BIN
demo.gif
Normal file
Binary file not shown.
Before Width: | Height: | Size: 621 KiB After Width: | Height: | Size: 621 KiB |
38
go.mod
38
go.mod
|
@ -4,34 +4,36 @@ go 1.13
|
|||
|
||||
require (
|
||||
code.gitea.io/gitea-vet v0.2.1
|
||||
code.gitea.io/sdk/gitea v0.13.1-0.20201209180822-68eec69f472e
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2
|
||||
github.com/Microsoft/go-winio v0.4.15 // indirect
|
||||
github.com/adrg/xdg v0.2.2
|
||||
github.com/alecthomas/chroma v0.8.1 // indirect
|
||||
github.com/araddon/dateparse v0.0.0-20201001162425-8aadafed4dc4
|
||||
code.gitea.io/sdk/gitea v0.15.0
|
||||
gitea.com/noerw/unidiff-comments v0.0.0-20201219085024-64aec5658f2b
|
||||
github.com/AlecAivazis/survey/v2 v2.2.8
|
||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
||||
github.com/adrg/xdg v0.3.1
|
||||
github.com/araddon/dateparse v0.0.0-20210207001429-0eec95c9db7e
|
||||
github.com/charmbracelet/glamour v0.2.0
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.2.0
|
||||
github.com/hashicorp/go-version v1.3.0 // indirect
|
||||
github.com/imdario/mergo v0.3.11 // indirect
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/microcosm-cc/bluemonday v1.0.4 // indirect
|
||||
github.com/muesli/reflow v0.2.0 // indirect
|
||||
github.com/muesli/termenv v0.7.4
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/xanzy/ssh-agent v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 // indirect
|
||||
golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf // indirect
|
||||
golang.org/x/text v0.3.4 // indirect
|
||||
golang.org/x/tools v0.0.0-20201105220310-78b158585360 // indirect
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
|
||||
golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3 // indirect
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect
|
||||
golang.org/x/text v0.3.5 // indirect
|
||||
golang.org/x/tools v0.1.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
replace github.com/charmbracelet/glamour => github.com/noerw/glamour v0.2.1-0.20210305125354-f0a29f1de0c2
|
||||
|
|
125
go.sum
125
go.sum
|
@ -1,24 +1,23 @@
|
|||
code.gitea.io/gitea-vet v0.2.1 h1:b30by7+3SkmiftK0RjuXqFvZg2q4p68uoPGuxhzBN0s=
|
||||
code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
|
||||
code.gitea.io/sdk/gitea v0.13.1-0.20201209180822-68eec69f472e h1:oJOoT5TGbSYRNGUhEiiEz3MqFjU6wELN0/liCZ3RmVg=
|
||||
code.gitea.io/sdk/gitea v0.13.1-0.20201209180822-68eec69f472e/go.mod h1:89WiyOX1KEcvjP66sRHdu0RafojGo60bT9UqW17VbWs=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2 h1:1I4qBrNsHQE+91tQCqVlfrKe9DEL65949d1oKZWVELY=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.2/go.mod h1:9FJRdMdDm8rnT+zHVbvQT2RTSTLq0Ttd6q3Vl2fahjk=
|
||||
code.gitea.io/sdk/gitea v0.15.0 h1:tsNhxDM/2N1Ohv1Xq5UWrht/esg0WmtRj4wsHVHriTg=
|
||||
code.gitea.io/sdk/gitea v0.15.0/go.mod h1:klY2LVI3s3NChzIk/MzMn7G1FHrfU7qd63iSMVoHRBA=
|
||||
gitea.com/noerw/unidiff-comments v0.0.0-20201219085024-64aec5658f2b h1:CLYsMGcGLohESQDMth+RgJ4cB3CCHToxnj0zBbvB3sE=
|
||||
gitea.com/noerw/unidiff-comments v0.0.0-20201219085024-64aec5658f2b/go.mod h1:Fc8iyPm4NINRWujeIk2bTfcbGc4ZYY29/oMAAGcr4qI=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.8 h1:TgxCwybKdBckmC+/P9/5h49rw/nAHe/itZL0dgHs+Q0=
|
||||
github.com/AlecAivazis/survey/v2 v2.2.8/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
|
||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||
github.com/Microsoft/go-winio v0.4.15 h1:qkLXKzb1QoVatRyd/YlXZ/Kg0m5K3SPuoD82jjSOaBc=
|
||||
github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
|
||||
github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk=
|
||||
github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
|
||||
github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
|
||||
github.com/adrg/xdg v0.2.2 h1:A7ZHKRz5KGOLJX/bg7IPzStryhvCzAE1wX+KWawPiAo=
|
||||
github.com/adrg/xdg v0.2.2/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ=
|
||||
github.com/adrg/xdg v0.3.1 h1:uIyL9BYfXaFgDyVRKE8wjtm6ETQULweQqTofphEFJYY=
|
||||
github.com/adrg/xdg v0.3.1/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
|
||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||
github.com/alecthomas/chroma v0.7.3 h1:NfdAERMy+esYQs8OXk0I868/qDxxCEo7FMz1WIqMAeI=
|
||||
github.com/alecthomas/chroma v0.7.3/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||
github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE=
|
||||
github.com/alecthomas/chroma v0.8.1/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
||||
|
@ -28,17 +27,14 @@ github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkx
|
|||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/araddon/dateparse v0.0.0-20201001162425-8aadafed4dc4 h1:OkS1BqB3CzLtGRznRyvriSY8jeaVk2CrDn2ZiRQgMUI=
|
||||
github.com/araddon/dateparse v0.0.0-20201001162425-8aadafed4dc4/go.mod h1:hMAUZFIkk4B1FouGxqlogyMyU6BwY/UiVmmbbzz9Up8=
|
||||
github.com/araddon/dateparse v0.0.0-20210207001429-0eec95c9db7e h1:OjdSMCht0ZVX7IH0nTdf00xEustvbtUGRgMh3gbdmOg=
|
||||
github.com/araddon/dateparse v0.0.0-20210207001429-0eec95c9db7e/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/charmbracelet/glamour v0.2.0 h1:mTgaiNiumpqTZp3qVM6DH9UB0NlbY17wejoMf1kM8Pg=
|
||||
github.com/charmbracelet/glamour v0.2.0/go.mod h1:UA27Kwj3QHialP74iU6C+Gpc8Y7IOAKupeKMLLBURWM=
|
||||
github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=
|
||||
github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
|
@ -50,8 +46,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
|
||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
|
||||
|
@ -68,15 +62,13 @@ github.com/go-git/go-git/v5 v5.2.0 h1:YPBLG/3UK1we1ohRkncLjaXWLW+HKp5QNM/jTli2Jg
|
|||
github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f h1:5CjVwnuUcp5adK4gmY6i72gpVFVnZDP2h5TmPScB6u4=
|
||||
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
|
||||
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw=
|
||||
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ=
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A=
|
||||
github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
|
||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
|
@ -85,107 +77,98 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i
|
|||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 h1:DowS9hvgyYSX4TO5NpyC606/Z4SxnNYbT+WX27or6Ck=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.4 h1:5Myjjh3JY/NaAi4IsUbHADytDyl1VE1Y9PXDlL+P/VQ=
|
||||
github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4=
|
||||
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
|
||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s=
|
||||
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
|
||||
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
|
||||
github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/muesli/reflow v0.1.0 h1:oQdpLfO56lr5pgLvqD0TcjW85rDjSYSBVdiG1Ch1ddM=
|
||||
github.com/muesli/reflow v0.1.0/go.mod h1:I9bWAt7QTg/que/qmUCJBGlj7wEq8OAFBjPNjc6xK4I=
|
||||
github.com/muesli/reflow v0.2.0 h1:2o0UBJPHHH4fa2GCXU4Rg4DwOtWPMekCeyc5EWbAQp0=
|
||||
github.com/muesli/reflow v0.2.0/go.mod h1:qT22vjVmM9MIUeLgsVYe/Ye7eZlbv9dZjL3dVhUqLX8=
|
||||
github.com/muesli/termenv v0.6.0 h1:zxvzTBmo4ZcxhNGGWeMz+Tttm51eF5bmPjfy4MCRYlk=
|
||||
github.com/muesli/termenv v0.6.0/go.mod h1:SohX91w6swWA4AYU+QmPx+aSgXhWO0juiyID9UZmbpA=
|
||||
github.com/muesli/termenv v0.7.4 h1:/pBqvU5CpkY53tU0vVn+xgs2ZTX63aH5nY+SSps5Xa8=
|
||||
github.com/muesli/termenv v0.7.4/go.mod h1:pZ7qY9l3F7e5xsAOS0zCew2tME+p7bWeBkotCEcIIcc=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||
github.com/noerw/glamour v0.2.1-0.20210305125354-f0a29f1de0c2 h1:ACjOTGUGi7rt3JQU9GIFFs8sueFGShy6GcGjQhMmKjs=
|
||||
github.com/noerw/glamour v0.2.1-0.20210305125354-f0a29f1de0c2/go.mod h1:WIVFX8Y2VIK1Y/1qtXYL/Vvzqlcbo3VgVop9i2piPkE=
|
||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
|
||||
github.com/seletskiy/tplutil v0.0.0-20200921103632-f880f6245597 h1:nZY1S2jo+VtDrUfjO9XYI137O41hhRkxZNV5Fb5ixCA=
|
||||
github.com/seletskiy/tplutil v0.0.0-20200921103632-f880f6245597/go.mod h1:F8CBHSOjnzjx9EeXyWJTAzJyVxN+Y8JH2WjLMn4utiw=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
|
||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||
github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI=
|
||||
github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.0 h1:WOOcyaJPlzb8fZ8TloxFe8QZkhOOJx87leDa9MIT9dc=
|
||||
github.com/yuin/goldmark v1.2.0/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.1 h1:eVwehsLsZlCJCwXyGLgg+Q4iFWE/eTIMG0e8waCmm/I=
|
||||
github.com/yuin/goldmark v1.3.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
|
||||
github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
|
||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
|
||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
|
@ -193,12 +176,10 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r
|
|||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102 h1:42cLlJJdEh+ySyeUUbEQ5bsTiq8voBeTuweGVkY6Puw=
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -210,32 +191,32 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4 h1:opSr2sbRXk5X5/givKrrKj9HXxFpW2sdCiP8MJSKLQY=
|
||||
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf h1:kt3wY1Lu5MJAnKTfoMR52Cu4gwvna4VTzNOiT8tY73s=
|
||||
golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3 h1:RdE7htvBru4I4VZQofQjCZk5W9+aLNlSF5n0zgVwm8s=
|
||||
golang.org/x/sys v0.0.0-20210305034016-7844c3c200c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224 h1:azwY/v0y0K4mFHVsg5+UrTgchqALYWpqVo6vL5OmkmI=
|
||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/tools v0.0.0-20201105220310-78b158585360 h1:/9CzsU8hOpnSUCtem1vfWNgsVeCTgkMdx+VE5YIYxnU=
|
||||
golang.org/x/tools v0.0.0-20201105220310-78b158585360/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -245,13 +226,11 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8X
|
|||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
73
main.go
73
main.go
|
@ -22,24 +22,32 @@ var Version = "development"
|
|||
var Tags = ""
|
||||
|
||||
func main() {
|
||||
// make parsing tea --version easier, by printing /just/ the version string
|
||||
cli.VersionPrinter = func(c *cli.Context) { fmt.Fprintln(c.App.Writer, c.App.Version) }
|
||||
|
||||
app := cli.NewApp()
|
||||
app.Name = "tea"
|
||||
app.Usage = "Command line tool to interact with Gitea"
|
||||
app.Usage = "command line tool to interact with Gitea"
|
||||
app.Description = appDescription
|
||||
app.CustomAppHelpTemplate = helpTemplate
|
||||
app.Version = Version + formatBuiltWith(Tags)
|
||||
app.Commands = []*cli.Command{
|
||||
&cmd.CmdLogin,
|
||||
&cmd.CmdLogout,
|
||||
&cmd.CmdAutocomplete,
|
||||
|
||||
&cmd.CmdIssues,
|
||||
&cmd.CmdPulls,
|
||||
&cmd.CmdReleases,
|
||||
&cmd.CmdRepos,
|
||||
&cmd.CmdLabels,
|
||||
&cmd.CmdMilestones,
|
||||
&cmd.CmdReleases,
|
||||
&cmd.CmdTrackedTimes,
|
||||
&cmd.CmdOrgs,
|
||||
&cmd.CmdRepos,
|
||||
&cmd.CmdAddComment,
|
||||
|
||||
&cmd.CmdOpen,
|
||||
&cmd.CmdNotifications,
|
||||
&cmd.CmdMilestones,
|
||||
&cmd.CmdOrgs,
|
||||
&cmd.CmdAutocomplete,
|
||||
}
|
||||
app.EnableBashCompletion = true
|
||||
err := app.Run(os.Args)
|
||||
|
@ -58,3 +66,56 @@ func formatBuiltWith(Tags string) string {
|
|||
|
||||
return " built with: " + strings.Replace(Tags, " ", ", ", -1)
|
||||
}
|
||||
|
||||
var appDescription = `tea is a productivity helper for Gitea. It can be used to manage most entities on one
|
||||
or multiple Gitea instances and provides local helpers like 'tea pull checkout'.
|
||||
tea makes use of context provided by the repository in $PWD if available, but is still
|
||||
usable independently of $PWD. Configuration is persisted in $XDG_CONFIG_HOME/tea.
|
||||
`
|
||||
|
||||
var helpTemplate = bold(`
|
||||
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}`) + `
|
||||
{{if .Version}}{{if not .HideVersion}}version {{.Version}}{{end}}{{end}}
|
||||
|
||||
USAGE
|
||||
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .Commands}} command [subcommand] [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}}
|
||||
|
||||
DESCRIPTION
|
||||
{{.Description | nindent 3 | trim}}{{end}}{{if .VisibleCommands}}
|
||||
|
||||
COMMANDS{{range .VisibleCategories}}{{if .Name}}
|
||||
{{.Name}}:{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}}
|
||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
||||
|
||||
OPTIONS
|
||||
{{range $index, $option := .VisibleFlags}}{{if $index}}
|
||||
{{end}}{{$option}}{{end}}{{end}}
|
||||
|
||||
EXAMPLES
|
||||
tea login add # add a login once to get started
|
||||
|
||||
tea pulls # list open pulls for the repo in $PWD
|
||||
tea pulls --repo $HOME/foo # list open pulls for the repo in $HOME/foo
|
||||
tea pulls --remote upstream # list open pulls for the repo pointed at by
|
||||
# your local "upstream" git remote
|
||||
# list open pulls for any gitea repo at the given login instance
|
||||
tea pulls --repo gitea/tea --login gitea.com
|
||||
|
||||
tea milestone issues 0.7.0 # view open issues for milestone '0.7.0'
|
||||
tea issue 189 # view contents of issue 189
|
||||
tea open 189 # open web ui for issue 189
|
||||
tea open milestones # open web ui for milestones
|
||||
|
||||
# send gitea desktop notifications every 5 minutes (bash + libnotify)
|
||||
while :; do tea notifications --all -o simple | xargs -i notify-send {}; sleep 300; done
|
||||
|
||||
ABOUT
|
||||
Written & maintained by The Gitea Authors.
|
||||
If you find a bug or want to contribute, we'll welcome you at https://gitea.com/gitea/tea.
|
||||
More info about Gitea itself on https://gitea.io.
|
||||
`
|
||||
|
||||
func bold(t string) string {
|
||||
return fmt.Sprintf("\033[1m%s\033[0m", t)
|
||||
}
|
||||
|
|
|
@ -20,21 +20,28 @@ import (
|
|||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
errNotAGiteaRepo = errors.New("No Gitea login found. You might want to specify --repo (and --login) to work outside of a repository")
|
||||
)
|
||||
|
||||
// TeaContext contains all context derived during command initialization and wraps cli.Context
|
||||
type TeaContext struct {
|
||||
*cli.Context
|
||||
Login *config.Login
|
||||
RepoSlug string // <owner>/<repo>
|
||||
Owner string // repo owner as derived from context
|
||||
Repo string // repo name as derived from context or provided in flag
|
||||
Output string // value of output flag
|
||||
LocalRepo *git.TeaRepo // maybe, we have opened it already anyway
|
||||
Login *config.Login // config data & client for selected login
|
||||
RepoSlug string // <owner>/<repo>, optional
|
||||
Owner string // repo owner as derived from context or provided in flag, optional
|
||||
Repo string // repo name as derived from context or provided in flag, optional
|
||||
Output string // value of output flag
|
||||
LocalRepo *git.TeaRepo // is set if flags specified a local repo via --repo, or if $PWD is a git repo
|
||||
}
|
||||
|
||||
// GetListOptions return ListOptions based on PaginationFlags
|
||||
func (ctx *TeaContext) GetListOptions() gitea.ListOptions {
|
||||
page := ctx.Int("page")
|
||||
limit := ctx.Int("limit")
|
||||
if limit < 0 {
|
||||
limit = 0
|
||||
}
|
||||
if limit != 0 && page == 0 {
|
||||
page = 1
|
||||
}
|
||||
|
@ -75,14 +82,16 @@ func InitCommand(ctx *cli.Context) *TeaContext {
|
|||
loginFlag := ctx.String("login")
|
||||
remoteFlag := ctx.String("remote")
|
||||
|
||||
var repoSlug string
|
||||
var repoPath string // empty means PWD
|
||||
var repoFlagPathExists bool
|
||||
var (
|
||||
c TeaContext
|
||||
err error
|
||||
repoPath string // empty means PWD
|
||||
repoFlagPathExists bool
|
||||
)
|
||||
|
||||
// check if repoFlag can be interpreted as path to local repo.
|
||||
if len(repoFlag) != 0 {
|
||||
repoFlagPathExists, err := utils.PathExists(repoFlag)
|
||||
if err != nil {
|
||||
if repoFlagPathExists, err = utils.DirExists(repoFlag); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
if repoFlagPathExists {
|
||||
|
@ -90,38 +99,53 @@ func InitCommand(ctx *cli.Context) *TeaContext {
|
|||
}
|
||||
}
|
||||
|
||||
// try to read git repo & extract context, ignoring if PWD is not a repo
|
||||
localRepo, login, repoSlug, err := contextFromLocalRepo(repoPath, remoteFlag)
|
||||
if err != nil && err != gogit.ErrRepositoryNotExists {
|
||||
log.Fatal(err.Error())
|
||||
if len(repoFlag) == 0 || repoFlagPathExists {
|
||||
// try to read git repo & extract context, ignoring if PWD is not a repo
|
||||
if c.LocalRepo, c.Login, c.RepoSlug, err = contextFromLocalRepo(repoPath, remoteFlag); err != nil {
|
||||
if err == errNotAGiteaRepo || err == gogit.ErrRepositoryNotExists {
|
||||
// we can deal with that, commands needing the optional values use ctx.Ensure()
|
||||
} else {
|
||||
log.Fatal(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if repoFlag is not a path, use it to override repoSlug
|
||||
if len(repoFlag) != 0 && !repoFlagPathExists {
|
||||
repoSlug = repoFlag
|
||||
// if repoFlag is not a valid path, use it to override repoSlug
|
||||
c.RepoSlug = repoFlag
|
||||
}
|
||||
|
||||
// override login from flag, or use default login if repo based detection failed
|
||||
if len(loginFlag) != 0 {
|
||||
login = config.GetLoginByName(loginFlag)
|
||||
if login == nil {
|
||||
c.Login = config.GetLoginByName(loginFlag)
|
||||
if c.Login == nil {
|
||||
log.Fatalf("Login name '%s' does not exist", loginFlag)
|
||||
}
|
||||
} else if login == nil {
|
||||
if login, err = config.GetDefaultLogin(); err != nil {
|
||||
log.Fatal(err.Error())
|
||||
} else if c.Login == nil {
|
||||
if c.Login, err = config.GetDefaultLogin(); err != nil {
|
||||
if err.Error() == "No available login" {
|
||||
// TODO: maybe we can directly start interact.CreateLogin() (only if
|
||||
// we're sure we can interactively!), as gh cli does.
|
||||
fmt.Println(`No gitea login configured. To start using tea, first run
|
||||
tea login add
|
||||
and then run your command again.`)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("NOTE: no gitea login detected, falling back to login '%s'\n", c.Login.Name)
|
||||
}
|
||||
|
||||
// parse reposlug (owner falling back to login owner if reposlug contains only repo name)
|
||||
owner, reponame := utils.GetOwnerAndRepo(repoSlug, login.User)
|
||||
c.Owner, c.Repo = utils.GetOwnerAndRepo(c.RepoSlug, c.Login.User)
|
||||
|
||||
return &TeaContext{ctx, login, repoSlug, owner, reponame, ctx.String("output"), localRepo}
|
||||
c.Context = ctx
|
||||
c.Output = ctx.String("output")
|
||||
return &c
|
||||
}
|
||||
|
||||
// contextFromLocalRepo discovers login & repo slug from the default branch remote of the given local repo
|
||||
func contextFromLocalRepo(repoValue, remoteValue string) (*git.TeaRepo, *config.Login, string, error) {
|
||||
repo, err := git.RepoFromPath(repoValue)
|
||||
func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.Login, string, error) {
|
||||
repo, err := git.RepoFromPath(repoPath)
|
||||
if err != nil {
|
||||
return nil, nil, "", err
|
||||
}
|
||||
|
@ -180,5 +204,5 @@ func contextFromLocalRepo(repoValue, remoteValue string) (*git.TeaRepo, *config.
|
|||
}
|
||||
}
|
||||
|
||||
return repo, nil, "", errors.New("No Gitea login found. You might want to specify --repo (and --login) to work outside of a repository")
|
||||
return repo, nil, "", errNotAGiteaRepo
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ func readSSHPrivKey(keyFile string, passwordCallback pwCallback) (sig ssh.Signer
|
|||
}
|
||||
sshKey, err := ioutil.ReadFile(keyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("can not read ssh key '%s'", keyFile)
|
||||
}
|
||||
sig, err = ssh.ParsePrivateKey(sshKey)
|
||||
if _, ok := err.(*ssh.PassphraseMissingError); ok && passwordCallback != nil {
|
||||
|
|
|
@ -38,42 +38,36 @@ func (r TeaRepo) TeaCreateBranch(localBranchName, remoteBranchName, remoteName s
|
|||
}
|
||||
|
||||
// TeaCheckout checks out the given branch in the worktree.
|
||||
func (r TeaRepo) TeaCheckout(branchName string) error {
|
||||
func (r TeaRepo) TeaCheckout(ref git_plumbing.ReferenceName) error {
|
||||
tree, err := r.Worktree()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
localBranchRefName := git_plumbing.NewBranchReferenceName(branchName)
|
||||
return tree.Checkout(&git.CheckoutOptions{Branch: localBranchRefName})
|
||||
return tree.Checkout(&git.CheckoutOptions{Branch: ref})
|
||||
}
|
||||
|
||||
// TeaDeleteBranch removes the given branch locally, and if `remoteBranch` is
|
||||
// not empty deletes it at it's remote repo.
|
||||
func (r TeaRepo) TeaDeleteBranch(branch *git_config.Branch, remoteBranch string, auth git_transport.AuthMethod) error {
|
||||
// TeaDeleteLocalBranch removes the given branch locally
|
||||
func (r TeaRepo) TeaDeleteLocalBranch(branch *git_config.Branch) error {
|
||||
err := r.DeleteBranch(branch.Name)
|
||||
// if the branch is not found that's ok, as .git/config may have no entry if
|
||||
// no remote tracking branch is configured for it (eg push without -u flag)
|
||||
if err != nil && err.Error() != "branch not found" {
|
||||
return err
|
||||
}
|
||||
err = r.Storer.RemoveReference(git_plumbing.NewBranchReferenceName(branch.Name))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return r.Storer.RemoveReference(git_plumbing.NewBranchReferenceName(branch.Name))
|
||||
}
|
||||
|
||||
if remoteBranch != "" {
|
||||
// delete remote branch via git protocol:
|
||||
// an empty source in the refspec means remote deletion to git 🙃
|
||||
refspec := fmt.Sprintf(":%s", git_plumbing.NewBranchReferenceName(remoteBranch))
|
||||
err = r.Push(&git.PushOptions{
|
||||
RemoteName: branch.Remote,
|
||||
RefSpecs: []git_config.RefSpec{git_config.RefSpec(refspec)},
|
||||
Prune: true,
|
||||
Auth: auth,
|
||||
})
|
||||
}
|
||||
|
||||
return err
|
||||
// TeaDeleteRemoteBranch removes the given branch on the given remote via git protocol
|
||||
func (r TeaRepo) TeaDeleteRemoteBranch(remoteName, remoteBranch string, auth git_transport.AuthMethod) error {
|
||||
// delete remote branch via git protocol:
|
||||
// an empty source in the refspec means remote deletion to git 🙃
|
||||
refspec := fmt.Sprintf(":%s", git_plumbing.NewBranchReferenceName(remoteBranch))
|
||||
return r.Push(&git.PushOptions{
|
||||
RemoteName: remoteName,
|
||||
RefSpecs: []git_config.RefSpec{git_config.RefSpec(refspec)},
|
||||
Prune: true,
|
||||
Auth: auth,
|
||||
})
|
||||
}
|
||||
|
||||
// TeaFindBranchBySha returns a branch that is at the the given SHA and syncs to the
|
||||
|
@ -229,5 +223,5 @@ func (r TeaRepo) TeaGetCurrentBranchName() (string, error) {
|
|||
return "", fmt.Errorf("active ref is no branch")
|
||||
}
|
||||
|
||||
return strings.TrimPrefix(localHead.Name().String(), "refs/heads/"), nil
|
||||
return localHead.Name().Short(), nil
|
||||
}
|
||||
|
|
80
modules/interact/comments.go
Normal file
80
modules/interact/comments.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package interact
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
// ShowCommentsMaybeInteractive fetches & prints comments, depending on the --comments flag.
|
||||
// If that flag is unset, and output is not piped, prompts the user first.
|
||||
func ShowCommentsMaybeInteractive(ctx *context.TeaContext, idx int64, totalComments int) error {
|
||||
if ctx.Bool("comments") {
|
||||
opts := gitea.ListIssueCommentOptions{ListOptions: ctx.GetListOptions()}
|
||||
c := ctx.Login.Client()
|
||||
comments, _, err := c.ListIssueComments(ctx.Owner, ctx.Repo, idx, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
print.Comments(comments)
|
||||
} else if IsInteractive() && !ctx.IsSet("comments") {
|
||||
// if we're interactive, but --comments hasn't been explicitly set to false
|
||||
if err := ShowCommentsPaginated(ctx, idx, totalComments); err != nil {
|
||||
fmt.Printf("error while loading comments: %v\n", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ShowCommentsPaginated prompts if issue/pr comments should be shown and continues to do so.
|
||||
func ShowCommentsPaginated(ctx *context.TeaContext, idx int64, totalComments int) error {
|
||||
c := ctx.Login.Client()
|
||||
opts := gitea.ListIssueCommentOptions{ListOptions: ctx.GetListOptions()}
|
||||
prompt := "show comments?"
|
||||
commentsLoaded := 0
|
||||
|
||||
// paginated fetch
|
||||
// NOTE: as of gitea 1.13, pagination is not provided by this endpoint, but handles
|
||||
// this function gracefully anyways.
|
||||
for {
|
||||
loadComments := false
|
||||
confirm := survey.Confirm{Message: prompt, Default: true}
|
||||
if err := survey.AskOne(&confirm, &loadComments); err != nil {
|
||||
return err
|
||||
} else if !loadComments {
|
||||
break
|
||||
} else {
|
||||
if comments, _, err := c.ListIssueComments(ctx.Owner, ctx.Repo, idx, opts); err != nil {
|
||||
return err
|
||||
} else if len(comments) != 0 {
|
||||
print.Comments(comments)
|
||||
commentsLoaded += len(comments)
|
||||
}
|
||||
if commentsLoaded >= totalComments {
|
||||
break
|
||||
}
|
||||
opts.ListOptions.Page++
|
||||
prompt = "load more?"
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsInteractive checks if the output is piped, but NOT if the session is run interactively..
|
||||
func IsInteractive() bool {
|
||||
return terminal.IsTerminal(int(os.Stdout.Fd()))
|
||||
}
|
||||
|
||||
// IsStdinPiped checks if stdin is piped
|
||||
func IsStdinPiped() bool {
|
||||
return !terminal.IsTerminal(int(os.Stdin.Fd()))
|
||||
}
|
|
@ -5,39 +5,158 @@
|
|||
package interact
|
||||
|
||||
import (
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/modules/config"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
)
|
||||
|
||||
// CreateIssue interactively creates a PR
|
||||
// CreateIssue interactively creates an issue
|
||||
func CreateIssue(login *config.Login, owner, repo string) error {
|
||||
var title, description string
|
||||
|
||||
// owner, repo
|
||||
owner, repo, err := promptRepoSlug(owner, repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var opts gitea.CreateIssueOption
|
||||
if err := promptIssueProperties(login, owner, repo, &opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.CreateIssue(login, owner, repo, opts)
|
||||
}
|
||||
|
||||
func promptIssueProperties(login *config.Login, owner, repo string, o *gitea.CreateIssueOption) error {
|
||||
var milestoneName string
|
||||
var labels []string
|
||||
var err error
|
||||
|
||||
selectableChan := make(chan (issueSelectables), 1)
|
||||
go fetchIssueSelectables(login, owner, repo, selectableChan)
|
||||
|
||||
// title
|
||||
promptOpts := survey.WithValidator(survey.Required)
|
||||
promptI := &survey.Input{Message: "Issue title:"}
|
||||
if err := survey.AskOne(promptI, &title, promptOpts); err != nil {
|
||||
promptI := &survey.Input{Message: "Issue title:", Default: o.Title}
|
||||
if err = survey.AskOne(promptI, &o.Title, promptOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// description
|
||||
promptM := &survey.Multiline{Message: "Issue description:"}
|
||||
if err := survey.AskOne(promptM, &description); err != nil {
|
||||
promptD := &survey.Multiline{Message: "Issue description:", Default: o.Body}
|
||||
if err = survey.AskOne(promptD, &o.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.CreateIssue(
|
||||
login,
|
||||
owner,
|
||||
repo,
|
||||
title,
|
||||
description)
|
||||
// wait until selectables are fetched
|
||||
selectables := <-selectableChan
|
||||
if selectables.Err != nil {
|
||||
return selectables.Err
|
||||
}
|
||||
|
||||
// skip remaining props if we don't have permission to set them
|
||||
if !selectables.Repo.Permissions.Push {
|
||||
return nil
|
||||
}
|
||||
|
||||
// assignees
|
||||
if o.Assignees, err = promptMultiSelect("Assignees:", selectables.Collaborators, "[other]"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// milestone
|
||||
if len(selectables.MilestoneList) != 0 {
|
||||
if milestoneName, err = promptSelect("Milestone:", selectables.MilestoneList, "", "[none]"); err != nil {
|
||||
return err
|
||||
}
|
||||
o.Milestone = selectables.MilestoneMap[milestoneName]
|
||||
}
|
||||
|
||||
// labels
|
||||
if len(selectables.LabelList) != 0 {
|
||||
promptL := &survey.MultiSelect{Message: "Labels:", Options: selectables.LabelList, VimMode: true, Default: o.Labels}
|
||||
if err := survey.AskOne(promptL, &labels); err != nil {
|
||||
return err
|
||||
}
|
||||
o.Labels = make([]int64, len(labels))
|
||||
for i, l := range labels {
|
||||
o.Labels[i] = selectables.LabelMap[l]
|
||||
}
|
||||
}
|
||||
|
||||
// deadline
|
||||
if o.Deadline, err = promptDatetime("Due date:"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type issueSelectables struct {
|
||||
Repo *gitea.Repository
|
||||
Collaborators []string
|
||||
MilestoneList []string
|
||||
MilestoneMap map[string]int64
|
||||
LabelList []string
|
||||
LabelMap map[string]int64
|
||||
Err error
|
||||
}
|
||||
|
||||
func fetchIssueSelectables(login *config.Login, owner, repo string, done chan issueSelectables) {
|
||||
// TODO PERF make these calls concurrent
|
||||
r := issueSelectables{}
|
||||
c := login.Client()
|
||||
|
||||
r.Repo, _, r.Err = c.GetRepo(owner, repo)
|
||||
if r.Err != nil {
|
||||
done <- r
|
||||
return
|
||||
}
|
||||
// we can set the following properties only if we have write access to the repo
|
||||
// so we fastpath this if not.
|
||||
if !r.Repo.Permissions.Push {
|
||||
done <- r
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME: this should ideally be ListAssignees(), https://github.com/go-gitea/gitea/issues/14856
|
||||
colabs, _, err := c.ListCollaborators(owner, repo, gitea.ListCollaboratorsOptions{})
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
done <- r
|
||||
return
|
||||
}
|
||||
r.Collaborators = make([]string, len(colabs)+1)
|
||||
r.Collaborators[0] = login.User
|
||||
for i, u := range colabs {
|
||||
r.Collaborators[i+1] = u.UserName
|
||||
}
|
||||
|
||||
milestones, _, err := c.ListRepoMilestones(owner, repo, gitea.ListMilestoneOption{})
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
done <- r
|
||||
return
|
||||
}
|
||||
r.MilestoneMap = make(map[string]int64)
|
||||
r.MilestoneList = make([]string, len(milestones))
|
||||
for i, m := range milestones {
|
||||
r.MilestoneMap[m.Title] = m.ID
|
||||
r.MilestoneList[i] = m.Title
|
||||
}
|
||||
|
||||
labels, _, err := c.ListRepoLabels(owner, repo, gitea.ListLabelsOptions{})
|
||||
if err != nil {
|
||||
r.Err = err
|
||||
done <- r
|
||||
return
|
||||
}
|
||||
r.LabelMap = make(map[string]int64)
|
||||
r.LabelList = make([]string, len(labels))
|
||||
for i, l := range labels {
|
||||
r.LabelMap[l.Name] = l.ID
|
||||
r.LabelList[i] = l.Name
|
||||
}
|
||||
|
||||
done <- r
|
||||
}
|
||||
|
|
54
modules/interact/milestone_create.go
Normal file
54
modules/interact/milestone_create.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package interact
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/tea/modules/config"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
)
|
||||
|
||||
// CreateMilestone interactively creates a milestone
|
||||
func CreateMilestone(login *config.Login, owner, repo string) error {
|
||||
var title, description string
|
||||
var deadline *time.Time
|
||||
|
||||
// owner, repo
|
||||
owner, repo, err := promptRepoSlug(owner, repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// title
|
||||
promptOpts := survey.WithValidator(survey.Required)
|
||||
promptI := &survey.Input{Message: "Milestone title:"}
|
||||
if err := survey.AskOne(promptI, &title, promptOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// description
|
||||
promptM := &survey.Multiline{Message: "Milestone description:"}
|
||||
if err := survey.AskOne(promptM, &description); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// deadline
|
||||
if deadline, err = promptDatetime("Milestone deadline:"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.CreateMilestone(
|
||||
login,
|
||||
owner,
|
||||
repo,
|
||||
title,
|
||||
description,
|
||||
deadline,
|
||||
gitea.StateOpen)
|
||||
}
|
|
@ -7,10 +7,19 @@ package interact
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/araddon/dateparse"
|
||||
)
|
||||
|
||||
// PromptMultiline runs a textfield-style prompt and blocks until input was made.
|
||||
func PromptMultiline(message string) (content string, err error) {
|
||||
err = survey.AskOne(&survey.Multiline{Message: message}, &content)
|
||||
return
|
||||
}
|
||||
|
||||
// PromptPassword asks for a password and blocks until input was made.
|
||||
func PromptPassword(name string) (pass string, err error) {
|
||||
promptPW := &survey.Password{Message: name + " password:"}
|
||||
|
@ -21,9 +30,10 @@ func PromptPassword(name string) (pass string, err error) {
|
|||
// promptRepoSlug interactively prompts for a Gitea repository or returns the current one
|
||||
func promptRepoSlug(defaultOwner, defaultRepo string) (owner, repo string, err error) {
|
||||
prompt := "Target repo:"
|
||||
defaultVal := ""
|
||||
required := true
|
||||
if len(defaultOwner) != 0 && len(defaultRepo) != 0 {
|
||||
prompt = fmt.Sprintf("Target repo [%s/%s]:", defaultOwner, defaultRepo)
|
||||
defaultVal = fmt.Sprintf("%s/%s", defaultOwner, defaultRepo)
|
||||
required = false
|
||||
}
|
||||
var repoSlug string
|
||||
|
@ -32,7 +42,10 @@ func promptRepoSlug(defaultOwner, defaultRepo string) (owner, repo string, err e
|
|||
repo = defaultRepo
|
||||
|
||||
err = survey.AskOne(
|
||||
&survey.Input{Message: prompt},
|
||||
&survey.Input{
|
||||
Message: prompt,
|
||||
Default: defaultVal,
|
||||
},
|
||||
&repoSlug,
|
||||
survey.WithValidator(func(input interface{}) error {
|
||||
if str, ok := input.(string); ok {
|
||||
|
@ -57,3 +70,96 @@ func promptRepoSlug(defaultOwner, defaultRepo string) (owner, repo string, err e
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
// promptDatetime prompts for a date or datetime string.
|
||||
// Supports all formats understood by araddon/dateparse.
|
||||
func promptDatetime(prompt string) (val *time.Time, err error) {
|
||||
var input string
|
||||
err = survey.AskOne(
|
||||
&survey.Input{Message: prompt},
|
||||
&input,
|
||||
survey.WithValidator(func(input interface{}) error {
|
||||
if str, ok := input.(string); ok {
|
||||
if len(str) == 0 {
|
||||
return nil
|
||||
}
|
||||
t, err := dateparse.ParseAny(str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
val = &t
|
||||
} else {
|
||||
return fmt.Errorf("invalid result type")
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// promptSelect creates a generic multiselect prompt, with processing of custom values.
|
||||
func promptMultiSelect(prompt string, options []string, customVal string) ([]string, error) {
|
||||
var selection []string
|
||||
promptA := &survey.MultiSelect{
|
||||
Message: prompt,
|
||||
Options: makeSelectOpts(options, customVal, ""),
|
||||
VimMode: true,
|
||||
}
|
||||
if err := survey.AskOne(promptA, &selection); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return promptCustomVal(prompt, customVal, selection)
|
||||
}
|
||||
|
||||
// promptSelect creates a generic select prompt, with processing of custom values or none-option.
|
||||
func promptSelect(prompt string, options []string, customVal, noneVal string) (string, error) {
|
||||
var selection string
|
||||
promptA := &survey.Select{
|
||||
Message: prompt,
|
||||
Options: makeSelectOpts(options, customVal, noneVal),
|
||||
VimMode: true,
|
||||
Default: noneVal,
|
||||
}
|
||||
if err := survey.AskOne(promptA, &selection); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if noneVal != "" && selection == noneVal {
|
||||
return "", nil
|
||||
}
|
||||
if customVal != "" {
|
||||
sel, err := promptCustomVal(prompt, customVal, []string{selection})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
selection = sel[0]
|
||||
}
|
||||
return selection, nil
|
||||
}
|
||||
|
||||
// makeSelectOpts adds cusotmVal & noneVal to opts if set.
|
||||
func makeSelectOpts(opts []string, customVal, noneVal string) []string {
|
||||
if customVal != "" {
|
||||
opts = append(opts, customVal)
|
||||
}
|
||||
if noneVal != "" {
|
||||
opts = append(opts, noneVal)
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
// promptCustomVal checks if customVal is present in selection, and prompts
|
||||
// for custom input to add to the selection instead.
|
||||
func promptCustomVal(prompt, customVal string, selection []string) ([]string, error) {
|
||||
// check for custom value & prompt again with text input
|
||||
// HACK until https://github.com/AlecAivazis/survey/issues/339 is implemented
|
||||
if otherIndex := utils.IndexOf(selection, customVal); otherIndex != -1 {
|
||||
var customAssignees string
|
||||
promptA := &survey.Input{Message: prompt, Help: "comma separated list"}
|
||||
if err := survey.AskOne(promptA, &customAssignees); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selection = append(selection[:otherIndex], selection[otherIndex+1:]...)
|
||||
selection = append(selection, strings.Split(customAssignees, ",")...)
|
||||
}
|
||||
return selection, nil
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package interact
|
||||
|
||||
import (
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/modules/config"
|
||||
"code.gitea.io/tea/modules/git"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
|
@ -14,7 +15,7 @@ import (
|
|||
|
||||
// CreatePull interactively creates a PR
|
||||
func CreatePull(login *config.Login, owner, repo string) error {
|
||||
var base, head, title, description string
|
||||
var base, head string
|
||||
|
||||
// owner, repo
|
||||
owner, repo, err := promptRepoSlug(owner, repo)
|
||||
|
@ -23,17 +24,14 @@ func CreatePull(login *config.Login, owner, repo string) error {
|
|||
}
|
||||
|
||||
// base
|
||||
baseBranch, err := task.GetDefaultPRBase(login, owner, repo)
|
||||
base, err = task.GetDefaultPRBase(login, owner, repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
promptI := &survey.Input{Message: "Target branch [" + baseBranch + "]:"}
|
||||
promptI := &survey.Input{Message: "Target branch:", Default: base}
|
||||
if err := survey.AskOne(promptI, &base); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(base) == 0 {
|
||||
base = baseBranch
|
||||
}
|
||||
|
||||
// head
|
||||
localRepo, err := git.RepoForWorkdir()
|
||||
|
@ -45,38 +43,19 @@ func CreatePull(login *config.Login, owner, repo string) error {
|
|||
if err == nil {
|
||||
promptOpts = nil
|
||||
}
|
||||
var headOwnerInput, headBranchInput string
|
||||
promptI = &survey.Input{Message: "Source repo owner [" + headOwner + "]:"}
|
||||
if err := survey.AskOne(promptI, &headOwnerInput); err != nil {
|
||||
promptI = &survey.Input{Message: "Source repo owner:", Default: headOwner}
|
||||
if err := survey.AskOne(promptI, &headOwner); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(headOwnerInput) != 0 {
|
||||
headOwner = headOwnerInput
|
||||
}
|
||||
promptI = &survey.Input{Message: "Source branch [" + headBranch + "]:"}
|
||||
if err := survey.AskOne(promptI, &headBranchInput, promptOpts); err != nil {
|
||||
promptI = &survey.Input{Message: "Source branch:", Default: headBranch}
|
||||
if err := survey.AskOne(promptI, &headBranch, promptOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(headBranchInput) != 0 {
|
||||
headBranch = headBranchInput
|
||||
}
|
||||
|
||||
head = task.GetHeadSpec(headOwner, headBranch, owner)
|
||||
|
||||
// title
|
||||
title = task.GetDefaultPRTitle(head)
|
||||
promptOpts = survey.WithValidator(survey.Required)
|
||||
if len(title) != 0 {
|
||||
promptOpts = nil
|
||||
}
|
||||
promptI = &survey.Input{Message: "PR title [" + title + "]:"}
|
||||
if err := survey.AskOne(promptI, &title, promptOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// description
|
||||
promptM := &survey.Multiline{Message: "PR description:"}
|
||||
if err := survey.AskOne(promptM, &description); err != nil {
|
||||
opts := gitea.CreateIssueOption{Title: task.GetDefaultPRTitle(head)}
|
||||
if err = promptIssueProperties(login, owner, repo, &opts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -86,6 +65,5 @@ func CreatePull(login *config.Login, owner, repo string) error {
|
|||
repo,
|
||||
base,
|
||||
head,
|
||||
title,
|
||||
description)
|
||||
&opts)
|
||||
}
|
||||
|
|
80
modules/interact/pull_review.go
Normal file
80
modules/interact/pull_review.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package interact
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"code.gitea.io/tea/modules/context"
|
||||
"code.gitea.io/tea/modules/task"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
)
|
||||
|
||||
var reviewStates = map[string]gitea.ReviewStateType{
|
||||
"approve": gitea.ReviewStateApproved,
|
||||
"comment": gitea.ReviewStateComment,
|
||||
"request changes": gitea.ReviewStateRequestChanges,
|
||||
}
|
||||
var reviewStateOptions = []string{"comment", "request changes", "approve"}
|
||||
|
||||
// ReviewPull interactively reviews a PR
|
||||
func ReviewPull(ctx *context.TeaContext, idx int64) error {
|
||||
var state gitea.ReviewStateType
|
||||
var comment string
|
||||
var codeComments []gitea.CreatePullReviewComment
|
||||
var err error
|
||||
|
||||
// codeComments
|
||||
var reviewDiff bool
|
||||
promptDiff := &survey.Confirm{Message: "Review / comment the diff?", Default: true}
|
||||
if err = survey.AskOne(promptDiff, &reviewDiff); err != nil {
|
||||
return err
|
||||
}
|
||||
if reviewDiff {
|
||||
if codeComments, err = DoDiffReview(ctx, idx); err != nil {
|
||||
fmt.Printf("Error during diff review: %s\n", err)
|
||||
}
|
||||
fmt.Printf("Found %d code comments in your review\n", len(codeComments))
|
||||
}
|
||||
|
||||
// state
|
||||
var stateString string
|
||||
promptState := &survey.Select{Message: "Your assessment:", Options: reviewStateOptions, VimMode: true}
|
||||
if err = survey.AskOne(promptState, &stateString); err != nil {
|
||||
return err
|
||||
}
|
||||
state = reviewStates[stateString]
|
||||
|
||||
// comment
|
||||
var promptOpts survey.AskOpt
|
||||
if state == gitea.ReviewStateComment || state == gitea.ReviewStateRequestChanges {
|
||||
promptOpts = survey.WithValidator(survey.Required)
|
||||
}
|
||||
err = survey.AskOne(&survey.Multiline{Message: "Concluding comment:"}, &comment, promptOpts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return task.CreatePullReview(ctx, idx, state, comment, codeComments)
|
||||
}
|
||||
|
||||
// DoDiffReview (1) fetches & saves diff in tempfile, (2) starts $VISUAL or $EDITOR to comment on diff,
|
||||
// (3) parses resulting file into code comments.
|
||||
func DoDiffReview(ctx *context.TeaContext, idx int64) ([]gitea.CreatePullReviewComment, error) {
|
||||
tmpFile, err := task.SavePullDiff(ctx, idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer os.Remove(tmpFile)
|
||||
|
||||
if err = task.OpenFileInEditor(tmpFile); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return task.ParseDiffComments(tmpFile)
|
||||
}
|
50
modules/print/comment.go
Normal file
50
modules/print/comment.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package print
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
||||
// Comments renders a list of comments to stdout
|
||||
func Comments(comments []*gitea.Comment) {
|
||||
var baseURL string
|
||||
if len(comments) != 0 {
|
||||
baseURL = comments[0].HTMLURL
|
||||
}
|
||||
|
||||
var out = make([]string, len(comments))
|
||||
for i, c := range comments {
|
||||
out[i] = formatComment(c)
|
||||
}
|
||||
|
||||
outputMarkdown(fmt.Sprintf(
|
||||
// this will become a heading by means of the first --- from a comment
|
||||
"Comments\n%s",
|
||||
strings.Join(out, "\n"),
|
||||
), baseURL)
|
||||
}
|
||||
|
||||
// Comment renders a comment to stdout
|
||||
func Comment(c *gitea.Comment) {
|
||||
outputMarkdown(formatComment(c), c.HTMLURL)
|
||||
}
|
||||
|
||||
func formatComment(c *gitea.Comment) string {
|
||||
edited := ""
|
||||
if c.Updated.After(c.Created) {
|
||||
edited = fmt.Sprintf(" *(edited on %s)*", FormatTime(c.Updated))
|
||||
}
|
||||
return fmt.Sprintf(
|
||||
"---\n\n**@%s** wrote on %s%s:\n\n%s\n",
|
||||
c.Poster.UserName,
|
||||
FormatTime(c.Created),
|
||||
edited,
|
||||
c.Body,
|
||||
)
|
||||
}
|
74
modules/print/formatters.go
Normal file
74
modules/print/formatters.go
Normal file
|
@ -0,0 +1,74 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package print
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/muesli/termenv"
|
||||
)
|
||||
|
||||
// formatSize get kb in int and return string
|
||||
func formatSize(kb int64) string {
|
||||
if kb < 1024 {
|
||||
return fmt.Sprintf("%d Kb", kb)
|
||||
}
|
||||
mb := kb / 1024
|
||||
if mb < 1024 {
|
||||
return fmt.Sprintf("%d Mb", mb)
|
||||
}
|
||||
gb := mb / 1024
|
||||
if gb < 1024 {
|
||||
return fmt.Sprintf("%d Gb", gb)
|
||||
}
|
||||
return fmt.Sprintf("%d Tb", gb/1024)
|
||||
}
|
||||
|
||||
// FormatTime give a date-time in local timezone if available
|
||||
func FormatTime(t time.Time) string {
|
||||
location, err := time.LoadLocation("Local")
|
||||
if err != nil {
|
||||
return t.Format("2006-01-02 15:04 UTC")
|
||||
}
|
||||
return t.In(location).Format("2006-01-02 15:04")
|
||||
}
|
||||
|
||||
func formatDuration(seconds int64, outputType string) string {
|
||||
if isMachineReadable(outputType) {
|
||||
return fmt.Sprint(seconds)
|
||||
}
|
||||
return time.Duration(1e9 * seconds).String()
|
||||
}
|
||||
|
||||
func formatLabel(label *gitea.Label, allowColor bool, text string) string {
|
||||
colorProfile := termenv.Ascii
|
||||
if allowColor {
|
||||
colorProfile = termenv.EnvColorProfile()
|
||||
}
|
||||
if len(text) == 0 {
|
||||
text = label.Name
|
||||
}
|
||||
styled := termenv.String(text)
|
||||
styled = styled.Foreground(colorProfile.Color("#" + label.Color))
|
||||
return fmt.Sprint(styled)
|
||||
}
|
||||
|
||||
func formatPermission(p *gitea.Permission) string {
|
||||
if p.Admin {
|
||||
return "admin"
|
||||
} else if p.Push {
|
||||
return "write"
|
||||
}
|
||||
return "read"
|
||||
}
|
||||
|
||||
func formatUserName(u *gitea.User) string {
|
||||
if len(u.FullName) == 0 {
|
||||
return u.UserName
|
||||
}
|
||||
return u.FullName
|
||||
}
|
|
@ -6,7 +6,7 @@ package print
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
@ -21,71 +21,106 @@ func IssueDetails(issue *gitea.Issue) {
|
|||
issue.Poster.UserName,
|
||||
FormatTime(issue.Created),
|
||||
issue.Body,
|
||||
))
|
||||
}
|
||||
|
||||
// IssuesList prints a listing of issues
|
||||
func IssuesList(issues []*gitea.Issue, output string) {
|
||||
t := tableWithHeader(
|
||||
"Index",
|
||||
"Title",
|
||||
"State",
|
||||
"Author",
|
||||
"Milestone",
|
||||
"Updated",
|
||||
)
|
||||
|
||||
for _, issue := range issues {
|
||||
author := issue.Poster.FullName
|
||||
if len(author) == 0 {
|
||||
author = issue.Poster.UserName
|
||||
}
|
||||
mile := ""
|
||||
if issue.Milestone != nil {
|
||||
mile = issue.Milestone.Title
|
||||
}
|
||||
t.addRow(
|
||||
strconv.FormatInt(issue.Index, 10),
|
||||
issue.Title,
|
||||
string(issue.State),
|
||||
author,
|
||||
mile,
|
||||
FormatTime(issue.Updated),
|
||||
)
|
||||
}
|
||||
t.print(output)
|
||||
), issue.HTMLURL)
|
||||
}
|
||||
|
||||
// IssuesPullsList prints a listing of issues & pulls
|
||||
// TODO combine with IssuesList
|
||||
func IssuesPullsList(issues []*gitea.Issue, output string) {
|
||||
t := tableWithHeader(
|
||||
"Index",
|
||||
"State",
|
||||
"Kind",
|
||||
"Author",
|
||||
"Updated",
|
||||
"Title",
|
||||
)
|
||||
func IssuesPullsList(issues []*gitea.Issue, output string, fields []string) {
|
||||
printIssues(issues, output, fields)
|
||||
}
|
||||
|
||||
for _, issue := range issues {
|
||||
name := issue.Poster.FullName
|
||||
if len(name) == 0 {
|
||||
name = issue.Poster.UserName
|
||||
// IssueFields are all available fields to print with IssuesList()
|
||||
var IssueFields = []string{
|
||||
"index",
|
||||
"state",
|
||||
"kind",
|
||||
"author",
|
||||
"author-id",
|
||||
"url",
|
||||
|
||||
"title",
|
||||
"body",
|
||||
|
||||
"created",
|
||||
"updated",
|
||||
"deadline",
|
||||
|
||||
"assignees",
|
||||
"milestone",
|
||||
"labels",
|
||||
"comments",
|
||||
}
|
||||
|
||||
func printIssues(issues []*gitea.Issue, output string, fields []string) {
|
||||
labelMap := map[int64]string{}
|
||||
var printables = make([]printable, len(issues))
|
||||
|
||||
for i, x := range issues {
|
||||
// pre-serialize labels for performance
|
||||
for _, label := range x.Labels {
|
||||
if _, ok := labelMap[label.ID]; !ok {
|
||||
labelMap[label.ID] = formatLabel(label, !isMachineReadable(output), "")
|
||||
}
|
||||
}
|
||||
kind := "Issue"
|
||||
if issue.PullRequest != nil {
|
||||
kind = "Pull"
|
||||
}
|
||||
t.addRow(
|
||||
strconv.FormatInt(issue.Index, 10),
|
||||
string(issue.State),
|
||||
kind,
|
||||
name,
|
||||
FormatTime(issue.Updated),
|
||||
issue.Title,
|
||||
)
|
||||
// store items with printable interface
|
||||
printables[i] = &printableIssue{x, &labelMap}
|
||||
}
|
||||
|
||||
t := tableFromItems(fields, printables)
|
||||
t.print(output)
|
||||
}
|
||||
|
||||
type printableIssue struct {
|
||||
*gitea.Issue
|
||||
formattedLabels *map[int64]string
|
||||
}
|
||||
|
||||
func (x printableIssue) FormatField(field string) string {
|
||||
switch field {
|
||||
case "index":
|
||||
return fmt.Sprintf("%d", x.Index)
|
||||
case "state":
|
||||
return string(x.State)
|
||||
case "kind":
|
||||
if x.PullRequest != nil {
|
||||
return "Pull"
|
||||
}
|
||||
return "Issue"
|
||||
case "author":
|
||||
return formatUserName(x.Poster)
|
||||
case "author-id":
|
||||
return x.Poster.UserName
|
||||
case "url":
|
||||
return x.HTMLURL
|
||||
case "title":
|
||||
return x.Title
|
||||
case "body":
|
||||
return x.Body
|
||||
case "created":
|
||||
return FormatTime(x.Created)
|
||||
case "updated":
|
||||
return FormatTime(x.Updated)
|
||||
case "deadline":
|
||||
return FormatTime(*x.Deadline)
|
||||
case "milestone":
|
||||
if x.Milestone != nil {
|
||||
return x.Milestone.Title
|
||||
}
|
||||
return ""
|
||||
case "labels":
|
||||
var labels = make([]string, len(x.Labels))
|
||||
for i, l := range x.Labels {
|
||||
labels[i] = (*x.formattedLabels)[l.ID]
|
||||
}
|
||||
return strings.Join(labels, " ")
|
||||
case "assignees":
|
||||
var assignees = make([]string, len(x.Assignees))
|
||||
for i, a := range x.Assignees {
|
||||
assignees[i] = formatUserName(a)
|
||||
}
|
||||
return strings.Join(assignees, " ")
|
||||
case "comments":
|
||||
return fmt.Sprintf("%d", x.Comments)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -5,11 +5,9 @@
|
|||
package print
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/muesli/termenv"
|
||||
)
|
||||
|
||||
// LabelsList prints a listing of labels
|
||||
|
@ -21,14 +19,10 @@ func LabelsList(labels []*gitea.Label, output string) {
|
|||
"Description",
|
||||
)
|
||||
|
||||
p := termenv.ColorProfile()
|
||||
|
||||
for _, label := range labels {
|
||||
color := termenv.String(label.Color)
|
||||
|
||||
t.addRow(
|
||||
strconv.FormatInt(label.ID, 10),
|
||||
fmt.Sprint(color.Background(p.Color("#"+label.Color))),
|
||||
formatLabel(label, !isMachineReadable(output), label.Color),
|
||||
label.Name,
|
||||
label.Description,
|
||||
)
|
||||
|
|
|
@ -28,7 +28,7 @@ func LoginDetails(login *config.Login) {
|
|||
}
|
||||
in += fmt.Sprintf("\nCreated: %s", time.Unix(login.Created, 0).Format(time.RFC822))
|
||||
|
||||
outputMarkdown(in)
|
||||
outputMarkdown(in, "")
|
||||
}
|
||||
|
||||
// LoginsList prints a listing of logins
|
||||
|
|
|
@ -6,15 +6,27 @@ package print
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/charmbracelet/glamour"
|
||||
"golang.org/x/crypto/ssh/terminal"
|
||||
)
|
||||
|
||||
// outputMarkdown prints markdown to stdout, formatted for terminals.
|
||||
// If the input could not be parsed, it is printed unformatted, the error
|
||||
// is returned anyway.
|
||||
func outputMarkdown(markdown string) error {
|
||||
out, err := glamour.Render(markdown, "auto")
|
||||
func outputMarkdown(markdown string, baseURL string) error {
|
||||
renderer, err := glamour.NewTermRenderer(
|
||||
glamour.WithAutoStyle(),
|
||||
glamour.WithBaseURL(baseURL),
|
||||
glamour.WithWordWrap(getWordWrap()),
|
||||
)
|
||||
if err != nil {
|
||||
fmt.Printf(markdown)
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := renderer.Render(markdown)
|
||||
if err != nil {
|
||||
fmt.Printf(markdown)
|
||||
return err
|
||||
|
@ -22,3 +34,18 @@ func outputMarkdown(markdown string) error {
|
|||
fmt.Print(out)
|
||||
return nil
|
||||
}
|
||||
|
||||
// stolen from https://github.com/charmbracelet/glow/blob/e9d728c/main.go#L152-L165
|
||||
func getWordWrap() int {
|
||||
fd := int(os.Stdout.Fd())
|
||||
width := 80
|
||||
if terminal.IsTerminal(fd) {
|
||||
if w, _, err := terminal.GetSize(fd); err == nil {
|
||||
width = w
|
||||
}
|
||||
}
|
||||
if width > 120 {
|
||||
width = 120
|
||||
}
|
||||
return width
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func NotificationsList(news []*gitea.NotificationThread, output string, showRepo
|
|||
index = "#" + index
|
||||
}
|
||||
|
||||
item := []string{n.Subject.Type, index, n.Subject.Title}
|
||||
item := []string{string(n.Subject.Type), index, n.Subject.Title}
|
||||
if showRepository {
|
||||
item = append(item, n.Repository.FullName)
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package print
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// formatSize get kb in int and return string
|
||||
func formatSize(kb int64) string {
|
||||
if kb < 1024 {
|
||||
return fmt.Sprintf("%d Kb", kb)
|
||||
}
|
||||
mb := kb / 1024
|
||||
if mb < 1024 {
|
||||
return fmt.Sprintf("%d Mb", mb)
|
||||
}
|
||||
gb := mb / 1024
|
||||
if gb < 1024 {
|
||||
return fmt.Sprintf("%d Gb", gb)
|
||||
}
|
||||
return fmt.Sprintf("%d Tb", gb/1024)
|
||||
}
|
||||
|
||||
// FormatTime give a date-time in local timezone if available
|
||||
func FormatTime(t time.Time) string {
|
||||
location, err := time.LoadLocation("Local")
|
||||
if err != nil {
|
||||
return t.Format("2006-01-02 15:04 UTC")
|
||||
}
|
||||
return t.In(location).Format("2006-01-02 15:04")
|
||||
}
|
|
@ -76,7 +76,7 @@ func PullDetails(pr *gitea.PullRequest, reviews []*gitea.PullReview, ciStatus *g
|
|||
}
|
||||
}
|
||||
|
||||
outputMarkdown(out)
|
||||
outputMarkdown(out, pr.HTMLURL)
|
||||
}
|
||||
|
||||
func formatReviews(reviews []*gitea.PullReview) string {
|
||||
|
|
|
@ -6,91 +6,19 @@ package print
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
||||
type rp = *gitea.Repository
|
||||
type fieldFormatter = func(*gitea.Repository) string
|
||||
|
||||
var (
|
||||
fieldFormatters map[string]fieldFormatter
|
||||
|
||||
// RepoFields are the available fields to print with ReposList()
|
||||
RepoFields []string
|
||||
)
|
||||
|
||||
func init() {
|
||||
fieldFormatters = map[string]fieldFormatter{
|
||||
"description": func(r rp) string { return r.Description },
|
||||
"forks": func(r rp) string { return fmt.Sprintf("%d", r.Forks) },
|
||||
"id": func(r rp) string { return r.FullName },
|
||||
"name": func(r rp) string { return r.Name },
|
||||
"owner": func(r rp) string { return r.Owner.UserName },
|
||||
"stars": func(r rp) string { return fmt.Sprintf("%d", r.Stars) },
|
||||
"ssh": func(r rp) string { return r.SSHURL },
|
||||
"updated": func(r rp) string { return FormatTime(r.Updated) },
|
||||
"url": func(r rp) string { return r.HTMLURL },
|
||||
"permission": func(r rp) string {
|
||||
if r.Permissions.Admin {
|
||||
return "admin"
|
||||
} else if r.Permissions.Push {
|
||||
return "write"
|
||||
}
|
||||
return "read"
|
||||
},
|
||||
"type": func(r rp) string {
|
||||
if r.Fork {
|
||||
return "fork"
|
||||
}
|
||||
if r.Mirror {
|
||||
return "mirror"
|
||||
}
|
||||
return "source"
|
||||
},
|
||||
}
|
||||
|
||||
for f := range fieldFormatters {
|
||||
RepoFields = append(RepoFields, f)
|
||||
}
|
||||
}
|
||||
|
||||
// ReposList prints a listing of the repos
|
||||
func ReposList(repos []*gitea.Repository, output string, fields []string) {
|
||||
if len(repos) == 0 {
|
||||
fmt.Println("No repositories found")
|
||||
return
|
||||
var printables = make([]printable, len(repos))
|
||||
for i, r := range repos {
|
||||
printables[i] = &printableRepo{r}
|
||||
}
|
||||
|
||||
if len(fields) == 0 {
|
||||
fmt.Println("No fields to print")
|
||||
return
|
||||
}
|
||||
|
||||
formatters := make([]fieldFormatter, len(fields))
|
||||
values := make([][]string, len(repos))
|
||||
|
||||
// find field format functions by header name
|
||||
for i, f := range fields {
|
||||
if formatter, ok := fieldFormatters[strings.ToLower(f)]; ok {
|
||||
formatters[i] = formatter
|
||||
} else {
|
||||
log.Fatalf("invalid field '%s'", f)
|
||||
}
|
||||
}
|
||||
|
||||
// extract values from each repo and store them in 2D table
|
||||
for i, repo := range repos {
|
||||
values[i] = make([]string, len(formatters))
|
||||
for j, format := range formatters {
|
||||
values[i][j] = format(repo)
|
||||
}
|
||||
}
|
||||
|
||||
t := table{headers: fields, values: values}
|
||||
t := tableFromItems(fields, printables)
|
||||
t.print(output)
|
||||
}
|
||||
|
||||
|
@ -142,7 +70,7 @@ func RepoDetails(repo *gitea.Repository, topics []string) {
|
|||
|
||||
perm := fmt.Sprintf(
|
||||
"- Permission:\t%s\n",
|
||||
fieldFormatters["permission"](repo),
|
||||
formatPermission(repo.Permissions),
|
||||
)
|
||||
|
||||
var tops string
|
||||
|
@ -159,5 +87,56 @@ func RepoDetails(repo *gitea.Repository, topics []string) {
|
|||
urls,
|
||||
perm,
|
||||
tops,
|
||||
))
|
||||
), repo.HTMLURL)
|
||||
}
|
||||
|
||||
// RepoFields are the available fields to print with ReposList()
|
||||
var RepoFields = []string{
|
||||
"description",
|
||||
"forks",
|
||||
"id",
|
||||
"name",
|
||||
"owner",
|
||||
"stars",
|
||||
"ssh",
|
||||
"updated",
|
||||
"url",
|
||||
"permission",
|
||||
"type",
|
||||
}
|
||||
|
||||
type printableRepo struct{ *gitea.Repository }
|
||||
|
||||
func (x printableRepo) FormatField(field string) string {
|
||||
switch field {
|
||||
case "description":
|
||||
return x.Description
|
||||
case "forks":
|
||||
return fmt.Sprintf("%d", x.Forks)
|
||||
case "id":
|
||||
return x.FullName
|
||||
case "name":
|
||||
return x.Name
|
||||
case "owner":
|
||||
return x.Owner.UserName
|
||||
case "stars":
|
||||
return fmt.Sprintf("%d", x.Stars)
|
||||
case "ssh":
|
||||
return x.SSHURL
|
||||
case "updated":
|
||||
return FormatTime(x.Updated)
|
||||
case "url":
|
||||
return x.HTMLURL
|
||||
case "permission":
|
||||
return formatPermission(x.Permissions)
|
||||
case "type":
|
||||
if x.Fork {
|
||||
return "fork"
|
||||
}
|
||||
if x.Mirror {
|
||||
return "mirror"
|
||||
}
|
||||
return "source"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -22,6 +22,24 @@ type table struct {
|
|||
sortColumn uint // ↑
|
||||
}
|
||||
|
||||
// printable can be implemented for structs to put fields dynamically into a table
|
||||
type printable interface {
|
||||
FormatField(field string) string
|
||||
}
|
||||
|
||||
// high level api to print a table of items with dynamic fields
|
||||
func tableFromItems(fields []string, values []printable) table {
|
||||
t := table{headers: fields}
|
||||
for _, v := range values {
|
||||
row := make([]string, len(fields))
|
||||
for i, f := range fields {
|
||||
row[i] = v.FormatField(f)
|
||||
}
|
||||
t.addRowSlice(row)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func tableWithHeader(header ...string) table {
|
||||
return table{headers: header}
|
||||
}
|
||||
|
@ -54,16 +72,16 @@ func (t table) Less(i, j int) bool {
|
|||
}
|
||||
|
||||
func (t *table) print(output string) {
|
||||
switch {
|
||||
case output == "" || output == "table":
|
||||
switch output {
|
||||
case "", "table":
|
||||
outputtable(t.headers, t.values)
|
||||
case output == "csv":
|
||||
case "csv":
|
||||
outputdsv(t.headers, t.values, ",")
|
||||
case output == "simple":
|
||||
case "simple":
|
||||
outputsimple(t.headers, t.values)
|
||||
case output == "tsv":
|
||||
case "tsv":
|
||||
outputdsv(t.headers, t.values, "\t")
|
||||
case output == "yaml":
|
||||
case "yml", "yaml":
|
||||
outputyaml(t.headers, t.values)
|
||||
default:
|
||||
fmt.Printf("unknown output type '" + output + "', available types are:\n- csv: comma-separated values\n- simple: space-separated values\n- table: auto-aligned table format (default)\n- tsv: tab-separated values\n- yaml: YAML format\n")
|
||||
|
@ -119,3 +137,11 @@ func outputyaml(headers []string, values [][]string) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isMachineReadable(outputFormat string) bool {
|
||||
switch outputFormat {
|
||||
case "yml", "yaml", "csv":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -6,50 +6,59 @@ package print
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
||||
func formatDuration(seconds int64, outputType string) string {
|
||||
switch outputType {
|
||||
case "yaml":
|
||||
case "csv":
|
||||
return fmt.Sprint(seconds)
|
||||
}
|
||||
return time.Duration(1e9 * seconds).String()
|
||||
}
|
||||
|
||||
// TrackedTimesList print list of tracked times to stdout
|
||||
func TrackedTimesList(times []*gitea.TrackedTime, outputType string, from, until time.Time, printTotal bool) {
|
||||
tab := tableWithHeader(
|
||||
"Created",
|
||||
"Issue",
|
||||
"User",
|
||||
"Duration",
|
||||
)
|
||||
func TrackedTimesList(times []*gitea.TrackedTime, outputType string, fields []string, printTotal bool) {
|
||||
var printables = make([]printable, len(times))
|
||||
var totalDuration int64
|
||||
|
||||
for _, t := range times {
|
||||
if !from.IsZero() && from.After(t.Created) {
|
||||
continue
|
||||
}
|
||||
if !until.IsZero() && until.Before(t.Created) {
|
||||
continue
|
||||
}
|
||||
|
||||
for i, t := range times {
|
||||
totalDuration += t.Time
|
||||
tab.addRow(
|
||||
FormatTime(t.Created),
|
||||
"#"+strconv.FormatInt(t.Issue.Index, 10),
|
||||
t.UserName,
|
||||
formatDuration(t.Time, outputType),
|
||||
)
|
||||
printables[i] = &printableTrackedTime{t, outputType}
|
||||
}
|
||||
t := tableFromItems(fields, printables)
|
||||
|
||||
if printTotal {
|
||||
tab.addRow("TOTAL", "", "", formatDuration(totalDuration, outputType))
|
||||
total := make([]string, len(fields))
|
||||
total[0] = "TOTAL"
|
||||
total[len(fields)-1] = formatDuration(totalDuration, outputType)
|
||||
t.addRowSlice(total)
|
||||
}
|
||||
tab.print(outputType)
|
||||
|
||||
t.print(outputType)
|
||||
}
|
||||
|
||||
// TrackedTimeFields contains all available fields for printing of tracked times.
|
||||
var TrackedTimeFields = []string{
|
||||
"id",
|
||||
"created",
|
||||
"repo",
|
||||
"issue",
|
||||
"user",
|
||||
"duration",
|
||||
}
|
||||
|
||||
type printableTrackedTime struct {
|
||||
*gitea.TrackedTime
|
||||
outputFormat string
|
||||
}
|
||||
|
||||
func (t printableTrackedTime) FormatField(field string) string {
|
||||
switch field {
|
||||
case "id":
|
||||
return fmt.Sprintf("%d", t.ID)
|
||||
case "created":
|
||||
return FormatTime(t.Created)
|
||||
case "repo":
|
||||
return t.Issue.Repository.FullName
|
||||
case "issue":
|
||||
return fmt.Sprintf("#%d", t.Issue.Index)
|
||||
case "user":
|
||||
return t.UserName
|
||||
case "duration":
|
||||
return formatDuration(t.Time, t.outputFormat)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -12,26 +12,15 @@ import (
|
|||
"code.gitea.io/tea/modules/print"
|
||||
)
|
||||
|
||||
// CreateIssue creates a PR in the given repo and prints the result
|
||||
func CreateIssue(login *config.Login, repoOwner, repoName, title, description string) error {
|
||||
// CreateIssue creates an issue in the given repo and prints the result
|
||||
func CreateIssue(login *config.Login, repoOwner, repoName string, opts gitea.CreateIssueOption) error {
|
||||
|
||||
// title is required
|
||||
if len(title) == 0 {
|
||||
if len(opts.Title) == 0 {
|
||||
return fmt.Errorf("Title is required")
|
||||
}
|
||||
|
||||
issue, _, err := login.Client().CreateIssue(repoOwner, repoName, gitea.CreateIssueOption{
|
||||
Title: title,
|
||||
Body: description,
|
||||
// TODO:
|
||||
//Assignee string `json:"assignee"`
|
||||
//Assignees []string `json:"assignees"`
|
||||
//Deadline *time.Time `json:"due_date"`
|
||||
//Milestone int64 `json:"milestone"`
|
||||
//Labels []int64 `json:"labels"`
|
||||
//Closed bool `json:"closed"`
|
||||
})
|
||||
|
||||
issue, _, err := login.Client().CreateIssue(repoOwner, repoName, opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create issue: %s", err)
|
||||
}
|
||||
|
|
25
modules/task/labels.go
Normal file
25
modules/task/labels.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package task
|
||||
|
||||
import (
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
)
|
||||
|
||||
// ResolveLabelNames returns a list of label IDs for a given list of label names
|
||||
func ResolveLabelNames(client *gitea.Client, owner, repo string, labelNames []string) ([]int64, error) {
|
||||
labelIDs := make([]int64, len(labelNames))
|
||||
labels, _, err := client.ListRepoLabels(owner, repo, gitea.ListLabelsOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, l := range labels {
|
||||
if utils.Contains(labelNames, l.Name) {
|
||||
labelIDs = append(labelIDs, l.ID)
|
||||
}
|
||||
}
|
||||
return labelIDs, nil
|
||||
}
|
37
modules/task/milestone_create.go
Normal file
37
modules/task/milestone_create.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package task
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/tea/modules/config"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
||||
// CreateMilestone creates a milestone in the given repo and prints the result
|
||||
func CreateMilestone(login *config.Login, repoOwner, repoName, title, description string, deadline *time.Time, state gitea.StateType) error {
|
||||
|
||||
// title is required
|
||||
if len(title) == 0 {
|
||||
return fmt.Errorf("Title is required")
|
||||
}
|
||||
|
||||
mile, _, err := login.Client().CreateMilestone(repoOwner, repoName, gitea.CreateMilestoneOption{
|
||||
Title: title,
|
||||
Description: description,
|
||||
Deadline: deadline,
|
||||
State: state,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
print.MilestoneDetails(mile)
|
||||
return nil
|
||||
}
|
|
@ -7,43 +7,42 @@ package task
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"code.gitea.io/tea/modules/config"
|
||||
local_git "code.gitea.io/tea/modules/git"
|
||||
"code.gitea.io/tea/modules/workaround"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
git_config "github.com/go-git/go-git/v5/config"
|
||||
git_plumbing "github.com/go-git/go-git/v5/plumbing"
|
||||
)
|
||||
|
||||
// PullCheckout checkout current workdir to the head branch of specified pull request
|
||||
func PullCheckout(login *config.Login, repoOwner, repoName string, index int64, callback func(string) (string, error)) error {
|
||||
func PullCheckout(
|
||||
login *config.Login,
|
||||
repoOwner, repoName string,
|
||||
forceCreateBranch bool,
|
||||
index int64,
|
||||
callback func(string) (string, error),
|
||||
) error {
|
||||
client := login.Client()
|
||||
pr, _, err := client.GetPullRequest(repoOwner, repoName, index)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't fetch PR: %s", err)
|
||||
}
|
||||
if err := workaround.FixPullHeadSha(client, pr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// FIXME: should use ctx.LocalRepo..?
|
||||
localRepo, err := local_git.RepoForWorkdir()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// fetch PR source-localRepo & -branch from gitea
|
||||
pr, _, err := client.GetPullRequest(repoOwner, repoName, index)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
remoteURL := pr.Head.Repository.CloneURL
|
||||
if len(login.SSHKey) != 0 {
|
||||
// login.SSHKey is nonempty, if user specified a key manually or we automatically
|
||||
// found a matching private key on this machine during login creation.
|
||||
// this means, we are very likely to have a working ssh setup.
|
||||
remoteURL = pr.Head.Repository.SSHURL
|
||||
}
|
||||
|
||||
// try to find a matching existing branch, otherwise return branch in pulls/ namespace
|
||||
localBranchName := fmt.Sprintf("pulls/%v-%v", index, pr.Head.Ref)
|
||||
if b, _ := localRepo.TeaFindBranchBySha(pr.Head.Sha, remoteURL); b != nil {
|
||||
localBranchName = b.Name
|
||||
}
|
||||
|
||||
// find or create a matching remote
|
||||
remoteURL := remoteURLForPR(login, pr)
|
||||
newRemoteName := fmt.Sprintf("pulls/%v", pr.Head.Repository.Owner.UserName)
|
||||
|
||||
// verify related remote is in local repo, otherwise add it
|
||||
localRemote, err := localRepo.GetOrCreateRemote(remoteURL, newRemoteName)
|
||||
if err != nil {
|
||||
|
@ -51,32 +50,118 @@ func PullCheckout(login *config.Login, repoOwner, repoName string, index int64,
|
|||
}
|
||||
localRemoteName := localRemote.Config().Name
|
||||
|
||||
localRemoteBranchName, err := doPRFetch(login, pr, localRepo, localRemote, callback)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return doPRCheckout(localRepo, pr, localRemoteName, localRemoteBranchName, remoteURL, forceCreateBranch)
|
||||
}
|
||||
|
||||
func isRemoteDeleted(pr *gitea.PullRequest) bool {
|
||||
return pr.Head.Ref == fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
||||
}
|
||||
|
||||
func remoteURLForPR(login *config.Login, pr *gitea.PullRequest) string {
|
||||
repo := pr.Head.Repository
|
||||
if isRemoteDeleted(pr) {
|
||||
repo = pr.Base.Repository
|
||||
}
|
||||
if len(login.SSHKey) != 0 {
|
||||
// login.SSHKey is nonempty, if user specified a key manually or we automatically
|
||||
// found a matching private key on this machine during login creation.
|
||||
// this means, we are very likely to have a working ssh setup.
|
||||
return repo.SSHURL
|
||||
}
|
||||
return repo.CloneURL
|
||||
}
|
||||
|
||||
func doPRFetch(
|
||||
login *config.Login,
|
||||
pr *gitea.PullRequest,
|
||||
localRepo *local_git.TeaRepo,
|
||||
localRemote *git.Remote,
|
||||
callback func(string) (string, error),
|
||||
) (string, error) {
|
||||
localRemoteName := localRemote.Config().Name
|
||||
localBranchName := pr.Head.Ref
|
||||
// get auth & fetch remote via its configured protocol
|
||||
url, err := localRepo.TeaRemoteURL(localRemoteName)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
auth, err := local_git.GetAuthForURL(url, login.Token, login.SSHKey, callback)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
fmt.Printf("Fetching PR %v (head %s:%s) from remote '%s'\n", index, url, pr.Head.Ref, localRemoteName)
|
||||
err = localRemote.Fetch(&git.FetchOptions{Auth: auth})
|
||||
fetchOpts := &git.FetchOptions{Auth: auth}
|
||||
if isRemoteDeleted(pr) {
|
||||
// When the head branch is already deleted, pr.Head.Ref points to
|
||||
// `refs/pull/<idx>/head`, where the commits stay available.
|
||||
// This ref must be fetched explicitly, and does not allow pushing, so we use it
|
||||
// only in this case as fallback.
|
||||
localBranchName = fmt.Sprintf("pulls/%d", pr.Index)
|
||||
fetchOpts.RefSpecs = []git_config.RefSpec{git_config.RefSpec(fmt.Sprintf("%s:refs/remotes/%s/%s",
|
||||
pr.Head.Ref,
|
||||
localRemoteName,
|
||||
localBranchName,
|
||||
))}
|
||||
}
|
||||
fmt.Printf("Fetching PR %v (head %s:%s) from remote '%s'\n", pr.Index, url, pr.Head.Ref, localRemoteName)
|
||||
|
||||
err = localRemote.Fetch(fetchOpts)
|
||||
if err == git.NoErrAlreadyUpToDate {
|
||||
fmt.Println(err)
|
||||
} else if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
|
||||
// checkout local branch
|
||||
err = localRepo.TeaCreateBranch(localBranchName, pr.Head.Ref, localRemoteName)
|
||||
if err == nil {
|
||||
fmt.Printf("Created branch '%s'\n", localBranchName)
|
||||
} else if err == git.ErrBranchExists {
|
||||
fmt.Println("There may be changes since you last checked out, run `git pull` to get them.")
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return localRepo.TeaCheckout(localBranchName)
|
||||
return localBranchName, nil
|
||||
}
|
||||
|
||||
func doPRCheckout(
|
||||
localRepo *local_git.TeaRepo,
|
||||
pr *gitea.PullRequest,
|
||||
localRemoteName,
|
||||
localRemoteBranchName,
|
||||
remoteURL string,
|
||||
forceCreateBranch bool,
|
||||
) error {
|
||||
// determine the ref to checkout, depending on existence of a matching commit on a local branch
|
||||
var info string
|
||||
var checkoutRef git_plumbing.ReferenceName
|
||||
|
||||
if b, _ := localRepo.TeaFindBranchBySha(pr.Head.Sha, remoteURL); b != nil {
|
||||
|
||||
// if a matching branch exists, use that
|
||||
checkoutRef = git_plumbing.NewBranchReferenceName(b.Name)
|
||||
info = fmt.Sprintf("Found matching local branch %s, checking it out", checkoutRef.Short())
|
||||
|
||||
} else if forceCreateBranch {
|
||||
|
||||
// create a branch if wanted
|
||||
localBranchName := fmt.Sprintf("pulls/%v", pr.Index)
|
||||
if isRemoteDeleted(pr) {
|
||||
localBranchName += "-" + pr.Head.Ref
|
||||
}
|
||||
checkoutRef = git_plumbing.NewBranchReferenceName(localBranchName)
|
||||
if err := localRepo.TeaCreateBranch(localBranchName, localRemoteBranchName, localRemoteName); err == nil {
|
||||
info = fmt.Sprintf("Created branch '%s'\n", localBranchName)
|
||||
} else if err == git.ErrBranchExists {
|
||||
info = "There may be changes since you last checked out, run `git pull` to get them."
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// use the remote tracking branch
|
||||
checkoutRef = git_plumbing.NewRemoteReferenceName(localRemoteName, localRemoteBranchName)
|
||||
info = fmt.Sprintf(
|
||||
"Checking out remote tracking branch %s. To make changes, create a new branch:\n git checkout %s",
|
||||
checkoutRef.String(), localRemoteBranchName)
|
||||
|
||||
}
|
||||
|
||||
fmt.Println(info)
|
||||
return localRepo.TeaCheckout(checkoutRef)
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@ import (
|
|||
|
||||
"code.gitea.io/tea/modules/config"
|
||||
local_git "code.gitea.io/tea/modules/git"
|
||||
"code.gitea.io/tea/modules/workaround"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
git_config "github.com/go-git/go-git/v5/config"
|
||||
git_plumbing "github.com/go-git/go-git/v5/plumbing"
|
||||
)
|
||||
|
||||
// PullClean deletes local & remote feature-branches for a closed pull
|
||||
|
@ -19,6 +21,9 @@ func PullClean(login *config.Login, repoOwner, repoName string, index int64, ign
|
|||
client := login.Client()
|
||||
|
||||
repo, _, err := client.GetRepo(repoOwner, repoName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defaultBranch := repo.DefaultBranch
|
||||
if len(defaultBranch) == 0 {
|
||||
defaultBranch = "master"
|
||||
|
@ -29,11 +34,21 @@ func PullClean(login *config.Login, repoOwner, repoName string, index int64, ign
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := workaround.FixPullHeadSha(client, pr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if pr.State == gitea.StateOpen {
|
||||
return fmt.Errorf("PR is still open, won't delete branches")
|
||||
}
|
||||
|
||||
// IDEA: abort if PR.Head.Repository.CloneURL does not match login.URL?
|
||||
// if remote head branch is already deleted, pr.Head.Ref points to "pulls/<idx>/head"
|
||||
remoteBranch := pr.Head.Ref
|
||||
remoteDeleted := remoteBranch == fmt.Sprintf("refs/pull/%d/head", pr.Index)
|
||||
if remoteDeleted {
|
||||
remoteBranch = pr.Head.Name // this still holds the original branch name
|
||||
fmt.Printf("Remote branch '%s' already deleted.\n", remoteBranch)
|
||||
}
|
||||
|
||||
r, err := local_git.RepoForWorkdir()
|
||||
if err != nil {
|
||||
|
@ -43,7 +58,7 @@ func PullClean(login *config.Login, repoOwner, repoName string, index int64, ign
|
|||
// find a branch with matching sha or name, that has a remote matching the repo url
|
||||
var branch *git_config.Branch
|
||||
if ignoreSHA {
|
||||
branch, err = r.TeaFindBranchByName(pr.Head.Ref, pr.Head.Repository.CloneURL)
|
||||
branch, err = r.TeaFindBranchByName(remoteBranch, pr.Head.Repository.CloneURL)
|
||||
} else {
|
||||
branch, err = r.TeaFindBranchBySha(pr.Head.Sha, pr.Head.Repository.CloneURL)
|
||||
}
|
||||
|
@ -52,12 +67,12 @@ func PullClean(login *config.Login, repoOwner, repoName string, index int64, ign
|
|||
}
|
||||
if branch == nil {
|
||||
if ignoreSHA {
|
||||
return fmt.Errorf("Remote branch %s not found in local repo", pr.Head.Ref)
|
||||
return fmt.Errorf("Remote branch %s not found in local repo", remoteBranch)
|
||||
}
|
||||
return fmt.Errorf(`Remote branch %s not found in local repo.
|
||||
Either you don't track this PR, or the local branch has diverged from the remote.
|
||||
If you still want to continue & are sure you don't loose any important commits,
|
||||
call me again with the --ignore-sha flag`, pr.Head.Ref)
|
||||
call me again with the --ignore-sha flag`, remoteBranch)
|
||||
}
|
||||
|
||||
// prepare deletion of local branch:
|
||||
|
@ -67,20 +82,30 @@ call me again with the --ignore-sha flag`, pr.Head.Ref)
|
|||
}
|
||||
if headRef.Name().Short() == branch.Name {
|
||||
fmt.Printf("Checking out '%s' to delete local branch '%s'\n", defaultBranch, branch.Name)
|
||||
if err = r.TeaCheckout(defaultBranch); err != nil {
|
||||
ref := git_plumbing.NewBranchReferenceName(defaultBranch)
|
||||
if err = r.TeaCheckout(ref); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// remove local & remote branch
|
||||
fmt.Printf("Deleting local branch %s and remote branch %s\n", branch.Name, pr.Head.Ref)
|
||||
url, err := r.TeaRemoteURL(branch.Remote)
|
||||
fmt.Printf("Deleting local branch %s\n", branch.Name)
|
||||
err = r.TeaDeleteLocalBranch(branch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
auth, err := local_git.GetAuthForURL(url, login.Token, login.SSHKey, callback)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
if !remoteDeleted && pr.Head.Repository.Permissions.Push {
|
||||
fmt.Printf("Deleting remote branch %s\n", remoteBranch)
|
||||
url, err := r.TeaRemoteURL(branch.Remote)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
auth, err := local_git.GetAuthForURL(url, login.Token, login.SSHKey, callback)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = r.TeaDeleteRemoteBranch(branch.Remote, remoteBranch, auth)
|
||||
}
|
||||
return r.TeaDeleteBranch(branch, pr.Head.Ref, auth)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -13,26 +13,16 @@ import (
|
|||
local_git "code.gitea.io/tea/modules/git"
|
||||
"code.gitea.io/tea/modules/print"
|
||||
"code.gitea.io/tea/modules/utils"
|
||||
|
||||
"github.com/go-git/go-git/v5"
|
||||
)
|
||||
|
||||
// CreatePull creates a PR in the given repo and prints the result
|
||||
func CreatePull(login *config.Login, repoOwner, repoName, base, head, title, description string) error {
|
||||
|
||||
func CreatePull(login *config.Login, repoOwner, repoName, base, head string, opts *gitea.CreateIssueOption) error {
|
||||
// open local git repo
|
||||
localRepo, err := local_git.RepoForWorkdir()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not open local repo: %s", err)
|
||||
}
|
||||
|
||||
// push if possible
|
||||
fmt.Println("git push")
|
||||
err = localRepo.Push(&git.PushOptions{})
|
||||
if err != nil && err != git.NoErrAlreadyUpToDate {
|
||||
fmt.Printf("Error occurred during 'git push':\n%s\n", err.Error())
|
||||
}
|
||||
|
||||
// default is default branch
|
||||
if len(base) == 0 {
|
||||
base, err = GetDefaultPRBase(login, repoOwner, repoName)
|
||||
|
@ -57,19 +47,23 @@ func CreatePull(login *config.Login, repoOwner, repoName, base, head, title, des
|
|||
}
|
||||
|
||||
// default is head branch name
|
||||
if len(title) == 0 {
|
||||
title = GetDefaultPRTitle(head)
|
||||
if len(opts.Title) == 0 {
|
||||
opts.Title = GetDefaultPRTitle(head)
|
||||
}
|
||||
// title is required
|
||||
if len(title) == 0 {
|
||||
if len(opts.Title) == 0 {
|
||||
return fmt.Errorf("Title is required")
|
||||
}
|
||||
|
||||
pr, _, err := login.Client().CreatePullRequest(repoOwner, repoName, gitea.CreatePullRequestOption{
|
||||
Head: head,
|
||||
Base: base,
|
||||
Title: title,
|
||||
Body: description,
|
||||
Head: head,
|
||||
Base: base,
|
||||
Title: opts.Title,
|
||||
Body: opts.Body,
|
||||
Assignees: opts.Assignees,
|
||||
Labels: opts.Labels,
|
||||
Milestone: opts.Milestone,
|
||||
Deadline: opts.Deadline,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
@ -92,32 +86,23 @@ func GetDefaultPRBase(login *config.Login, owner, repo string) (string, error) {
|
|||
return meta.DefaultBranch, nil
|
||||
}
|
||||
|
||||
// GetDefaultPRHead uses the currently checked out branch, checks if
|
||||
// a remote currently holds the commit it points to, extracts the owner
|
||||
// from its URL, and assembles the result to a valid head spec for gitea.
|
||||
// GetDefaultPRHead uses the currently checked out branch, tries to find a remote
|
||||
// that has a branch with the same name, and extracts the owner from its URL.
|
||||
// If no remote matches, owner is empty, meaning same as head repo owner.
|
||||
func GetDefaultPRHead(localRepo *local_git.TeaRepo) (owner, branch string, err error) {
|
||||
headBranch, err := localRepo.Head()
|
||||
if err != nil {
|
||||
if branch, err = localRepo.TeaGetCurrentBranchName(); err != nil {
|
||||
return
|
||||
}
|
||||
sha := headBranch.Hash().String()
|
||||
|
||||
remote, err := localRepo.TeaFindBranchRemote("", sha)
|
||||
remote, err := localRepo.TeaFindBranchRemote(branch, "")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("could not determine remote for current branch: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if remote == nil {
|
||||
// if no remote branch is found for the local hash, we abort:
|
||||
// user has probably not configured a remote for the local branch,
|
||||
// or local branch does not represent remote state.
|
||||
err = fmt.Errorf("no matching remote found for this branch. try git push -u <remote> <branch>")
|
||||
return
|
||||
}
|
||||
|
||||
branch, err = localRepo.TeaGetCurrentBranchName()
|
||||
if err != nil {
|
||||
// if no remote branch is found for the local branch,
|
||||
// we leave owner empty, meaning "use same repo as head" to gitea.
|
||||
return
|
||||
}
|
||||
|
||||
|
|
131
modules/task/pull_review.go
Normal file
131
modules/task/pull_review.go
Normal file
|
@ -0,0 +1,131 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package task
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/tea/modules/context"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
unidiff "gitea.com/noerw/unidiff-comments"
|
||||
)
|
||||
|
||||
var diffReviewHelp = `# This is the current diff of PR #%d on %s.
|
||||
# To add code comments, just insert a line inside the diff with your comment,
|
||||
# prefixed with '# '. For example:
|
||||
#
|
||||
# - foo: string,
|
||||
# - bar: string,
|
||||
# + foo: int,
|
||||
# # This is a code comment
|
||||
# + bar: int,
|
||||
|
||||
`
|
||||
|
||||
// CreatePullReview submits a review for a PR
|
||||
func CreatePullReview(ctx *context.TeaContext, idx int64, status gitea.ReviewStateType, comment string, codeComments []gitea.CreatePullReviewComment) error {
|
||||
c := ctx.Login.Client()
|
||||
|
||||
review, _, err := c.CreatePullReview(ctx.Owner, ctx.Repo, idx, gitea.CreatePullReviewOptions{
|
||||
State: status,
|
||||
Body: comment,
|
||||
Comments: codeComments,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println(review.HTMLURL)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SavePullDiff fetches the diff of a pull request and stores it as a temporary file.
|
||||
// The path to the file is returned.
|
||||
func SavePullDiff(ctx *context.TeaContext, idx int64) (string, error) {
|
||||
diff, _, err := ctx.Login.Client().GetPullRequestDiff(ctx.Owner, ctx.Repo, idx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
writer, err := ioutil.TempFile(os.TempDir(), fmt.Sprintf("pull-%d-review-*.diff", idx))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer writer.Close()
|
||||
|
||||
// add a help header before the actual diff
|
||||
if _, err = fmt.Fprintf(writer, diffReviewHelp, idx, ctx.RepoSlug); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if _, err = writer.Write(diff); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return writer.Name(), nil
|
||||
}
|
||||
|
||||
// ParseDiffComments reads a diff, extracts comments from it & returns them in a gitea compatible struct
|
||||
func ParseDiffComments(diffFile string) ([]gitea.CreatePullReviewComment, error) {
|
||||
reader, err := os.Open(diffFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't load diff: %s", err)
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
changeset, err := unidiff.ReadChangeset(reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't parse patch: %s", err)
|
||||
}
|
||||
|
||||
var comments []gitea.CreatePullReviewComment
|
||||
for _, file := range changeset.Diffs {
|
||||
for _, c := range file.LineComments {
|
||||
comment := gitea.CreatePullReviewComment{
|
||||
Body: c.Text,
|
||||
Path: c.Anchor.Path,
|
||||
}
|
||||
comment.Path = strings.TrimPrefix(comment.Path, "a/")
|
||||
comment.Path = strings.TrimPrefix(comment.Path, "b/")
|
||||
switch c.Anchor.LineType {
|
||||
case "ADDED":
|
||||
comment.NewLineNum = c.Anchor.Line
|
||||
case "REMOVED", "CONTEXT":
|
||||
comment.OldLineNum = c.Anchor.Line
|
||||
}
|
||||
comments = append(comments, comment)
|
||||
}
|
||||
}
|
||||
|
||||
return comments, nil
|
||||
}
|
||||
|
||||
// OpenFileInEditor opens filename in a text editor, and blocks until the editor terminates.
|
||||
func OpenFileInEditor(filename string) error {
|
||||
editor := os.Getenv("VISUAL")
|
||||
if editor == "" {
|
||||
editor = os.Getenv("EDITOR")
|
||||
if editor == "" {
|
||||
fmt.Println("No $VISUAL or $EDITOR env is set, defaulting to vim")
|
||||
editor = "vi"
|
||||
}
|
||||
}
|
||||
|
||||
// Get the full executable path for the editor.
|
||||
executable, err := exec.LookPath(editor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := exec.Command(executable, filename)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
|
||||
return cmd.Run()
|
||||
}
|
|
@ -26,15 +26,31 @@ func PathExists(path string) (bool, error) {
|
|||
|
||||
// FileExist returns whether the given file exists or not
|
||||
func FileExist(fileName string) (bool, error) {
|
||||
f, err := os.Stat(fileName)
|
||||
return exists(fileName, false)
|
||||
}
|
||||
|
||||
// DirExists returns whether the given file exists or not
|
||||
func DirExists(path string) (bool, error) {
|
||||
return exists(path, true)
|
||||
}
|
||||
|
||||
func exists(path string, expectDir bool) (bool, error) {
|
||||
f, err := os.Stat(path)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return false, nil
|
||||
} else if err.(*os.PathError).Err.Error() == "not a directory" {
|
||||
// some middle segment of path is a file, cannot traverse
|
||||
// FIXME: catches error on linux; go does not provide a way to catch this properly..
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
if f.IsDir() {
|
||||
isDir := f.IsDir()
|
||||
if isDir && !expectDir {
|
||||
return false, errors.New("A directory with the same name exists")
|
||||
} else if !isDir && expectDir {
|
||||
return false, errors.New("A file with the same name exists")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
|
20
modules/utils/utils.go
Normal file
20
modules/utils/utils.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2020 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package utils
|
||||
|
||||
// Contains checks containment
|
||||
func Contains(haystack []string, needle string) bool {
|
||||
return IndexOf(haystack, needle) != -1
|
||||
}
|
||||
|
||||
// IndexOf returns the index of first occurrence of needle in haystack
|
||||
func IndexOf(haystack []string, needle string) int {
|
||||
for i, s := range haystack {
|
||||
if s == needle {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
30
modules/workaround/pull.go
Normal file
30
modules/workaround/pull.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package workaround
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
)
|
||||
|
||||
// FixPullHeadSha is a workaround for https://github.com/go-gitea/gitea/issues/12675
|
||||
// When no head sha is available, this is because the branch got deleted in the base repo.
|
||||
// pr.Head.Ref points in this case not to the head repo branch name, but the base repo ref,
|
||||
// which stays available to resolve the commit sha.
|
||||
func FixPullHeadSha(client *gitea.Client, pr *gitea.PullRequest) error {
|
||||
owner := pr.Base.Repository.Owner.UserName
|
||||
repo := pr.Base.Repository.Name
|
||||
if pr.Head != nil && pr.Head.Sha == "" {
|
||||
refs, _, err := client.GetRepoRefs(owner, repo, pr.Head.Ref)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(refs) == 0 {
|
||||
return fmt.Errorf("unable to resolve PR ref '%s'", pr.Head.Ref)
|
||||
}
|
||||
pr.Head.Sha = refs[0].Object.SHA
|
||||
}
|
||||
return nil
|
||||
}
|
3
vendor/code.gitea.io/sdk/gitea/admin_cron.go
generated
vendored
3
vendor/code.gitea.io/sdk/gitea/admin_cron.go
generated
vendored
|
@ -39,6 +39,9 @@ func (c *Client) RunCronTasks(task string) (*Response, error) {
|
|||
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&task); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("POST", fmt.Sprintf("/admin/cron/%s", task), jsonHeader, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
3
vendor/code.gitea.io/sdk/gitea/admin_org.go
generated
vendored
3
vendor/code.gitea.io/sdk/gitea/admin_org.go
generated
vendored
|
@ -26,6 +26,9 @@ func (c *Client) AdminListOrgs(opt AdminListOrgsOptions) ([]*Organization, *Resp
|
|||
|
||||
// AdminCreateOrg create an organization
|
||||
func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
3
vendor/code.gitea.io/sdk/gitea/admin_repo.go
generated
vendored
3
vendor/code.gitea.io/sdk/gitea/admin_repo.go
generated
vendored
|
@ -12,6 +12,9 @@ import (
|
|||
|
||||
// AdminCreateRepo create a repo
|
||||
func (c *Client) AdminCreateRepo(user string, opt CreateRepoOption) (*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
62
vendor/code.gitea.io/sdk/gitea/admin_user.go
generated
vendored
62
vendor/code.gitea.io/sdk/gitea/admin_user.go
generated
vendored
|
@ -26,14 +26,15 @@ func (c *Client) AdminListUsers(opt AdminListUsersOptions) ([]*User, *Response,
|
|||
|
||||
// CreateUserOption create user options
|
||||
type CreateUserOption struct {
|
||||
SourceID int64 `json:"source_id"`
|
||||
LoginName string `json:"login_name"`
|
||||
Username string `json:"username"`
|
||||
FullName string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
MustChangePassword *bool `json:"must_change_password"`
|
||||
SendNotify bool `json:"send_notify"`
|
||||
SourceID int64 `json:"source_id"`
|
||||
LoginName string `json:"login_name"`
|
||||
Username string `json:"username"`
|
||||
FullName string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
MustChangePassword *bool `json:"must_change_password"`
|
||||
SendNotify bool `json:"send_notify"`
|
||||
Visibility *VisibleType `json:"visibility"`
|
||||
}
|
||||
|
||||
// Validate the CreateUserOption struct
|
||||
|
@ -63,25 +64,31 @@ func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, *Response, error)
|
|||
|
||||
// EditUserOption edit user options
|
||||
type EditUserOption struct {
|
||||
SourceID int64 `json:"source_id"`
|
||||
LoginName string `json:"login_name"`
|
||||
FullName string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
Password string `json:"password"`
|
||||
MustChangePassword *bool `json:"must_change_password"`
|
||||
Website string `json:"website"`
|
||||
Location string `json:"location"`
|
||||
Active *bool `json:"active"`
|
||||
Admin *bool `json:"admin"`
|
||||
AllowGitHook *bool `json:"allow_git_hook"`
|
||||
AllowImportLocal *bool `json:"allow_import_local"`
|
||||
MaxRepoCreation *int `json:"max_repo_creation"`
|
||||
ProhibitLogin *bool `json:"prohibit_login"`
|
||||
AllowCreateOrganization *bool `json:"allow_create_organization"`
|
||||
SourceID int64 `json:"source_id"`
|
||||
LoginName string `json:"login_name"`
|
||||
Email *string `json:"email"`
|
||||
FullName *string `json:"full_name"`
|
||||
Password string `json:"password"`
|
||||
Description *string `json:"description"`
|
||||
MustChangePassword *bool `json:"must_change_password"`
|
||||
Website *string `json:"website"`
|
||||
Location *string `json:"location"`
|
||||
Active *bool `json:"active"`
|
||||
Admin *bool `json:"admin"`
|
||||
AllowGitHook *bool `json:"allow_git_hook"`
|
||||
AllowImportLocal *bool `json:"allow_import_local"`
|
||||
MaxRepoCreation *int `json:"max_repo_creation"`
|
||||
ProhibitLogin *bool `json:"prohibit_login"`
|
||||
AllowCreateOrganization *bool `json:"allow_create_organization"`
|
||||
Restricted *bool `json:"restricted"`
|
||||
Visibility *VisibleType `json:"visibility"`
|
||||
}
|
||||
|
||||
// AdminEditUser modify user informations
|
||||
func (c *Client) AdminEditUser(user string, opt EditUserOption) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -92,12 +99,18 @@ func (c *Client) AdminEditUser(user string, opt EditUserOption) (*Response, erro
|
|||
|
||||
// AdminDeleteUser delete one user according name
|
||||
func (c *Client) AdminDeleteUser(user string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// AdminCreateUserPublicKey adds a public key for the user
|
||||
func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -109,6 +122,9 @@ func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*Pu
|
|||
|
||||
// AdminDeleteUserPublicKey deletes a user's public key
|
||||
func (c *Client) AdminDeleteUserPublicKey(user string, keyID int) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s/keys/%d", user, keyID), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
15
vendor/code.gitea.io/sdk/gitea/attachment.go
generated
vendored
15
vendor/code.gitea.io/sdk/gitea/attachment.go
generated
vendored
|
@ -31,6 +31,9 @@ type ListReleaseAttachmentsOptions struct {
|
|||
|
||||
// ListReleaseAttachments list release's attachments
|
||||
func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt ListReleaseAttachmentsOptions) ([]*Attachment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
attachments := make([]*Attachment, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET",
|
||||
|
@ -41,6 +44,9 @@ func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt Li
|
|||
|
||||
// GetReleaseAttachment returns the requested attachment
|
||||
func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64) (*Attachment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
a := new(Attachment)
|
||||
resp, err := c.getParsedResponse("GET",
|
||||
fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id),
|
||||
|
@ -50,6 +56,9 @@ func (c *Client) GetReleaseAttachment(user, repo string, release int64, id int64
|
|||
|
||||
// CreateReleaseAttachment creates an attachment for the given release
|
||||
func (c *Client) CreateReleaseAttachment(user, repo string, release int64, file io.Reader, filename string) (*Attachment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
// Write file to body
|
||||
body := new(bytes.Buffer)
|
||||
writer := multipart.NewWriter(body)
|
||||
|
@ -80,6 +89,9 @@ type EditAttachmentOptions struct {
|
|||
|
||||
// EditReleaseAttachment updates the given attachment with the given options
|
||||
func (c *Client) EditReleaseAttachment(user, repo string, release int64, attachment int64, form EditAttachmentOptions) (*Attachment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&form)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -91,6 +103,9 @@ func (c *Client) EditReleaseAttachment(user, repo string, release int64, attachm
|
|||
|
||||
// DeleteReleaseAttachment deletes the given attachment including the uploaded file
|
||||
func (c *Client) DeleteReleaseAttachment(user, repo string, release int64, id int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/releases/%d/assets/%d", user, repo, release, id), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
150
vendor/code.gitea.io/sdk/gitea/client.go
generated
vendored
150
vendor/code.gitea.io/sdk/gitea/client.go
generated
vendored
|
@ -13,6 +13,7 @@ import (
|
|||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
|
@ -26,7 +27,7 @@ func Version() string {
|
|||
return "0.14.0"
|
||||
}
|
||||
|
||||
// Client represents a Gitea API client.
|
||||
// Client represents a thread-safe Gitea API client.
|
||||
type Client struct {
|
||||
url string
|
||||
accessToken string
|
||||
|
@ -37,6 +38,7 @@ type Client struct {
|
|||
debug bool
|
||||
client *http.Client
|
||||
ctx context.Context
|
||||
mutex sync.RWMutex
|
||||
serverVersion *version.Version
|
||||
getVersionOnce sync.Once
|
||||
}
|
||||
|
@ -47,6 +49,7 @@ type Response struct {
|
|||
}
|
||||
|
||||
// NewClient initializes and returns a API client.
|
||||
// Usage of all gitea.Client methods is concurrency-safe.
|
||||
func NewClient(url string, options ...func(*Client)) (*Client, error) {
|
||||
client := &Client{
|
||||
url: strings.TrimSuffix(url, "/"),
|
||||
|
@ -72,14 +75,23 @@ func NewClientWithHTTP(url string, httpClient *http.Client) *Client {
|
|||
// SetHTTPClient is an option for NewClient to set custom http client
|
||||
func SetHTTPClient(httpClient *http.Client) func(client *Client) {
|
||||
return func(client *Client) {
|
||||
client.client = httpClient
|
||||
client.SetHTTPClient(httpClient)
|
||||
}
|
||||
}
|
||||
|
||||
// SetHTTPClient replaces default http.Client with user given one.
|
||||
func (c *Client) SetHTTPClient(client *http.Client) {
|
||||
c.mutex.Lock()
|
||||
c.client = client
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
|
||||
// SetToken is an option for NewClient to set token
|
||||
func SetToken(token string) func(client *Client) {
|
||||
return func(client *Client) {
|
||||
client.mutex.Lock()
|
||||
client.accessToken = token
|
||||
client.mutex.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +104,9 @@ func SetBasicAuth(username, password string) func(client *Client) {
|
|||
|
||||
// SetBasicAuth sets username and password
|
||||
func (c *Client) SetBasicAuth(username, password string) {
|
||||
c.mutex.Lock()
|
||||
c.username, c.password = username, password
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
|
||||
// SetOTP is an option for NewClient to set OTP for 2FA
|
||||
|
@ -104,7 +118,9 @@ func SetOTP(otp string) func(client *Client) {
|
|||
|
||||
// SetOTP sets OTP for 2FA
|
||||
func (c *Client) SetOTP(otp string) {
|
||||
c.mutex.Lock()
|
||||
c.otp = otp
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
|
||||
// SetContext is an option for NewClient to set context
|
||||
|
@ -116,12 +132,9 @@ func SetContext(ctx context.Context) func(client *Client) {
|
|||
|
||||
// SetContext set context witch is used for http requests
|
||||
func (c *Client) SetContext(ctx context.Context) {
|
||||
c.mutex.Lock()
|
||||
c.ctx = ctx
|
||||
}
|
||||
|
||||
// SetHTTPClient replaces default http.Client with user given one.
|
||||
func (c *Client) SetHTTPClient(client *http.Client) {
|
||||
c.client = client
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
|
||||
// SetSudo is an option for NewClient to set sudo header
|
||||
|
@ -133,43 +146,57 @@ func SetSudo(sudo string) func(client *Client) {
|
|||
|
||||
// SetSudo sets username to impersonate.
|
||||
func (c *Client) SetSudo(sudo string) {
|
||||
c.mutex.Lock()
|
||||
c.sudo = sudo
|
||||
c.mutex.Unlock()
|
||||
}
|
||||
|
||||
// SetDebugMode is an option for NewClient to enable debug mode
|
||||
func SetDebugMode() func(client *Client) {
|
||||
return func(client *Client) {
|
||||
client.mutex.Lock()
|
||||
client.debug = true
|
||||
client.mutex.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) getWebResponse(method, path string, body io.Reader) ([]byte, *Response, error) {
|
||||
if c.debug {
|
||||
c.mutex.RLock()
|
||||
debug := c.debug
|
||||
if debug {
|
||||
fmt.Printf("%s: %s\nBody: %v\n", method, c.url+path, body)
|
||||
}
|
||||
req, err := http.NewRequestWithContext(c.ctx, method, c.url+path, body)
|
||||
|
||||
client := c.client // client ref can change from this point on so safe it
|
||||
c.mutex.RUnlock()
|
||||
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
resp, err := c.client.Do(req)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if c.debug {
|
||||
if debug {
|
||||
fmt.Printf("Response: %v\n\n", resp)
|
||||
}
|
||||
return data, &Response{resp}, nil
|
||||
}
|
||||
|
||||
func (c *Client) doRequest(method, path string, header http.Header, body io.Reader) (*Response, error) {
|
||||
if c.debug {
|
||||
c.mutex.RLock()
|
||||
debug := c.debug
|
||||
if debug {
|
||||
fmt.Printf("%s: %s\nHeader: %v\nBody: %s\n", method, c.url+"/api/v1"+path, header, body)
|
||||
}
|
||||
req, err := http.NewRequestWithContext(c.ctx, method, c.url+"/api/v1"+path, body)
|
||||
if err != nil {
|
||||
c.mutex.RUnlock()
|
||||
return nil, err
|
||||
}
|
||||
if len(c.accessToken) != 0 {
|
||||
|
@ -184,20 +211,66 @@ func (c *Client) doRequest(method, path string, header http.Header, body io.Read
|
|||
if len(c.sudo) != 0 {
|
||||
req.Header.Set("Sudo", c.sudo)
|
||||
}
|
||||
|
||||
client := c.client // client ref can change from this point on so safe it
|
||||
c.mutex.RUnlock()
|
||||
|
||||
for k, v := range header {
|
||||
req.Header[k] = v
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if c.debug {
|
||||
if debug {
|
||||
fmt.Printf("Response: %v\n\n", resp)
|
||||
}
|
||||
return &Response{resp}, nil
|
||||
}
|
||||
|
||||
// Converts a response for a HTTP status code indicating an error condition
|
||||
// (non-2XX) to a well-known error value and response body. For non-problematic
|
||||
// (2XX) status codes nil will be returned. Note that on a non-2XX response, the
|
||||
// response body stream will have been read and, hence, is closed on return.
|
||||
func statusCodeToErr(resp *Response) (body []byte, err error) {
|
||||
// no error
|
||||
if resp.StatusCode/100 == 2 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
//
|
||||
// error: body will be read for details
|
||||
//
|
||||
defer resp.Body.Close()
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("body read on HTTP error %d: %v", resp.StatusCode, err)
|
||||
}
|
||||
|
||||
switch resp.StatusCode {
|
||||
case 403:
|
||||
return data, errors.New("403 Forbidden")
|
||||
case 404:
|
||||
return data, errors.New("404 Not Found")
|
||||
case 409:
|
||||
return data, errors.New("409 Conflict")
|
||||
case 422:
|
||||
return data, fmt.Errorf("422 Unprocessable Entity: %s", string(data))
|
||||
}
|
||||
|
||||
path := resp.Request.URL.Path
|
||||
method := resp.Request.Method
|
||||
header := resp.Request.Header
|
||||
errMap := make(map[string]interface{})
|
||||
if err = json.Unmarshal(data, &errMap); err != nil {
|
||||
// when the JSON can't be parsed, data was probably empty or a
|
||||
// plain string, so we try to return a helpful error anyway
|
||||
return data, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method '%s' header and '%s' body", resp.StatusCode, path, method, header, string(data))
|
||||
}
|
||||
return data, errors.New(errMap["message"].(string))
|
||||
}
|
||||
|
||||
func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, *Response, error) {
|
||||
resp, err := c.doRequest(method, path, header, body)
|
||||
if err != nil {
|
||||
|
@ -205,32 +278,18 @@ func (c *Client) getResponse(method, path string, header http.Header, body io.Re
|
|||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
// check for errors
|
||||
data, err := statusCodeToErr(resp)
|
||||
if err != nil {
|
||||
return data, resp, err
|
||||
}
|
||||
|
||||
// success (2XX), read body
|
||||
data, err = ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
switch resp.StatusCode {
|
||||
case 403:
|
||||
return data, resp, errors.New("403 Forbidden")
|
||||
case 404:
|
||||
return data, resp, errors.New("404 Not Found")
|
||||
case 409:
|
||||
return data, resp, errors.New("409 Conflict")
|
||||
case 422:
|
||||
return data, resp, fmt.Errorf("422 Unprocessable Entity: %s", string(data))
|
||||
}
|
||||
|
||||
if resp.StatusCode/100 != 2 {
|
||||
errMap := make(map[string]interface{})
|
||||
if err = json.Unmarshal(data, &errMap); err != nil {
|
||||
// when the JSON can't be parsed, data was probably empty or a plain string,
|
||||
// so we try to return a helpful error anyway
|
||||
return data, resp, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method '%s' header and '%s' body", resp.StatusCode, path, method, header, string(data))
|
||||
}
|
||||
return data, resp, errors.New(errMap["message"].(string))
|
||||
}
|
||||
|
||||
return data, resp, nil
|
||||
}
|
||||
|
||||
|
@ -251,3 +310,24 @@ func (c *Client) getStatusCode(method, path string, header http.Header, body io.
|
|||
|
||||
return resp.StatusCode, resp, nil
|
||||
}
|
||||
|
||||
// pathEscapeSegments escapes segments of a path while not escaping forward slash
|
||||
func pathEscapeSegments(path string) string {
|
||||
slice := strings.Split(path, "/")
|
||||
for index := range slice {
|
||||
slice[index] = url.PathEscape(slice[index])
|
||||
}
|
||||
escapedPath := strings.Join(slice, "/")
|
||||
return escapedPath
|
||||
}
|
||||
|
||||
// escapeValidatePathSegments is a help function to validate and encode url path segments
|
||||
func escapeValidatePathSegments(seg ...*string) error {
|
||||
for i := range seg {
|
||||
if seg[i] == nil || len(*seg[i]) == 0 {
|
||||
return fmt.Errorf("path segment [%d] is empty", i)
|
||||
}
|
||||
*seg[i] = url.PathEscape(*seg[i])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
6
vendor/code.gitea.io/sdk/gitea/fork.go
generated
vendored
6
vendor/code.gitea.io/sdk/gitea/fork.go
generated
vendored
|
@ -17,6 +17,9 @@ type ListForksOptions struct {
|
|||
|
||||
// ListForks list a repository's forks
|
||||
func (c *Client) ListForks(user string, repo string, opt ListForksOptions) ([]*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
forks := make([]*Repository, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET",
|
||||
|
@ -33,6 +36,9 @@ type CreateForkOption struct {
|
|||
|
||||
// CreateFork create a fork of a repository
|
||||
func (c *Client) CreateFork(user, repo string, form CreateForkOption) (*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(form)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
|
3
vendor/code.gitea.io/sdk/gitea/git_blob.go
generated
vendored
3
vendor/code.gitea.io/sdk/gitea/git_blob.go
generated
vendored
|
@ -19,6 +19,9 @@ type GitBlobResponse struct {
|
|||
|
||||
// GetBlob get the blob of a repository file
|
||||
func (c *Client) GetBlob(user, repo, sha string) (*GitBlobResponse, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &sha); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
blob := new(GitBlobResponse)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/blobs/%s", user, repo, sha), nil, nil, blob)
|
||||
return blob, resp, err
|
||||
|
|
12
vendor/code.gitea.io/sdk/gitea/git_hook.go
generated
vendored
12
vendor/code.gitea.io/sdk/gitea/git_hook.go
generated
vendored
|
@ -24,6 +24,9 @@ type ListRepoGitHooksOptions struct {
|
|||
|
||||
// ListRepoGitHooks list all the Git hooks of one repository
|
||||
func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions) ([]*GitHook, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
hooks := make([]*GitHook, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
|
||||
|
@ -32,6 +35,9 @@ func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions
|
|||
|
||||
// GetRepoGitHook get a Git hook of a repository
|
||||
func (c *Client) GetRepoGitHook(user, repo, id string) (*GitHook, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
h := new(GitHook)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil, h)
|
||||
return h, resp, err
|
||||
|
@ -44,6 +50,9 @@ type EditGitHookOption struct {
|
|||
|
||||
// EditRepoGitHook modify one Git hook of a repository
|
||||
func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -54,6 +63,9 @@ func (c *Client) EditRepoGitHook(user, repo, id string, opt EditGitHookOption) (
|
|||
|
||||
// DeleteRepoGitHook delete one Git hook from a repository
|
||||
func (c *Client) DeleteRepoGitHook(user, repo, id string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/git/%s", user, repo, id), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
1
vendor/code.gitea.io/sdk/gitea/go.mod
generated
vendored
1
vendor/code.gitea.io/sdk/gitea/go.mod
generated
vendored
|
@ -3,6 +3,7 @@ module code.gitea.io/sdk/gitea
|
|||
go 1.13
|
||||
|
||||
require (
|
||||
code.gitea.io/gitea-vet v0.2.1 // indirect
|
||||
github.com/hashicorp/go-version v1.2.1
|
||||
github.com/stretchr/testify v1.4.0
|
||||
)
|
||||
|
|
22
vendor/code.gitea.io/sdk/gitea/go.sum
generated
vendored
22
vendor/code.gitea.io/sdk/gitea/go.sum
generated
vendored
|
@ -1,7 +1,7 @@
|
|||
code.gitea.io/gitea-vet v0.2.1 h1:b30by7+3SkmiftK0RjuXqFvZg2q4p68uoPGuxhzBN0s=
|
||||
code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
|
||||
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
|
@ -9,6 +9,24 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224 h1:azwY/v0y0K4mFHVsg5+UrTgchqALYWpqVo6vL5OmkmI=
|
||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
|
|
54
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
54
vendor/code.gitea.io/sdk/gitea/hook.go
generated
vendored
|
@ -24,6 +24,28 @@ type Hook struct {
|
|||
Created time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
// HookType represent all webhook types gitea currently offer
|
||||
type HookType string
|
||||
|
||||
const (
|
||||
// HookTypeDingtalk webhook that dingtalk understand
|
||||
HookTypeDingtalk HookType = "dingtalk"
|
||||
// HookTypeDiscord webhook that discord understand
|
||||
HookTypeDiscord HookType = "discord"
|
||||
// HookTypeGitea webhook that gitea understand
|
||||
HookTypeGitea HookType = "gitea"
|
||||
// HookTypeGogs webhook that gogs understand
|
||||
HookTypeGogs HookType = "gogs"
|
||||
// HookTypeMsteams webhook that msteams understand
|
||||
HookTypeMsteams HookType = "msteams"
|
||||
// HookTypeSlack webhook that slack understand
|
||||
HookTypeSlack HookType = "slack"
|
||||
// HookTypeTelegram webhook that telegram understand
|
||||
HookTypeTelegram HookType = "telegram"
|
||||
// HookTypeFeishu webhook that feishu understand
|
||||
HookTypeFeishu HookType = "feishu"
|
||||
)
|
||||
|
||||
// ListHooksOptions options for listing hooks
|
||||
type ListHooksOptions struct {
|
||||
ListOptions
|
||||
|
@ -31,6 +53,9 @@ type ListHooksOptions struct {
|
|||
|
||||
// ListOrgHooks list all the hooks of one organization
|
||||
func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
hooks := make([]*Hook, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks?%s", org, opt.getURLQuery().Encode()), nil, nil, &hooks)
|
||||
|
@ -39,6 +64,9 @@ func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, *Respo
|
|||
|
||||
// ListRepoHooks list all the hooks of one repository
|
||||
func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
hooks := make([]*Hook, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
|
||||
|
@ -47,6 +75,9 @@ func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook
|
|||
|
||||
// GetOrgHook get a hook of an organization
|
||||
func (c *Client) GetOrgHook(org string, id int64) (*Hook, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
h := new(Hook)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil, h)
|
||||
return h, resp, err
|
||||
|
@ -54,6 +85,9 @@ func (c *Client) GetOrgHook(org string, id int64) (*Hook, *Response, error) {
|
|||
|
||||
// GetRepoHook get a hook of a repository
|
||||
func (c *Client) GetRepoHook(user, repo string, id int64) (*Hook, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
h := new(Hook)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil, h)
|
||||
return h, resp, err
|
||||
|
@ -61,7 +95,7 @@ func (c *Client) GetRepoHook(user, repo string, id int64) (*Hook, *Response, err
|
|||
|
||||
// CreateHookOption options when create a hook
|
||||
type CreateHookOption struct {
|
||||
Type string `json:"type"`
|
||||
Type HookType `json:"type"`
|
||||
Config map[string]string `json:"config"`
|
||||
Events []string `json:"events"`
|
||||
BranchFilter string `json:"branch_filter"`
|
||||
|
@ -78,6 +112,9 @@ func (opt CreateHookOption) Validate() error {
|
|||
|
||||
// CreateOrgHook create one hook for an organization, with options
|
||||
func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -92,6 +129,9 @@ func (c *Client) CreateOrgHook(org string, opt CreateHookOption) (*Hook, *Respon
|
|||
|
||||
// CreateRepoHook create one hook for a repository, with options
|
||||
func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -111,6 +151,9 @@ type EditHookOption struct {
|
|||
|
||||
// EditOrgHook modify one hook of an organization, with hook id and options
|
||||
func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -121,6 +164,9 @@ func (c *Client) EditOrgHook(org string, id int64, opt EditHookOption) (*Respons
|
|||
|
||||
// EditRepoHook modify one hook of a repository, with hook id and options
|
||||
func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -131,12 +177,18 @@ func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) (
|
|||
|
||||
// DeleteOrgHook delete one hook from an organization, with hook id
|
||||
func (c *Client) DeleteOrgHook(org string, id int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/hooks/%d", org, id), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// DeleteRepoHook delete one hook from a repository, with hook id
|
||||
func (c *Client) DeleteRepoHook(user, repo string, id int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
67
vendor/code.gitea.io/sdk/gitea/issue.go
generated
vendored
67
vendor/code.gitea.io/sdk/gitea/issue.go
generated
vendored
|
@ -39,12 +39,10 @@ type Issue struct {
|
|||
OriginalAuthorID int64 `json:"original_author_id"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
Ref string `json:"ref"`
|
||||
Labels []*Label `json:"labels"`
|
||||
Milestone *Milestone `json:"milestone"`
|
||||
// deprecated
|
||||
// TODO: rm on sdk 0.15.0
|
||||
Assignee *User `json:"assignee"`
|
||||
Assignees []*User `json:"assignees"`
|
||||
Assignees []*User `json:"assignees"`
|
||||
// Whether the issue is open or closed
|
||||
State StateType `json:"state"`
|
||||
IsLocked bool `json:"is_locked"`
|
||||
|
@ -65,6 +63,14 @@ type ListIssueOption struct {
|
|||
Labels []string
|
||||
Milestones []string
|
||||
KeyWord string
|
||||
Since time.Time
|
||||
Before time.Time
|
||||
// filter by created by username
|
||||
CreatedBy string
|
||||
// filter by assigned to username
|
||||
AssignedBy string
|
||||
// filter by username mentioned
|
||||
MentionedBy string
|
||||
}
|
||||
|
||||
// StateType issue state type
|
||||
|
@ -113,6 +119,23 @@ func (opt *ListIssueOption) QueryEncode() string {
|
|||
query.Add("milestones", strings.Join(opt.Milestones, ","))
|
||||
}
|
||||
|
||||
if !opt.Since.IsZero() {
|
||||
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||
}
|
||||
if !opt.Before.IsZero() {
|
||||
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||
}
|
||||
|
||||
if len(opt.CreatedBy) > 0 {
|
||||
query.Add("created_by", opt.CreatedBy)
|
||||
}
|
||||
if len(opt.AssignedBy) > 0 {
|
||||
query.Add("assigned_by", opt.AssignedBy)
|
||||
}
|
||||
if len(opt.MentionedBy) > 0 {
|
||||
query.Add("mentioned_by", opt.MentionedBy)
|
||||
}
|
||||
|
||||
return query.Encode()
|
||||
}
|
||||
|
||||
|
@ -139,6 +162,9 @@ func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, *Response, error) {
|
|||
|
||||
// ListRepoIssues returns all issues for a given repository
|
||||
func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
issues := make([]*Issue, 0, opt.PageSize)
|
||||
|
||||
|
@ -160,6 +186,9 @@ func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Iss
|
|||
|
||||
// GetIssue returns a single issue for a given repository
|
||||
func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
issue := new(Issue)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue)
|
||||
if e := c.checkServerVersionGreaterThanOrEqual(version1_12_0); e != nil && issue.Repository != nil {
|
||||
|
@ -171,10 +200,9 @@ func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, *Response, e
|
|||
|
||||
// CreateIssueOption options to create one issue
|
||||
type CreateIssueOption struct {
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
// username of assignee
|
||||
Assignee string `json:"assignee"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
Ref string `json:"ref"`
|
||||
Assignees []string `json:"assignees"`
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
// milestone id
|
||||
|
@ -194,6 +222,9 @@ func (opt CreateIssueOption) Validate() error {
|
|||
|
||||
// CreateIssue create a new issue for a given repository
|
||||
func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -210,13 +241,14 @@ func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue,
|
|||
|
||||
// EditIssueOption options for editing an issue
|
||||
type EditIssueOption struct {
|
||||
Title string `json:"title"`
|
||||
Body *string `json:"body"`
|
||||
Assignee *string `json:"assignee"`
|
||||
Assignees []string `json:"assignees"`
|
||||
Milestone *int64 `json:"milestone"`
|
||||
State *StateType `json:"state"`
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
Title string `json:"title"`
|
||||
Body *string `json:"body"`
|
||||
Ref *string `json:"ref"`
|
||||
Assignees []string `json:"assignees"`
|
||||
Milestone *int64 `json:"milestone"`
|
||||
State *StateType `json:"state"`
|
||||
Deadline *time.Time `json:"due_date"`
|
||||
RemoveDeadline *bool `json:"unset_due_date"`
|
||||
}
|
||||
|
||||
// Validate the EditIssueOption struct
|
||||
|
@ -229,6 +261,9 @@ func (opt EditIssueOption) Validate() error {
|
|||
|
||||
// EditIssue modify an existing issue for a given repository
|
||||
func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -246,6 +281,8 @@ func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption)
|
|||
|
||||
func (c *Client) issueBackwardsCompatibility(issue *Issue) {
|
||||
if c.checkServerVersionGreaterThanOrEqual(version1_12_0) != nil {
|
||||
c.mutex.RLock()
|
||||
issue.HTMLURL = fmt.Sprintf("%s/%s/issues/%d", c.url, issue.Repository.FullName, issue.Index)
|
||||
c.mutex.RUnlock()
|
||||
}
|
||||
}
|
||||
|
|
18
vendor/code.gitea.io/sdk/gitea/issue_comment.go
generated
vendored
18
vendor/code.gitea.io/sdk/gitea/issue_comment.go
generated
vendored
|
@ -47,6 +47,9 @@ func (opt *ListIssueCommentOptions) QueryEncode() string {
|
|||
|
||||
// ListIssueComments list comments on an issue.
|
||||
func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index))
|
||||
link.RawQuery = opt.QueryEncode()
|
||||
|
@ -57,6 +60,9 @@ func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssu
|
|||
|
||||
// ListRepoIssueComments list comments for a given repo.
|
||||
func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentOptions) ([]*Comment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo))
|
||||
link.RawQuery = opt.QueryEncode()
|
||||
|
@ -67,6 +73,9 @@ func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentO
|
|||
|
||||
// GetIssueComment get a comment for a given repo by id.
|
||||
func (c *Client) GetIssueComment(owner, repo string, id int64) (*Comment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
comment := new(Comment)
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return comment, nil, err
|
||||
|
@ -90,6 +99,9 @@ func (opt CreateIssueCommentOption) Validate() error {
|
|||
|
||||
// CreateIssueComment create comment on an issue.
|
||||
func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -117,6 +129,9 @@ func (opt EditIssueCommentOption) Validate() error {
|
|||
|
||||
// EditIssueComment edits an issue comment.
|
||||
func (c *Client) EditIssueComment(owner, repo string, commentID int64, opt EditIssueCommentOption) (*Comment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -131,6 +146,9 @@ func (c *Client) EditIssueComment(owner, repo string, commentID int64, opt EditI
|
|||
|
||||
// DeleteIssueComment deletes an issue comment.
|
||||
func (c *Client) DeleteIssueComment(owner, repo string, commentID int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, commentID), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
30
vendor/code.gitea.io/sdk/gitea/issue_label.go
generated
vendored
30
vendor/code.gitea.io/sdk/gitea/issue_label.go
generated
vendored
|
@ -29,6 +29,9 @@ type ListLabelsOptions struct {
|
|||
|
||||
// ListRepoLabels list labels of one repository
|
||||
func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
labels := make([]*Label, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels)
|
||||
|
@ -37,6 +40,9 @@ func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*L
|
|||
|
||||
// GetRepoLabel get one label of repository by repo it
|
||||
func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
label := new(Label)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label)
|
||||
return label, resp, err
|
||||
|
@ -67,6 +73,9 @@ func (opt CreateLabelOption) Validate() error {
|
|||
|
||||
// CreateLabel create one label of repository
|
||||
func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -114,6 +123,9 @@ func (opt EditLabelOption) Validate() error {
|
|||
|
||||
// EditLabel modify one label with options
|
||||
func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -128,12 +140,18 @@ func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*
|
|||
|
||||
// DeleteLabel delete one label of repository by id
|
||||
func (c *Client) DeleteLabel(owner, repo string, id int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// GetIssueLabels get labels of one issue via issue id
|
||||
func (c *Client) GetIssueLabels(owner, repo string, index int64, opts ListLabelsOptions) ([]*Label, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
labels := make([]*Label, 0, 5)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels?%s", owner, repo, index, opts.getURLQuery().Encode()), nil, nil, &labels)
|
||||
return labels, resp, err
|
||||
|
@ -147,6 +165,9 @@ type IssueLabelsOption struct {
|
|||
|
||||
// AddIssueLabels add one or more labels to one issue
|
||||
func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -158,6 +179,9 @@ func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabels
|
|||
|
||||
// ReplaceIssueLabels replace old labels of issue with new labels
|
||||
func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -170,12 +194,18 @@ func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLa
|
|||
// DeleteIssueLabel delete one label of one issue by issue id and label id
|
||||
// TODO: maybe we need delete by label name and issue id
|
||||
func (c *Client) DeleteIssueLabel(owner, repo string, index, label int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// ClearIssueLabels delete all the labels of one issue.
|
||||
func (c *Client) ClearIssueLabels(owner, repo string, index int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
24
vendor/code.gitea.io/sdk/gitea/issue_milestone.go
generated
vendored
24
vendor/code.gitea.io/sdk/gitea/issue_milestone.go
generated
vendored
|
@ -49,6 +49,9 @@ func (opt *ListMilestoneOption) QueryEncode() string {
|
|||
|
||||
// ListRepoMilestones list all the milestones of one repository
|
||||
func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption) ([]*Milestone, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
milestones := make([]*Milestone, 0, opt.PageSize)
|
||||
|
||||
|
@ -60,6 +63,9 @@ func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption)
|
|||
|
||||
// GetMilestone get one milestone by repo name and milestone id
|
||||
func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
milestone := new(Milestone)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone)
|
||||
return milestone, resp, err
|
||||
|
@ -72,6 +78,9 @@ func (c *Client) GetMilestoneByName(owner, repo string, name string) (*Milestone
|
|||
m, resp, err := c.resolveMilestoneByName(owner, repo, name)
|
||||
return m, resp, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
milestone := new(Milestone)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil, milestone)
|
||||
return milestone, resp, err
|
||||
|
@ -95,6 +104,9 @@ func (opt CreateMilestoneOption) Validate() error {
|
|||
|
||||
// CreateMilestone create one milestone with options
|
||||
func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -135,6 +147,9 @@ func (opt EditMilestoneOption) Validate() error {
|
|||
|
||||
// EditMilestone modify milestone with options
|
||||
func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -157,6 +172,9 @@ func (c *Client) EditMilestoneByName(owner, repo string, name string, opt EditMi
|
|||
}
|
||||
return c.EditMilestone(owner, repo, m.ID, opt)
|
||||
}
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -171,6 +189,9 @@ func (c *Client) EditMilestoneByName(owner, repo string, name string, opt EditMi
|
|||
|
||||
// DeleteMilestone delete one milestone by id
|
||||
func (c *Client) DeleteMilestone(owner, repo string, id int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
@ -185,6 +206,9 @@ func (c *Client) DeleteMilestoneByName(owner, repo string, name string) (*Respon
|
|||
}
|
||||
return c.DeleteMilestone(owner, repo, m.ID)
|
||||
}
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%s", owner, repo, name), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
18
vendor/code.gitea.io/sdk/gitea/issue_reaction.go
generated
vendored
18
vendor/code.gitea.io/sdk/gitea/issue_reaction.go
generated
vendored
|
@ -20,6 +20,9 @@ type Reaction struct {
|
|||
|
||||
// GetIssueReactions get a list reactions of an issue
|
||||
func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
reactions := make([]*Reaction, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/reactions", owner, repo, index), nil, nil, &reactions)
|
||||
return reactions, resp, err
|
||||
|
@ -27,6 +30,9 @@ func (c *Client) GetIssueReactions(owner, repo string, index int64) ([]*Reaction
|
|||
|
||||
// GetIssueCommentReactions get a list of reactions from a comment of an issue
|
||||
func (c *Client) GetIssueCommentReactions(owner, repo string, commentID int64) ([]*Reaction, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
reactions := make([]*Reaction, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d/reactions", owner, repo, commentID), nil, nil, &reactions)
|
||||
return reactions, resp, err
|
||||
|
@ -39,6 +45,9 @@ type editReactionOption struct {
|
|||
|
||||
// PostIssueReaction add a reaction to an issue
|
||||
func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction string) (*Reaction, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
reactionResponse := new(Reaction)
|
||||
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||
if err != nil {
|
||||
|
@ -52,6 +61,9 @@ func (c *Client) PostIssueReaction(owner, repo string, index int64, reaction str
|
|||
|
||||
// DeleteIssueReaction remove a reaction from an issue
|
||||
func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -62,6 +74,9 @@ func (c *Client) DeleteIssueReaction(owner, repo string, index int64, reaction s
|
|||
|
||||
// PostIssueCommentReaction add a reaction to a comment of an issue
|
||||
func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Reaction, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
reactionResponse := new(Reaction)
|
||||
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||
if err != nil {
|
||||
|
@ -75,6 +90,9 @@ func (c *Client) PostIssueCommentReaction(owner, repo string, commentID int64, r
|
|||
|
||||
// DeleteIssueCommentReaction remove a reaction from a comment of an issue
|
||||
func (c *Client) DeleteIssueCommentReaction(owner, repo string, commentID int64, reaction string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := json.Marshal(&editReactionOption{Reaction: reaction})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
18
vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go
generated
vendored
18
vendor/code.gitea.io/sdk/gitea/issue_stopwatch.go
generated
vendored
|
@ -11,8 +11,13 @@ import (
|
|||
|
||||
// StopWatch represents a running stopwatch of an issue / pr
|
||||
type StopWatch struct {
|
||||
Created time.Time `json:"created"`
|
||||
IssueIndex int64 `json:"issue_index"`
|
||||
Created time.Time `json:"created"`
|
||||
Seconds int64 `json:"seconds"`
|
||||
Duration string `json:"duration"`
|
||||
IssueIndex int64 `json:"issue_index"`
|
||||
IssueTitle string `json:"issue_title"`
|
||||
RepoOwnerName string `json:"repo_owner_name"`
|
||||
RepoName string `json:"repo_name"`
|
||||
}
|
||||
|
||||
// GetMyStopwatches list all stopwatches
|
||||
|
@ -24,6 +29,9 @@ func (c *Client) GetMyStopwatches() ([]*StopWatch, *Response, error) {
|
|||
|
||||
// DeleteIssueStopwatch delete / cancel a specific stopwatch
|
||||
func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/delete", owner, repo, index), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
@ -31,6 +39,9 @@ func (c *Client) DeleteIssueStopwatch(owner, repo string, index int64) (*Respons
|
|||
// StartIssueStopWatch starts a stopwatch for an existing issue for a given
|
||||
// repository
|
||||
func (c *Client) StartIssueStopWatch(owner, repo string, index int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/start", owner, repo, index), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
@ -38,6 +49,9 @@ func (c *Client) StartIssueStopWatch(owner, repo string, index int64) (*Response
|
|||
// StopIssueStopWatch stops an existing stopwatch for an issue in a given
|
||||
// repository
|
||||
func (c *Client) StopIssueStopWatch(owner, repo string, index int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/stopwatch/stop", owner, repo, index), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
12
vendor/code.gitea.io/sdk/gitea/issue_subscription.go
generated
vendored
12
vendor/code.gitea.io/sdk/gitea/issue_subscription.go
generated
vendored
|
@ -11,6 +11,9 @@ import (
|
|||
|
||||
// GetIssueSubscribers get list of users who subscribed on an issue
|
||||
func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
subscribers := make([]*User, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions", owner, repo, index), nil, nil, &subscribers)
|
||||
return subscribers, resp, err
|
||||
|
@ -18,6 +21,9 @@ func (c *Client) GetIssueSubscribers(owner, repo string, index int64) ([]*User,
|
|||
|
||||
// AddIssueSubscription Subscribe user to issue
|
||||
func (c *Client) AddIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
|
@ -33,6 +39,9 @@ func (c *Client) AddIssueSubscription(owner, repo string, index int64, user stri
|
|||
|
||||
// DeleteIssueSubscription unsubscribe user from issue
|
||||
func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
|
@ -48,6 +57,9 @@ func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user s
|
|||
|
||||
// CheckIssueSubscription check if current user is subscribed to an issue
|
||||
func (c *Client) CheckIssueSubscription(owner, repo string, index int64) (*WatchInfo, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
76
vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go
generated
vendored
76
vendor/code.gitea.io/sdk/gitea/issue_tracked_time.go
generated
vendored
|
@ -8,6 +8,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -25,24 +26,50 @@ type TrackedTime struct {
|
|||
Issue *Issue `json:"issue"`
|
||||
}
|
||||
|
||||
// GetUserTrackedTimes list tracked times of a user
|
||||
func (c *Client) GetUserTrackedTimes(owner, repo, user string) ([]*TrackedTime, *Response, error) {
|
||||
times := make([]*TrackedTime, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/times/%s", owner, repo, user), nil, nil, ×)
|
||||
return times, resp, err
|
||||
// ListTrackedTimesOptions options for listing repository's tracked times
|
||||
type ListTrackedTimesOptions struct {
|
||||
ListOptions
|
||||
Since time.Time
|
||||
Before time.Time
|
||||
// User filter is only used by ListRepoTrackedTimes !!!
|
||||
User string
|
||||
}
|
||||
|
||||
// GetRepoTrackedTimes list tracked times of a repository
|
||||
func (c *Client) GetRepoTrackedTimes(owner, repo string) ([]*TrackedTime, *Response, error) {
|
||||
times := make([]*TrackedTime, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/times", owner, repo), nil, nil, ×)
|
||||
// QueryEncode turns options into querystring argument
|
||||
func (opt *ListTrackedTimesOptions) QueryEncode() string {
|
||||
query := opt.getURLQuery()
|
||||
|
||||
if !opt.Since.IsZero() {
|
||||
query.Add("since", opt.Since.Format(time.RFC3339))
|
||||
}
|
||||
if !opt.Before.IsZero() {
|
||||
query.Add("before", opt.Before.Format(time.RFC3339))
|
||||
}
|
||||
|
||||
if len(opt.User) != 0 {
|
||||
query.Add("user", opt.User)
|
||||
}
|
||||
|
||||
return query.Encode()
|
||||
}
|
||||
|
||||
// ListRepoTrackedTimes list tracked times of a repository
|
||||
func (c *Client) ListRepoTrackedTimes(owner, repo string, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/times", owner, repo))
|
||||
opt.setDefaults()
|
||||
link.RawQuery = opt.QueryEncode()
|
||||
times := make([]*TrackedTime, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×)
|
||||
return times, resp, err
|
||||
}
|
||||
|
||||
// GetMyTrackedTimes list tracked times of the current user
|
||||
func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, *Response, error) {
|
||||
times := make([]*TrackedTime, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", "/user/times", nil, nil, ×)
|
||||
resp, err := c.getParsedResponse("GET", "/user/times", jsonHeader, nil, ×)
|
||||
return times, resp, err
|
||||
}
|
||||
|
||||
|
@ -66,6 +93,9 @@ func (opt AddTimeOption) Validate() error {
|
|||
|
||||
// AddTime adds time to issue with the given index
|
||||
func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*TrackedTime, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -80,27 +110,33 @@ func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*T
|
|||
return t, resp, err
|
||||
}
|
||||
|
||||
// ListTrackedTimesOptions options for listing repository's tracked times
|
||||
type ListTrackedTimesOptions struct {
|
||||
ListOptions
|
||||
}
|
||||
|
||||
// ListTrackedTimes list tracked times of a single issue for a given repository
|
||||
func (c *Client) ListTrackedTimes(owner, repo string, index int64, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
|
||||
// ListIssueTrackedTimes list tracked times of a single issue for a given repository
|
||||
func (c *Client) ListIssueTrackedTimes(owner, repo string, index int64, opt ListTrackedTimesOptions) ([]*TrackedTime, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index))
|
||||
opt.setDefaults()
|
||||
link.RawQuery = opt.QueryEncode()
|
||||
times := make([]*TrackedTime, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/times?%s", owner, repo, index, opt.getURLQuery().Encode()), nil, nil, ×)
|
||||
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, ×)
|
||||
return times, resp, err
|
||||
}
|
||||
|
||||
// ResetIssueTime reset tracked time of a single issue for a given repository
|
||||
func (c *Client) ResetIssueTime(owner, repo string, index int64) (*Response, error) {
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), nil, nil)
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), jsonHeader, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// DeleteTime delete a specific tracked time by id of a single issue for a given repository
|
||||
func (c *Client) DeleteTime(owner, repo string, index, timeID int64) (*Response, error) {
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), nil, nil)
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times/%d", owner, repo, index, timeID), jsonHeader, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
9
vendor/code.gitea.io/sdk/gitea/list_options.go
generated
vendored
9
vendor/code.gitea.io/sdk/gitea/list_options.go
generated
vendored
|
@ -26,8 +26,13 @@ func (o ListOptions) getURLQuery() url.Values {
|
|||
return query
|
||||
}
|
||||
|
||||
func (o ListOptions) setDefaults() {
|
||||
if o.Page < 1 {
|
||||
// setDefaults set default pagination options if none or wrong are set
|
||||
// if you set -1 as page it will set all to 0
|
||||
func (o *ListOptions) setDefaults() {
|
||||
if o.Page < 0 {
|
||||
o.Page, o.PageSize = 0, 0
|
||||
return
|
||||
} else if o.Page == 0 {
|
||||
o.Page = 1
|
||||
}
|
||||
|
||||
|
|
60
vendor/code.gitea.io/sdk/gitea/notifications.go
generated
vendored
60
vendor/code.gitea.io/sdk/gitea/notifications.go
generated
vendored
|
@ -29,11 +29,11 @@ type NotificationThread struct {
|
|||
|
||||
// NotificationSubject contains the notification subject (Issue/Pull/Commit)
|
||||
type NotificationSubject struct {
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
LatestCommentURL string `json:"latest_comment_url"`
|
||||
Type string `json:"type"`
|
||||
State StateType `json:"state"`
|
||||
Title string `json:"title"`
|
||||
URL string `json:"url"`
|
||||
LatestCommentURL string `json:"latest_comment_url"`
|
||||
Type NotifySubjectType `json:"type"`
|
||||
State NotifySubjectState `json:"state"`
|
||||
}
|
||||
|
||||
// NotifyStatus notification status type
|
||||
|
@ -48,12 +48,39 @@ const (
|
|||
NotifyStatusPinned NotifyStatus = "pinned"
|
||||
)
|
||||
|
||||
// NotifySubjectType represent type of notification subject
|
||||
type NotifySubjectType string
|
||||
|
||||
const (
|
||||
// NotifySubjectIssue an issue is subject of an notification
|
||||
NotifySubjectIssue NotifySubjectType = "Issue"
|
||||
// NotifySubjectPull an pull is subject of an notification
|
||||
NotifySubjectPull NotifySubjectType = "Pull"
|
||||
// NotifySubjectCommit an commit is subject of an notification
|
||||
NotifySubjectCommit NotifySubjectType = "Commit"
|
||||
// NotifySubjectRepository an repository is subject of an notification
|
||||
NotifySubjectRepository NotifySubjectType = "Repository"
|
||||
)
|
||||
|
||||
// NotifySubjectState reflect state of notification subject
|
||||
type NotifySubjectState string
|
||||
|
||||
const (
|
||||
// NotifySubjectOpen if subject is a pull/issue and is open at the moment
|
||||
NotifySubjectOpen NotifySubjectState = "open"
|
||||
// NotifySubjectClosed if subject is a pull/issue and is closed at the moment
|
||||
NotifySubjectClosed NotifySubjectState = "closed"
|
||||
// NotifySubjectMerged if subject is a pull and got merged
|
||||
NotifySubjectMerged NotifySubjectState = "merged"
|
||||
)
|
||||
|
||||
// ListNotificationOptions represents the filter options
|
||||
type ListNotificationOptions struct {
|
||||
ListOptions
|
||||
Since time.Time
|
||||
Before time.Time
|
||||
Status []NotifyStatus
|
||||
Since time.Time
|
||||
Before time.Time
|
||||
Status []NotifyStatus
|
||||
SubjectTypes []NotifySubjectType
|
||||
}
|
||||
|
||||
// MarkNotificationOptions represents the filter & modify options
|
||||
|
@ -75,6 +102,9 @@ func (opt *ListNotificationOptions) QueryEncode() string {
|
|||
for _, s := range opt.Status {
|
||||
query.Add("status-types", string(s))
|
||||
}
|
||||
for _, s := range opt.SubjectTypes {
|
||||
query.Add("subject-type", string(s))
|
||||
}
|
||||
return query.Encode()
|
||||
}
|
||||
|
||||
|
@ -176,14 +206,17 @@ func (c *Client) ReadNotifications(opt MarkNotificationOptions) (*Response, erro
|
|||
}
|
||||
|
||||
// ListRepoNotifications list users's notification threads on a specific repo
|
||||
func (c *Client) ListRepoNotifications(owner, reponame string, opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
|
||||
func (c *Client) ListRepoNotifications(owner, repo string, opt ListNotificationOptions) ([]*NotificationThread, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(c); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, reponame))
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
|
||||
link.RawQuery = opt.QueryEncode()
|
||||
threads := make([]*NotificationThread, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &threads)
|
||||
|
@ -191,14 +224,17 @@ func (c *Client) ListRepoNotifications(owner, reponame string, opt ListNotificat
|
|||
}
|
||||
|
||||
// ReadRepoNotifications mark notification threads as read on a specific repo
|
||||
func (c *Client) ReadRepoNotifications(owner, reponame string, opt MarkNotificationOptions) (*Response, error) {
|
||||
func (c *Client) ReadRepoNotifications(owner, repo string, opt MarkNotificationOptions) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := opt.Validate(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, reponame))
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, repo))
|
||||
link.RawQuery = opt.QueryEncode()
|
||||
_, resp, err := c.getResponse("PUT", link.String(), nil, nil)
|
||||
return resp, err
|
||||
|
|
25
vendor/code.gitea.io/sdk/gitea/org.go
generated
vendored
25
vendor/code.gitea.io/sdk/gitea/org.go
generated
vendored
|
@ -52,6 +52,9 @@ func (c *Client) ListMyOrgs(opt ListOrgsOptions) ([]*Organization, *Response, er
|
|||
|
||||
// ListUserOrgs list all of some user's organizations
|
||||
func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
orgs := make([]*Organization, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs?%s", user, opt.getURLQuery().Encode()), nil, nil, &orgs)
|
||||
|
@ -60,6 +63,9 @@ func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization
|
|||
|
||||
// GetOrg get one organization by name
|
||||
func (c *Client) GetOrg(orgname string) (*Organization, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&orgname); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
org := new(Organization)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org)
|
||||
return org, resp, err
|
||||
|
@ -67,12 +73,13 @@ func (c *Client) GetOrg(orgname string) (*Organization, *Response, error) {
|
|||
|
||||
// CreateOrgOption options for creating an organization
|
||||
type CreateOrgOption struct {
|
||||
Name string `json:"username"`
|
||||
FullName string `json:"full_name"`
|
||||
Description string `json:"description"`
|
||||
Website string `json:"website"`
|
||||
Location string `json:"location"`
|
||||
Visibility VisibleType `json:"visibility"`
|
||||
Name string `json:"username"`
|
||||
FullName string `json:"full_name"`
|
||||
Description string `json:"description"`
|
||||
Website string `json:"website"`
|
||||
Location string `json:"location"`
|
||||
Visibility VisibleType `json:"visibility"`
|
||||
RepoAdminChangeTeamAccess bool `json:"repo_admin_change_team_access"`
|
||||
}
|
||||
|
||||
// checkVisibilityOpt check if mode exist
|
||||
|
@ -124,6 +131,9 @@ func (opt EditOrgOption) Validate() error {
|
|||
|
||||
// EditOrg modify one organization via options
|
||||
func (c *Client) EditOrg(orgname string, opt EditOrgOption) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&orgname); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -137,6 +147,9 @@ func (c *Client) EditOrg(orgname string, opt EditOrgOption) (*Response, error) {
|
|||
|
||||
// DeleteOrg deletes an organization
|
||||
func (c *Client) DeleteOrg(orgname string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&orgname); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
32
vendor/code.gitea.io/sdk/gitea/org_member.go
generated
vendored
32
vendor/code.gitea.io/sdk/gitea/org_member.go
generated
vendored
|
@ -12,7 +12,10 @@ import (
|
|||
|
||||
// DeleteOrgMembership remove a member from an organization
|
||||
func (c *Client) DeleteOrgMembership(org, user string) (*Response, error) {
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
|
||||
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
|
@ -23,10 +26,13 @@ type ListOrgMembershipOption struct {
|
|||
|
||||
// ListOrgMembership list an organization's members
|
||||
func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
users := make([]*User, 0, opt.PageSize)
|
||||
|
||||
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/members", url.PathEscape(org)))
|
||||
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/members", org))
|
||||
link.RawQuery = opt.getURLQuery().Encode()
|
||||
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
|
||||
return users, resp, err
|
||||
|
@ -34,10 +40,13 @@ func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*
|
|||
|
||||
// ListPublicOrgMembership list an organization's members
|
||||
func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
users := make([]*User, 0, opt.PageSize)
|
||||
|
||||
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/public_members", url.PathEscape(org)))
|
||||
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/public_members", org))
|
||||
link.RawQuery = opt.getURLQuery().Encode()
|
||||
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
|
||||
return users, resp, err
|
||||
|
@ -45,7 +54,10 @@ func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption
|
|||
|
||||
// CheckOrgMembership Check if a user is a member of an organization
|
||||
func (c *Client) CheckOrgMembership(org, user string) (bool, *Response, error) {
|
||||
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
|
||||
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", org, user), nil, nil)
|
||||
if err != nil {
|
||||
return false, resp, err
|
||||
}
|
||||
|
@ -61,7 +73,10 @@ func (c *Client) CheckOrgMembership(org, user string) (bool, *Response, error) {
|
|||
|
||||
// CheckPublicOrgMembership Check if a user is a member of an organization
|
||||
func (c *Client) CheckPublicOrgMembership(org, user string) (bool, *Response, error) {
|
||||
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
|
||||
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
|
||||
if err != nil {
|
||||
return false, resp, err
|
||||
}
|
||||
|
@ -77,15 +92,18 @@ func (c *Client) CheckPublicOrgMembership(org, user string) (bool, *Response, er
|
|||
|
||||
// SetPublicOrgMembership publicize/conceal a user's membership
|
||||
func (c *Client) SetPublicOrgMembership(org, user string, visible bool) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&org, &user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var (
|
||||
status int
|
||||
err error
|
||||
resp *Response
|
||||
)
|
||||
if visible {
|
||||
status, resp, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
|
||||
status, resp, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
|
||||
} else {
|
||||
status, resp, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
|
||||
status, resp, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", org, user), nil, nil)
|
||||
}
|
||||
if err != nil {
|
||||
return resp, err
|
||||
|
|
86
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
86
vendor/code.gitea.io/sdk/gitea/org_team.go
generated
vendored
|
@ -12,17 +12,38 @@ import (
|
|||
|
||||
// Team represents a team in an organization
|
||||
type Team struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Organization *Organization `json:"organization"`
|
||||
Permission AccessMode `json:"permission"`
|
||||
CanCreateOrgRepo bool `json:"can_create_org_repo"`
|
||||
IncludesAllRepositories bool `json:"includes_all_repositories"`
|
||||
// example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.ext_wiki"]
|
||||
Units []string `json:"units"`
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Organization *Organization `json:"organization"`
|
||||
Permission AccessMode `json:"permission"`
|
||||
CanCreateOrgRepo bool `json:"can_create_org_repo"`
|
||||
IncludesAllRepositories bool `json:"includes_all_repositories"`
|
||||
Units []RepoUnitType `json:"units"`
|
||||
}
|
||||
|
||||
// RepoUnitType represent all unit types of a repo gitea currently offer
|
||||
type RepoUnitType string
|
||||
|
||||
const (
|
||||
// RepoUnitCode represent file view of a repository
|
||||
RepoUnitCode RepoUnitType = "repo.code"
|
||||
// RepoUnitIssues represent issues of a repository
|
||||
RepoUnitIssues RepoUnitType = "repo.issues"
|
||||
// RepoUnitPulls represent pulls of a repository
|
||||
RepoUnitPulls RepoUnitType = "repo.pulls"
|
||||
// RepoUnitExtIssues represent external issues of a repository
|
||||
RepoUnitExtIssues RepoUnitType = "repo.ext_issues"
|
||||
// RepoUnitWiki represent wiki of a repository
|
||||
RepoUnitWiki RepoUnitType = "repo.wiki"
|
||||
// RepoUnitExtWiki represent external wiki of a repository
|
||||
RepoUnitExtWiki RepoUnitType = "repo.ext_wiki"
|
||||
// RepoUnitReleases represent releases of a repository
|
||||
RepoUnitReleases RepoUnitType = "repo.releases"
|
||||
// RepoUnitProjects represent projects of a repository
|
||||
RepoUnitProjects RepoUnitType = "repo.projects"
|
||||
)
|
||||
|
||||
// ListTeamsOptions options for listing teams
|
||||
type ListTeamsOptions struct {
|
||||
ListOptions
|
||||
|
@ -30,6 +51,9 @@ type ListTeamsOptions struct {
|
|||
|
||||
// ListOrgTeams lists all teams of an organization
|
||||
func (c *Client) ListOrgTeams(org string, opt ListTeamsOptions) ([]*Team, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
teams := make([]*Team, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams?%s", org, opt.getURLQuery().Encode()), nil, nil, &teams)
|
||||
|
@ -53,13 +77,12 @@ func (c *Client) GetTeam(id int64) (*Team, *Response, error) {
|
|||
|
||||
// CreateTeamOption options for creating a team
|
||||
type CreateTeamOption struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Permission AccessMode `json:"permission"`
|
||||
CanCreateOrgRepo bool `json:"can_create_org_repo"`
|
||||
IncludesAllRepositories bool `json:"includes_all_repositories"`
|
||||
// example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.ext_wiki"]
|
||||
Units []string `json:"units"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Permission AccessMode `json:"permission"`
|
||||
CanCreateOrgRepo bool `json:"can_create_org_repo"`
|
||||
IncludesAllRepositories bool `json:"includes_all_repositories"`
|
||||
Units []RepoUnitType `json:"units"`
|
||||
}
|
||||
|
||||
// Validate the CreateTeamOption struct
|
||||
|
@ -83,6 +106,9 @@ func (opt CreateTeamOption) Validate() error {
|
|||
|
||||
// CreateTeam creates a team for an organization
|
||||
func (c *Client) CreateTeam(org string, opt CreateTeamOption) (*Team, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -97,13 +123,12 @@ func (c *Client) CreateTeam(org string, opt CreateTeamOption) (*Team, *Response,
|
|||
|
||||
// EditTeamOption options for editing a team
|
||||
type EditTeamOption struct {
|
||||
Name string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
Permission AccessMode `json:"permission"`
|
||||
CanCreateOrgRepo *bool `json:"can_create_org_repo"`
|
||||
IncludesAllRepositories *bool `json:"includes_all_repositories"`
|
||||
// example: ["repo.code","repo.issues","repo.ext_issues","repo.wiki","repo.pulls","repo.releases","repo.ext_wiki"]
|
||||
Units []string `json:"units"`
|
||||
Name string `json:"name"`
|
||||
Description *string `json:"description"`
|
||||
Permission AccessMode `json:"permission"`
|
||||
CanCreateOrgRepo *bool `json:"can_create_org_repo"`
|
||||
IncludesAllRepositories *bool `json:"includes_all_repositories"`
|
||||
Units []RepoUnitType `json:"units"`
|
||||
}
|
||||
|
||||
// Validate the EditTeamOption struct
|
||||
|
@ -159,6 +184,9 @@ func (c *Client) ListTeamMembers(id int64, opt ListTeamMembersOptions) ([]*User,
|
|||
|
||||
// GetTeamMember gets a member of a team
|
||||
func (c *Client) GetTeamMember(id int64, user string) (*User, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
m := new(User)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil, m)
|
||||
return m, resp, err
|
||||
|
@ -166,12 +194,18 @@ func (c *Client) GetTeamMember(id int64, user string) (*User, *Response, error)
|
|||
|
||||
// AddTeamMember adds a member to a team
|
||||
func (c *Client) AddTeamMember(id int64, user string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// RemoveTeamMember removes a member from a team
|
||||
func (c *Client) RemoveTeamMember(id int64, user string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/members/%s", id, user), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
@ -191,12 +225,18 @@ func (c *Client) ListTeamRepositories(id int64, opt ListTeamRepositoriesOptions)
|
|||
|
||||
// AddTeamRepository adds a repository to a team
|
||||
func (c *Client) AddTeamRepository(id int64, org, repo string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&org, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// RemoveTeamRepository removes a repository from a team
|
||||
func (c *Client) RemoveTeamRepository(id int64, org, repo string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&org, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/teams/%d/repos/%s/%s", id, org, repo), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
71
vendor/code.gitea.io/sdk/gitea/pull.go
generated
vendored
71
vendor/code.gitea.io/sdk/gitea/pull.go
generated
vendored
|
@ -99,19 +99,37 @@ func (opt *ListPullRequestsOptions) QueryEncode() string {
|
|||
|
||||
// ListRepoPullRequests list PRs of one repository
|
||||
func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
prs := make([]*PullRequest, 0, opt.PageSize)
|
||||
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls", owner, repo))
|
||||
link.RawQuery = opt.QueryEncode()
|
||||
resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &prs)
|
||||
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||
for i := range prs {
|
||||
if err := fixPullHeadSha(c, prs[i]); err != nil {
|
||||
return prs, resp, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return prs, resp, err
|
||||
}
|
||||
|
||||
// GetPullRequest get information of one PR
|
||||
func (c *Client) GetPullRequest(owner, repo string, index int64) (*PullRequest, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pr := new(PullRequest)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d", owner, repo, index), nil, nil, pr)
|
||||
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||
if err := fixPullHeadSha(c, pr); err != nil {
|
||||
return pr, resp, err
|
||||
}
|
||||
}
|
||||
return pr, resp, err
|
||||
}
|
||||
|
||||
|
@ -130,6 +148,9 @@ type CreatePullRequestOption struct {
|
|||
|
||||
// CreatePullRequest create pull request with options
|
||||
func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOption) (*PullRequest, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -169,6 +190,9 @@ func (opt EditPullRequestOption) Validate(c *Client) error {
|
|||
|
||||
// EditPullRequest modify pull request with PR id and options
|
||||
func (c *Client) EditPullRequest(owner, repo string, index int64, opt EditPullRequestOption) (*PullRequest, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(c); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -202,6 +226,9 @@ func (opt MergePullRequestOption) Validate(c *Client) error {
|
|||
|
||||
// MergePullRequest merge a PR to repository by PR id
|
||||
func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePullRequestOption) (bool, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
if err := opt.Validate(c); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
@ -218,6 +245,9 @@ func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePull
|
|||
|
||||
// IsPullRequestMerged test if one PR is merged to one repository
|
||||
func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), nil, nil)
|
||||
|
||||
if err != nil {
|
||||
|
@ -229,6 +259,9 @@ func (c *Client) IsPullRequestMerged(owner, repo string, index int64) (bool, *Re
|
|||
|
||||
// getPullRequestDiffOrPatch gets the patch or diff file as bytes for a PR
|
||||
func (c *Client) getPullRequestDiffOrPatch(owner, repo, kind string, index int64) ([]byte, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &kind); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||
r, _, err2 := c.GetRepo(owner, repo)
|
||||
if err2 != nil {
|
||||
|
@ -251,3 +284,41 @@ func (c *Client) GetPullRequestPatch(owner, repo string, index int64) ([]byte, *
|
|||
func (c *Client) GetPullRequestDiff(owner, repo string, index int64) ([]byte, *Response, error) {
|
||||
return c.getPullRequestDiffOrPatch(owner, repo, "diff", index)
|
||||
}
|
||||
|
||||
// ListPullRequestCommitsOptions options for listing pull requests
|
||||
type ListPullRequestCommitsOptions struct {
|
||||
ListOptions
|
||||
}
|
||||
|
||||
// ListPullRequestCommits list commits for a pull request
|
||||
func (c *Client) ListPullRequestCommits(owner, repo string, index int64, opt ListPullRequestCommitsOptions) ([]*Commit, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/commits", owner, repo, index))
|
||||
opt.setDefaults()
|
||||
commits := make([]*Commit, 0, opt.PageSize)
|
||||
link.RawQuery = opt.getURLQuery().Encode()
|
||||
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &commits)
|
||||
return commits, resp, err
|
||||
}
|
||||
|
||||
// fixPullHeadSha is a workaround for https://github.com/go-gitea/gitea/issues/12675
|
||||
// When no head sha is available, this is because the branch got deleted in the base repo.
|
||||
// pr.Head.Ref points in this case not to the head repo branch name, but the base repo ref,
|
||||
// which stays available to resolve the commit sha. This is fixed for gitea >= 1.14.0
|
||||
func fixPullHeadSha(client *Client, pr *PullRequest) error {
|
||||
if pr.Base != nil && pr.Base.Repository != nil && pr.Base.Repository.Owner != nil &&
|
||||
pr.Head != nil && pr.Head.Ref != "" && pr.Head.Sha == "" {
|
||||
owner := pr.Base.Repository.Owner.UserName
|
||||
repo := pr.Base.Repository.Name
|
||||
refs, _, err := client.GetRepoRefs(owner, repo, pr.Head.Ref)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(refs) == 0 {
|
||||
return fmt.Errorf("unable to resolve PR ref '%s'", pr.Head.Ref)
|
||||
}
|
||||
pr.Head.Sha = refs[0].Object.SHA
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
124
vendor/code.gitea.io/sdk/gitea/pull_review.go
generated
vendored
124
vendor/code.gitea.io/sdk/gitea/pull_review.go
generated
vendored
|
@ -33,15 +33,19 @@ const (
|
|||
|
||||
// PullReview represents a pull request review
|
||||
type PullReview struct {
|
||||
ID int64 `json:"id"`
|
||||
Reviewer *User `json:"user"`
|
||||
State ReviewStateType `json:"state"`
|
||||
Body string `json:"body"`
|
||||
CommitID string `json:"commit_id"`
|
||||
Stale bool `json:"stale"`
|
||||
Official bool `json:"official"`
|
||||
CodeCommentsCount int `json:"comments_count"`
|
||||
Submitted time.Time `json:"submitted_at"`
|
||||
ID int64 `json:"id"`
|
||||
Reviewer *User `json:"user"`
|
||||
ReviewerTeam *Team `json:"team"`
|
||||
State ReviewStateType `json:"state"`
|
||||
Body string `json:"body"`
|
||||
CommitID string `json:"commit_id"`
|
||||
// Stale indicates if the pull has changed since the review
|
||||
Stale bool `json:"stale"`
|
||||
// Official indicates if the review counts towards the required approval limit, if PR base is a protected branch
|
||||
Official bool `json:"official"`
|
||||
Dismissed bool `json:"dismissed"`
|
||||
CodeCommentsCount int `json:"comments_count"`
|
||||
Submitted time.Time `json:"submitted_at"`
|
||||
|
||||
HTMLURL string `json:"html_url"`
|
||||
HTMLPullURL string `json:"pull_request_url"`
|
||||
|
@ -53,6 +57,7 @@ type PullReviewComment struct {
|
|||
Body string `json:"body"`
|
||||
Reviewer *User `json:"user"`
|
||||
ReviewID int64 `json:"pull_request_review_id"`
|
||||
Resolver *User `json:"resolver"`
|
||||
|
||||
Created time.Time `json:"created_at"`
|
||||
Updated time.Time `json:"updated_at"`
|
||||
|
@ -93,6 +98,17 @@ type SubmitPullReviewOptions struct {
|
|||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
// DismissPullReviewOptions are options to dismiss a pull review
|
||||
type DismissPullReviewOptions struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// PullReviewRequestOptions are options to add or remove pull review requests
|
||||
type PullReviewRequestOptions struct {
|
||||
Reviewers []string `json:"reviewers"`
|
||||
TeamReviewers []string `json:"team_reviewers"`
|
||||
}
|
||||
|
||||
// ListPullReviewsOptions options for listing PullReviews
|
||||
type ListPullReviewsOptions struct {
|
||||
ListOptions
|
||||
|
@ -132,6 +148,9 @@ func (opt CreatePullReviewComment) Validate() error {
|
|||
|
||||
// ListPullReviews lists all reviews of a pull request
|
||||
func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullReviewsOptions) ([]*PullReview, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -147,6 +166,9 @@ func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullRe
|
|||
|
||||
// GetPullReview gets a specific review of a pull request
|
||||
func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -158,6 +180,9 @@ func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview
|
|||
|
||||
// ListPullReviewComments lists all comments of a pull request review
|
||||
func (c *Client) ListPullReviewComments(owner, repo string, index, id int64) ([]*PullReviewComment, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -170,6 +195,9 @@ func (c *Client) ListPullReviewComments(owner, repo string, index, id int64) ([]
|
|||
|
||||
// DeletePullReview delete a specific review from a pull request
|
||||
func (c *Client) DeletePullReview(owner, repo string, index, id int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -180,6 +208,9 @@ func (c *Client) DeletePullReview(owner, repo string, index, id int64) (*Respons
|
|||
|
||||
// CreatePullReview create a review to an pull request
|
||||
func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePullReviewOptions) (*PullReview, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -200,6 +231,9 @@ func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePul
|
|||
|
||||
// SubmitPullReview submit a pending review to an pull request
|
||||
func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt SubmitPullReviewOptions) (*PullReview, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -217,3 +251,75 @@ func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt Submi
|
|||
jsonHeader, bytes.NewReader(body), r)
|
||||
return r, resp, err
|
||||
}
|
||||
|
||||
// CreateReviewRequests create review requests to an pull request
|
||||
func (c *Client) CreateReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, resp, err := c.getResponse("POST",
|
||||
fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
|
||||
jsonHeader, bytes.NewReader(body))
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// DeleteReviewRequests delete review requests to an pull request
|
||||
func (c *Client) DeleteReviewRequests(owner, repo string, index int64, opt PullReviewRequestOptions) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, resp, err := c.getResponse("DELETE",
|
||||
fmt.Sprintf("/repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, index),
|
||||
jsonHeader, bytes.NewReader(body))
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// DismissPullReview dismiss a review for a pull request
|
||||
func (c *Client) DismissPullReview(owner, repo string, index, id int64, opt DismissPullReviewOptions) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, resp, err := c.getResponse("POST",
|
||||
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/dismissals", owner, repo, index, id),
|
||||
jsonHeader, bytes.NewReader(body))
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// UnDismissPullReview cancel to dismiss a review for a pull request
|
||||
func (c *Client) UnDismissPullReview(owner, repo string, index, id int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, resp, err := c.getResponse("POST",
|
||||
fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/undismissals", owner, repo, index, id),
|
||||
jsonHeader, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
68
vendor/code.gitea.io/sdk/gitea/release.go
generated
vendored
68
vendor/code.gitea.io/sdk/gitea/release.go
generated
vendored
|
@ -21,6 +21,7 @@ type Release struct {
|
|||
Title string `json:"name"`
|
||||
Note string `json:"body"`
|
||||
URL string `json:"url"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
TarURL string `json:"tarball_url"`
|
||||
ZipURL string `json:"zipball_url"`
|
||||
IsDraft bool `json:"draft"`
|
||||
|
@ -34,35 +35,60 @@ type Release struct {
|
|||
// ListReleasesOptions options for listing repository's releases
|
||||
type ListReleasesOptions struct {
|
||||
ListOptions
|
||||
IsDraft *bool
|
||||
IsPreRelease *bool
|
||||
}
|
||||
|
||||
// QueryEncode turns options into querystring argument
|
||||
func (opt *ListReleasesOptions) QueryEncode() string {
|
||||
query := opt.getURLQuery()
|
||||
|
||||
if opt.IsDraft != nil {
|
||||
query.Add("draft", fmt.Sprintf("%t", *opt.IsDraft))
|
||||
}
|
||||
if opt.IsPreRelease != nil {
|
||||
query.Add("draft", fmt.Sprintf("%t", *opt.IsPreRelease))
|
||||
}
|
||||
|
||||
return query.Encode()
|
||||
}
|
||||
|
||||
// ListReleases list releases of a repository
|
||||
func (c *Client) ListReleases(user, repo string, opt ListReleasesOptions) ([]*Release, *Response, error) {
|
||||
func (c *Client) ListReleases(owner, repo string, opt ListReleasesOptions) ([]*Release, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
releases := make([]*Release, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET",
|
||||
fmt.Sprintf("/repos/%s/%s/releases?%s", user, repo, opt.getURLQuery().Encode()),
|
||||
fmt.Sprintf("/repos/%s/%s/releases?%s", owner, repo, opt.QueryEncode()),
|
||||
nil, nil, &releases)
|
||||
return releases, resp, err
|
||||
}
|
||||
|
||||
// GetRelease get a release of a repository by id
|
||||
func (c *Client) GetRelease(user, repo string, id int64) (*Release, *Response, error) {
|
||||
func (c *Client) GetRelease(owner, repo string, id int64) (*Release, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
r := new(Release)
|
||||
resp, err := c.getParsedResponse("GET",
|
||||
fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
|
||||
fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
|
||||
jsonHeader, nil, &r)
|
||||
return r, resp, err
|
||||
}
|
||||
|
||||
// GetReleaseByTag get a release of a repository by tag
|
||||
func (c *Client) GetReleaseByTag(user, repo string, tag string) (*Release, *Response, error) {
|
||||
func (c *Client) GetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
|
||||
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||
return c.fallbackGetReleaseByTag(user, repo, tag)
|
||||
return c.fallbackGetReleaseByTag(owner, repo, tag)
|
||||
}
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &tag); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
r := new(Release)
|
||||
resp, err := c.getParsedResponse("GET",
|
||||
fmt.Sprintf("/repos/%s/%s/releases/tags/%s", user, repo, tag),
|
||||
fmt.Sprintf("/repos/%s/%s/releases/tags/%s", owner, repo, tag),
|
||||
nil, nil, &r)
|
||||
return r, resp, err
|
||||
}
|
||||
|
@ -86,7 +112,10 @@ func (opt CreateReleaseOption) Validate() error {
|
|||
}
|
||||
|
||||
// CreateRelease create a release
|
||||
func (c *Client) CreateRelease(user, repo string, opt CreateReleaseOption) (*Release, *Response, error) {
|
||||
func (c *Client) CreateRelease(owner, repo string, opt CreateReleaseOption) (*Release, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -96,7 +125,7 @@ func (c *Client) CreateRelease(user, repo string, opt CreateReleaseOption) (*Rel
|
|||
}
|
||||
r := new(Release)
|
||||
resp, err := c.getParsedResponse("POST",
|
||||
fmt.Sprintf("/repos/%s/%s/releases", user, repo),
|
||||
fmt.Sprintf("/repos/%s/%s/releases", owner, repo),
|
||||
jsonHeader, bytes.NewReader(body), r)
|
||||
return r, resp, err
|
||||
}
|
||||
|
@ -112,28 +141,37 @@ type EditReleaseOption struct {
|
|||
}
|
||||
|
||||
// EditRelease edit a release
|
||||
func (c *Client) EditRelease(user, repo string, id int64, form EditReleaseOption) (*Release, *Response, error) {
|
||||
func (c *Client) EditRelease(owner, repo string, id int64, form EditReleaseOption) (*Release, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(form)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
r := new(Release)
|
||||
resp, err := c.getParsedResponse("PATCH",
|
||||
fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
|
||||
fmt.Sprintf("/repos/%s/%s/releases/%d", owner, repo, id),
|
||||
jsonHeader, bytes.NewReader(body), r)
|
||||
return r, resp, err
|
||||
}
|
||||
|
||||
// DeleteRelease delete a release from a repository, keeping its tag
|
||||
func (c *Client) DeleteRelease(user, repo string, id int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE",
|
||||
fmt.Sprintf("/repos/%s/%s/releases/%d", user, repo, id),
|
||||
nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// DeleteReleaseTag deletes a tag from a repository, if no release refers to it.
|
||||
func (c *Client) DeleteReleaseTag(user, repo string, tag string) (*Response, error) {
|
||||
// DeleteReleaseByTag deletes a release frm a repository by tag
|
||||
func (c *Client) DeleteReleaseByTag(user, repo string, tag string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -144,9 +182,9 @@ func (c *Client) DeleteReleaseTag(user, repo string, tag string) (*Response, err
|
|||
}
|
||||
|
||||
// fallbackGetReleaseByTag is fallback for old gitea installations ( < 1.13.0 )
|
||||
func (c *Client) fallbackGetReleaseByTag(user, repo string, tag string) (*Release, *Response, error) {
|
||||
func (c *Client) fallbackGetReleaseByTag(owner, repo string, tag string) (*Release, *Response, error) {
|
||||
for i := 1; ; i++ {
|
||||
rl, resp, err := c.ListReleases(user, repo, ListReleasesOptions{ListOptions{Page: i}})
|
||||
rl, resp, err := c.ListReleases(owner, repo, ListReleasesOptions{ListOptions: ListOptions{Page: i}})
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
|
182
vendor/code.gitea.io/sdk/gitea/repo.go
generated
vendored
182
vendor/code.gitea.io/sdk/gitea/repo.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
@ -21,42 +22,78 @@ type Permission struct {
|
|||
Pull bool `json:"pull"`
|
||||
}
|
||||
|
||||
// InternalTracker represents settings for internal tracker
|
||||
type InternalTracker struct {
|
||||
// Enable time tracking (Built-in issue tracker)
|
||||
EnableTimeTracker bool `json:"enable_time_tracker"`
|
||||
// Let only contributors track time (Built-in issue tracker)
|
||||
AllowOnlyContributorsToTrackTime bool `json:"allow_only_contributors_to_track_time"`
|
||||
// Enable dependencies for issues and pull requests (Built-in issue tracker)
|
||||
EnableIssueDependencies bool `json:"enable_issue_dependencies"`
|
||||
}
|
||||
|
||||
// ExternalTracker represents settings for external tracker
|
||||
type ExternalTracker struct {
|
||||
// URL of external issue tracker.
|
||||
ExternalTrackerURL string `json:"external_tracker_url"`
|
||||
// External Issue Tracker URL Format. Use the placeholders {user}, {repo} and {index} for the username, repository name and issue index.
|
||||
ExternalTrackerFormat string `json:"external_tracker_format"`
|
||||
// External Issue Tracker Number Format, either `numeric` or `alphanumeric`
|
||||
ExternalTrackerStyle string `json:"external_tracker_style"`
|
||||
}
|
||||
|
||||
// ExternalWiki represents setting for external wiki
|
||||
type ExternalWiki struct {
|
||||
// URL of external wiki.
|
||||
ExternalWikiURL string `json:"external_wiki_url"`
|
||||
}
|
||||
|
||||
// Repository represents a repository
|
||||
type Repository struct {
|
||||
ID int64 `json:"id"`
|
||||
Owner *User `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
Description string `json:"description"`
|
||||
Empty bool `json:"empty"`
|
||||
Private bool `json:"private"`
|
||||
Fork bool `json:"fork"`
|
||||
Parent *Repository `json:"parent"`
|
||||
Mirror bool `json:"mirror"`
|
||||
Size int `json:"size"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
SSHURL string `json:"ssh_url"`
|
||||
CloneURL string `json:"clone_url"`
|
||||
OriginalURL string `json:"original_url"`
|
||||
Website string `json:"website"`
|
||||
Stars int `json:"stars_count"`
|
||||
Forks int `json:"forks_count"`
|
||||
Watchers int `json:"watchers_count"`
|
||||
OpenIssues int `json:"open_issues_count"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
Archived bool `json:"archived"`
|
||||
Created time.Time `json:"created_at"`
|
||||
Updated time.Time `json:"updated_at"`
|
||||
Permissions *Permission `json:"permissions,omitempty"`
|
||||
HasIssues bool `json:"has_issues"`
|
||||
HasWiki bool `json:"has_wiki"`
|
||||
HasPullRequests bool `json:"has_pull_requests"`
|
||||
IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"`
|
||||
AllowMerge bool `json:"allow_merge_commits"`
|
||||
AllowRebase bool `json:"allow_rebase"`
|
||||
AllowRebaseMerge bool `json:"allow_rebase_explicit"`
|
||||
AllowSquash bool `json:"allow_squash_merge"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
ID int64 `json:"id"`
|
||||
Owner *User `json:"owner"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
Description string `json:"description"`
|
||||
Empty bool `json:"empty"`
|
||||
Private bool `json:"private"`
|
||||
Fork bool `json:"fork"`
|
||||
Template bool `json:"template"`
|
||||
Parent *Repository `json:"parent"`
|
||||
Mirror bool `json:"mirror"`
|
||||
Size int `json:"size"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
SSHURL string `json:"ssh_url"`
|
||||
CloneURL string `json:"clone_url"`
|
||||
OriginalURL string `json:"original_url"`
|
||||
Website string `json:"website"`
|
||||
Stars int `json:"stars_count"`
|
||||
Forks int `json:"forks_count"`
|
||||
Watchers int `json:"watchers_count"`
|
||||
OpenIssues int `json:"open_issues_count"`
|
||||
OpenPulls int `json:"open_pr_counter"`
|
||||
Releases int `json:"release_counter"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
Archived bool `json:"archived"`
|
||||
Created time.Time `json:"created_at"`
|
||||
Updated time.Time `json:"updated_at"`
|
||||
Permissions *Permission `json:"permissions,omitempty"`
|
||||
HasIssues bool `json:"has_issues"`
|
||||
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
|
||||
ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
|
||||
HasWiki bool `json:"has_wiki"`
|
||||
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
||||
HasPullRequests bool `json:"has_pull_requests"`
|
||||
HasProjects bool `json:"has_projects"`
|
||||
IgnoreWhitespaceConflicts bool `json:"ignore_whitespace_conflicts"`
|
||||
AllowMerge bool `json:"allow_merge_commits"`
|
||||
AllowRebase bool `json:"allow_rebase"`
|
||||
AllowRebaseMerge bool `json:"allow_rebase_explicit"`
|
||||
AllowSquash bool `json:"allow_squash_merge"`
|
||||
AvatarURL string `json:"avatar_url"`
|
||||
Internal bool `json:"internal"`
|
||||
MirrorInterval string `json:"mirror_interval"`
|
||||
DefaultMergeStyle MergeStyle `json:"default_merge_style"`
|
||||
}
|
||||
|
||||
// RepoType represent repo type
|
||||
|
@ -102,6 +139,9 @@ func (c *Client) ListMyRepos(opt ListReposOptions) ([]*Repository, *Response, er
|
|||
|
||||
// ListUserRepos list all repositories of one user by user's name
|
||||
func (c *Client) ListUserRepos(user string, opt ListReposOptions) ([]*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
repos := make([]*Repository, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos?%s", user, opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||
|
@ -115,6 +155,9 @@ type ListOrgReposOptions struct {
|
|||
|
||||
// ListOrgRepos list all repositories of one organization by organization's name
|
||||
func (c *Client) ListOrgRepos(org string, opt ListOrgReposOptions) ([]*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
repos := make([]*Repository, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos?%s", org, opt.getURLQuery().Encode()), nil, nil, &repos)
|
||||
|
@ -315,6 +358,9 @@ func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, *Response, error
|
|||
|
||||
// CreateOrgRepo creates an organization repository for authenticated user.
|
||||
func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&org); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(c); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -329,11 +375,21 @@ func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, *
|
|||
|
||||
// GetRepo returns information of a repository of given owner.
|
||||
func (c *Client) GetRepo(owner, reponame string) (*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
repo := new(Repository)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo)
|
||||
return repo, resp, err
|
||||
}
|
||||
|
||||
// GetRepoByID returns information of a repository by a giver repository ID.
|
||||
func (c *Client) GetRepoByID(id int64) (*Repository, *Response, error) {
|
||||
repo := new(Repository)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repositories/%d", id), nil, nil, repo)
|
||||
return repo, resp, err
|
||||
}
|
||||
|
||||
// EditRepoOption options when editing a repository's properties
|
||||
type EditRepoOption struct {
|
||||
// name of the repository
|
||||
|
@ -346,14 +402,24 @@ type EditRepoOption struct {
|
|||
// Note: you will get a 422 error if the organization restricts changing repository visibility to organization
|
||||
// owners and a non-owner tries to change the value of private.
|
||||
Private *bool `json:"private,omitempty"`
|
||||
// either `true` to make this repository a template or `false` to make it a normal repository
|
||||
Template *bool `json:"template,omitempty"`
|
||||
// either `true` to enable issues for this repository or `false` to disable them.
|
||||
HasIssues *bool `json:"has_issues,omitempty"`
|
||||
// set this structure to configure internal issue tracker (requires has_issues)
|
||||
InternalTracker *InternalTracker `json:"internal_tracker,omitempty"`
|
||||
// set this structure to use external issue tracker (requires has_issues)
|
||||
ExternalTracker *ExternalTracker `json:"external_tracker,omitempty"`
|
||||
// either `true` to enable the wiki for this repository or `false` to disable it.
|
||||
HasWiki *bool `json:"has_wiki,omitempty"`
|
||||
// set this structure to use external wiki instead of internal (requires has_wiki)
|
||||
ExternalWiki *ExternalWiki `json:"external_wiki,omitempty"`
|
||||
// sets the default branch for this repository.
|
||||
DefaultBranch *string `json:"default_branch,omitempty"`
|
||||
// either `true` to allow pull requests, or `false` to prevent pull request.
|
||||
HasPullRequests *bool `json:"has_pull_requests,omitempty"`
|
||||
// either `true` to enable project unit, or `false` to disable them.
|
||||
HasProjects *bool `json:"has_projects,omitempty"`
|
||||
// either `true` to ignore whitespace for conflicts, or `false` to not ignore whitespace. `has_pull_requests` must be `true`.
|
||||
IgnoreWhitespaceConflicts *bool `json:"ignore_whitespace_conflicts,omitempty"`
|
||||
// either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits. `has_pull_requests` must be `true`.
|
||||
|
@ -366,10 +432,22 @@ type EditRepoOption struct {
|
|||
AllowSquash *bool `json:"allow_squash_merge,omitempty"`
|
||||
// set to `true` to archive this repository.
|
||||
Archived *bool `json:"archived,omitempty"`
|
||||
// set to a string like `8h30m0s` to set the mirror interval time
|
||||
MirrorInterval *string `json:"mirror_interval,omitempty"`
|
||||
// either `true` to allow mark pr as merged manually, or `false` to prevent it. `has_pull_requests` must be `true`.
|
||||
AllowManualMerge *bool `json:"allow_manual_merge,omitempty"`
|
||||
// either `true` to enable AutodetectManualMerge, or `false` to prevent it. `has_pull_requests` must be `true`, Note: In some special cases, misjudgments can occur.
|
||||
AutodetectManualMerge *bool `json:"autodetect_manual_merge,omitempty"`
|
||||
// set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". `has_pull_requests` must be `true`.
|
||||
DefaultMergeStyle *MergeStyle `json:"default_merge_style,omitempty"`
|
||||
// set to `true` to archive this repository.
|
||||
}
|
||||
|
||||
// EditRepo edit the properties of a repository
|
||||
func (c *Client) EditRepo(owner, reponame string, opt EditRepoOption) (*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -381,18 +459,27 @@ func (c *Client) EditRepo(owner, reponame string, opt EditRepoOption) (*Reposito
|
|||
|
||||
// DeleteRepo deletes a repository of user or organization.
|
||||
func (c *Client) DeleteRepo(owner, repo string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// MirrorSync adds a mirrored repository to the mirror sync queue.
|
||||
func (c *Client) MirrorSync(owner, repo string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("POST", fmt.Sprintf("/repos/%s/%s/mirror-sync", owner, repo), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// GetRepoLanguages return language stats of a repo
|
||||
func (c *Client) GetRepoLanguages(owner, repo string) (map[string]int64, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
langMap := make(map[string]int64)
|
||||
|
||||
data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/languages", owner, repo), jsonHeader, nil)
|
||||
|
@ -418,5 +505,30 @@ const (
|
|||
// GetArchive get an archive of a repository by git reference
|
||||
// e.g.: ref -> master, 70b7c74b33, v1.2.1, ...
|
||||
func (c *Client) GetArchive(owner, repo, ref string, ext ArchiveType) ([]byte, *Response, error) {
|
||||
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, url.PathEscape(ref), ext), nil, nil)
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ref = pathEscapeSegments(ref)
|
||||
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
|
||||
}
|
||||
|
||||
// GetArchiveReader gets a `git archive` for a particular tree-ish git reference
|
||||
// such as a branch name (`master`), a commit hash (`70b7c74b33`), a tag
|
||||
// (`v1.2.1`). The archive is returned as a byte stream in a ReadCloser. It is
|
||||
// the responsibility of the client to close the reader.
|
||||
func (c *Client) GetArchiveReader(owner, repo, ref string, ext ArchiveType) (io.ReadCloser, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ref = pathEscapeSegments(ref)
|
||||
resp, err := c.doRequest("GET", fmt.Sprintf("/repos/%s/%s/archive/%s%s", owner, repo, ref, ext), nil, nil)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
if _, err := statusCodeToErr(resp); err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
return resp.Body, resp, nil
|
||||
}
|
||||
|
|
15
vendor/code.gitea.io/sdk/gitea/repo_branch.go
generated
vendored
15
vendor/code.gitea.io/sdk/gitea/repo_branch.go
generated
vendored
|
@ -20,9 +20,6 @@ type PayloadUser struct {
|
|||
UserName string `json:"username"`
|
||||
}
|
||||
|
||||
// FIXME: consider using same format as API when commits API are added.
|
||||
// applies to PayloadCommit and PayloadCommitVerification
|
||||
|
||||
// PayloadCommit represents a commit
|
||||
type PayloadCommit struct {
|
||||
// sha1 hash of the commit
|
||||
|
@ -66,6 +63,9 @@ type ListRepoBranchesOptions struct {
|
|||
|
||||
// ListRepoBranches list all the branches of one repository
|
||||
func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions) ([]*Branch, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
branches := make([]*Branch, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &branches)
|
||||
|
@ -74,6 +74,9 @@ func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions
|
|||
|
||||
// GetRepoBranch get one branch's information of one repository
|
||||
func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
b := new(Branch)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
|
||||
if err != nil {
|
||||
|
@ -84,6 +87,9 @@ func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, *Response, e
|
|||
|
||||
// DeleteRepoBranch delete a branch in a repository
|
||||
func (c *Client) DeleteRepoBranch(user, repo, branch string) (bool, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &branch); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
|
@ -118,6 +124,9 @@ func (opt CreateBranchOption) Validate() error {
|
|||
|
||||
// CreateBranch creates a branch for a user's repository
|
||||
func (c *Client) CreateBranch(owner, repo string, opt CreateBranchOption) (*Branch, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
140
vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go
generated
vendored
140
vendor/code.gitea.io/sdk/gitea/repo_branch_protection.go
generated
vendored
|
@ -14,75 +14,78 @@ import (
|
|||
|
||||
// BranchProtection represents a branch protection for a repository
|
||||
type BranchProtection struct {
|
||||
BranchName string `json:"branch_name"`
|
||||
EnablePush bool `json:"enable_push"`
|
||||
EnablePushWhitelist bool `json:"enable_push_whitelist"`
|
||||
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||
EnableStatusCheck bool `json:"enable_status_check"`
|
||||
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||
RequiredApprovals int64 `json:"required_approvals"`
|
||||
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
|
||||
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
|
||||
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||
Created time.Time `json:"created_at"`
|
||||
Updated time.Time `json:"updated_at"`
|
||||
BranchName string `json:"branch_name"`
|
||||
EnablePush bool `json:"enable_push"`
|
||||
EnablePushWhitelist bool `json:"enable_push_whitelist"`
|
||||
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||
EnableStatusCheck bool `json:"enable_status_check"`
|
||||
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||
RequiredApprovals int64 `json:"required_approvals"`
|
||||
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
|
||||
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
|
||||
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
|
||||
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||
Created time.Time `json:"created_at"`
|
||||
Updated time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// CreateBranchProtectionOption options for creating a branch protection
|
||||
type CreateBranchProtectionOption struct {
|
||||
BranchName string `json:"branch_name"`
|
||||
EnablePush bool `json:"enable_push"`
|
||||
EnablePushWhitelist bool `json:"enable_push_whitelist"`
|
||||
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||
EnableStatusCheck bool `json:"enable_status_check"`
|
||||
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||
RequiredApprovals int64 `json:"required_approvals"`
|
||||
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
|
||||
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
|
||||
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||
BranchName string `json:"branch_name"`
|
||||
EnablePush bool `json:"enable_push"`
|
||||
EnablePushWhitelist bool `json:"enable_push_whitelist"`
|
||||
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||
EnableStatusCheck bool `json:"enable_status_check"`
|
||||
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||
RequiredApprovals int64 `json:"required_approvals"`
|
||||
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
|
||||
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||
BlockOnOfficialReviewRequests bool `json:"block_on_official_review_requests"`
|
||||
BlockOnOutdatedBranch bool `json:"block_on_outdated_branch"`
|
||||
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||
ProtectedFilePatterns string `json:"protected_file_patterns"`
|
||||
}
|
||||
|
||||
// EditBranchProtectionOption options for editing a branch protection
|
||||
type EditBranchProtectionOption struct {
|
||||
EnablePush *bool `json:"enable_push"`
|
||||
EnablePushWhitelist *bool `json:"enable_push_whitelist"`
|
||||
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||
PushWhitelistDeployKeys *bool `json:"push_whitelist_deploy_keys"`
|
||||
EnableMergeWhitelist *bool `json:"enable_merge_whitelist"`
|
||||
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||
EnableStatusCheck *bool `json:"enable_status_check"`
|
||||
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||
RequiredApprovals *int64 `json:"required_approvals"`
|
||||
EnableApprovalsWhitelist *bool `json:"enable_approvals_whitelist"`
|
||||
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||
BlockOnRejectedReviews *bool `json:"block_on_rejected_reviews"`
|
||||
BlockOnOutdatedBranch *bool `json:"block_on_outdated_branch"`
|
||||
DismissStaleApprovals *bool `json:"dismiss_stale_approvals"`
|
||||
RequireSignedCommits *bool `json:"require_signed_commits"`
|
||||
ProtectedFilePatterns *string `json:"protected_file_patterns"`
|
||||
EnablePush *bool `json:"enable_push"`
|
||||
EnablePushWhitelist *bool `json:"enable_push_whitelist"`
|
||||
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||
PushWhitelistDeployKeys *bool `json:"push_whitelist_deploy_keys"`
|
||||
EnableMergeWhitelist *bool `json:"enable_merge_whitelist"`
|
||||
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||
EnableStatusCheck *bool `json:"enable_status_check"`
|
||||
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||
RequiredApprovals *int64 `json:"required_approvals"`
|
||||
EnableApprovalsWhitelist *bool `json:"enable_approvals_whitelist"`
|
||||
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
|
||||
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||
BlockOnRejectedReviews *bool `json:"block_on_rejected_reviews"`
|
||||
BlockOnOfficialReviewRequests *bool `json:"block_on_official_review_requests"`
|
||||
BlockOnOutdatedBranch *bool `json:"block_on_outdated_branch"`
|
||||
DismissStaleApprovals *bool `json:"dismiss_stale_approvals"`
|
||||
RequireSignedCommits *bool `json:"require_signed_commits"`
|
||||
ProtectedFilePatterns *string `json:"protected_file_patterns"`
|
||||
}
|
||||
|
||||
// ListBranchProtectionsOptions list branch protection options
|
||||
|
@ -92,6 +95,9 @@ type ListBranchProtectionsOptions struct {
|
|||
|
||||
// ListBranchProtections list branch protections for a repo
|
||||
func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtectionsOptions) ([]*BranchProtection, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -104,6 +110,9 @@ func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtect
|
|||
|
||||
// GetBranchProtection gets a branch protection
|
||||
func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtection, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -114,6 +123,9 @@ func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtectio
|
|||
|
||||
// CreateBranchProtection creates a branch protection for a repo
|
||||
func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProtectionOption) (*BranchProtection, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -128,6 +140,9 @@ func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProt
|
|||
|
||||
// EditBranchProtection edits a branch protection for a repo
|
||||
func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchProtectionOption) (*BranchProtection, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -142,6 +157,9 @@ func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchPr
|
|||
|
||||
// DeleteBranchProtection deletes a branch protection for a repo
|
||||
func (c *Client) DeleteBranchProtection(owner, repo, name string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
39
vendor/code.gitea.io/sdk/gitea/repo_collaborator.go
generated
vendored
39
vendor/code.gitea.io/sdk/gitea/repo_collaborator.go
generated
vendored
|
@ -1,3 +1,4 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
@ -17,6 +18,9 @@ type ListCollaboratorsOptions struct {
|
|||
|
||||
// ListCollaborators list a repository's collaborators
|
||||
func (c *Client) ListCollaborators(user, repo string, opt ListCollaboratorsOptions) ([]*User, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
collaborators := make([]*User, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET",
|
||||
|
@ -27,6 +31,9 @@ func (c *Client) ListCollaborators(user, repo string, opt ListCollaboratorsOptio
|
|||
|
||||
// IsCollaborator check if a user is a collaborator of a repository
|
||||
func (c *Client) IsCollaborator(user, repo, collaborator string) (bool, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
|
||||
if err != nil {
|
||||
return false, resp, err
|
||||
|
@ -78,6 +85,9 @@ func (opt AddCollaboratorOption) Validate() error {
|
|||
|
||||
// AddCollaborator add some user as a collaborator of a repository
|
||||
func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollaboratorOption) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -91,7 +101,36 @@ func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollabo
|
|||
|
||||
// DeleteCollaborator remove a collaborator from a repository
|
||||
func (c *Client) DeleteCollaborator(user, repo, collaborator string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &collaborator); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE",
|
||||
fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// GetReviewers return all users that can be requested to review in this repo
|
||||
func (c *Client) GetReviewers(user, repo string) ([]*User, *Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
reviewers := make([]*User, 0, 5)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/reviewers", user, repo), nil, nil, &reviewers)
|
||||
return reviewers, resp, err
|
||||
}
|
||||
|
||||
// GetAssignees return all users that have write access and can be assigned to issues
|
||||
func (c *Client) GetAssignees(user, repo string) ([]*User, *Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
assignees := make([]*User, 0, 5)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/assignees", user, repo), nil, nil, &assignees)
|
||||
return assignees, resp, err
|
||||
}
|
||||
|
|
22
vendor/code.gitea.io/sdk/gitea/repo_commit.go
generated
vendored
22
vendor/code.gitea.io/sdk/gitea/repo_commit.go
generated
vendored
|
@ -42,11 +42,12 @@ type RepoCommit struct {
|
|||
// Commit contains information generated from a Git commit.
|
||||
type Commit struct {
|
||||
*CommitMeta
|
||||
HTMLURL string `json:"html_url"`
|
||||
RepoCommit *RepoCommit `json:"commit"`
|
||||
Author *User `json:"author"`
|
||||
Committer *User `json:"committer"`
|
||||
Parents []*CommitMeta `json:"parents"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
RepoCommit *RepoCommit `json:"commit"`
|
||||
Author *User `json:"author"`
|
||||
Committer *User `json:"committer"`
|
||||
Parents []*CommitMeta `json:"parents"`
|
||||
Files []*CommitAffectedFiles `json:"files"`
|
||||
}
|
||||
|
||||
// CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE
|
||||
|
@ -55,8 +56,16 @@ type CommitDateOptions struct {
|
|||
Committer time.Time `json:"committer"`
|
||||
}
|
||||
|
||||
// CommitAffectedFiles store information about files affected by the commit
|
||||
type CommitAffectedFiles struct {
|
||||
Filename string `json:"filename"`
|
||||
}
|
||||
|
||||
// GetSingleCommit returns a single commit
|
||||
func (c *Client) GetSingleCommit(user, repo, commitID string) (*Commit, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &commitID); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
commit := new(Commit)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s", user, repo, commitID), nil, nil, &commit)
|
||||
return commit, resp, err
|
||||
|
@ -80,6 +89,9 @@ func (opt *ListCommitOptions) QueryEncode() string {
|
|||
|
||||
// ListRepoCommits return list of commits from a repo
|
||||
func (c *Client) ListRepoCommits(user, repo string, opt ListCommitOptions) ([]*Commit, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/commits", user, repo))
|
||||
opt.setDefaults()
|
||||
commits := make([]*Commit, 0, opt.PageSize)
|
||||
|
|
63
vendor/code.gitea.io/sdk/gitea/repo_file.go
generated
vendored
63
vendor/code.gitea.io/sdk/gitea/repo_file.go
generated
vendored
|
@ -9,6 +9,8 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FileOptions options for all file APIs
|
||||
|
@ -23,6 +25,8 @@ type FileOptions struct {
|
|||
Author Identity `json:"author"`
|
||||
Committer Identity `json:"committer"`
|
||||
Dates CommitDateOptions `json:"dates"`
|
||||
// Add a Signed-off-by trailer by the committer at the end of the commit log message.
|
||||
Signoff bool `json:"signoff"`
|
||||
}
|
||||
|
||||
// CreateFileOptions options for creating files
|
||||
|
@ -113,25 +117,65 @@ type FileDeleteResponse struct {
|
|||
}
|
||||
|
||||
// GetFile downloads a file of repository, ref can be branch/tag/commit.
|
||||
// e.g.: ref -> master, tree -> macaron.go(no leading slash)
|
||||
func (c *Client) GetFile(user, repo, ref, tree string) ([]byte, *Response, error) {
|
||||
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", user, repo, ref, tree), nil, nil)
|
||||
// e.g.: ref -> master, filepath -> README.md (no leading slash)
|
||||
func (c *Client) GetFile(owner, repo, ref, filepath string) ([]byte, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
filepath = pathEscapeSegments(filepath)
|
||||
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||
ref = pathEscapeSegments(ref)
|
||||
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", owner, repo, ref, filepath), nil, nil)
|
||||
}
|
||||
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), nil, nil)
|
||||
}
|
||||
|
||||
// GetContents get the metadata and contents (if a file) of an entry in a repository, or a list of entries if a dir
|
||||
// GetContents get the metadata and contents of a file in a repository
|
||||
// ref is optional
|
||||
func (c *Client) GetContents(owner, repo, ref, filepath string) (*ContentsResponse, *Response, error) {
|
||||
data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
cr := new(ContentsResponse)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/contents/%s?ref=%s", owner, repo, filepath, ref), jsonHeader, nil, cr)
|
||||
if json.Unmarshal(data, &cr) != nil {
|
||||
return nil, resp, fmt.Errorf("expect file, got directory")
|
||||
}
|
||||
return cr, resp, err
|
||||
}
|
||||
|
||||
// ListContents gets a list of entries in a dir
|
||||
// ref is optional
|
||||
func (c *Client) ListContents(owner, repo, ref, filepath string) ([]*ContentsResponse, *Response, error) {
|
||||
data, resp, err := c.getDirOrFileContents(owner, repo, ref, filepath)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
crl := make([]*ContentsResponse, 0)
|
||||
if json.Unmarshal(data, &crl) != nil {
|
||||
return nil, resp, fmt.Errorf("expect directory, got file")
|
||||
}
|
||||
return crl, resp, err
|
||||
}
|
||||
|
||||
func (c *Client) getDirOrFileContents(owner, repo, ref, filepath string) ([]byte, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
filepath = pathEscapeSegments(strings.TrimPrefix(filepath, "/"))
|
||||
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/contents/%s?ref=%s", owner, repo, filepath, url.QueryEscape(ref)), jsonHeader, nil)
|
||||
}
|
||||
|
||||
// CreateFile create a file in a repository
|
||||
func (c *Client) CreateFile(owner, repo, filepath string, opt CreateFileOptions) (*FileResponse, *Response, error) {
|
||||
var err error
|
||||
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
filepath = pathEscapeSegments(filepath)
|
||||
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
|
@ -149,6 +193,11 @@ func (c *Client) UpdateFile(owner, repo, filepath string, opt UpdateFileOptions)
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
filepath = pathEscapeSegments(filepath)
|
||||
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -164,6 +213,10 @@ func (c *Client) DeleteFile(owner, repo, filepath string, opt DeleteFileOptions)
|
|||
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filepath = pathEscapeSegments(filepath)
|
||||
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
|
|
12
vendor/code.gitea.io/sdk/gitea/repo_key.go
generated
vendored
12
vendor/code.gitea.io/sdk/gitea/repo_key.go
generated
vendored
|
@ -46,6 +46,9 @@ func (opt *ListDeployKeysOptions) QueryEncode() string {
|
|||
|
||||
// ListDeployKeys list all the deploy keys of one repository
|
||||
func (c *Client) ListDeployKeys(user, repo string, opt ListDeployKeysOptions) ([]*DeployKey, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/keys", user, repo))
|
||||
opt.setDefaults()
|
||||
link.RawQuery = opt.QueryEncode()
|
||||
|
@ -56,6 +59,9 @@ func (c *Client) ListDeployKeys(user, repo string, opt ListDeployKeysOptions) ([
|
|||
|
||||
// GetDeployKey get one deploy key with key id
|
||||
func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
key := new(DeployKey)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys/%d", user, repo, keyID), nil, nil, &key)
|
||||
return key, resp, err
|
||||
|
@ -63,6 +69,9 @@ func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, *Resp
|
|||
|
||||
// CreateDeployKey options when create one deploy key
|
||||
func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*DeployKey, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -74,6 +83,9 @@ func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*Deplo
|
|||
|
||||
// DeleteDeployKey delete deploy key with key id
|
||||
func (c *Client) DeleteDeployKey(owner, repo string, keyID int64) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
50
vendor/code.gitea.io/sdk/gitea/repo_migrate.go
generated
vendored
50
vendor/code.gitea.io/sdk/gitea/repo_migrate.go
generated
vendored
|
@ -22,10 +22,8 @@ const (
|
|||
GitServiceGitlab GitServiceType = "gitlab"
|
||||
// GitServiceGitea represents a gitea service
|
||||
GitServiceGitea GitServiceType = "gitea"
|
||||
|
||||
// Not supported jet
|
||||
// // GitServiceGogs represents a gogs service
|
||||
// GitServiceGogs GitServiceType = "gogs"
|
||||
// GitServiceGogs represents a gogs service
|
||||
GitServiceGogs GitServiceType = "gogs"
|
||||
)
|
||||
|
||||
// MigrateRepoOption options for migrating a repository from an external service
|
||||
|
@ -33,21 +31,24 @@ type MigrateRepoOption struct {
|
|||
RepoName string `json:"repo_name"`
|
||||
RepoOwner string `json:"repo_owner"`
|
||||
// deprecated use RepoOwner
|
||||
RepoOwnerID int64 `json:"uid"`
|
||||
CloneAddr string `json:"clone_addr"`
|
||||
Service GitServiceType `json:"service"`
|
||||
AuthUsername string `json:"auth_username"`
|
||||
AuthPassword string `json:"auth_password"`
|
||||
AuthToken string `json:"auth_token"`
|
||||
Mirror bool `json:"mirror"`
|
||||
Private bool `json:"private"`
|
||||
Description string `json:"description"`
|
||||
Wiki bool `json:"wiki"`
|
||||
Milestones bool `json:"milestones"`
|
||||
Labels bool `json:"labels"`
|
||||
Issues bool `json:"issues"`
|
||||
PullRequests bool `json:"pull_requests"`
|
||||
Releases bool `json:"releases"`
|
||||
RepoOwnerID int64 `json:"uid"`
|
||||
CloneAddr string `json:"clone_addr"`
|
||||
Service GitServiceType `json:"service"`
|
||||
AuthUsername string `json:"auth_username"`
|
||||
AuthPassword string `json:"auth_password"`
|
||||
AuthToken string `json:"auth_token"`
|
||||
Mirror bool `json:"mirror"`
|
||||
Private bool `json:"private"`
|
||||
Description string `json:"description"`
|
||||
Wiki bool `json:"wiki"`
|
||||
Milestones bool `json:"milestones"`
|
||||
Labels bool `json:"labels"`
|
||||
Issues bool `json:"issues"`
|
||||
PullRequests bool `json:"pull_requests"`
|
||||
Releases bool `json:"releases"`
|
||||
MirrorInterval string `json:"mirror_interval"`
|
||||
LFS bool `json:"lfs"`
|
||||
LFSEndpoint string `json:"lfs_endpoint"`
|
||||
}
|
||||
|
||||
// Validate the MigrateRepoOption struct
|
||||
|
@ -67,17 +68,24 @@ func (opt *MigrateRepoOption) Validate(c *Client) error {
|
|||
switch opt.Service {
|
||||
case GitServiceGithub:
|
||||
if len(opt.AuthToken) == 0 {
|
||||
return fmt.Errorf("github require token authentication")
|
||||
return fmt.Errorf("github requires token authentication")
|
||||
}
|
||||
case GitServiceGitlab, GitServiceGitea:
|
||||
if len(opt.AuthToken) == 0 {
|
||||
return fmt.Errorf("%s require token authentication", opt.Service)
|
||||
return fmt.Errorf("%s requires token authentication", opt.Service)
|
||||
}
|
||||
// Gitlab is supported since 1.12.0 but api cant handle it until 1.13.0
|
||||
// https://github.com/go-gitea/gitea/pull/12672
|
||||
if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil {
|
||||
return fmt.Errorf("migrate from service %s need gitea >= 1.13.0", opt.Service)
|
||||
}
|
||||
case GitServiceGogs:
|
||||
if len(opt.AuthToken) == 0 {
|
||||
return fmt.Errorf("gogs requires token authentication")
|
||||
}
|
||||
if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil {
|
||||
return fmt.Errorf("migrate from service gogs need gitea >= 1.14.0")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
9
vendor/code.gitea.io/sdk/gitea/repo_refs.go
generated
vendored
9
vendor/code.gitea.io/sdk/gitea/repo_refs.go
generated
vendored
|
@ -27,7 +27,11 @@ type GitObject struct {
|
|||
|
||||
// GetRepoRef get one ref's information of one repository
|
||||
func (c *Client) GetRepoRef(user, repo, ref string) (*Reference, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ref = strings.TrimPrefix(ref, "refs/")
|
||||
ref = pathEscapeSegments(ref)
|
||||
r := new(Reference)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil, &r)
|
||||
if _, ok := err.(*json.UnmarshalTypeError); ok {
|
||||
|
@ -42,7 +46,12 @@ func (c *Client) GetRepoRef(user, repo, ref string) (*Reference, *Response, erro
|
|||
|
||||
// GetRepoRefs get list of ref's information of one repository
|
||||
func (c *Client) GetRepoRefs(user, repo, ref string) ([]*Reference, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ref = strings.TrimPrefix(ref, "refs/")
|
||||
ref = pathEscapeSegments(ref)
|
||||
|
||||
data, resp, err := c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/git/refs/%s", user, repo, ref), nil, nil)
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
|
|
96
vendor/code.gitea.io/sdk/gitea/repo_stars.go
generated
vendored
Normal file
96
vendor/code.gitea.io/sdk/gitea/repo_stars.go
generated
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ListStargazersOptions options for listing a repository's stargazers
|
||||
type ListStargazersOptions struct {
|
||||
ListOptions
|
||||
}
|
||||
|
||||
// ListRepoStargazers list a repository's stargazers
|
||||
func (c *Client) ListRepoStargazers(user, repo string, opt ListStargazersOptions) ([]*User, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
stargazers := make([]*User, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/stargazers?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &stargazers)
|
||||
return stargazers, resp, err
|
||||
}
|
||||
|
||||
// GetStarredRepos returns the repos that the given user has starred
|
||||
func (c *Client) GetStarredRepos(user string) ([]*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
repos := make([]*Repository, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/starred", user), jsonHeader, nil, &repos)
|
||||
return repos, resp, err
|
||||
}
|
||||
|
||||
// GetMyStarredRepos returns the repos that the authenticated user has starred
|
||||
func (c *Client) GetMyStarredRepos() ([]*Repository, *Response, error) {
|
||||
repos := make([]*Repository, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", "/user/starred", jsonHeader, nil, &repos)
|
||||
return repos, resp, err
|
||||
}
|
||||
|
||||
// IsRepoStarring returns whether the authenticated user has starred the repo or not
|
||||
func (c *Client) IsRepoStarring(user, repo string) (bool, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("GET", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
|
||||
if resp != nil {
|
||||
switch resp.StatusCode {
|
||||
case http.StatusNotFound:
|
||||
return false, resp, nil
|
||||
case http.StatusNoContent:
|
||||
return true, resp, nil
|
||||
default:
|
||||
return false, resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
return false, nil, err
|
||||
}
|
||||
|
||||
// StarRepo star specified repo as the authenticated user
|
||||
func (c *Client) StarRepo(user, repo string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
|
||||
if resp != nil {
|
||||
switch resp.StatusCode {
|
||||
case http.StatusNoContent:
|
||||
return resp, nil
|
||||
default:
|
||||
return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// UnStarRepo remove star to specified repo as the authenticated user
|
||||
func (c *Client) UnStarRepo(user, repo string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/starred/%s/%s", user, repo), jsonHeader, nil)
|
||||
if resp != nil {
|
||||
switch resp.StatusCode {
|
||||
case http.StatusNoContent:
|
||||
return resp, nil
|
||||
default:
|
||||
return resp, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
99
vendor/code.gitea.io/sdk/gitea/repo_tag.go
generated
vendored
99
vendor/code.gitea.io/sdk/gitea/repo_tag.go
generated
vendored
|
@ -5,18 +5,39 @@
|
|||
package gitea
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Tag represents a repository tag
|
||||
type Tag struct {
|
||||
Name string `json:"name"`
|
||||
Message string `json:"message"`
|
||||
ID string `json:"id"`
|
||||
Commit *CommitMeta `json:"commit"`
|
||||
ZipballURL string `json:"zipball_url"`
|
||||
TarballURL string `json:"tarball_url"`
|
||||
}
|
||||
|
||||
// AnnotatedTag represents an annotated tag
|
||||
type AnnotatedTag struct {
|
||||
Tag string `json:"tag"`
|
||||
SHA string `json:"sha"`
|
||||
URL string `json:"url"`
|
||||
Message string `json:"message"`
|
||||
Tagger *CommitUser `json:"tagger"`
|
||||
Object *AnnotatedTagObject `json:"object"`
|
||||
Verification *PayloadCommitVerification `json:"verification"`
|
||||
}
|
||||
|
||||
// AnnotatedTagObject contains meta information of the tag object
|
||||
type AnnotatedTagObject struct {
|
||||
Type string `json:"type"`
|
||||
URL string `json:"url"`
|
||||
SHA string `json:"sha"`
|
||||
}
|
||||
|
||||
// ListRepoTagsOptions options for listing a repository's tags
|
||||
type ListRepoTagsOptions struct {
|
||||
ListOptions
|
||||
|
@ -24,8 +45,86 @@ type ListRepoTagsOptions struct {
|
|||
|
||||
// ListRepoTags list all the branches of one repository
|
||||
func (c *Client) ListRepoTags(user, repo string, opt ListRepoTagsOptions) ([]*Tag, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
tags := make([]*Tag, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &tags)
|
||||
return tags, resp, err
|
||||
}
|
||||
|
||||
// GetTag get the tag of a repository
|
||||
func (c *Client) GetTag(user, repo, tag string) (*Tag, *Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
t := new(Tag)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag), nil, nil, &t)
|
||||
return t, resp, err
|
||||
}
|
||||
|
||||
// GetAnnotatedTag get the tag object of an annotated tag (not lightweight tags) of a repository
|
||||
func (c *Client) GetAnnotatedTag(user, repo, sha string) (*AnnotatedTag, *Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&user, &repo, &sha); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
t := new(AnnotatedTag)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/tags/%s", user, repo, sha), nil, nil, &t)
|
||||
return t, resp, err
|
||||
}
|
||||
|
||||
// CreateTagOption options when creating a tag
|
||||
type CreateTagOption struct {
|
||||
TagName string `json:"tag_name"`
|
||||
Message string `json:"message"`
|
||||
Target string `json:"target"`
|
||||
}
|
||||
|
||||
// Validate validates CreateTagOption
|
||||
func (opt CreateTagOption) Validate() error {
|
||||
if len(opt.TagName) == 0 {
|
||||
return fmt.Errorf("TagName is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateTag create a new git tag in a repository
|
||||
func (c *Client) CreateTag(user, repo string, opt CreateTagOption) (*Tag, *Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
t := new(Tag)
|
||||
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/tags", user, repo), jsonHeader, bytes.NewReader(body), &t)
|
||||
return t, resp, err
|
||||
}
|
||||
|
||||
// DeleteTag deletes a tag from a repository, if no release refers to it
|
||||
func (c *Client) DeleteTag(user, repo, tag string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &tag); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_14_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE",
|
||||
fmt.Sprintf("/repos/%s/%s/tags/%s", user, repo, tag),
|
||||
nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
65
vendor/code.gitea.io/sdk/gitea/repo_team.go
generated
vendored
Normal file
65
vendor/code.gitea.io/sdk/gitea/repo_team.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GetRepoTeams return teams from a repository
|
||||
func (c *Client) GetRepoTeams(user, repo string) ([]*Team, *Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
teams := make([]*Team, 0, 5)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/teams", user, repo), nil, nil, &teams)
|
||||
return teams, resp, err
|
||||
}
|
||||
|
||||
// AddRepoTeam add a team to a repository
|
||||
func (c *Client) AddRepoTeam(user, repo, team string) (*Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// RemoveRepoTeam delete a team from a repository
|
||||
func (c *Client) RemoveRepoTeam(user, repo, team string) (*Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// CheckRepoTeam check if team is assigned to repo by name and return it.
|
||||
// If not assigned, it will return nil.
|
||||
func (c *Client) CheckRepoTeam(user, repo, team string) (*Team, *Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := escapeValidatePathSegments(&user, &repo, &team); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
t := new(Team)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/teams/%s", user, repo, team), nil, nil, &t)
|
||||
if resp != nil && resp.StatusCode == http.StatusNotFound {
|
||||
// if not found it's not an error, it indicates it's not assigned
|
||||
return nil, resp, nil
|
||||
}
|
||||
return t, resp, err
|
||||
}
|
65
vendor/code.gitea.io/sdk/gitea/repo_template.go
generated
vendored
Normal file
65
vendor/code.gitea.io/sdk/gitea/repo_template.go
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// CreateRepoFromTemplateOption options when creating repository using a template
|
||||
type CreateRepoFromTemplateOption struct {
|
||||
// Owner is the organization or person who will own the new repository
|
||||
Owner string `json:"owner"`
|
||||
// Name of the repository to create
|
||||
Name string `json:"name"`
|
||||
// Description of the repository to create
|
||||
Description string `json:"description"`
|
||||
// Private is whether the repository is private
|
||||
Private bool `json:"private"`
|
||||
// GitContent include git content of default branch in template repo
|
||||
GitContent bool `json:"git_content"`
|
||||
// Topics include topics of template repo
|
||||
Topics bool `json:"topics"`
|
||||
// GitHooks include git hooks of template repo
|
||||
GitHooks bool `json:"git_hooks"`
|
||||
// Webhooks include webhooks of template repo
|
||||
Webhooks bool `json:"webhooks"`
|
||||
// Avatar include avatar of the template repo
|
||||
Avatar bool `json:"avatar"`
|
||||
// Labels include labels of template repo
|
||||
Labels bool `json:"labels"`
|
||||
}
|
||||
|
||||
// Validate validates CreateRepoFromTemplateOption
|
||||
func (opt CreateRepoFromTemplateOption) Validate() error {
|
||||
if len(opt.Owner) == 0 {
|
||||
return fmt.Errorf("field Owner is required")
|
||||
}
|
||||
if len(opt.Name) == 0 {
|
||||
return fmt.Errorf("field Name is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateRepoFromTemplate create a repository using a template
|
||||
func (c *Client) CreateRepoFromTemplate(templateOwner, templateRepo string, opt CreateRepoFromTemplateOption) (*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&templateOwner, &templateRepo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
if err := opt.Validate(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
repo := new(Repository)
|
||||
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/generate", templateOwner, templateRepo), jsonHeader, bytes.NewReader(body), &repo)
|
||||
return repo, resp, err
|
||||
}
|
14
vendor/code.gitea.io/sdk/gitea/repo_topics.go
generated
vendored
14
vendor/code.gitea.io/sdk/gitea/repo_topics.go
generated
vendored
|
@ -22,6 +22,9 @@ type topicsList struct {
|
|||
|
||||
// ListRepoTopics list all repository's topics
|
||||
func (c *Client) ListRepoTopics(user, repo string, opt ListRepoTopicsOptions) ([]string, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
|
||||
list := new(topicsList)
|
||||
|
@ -34,9 +37,10 @@ func (c *Client) ListRepoTopics(user, repo string, opt ListRepoTopicsOptions) ([
|
|||
|
||||
// SetRepoTopics replaces the list of repo's topics
|
||||
func (c *Client) SetRepoTopics(user, repo string, list []string) (*Response, error) {
|
||||
|
||||
if err := escapeValidatePathSegments(&user, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l := topicsList{Topics: list}
|
||||
|
||||
body, err := json.Marshal(&l)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -47,12 +51,18 @@ func (c *Client) SetRepoTopics(user, repo string, list []string) (*Response, err
|
|||
|
||||
// AddRepoTopic adds a topic to a repo's topics list
|
||||
func (c *Client) AddRepoTopic(user, repo, topic string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// DeleteRepoTopic deletes a topic from repo's topics list
|
||||
func (c *Client) DeleteRepoTopic(user, repo, topic string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &topic); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/topics/%s", user, repo, topic), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
3
vendor/code.gitea.io/sdk/gitea/repo_transfer.go
generated
vendored
3
vendor/code.gitea.io/sdk/gitea/repo_transfer.go
generated
vendored
|
@ -20,6 +20,9 @@ type TransferRepoOption struct {
|
|||
|
||||
// TransferRepo transfers the ownership of a repository
|
||||
func (c *Client) TransferRepo(owner, reponame string, opt TransferRepoOption) (*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &reponame); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_12_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
3
vendor/code.gitea.io/sdk/gitea/repo_tree.go
generated
vendored
3
vendor/code.gitea.io/sdk/gitea/repo_tree.go
generated
vendored
|
@ -31,6 +31,9 @@ type GitTreeResponse struct {
|
|||
// GetTrees downloads a file of repository, ref can be branch/tag/commit.
|
||||
// e.g.: ref -> master, tree -> macaron.go(no leading slash)
|
||||
func (c *Client) GetTrees(user, repo, ref string, recursive bool) (*GitTreeResponse, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user, &repo, &ref); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
trees := new(GitTreeResponse)
|
||||
var path = fmt.Sprintf("/repos/%s/%s/git/trees/%s", user, repo, ref)
|
||||
if recursive {
|
||||
|
|
24
vendor/code.gitea.io/sdk/gitea/repo_watch.go
generated
vendored
24
vendor/code.gitea.io/sdk/gitea/repo_watch.go
generated
vendored
|
@ -22,6 +22,9 @@ type WatchInfo struct {
|
|||
|
||||
// GetWatchedRepos list all the watched repos of user
|
||||
func (c *Client) GetWatchedRepos(user string) ([]*Repository, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
repos := make([]*Repository, 0, 10)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/subscriptions", user), nil, nil, &repos)
|
||||
return repos, resp, err
|
||||
|
@ -35,8 +38,11 @@ func (c *Client) GetMyWatchedRepos() ([]*Repository, *Response, error) {
|
|||
}
|
||||
|
||||
// CheckRepoWatch check if the current user is watching a repo
|
||||
func (c *Client) CheckRepoWatch(repoUser, repoName string) (bool, *Response, error) {
|
||||
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil)
|
||||
func (c *Client) CheckRepoWatch(owner, repo string) (bool, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
status, resp, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
|
||||
if err != nil {
|
||||
return false, resp, err
|
||||
}
|
||||
|
@ -51,8 +57,11 @@ func (c *Client) CheckRepoWatch(repoUser, repoName string) (bool, *Response, err
|
|||
}
|
||||
|
||||
// WatchRepo start to watch a repository
|
||||
func (c *Client) WatchRepo(repoUser, repoName string) (*Response, error) {
|
||||
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil)
|
||||
func (c *Client) WatchRepo(owner, repo string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
@ -63,8 +72,11 @@ func (c *Client) WatchRepo(repoUser, repoName string) (*Response, error) {
|
|||
}
|
||||
|
||||
// UnWatchRepo stop to watch a repository
|
||||
func (c *Client) UnWatchRepo(repoUser, repoName string) (*Response, error) {
|
||||
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil)
|
||||
func (c *Client) UnWatchRepo(owner, repo string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
status, resp, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", owner, repo), nil, nil)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
|
10
vendor/code.gitea.io/sdk/gitea/settings.go
generated
vendored
10
vendor/code.gitea.io/sdk/gitea/settings.go
generated
vendored
|
@ -6,13 +6,19 @@ package gitea
|
|||
|
||||
// GlobalUISettings represent the global ui settings of a gitea instance witch is exposed by API
|
||||
type GlobalUISettings struct {
|
||||
DefaultTheme string `json:"default_theme"`
|
||||
AllowedReactions []string `json:"allowed_reactions"`
|
||||
CustomEmojis []string `json:"custom_emojis"`
|
||||
}
|
||||
|
||||
// GlobalRepoSettings represent the global repository settings of a gitea instance witch is exposed by API
|
||||
type GlobalRepoSettings struct {
|
||||
MirrorsDisabled bool `json:"mirrors_disabled"`
|
||||
HTTPGitDisabled bool `json:"http_git_disabled"`
|
||||
MirrorsDisabled bool `json:"mirrors_disabled"`
|
||||
HTTPGitDisabled bool `json:"http_git_disabled"`
|
||||
MigrationsDisabled bool `json:"migrations_disabled"`
|
||||
StarsDisabled bool `json:"stars_disabled"`
|
||||
TimeTrackingDisabled bool `json:"time_tracking_disabled"`
|
||||
LFSDisabled bool `json:"lfs_disabled"`
|
||||
}
|
||||
|
||||
// GlobalAPISettings contains global api settings exposed by it
|
||||
|
|
28
vendor/code.gitea.io/sdk/gitea/status.go
generated
vendored
28
vendor/code.gitea.io/sdk/gitea/status.go
generated
vendored
|
@ -8,6 +8,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -51,12 +52,15 @@ type CreateStatusOption struct {
|
|||
|
||||
// CreateStatus creates a new Status for a given Commit
|
||||
func (c *Client) CreateStatus(owner, repo, sha string, opts CreateStatusOption) (*Status, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opts)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
status := new(Status)
|
||||
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/statuses/%s", owner, repo, sha), jsonHeader, bytes.NewReader(body), status)
|
||||
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/statuses/%s", owner, repo, url.QueryEscape(sha)), jsonHeader, bytes.NewReader(body), status)
|
||||
return status, resp, err
|
||||
}
|
||||
|
||||
|
@ -65,11 +69,14 @@ type ListStatusesOption struct {
|
|||
ListOptions
|
||||
}
|
||||
|
||||
// ListStatuses returns all statuses for a given Commit
|
||||
func (c *Client) ListStatuses(owner, repo, sha string, opt ListStatusesOption) ([]*Status, *Response, error) {
|
||||
// ListStatuses returns all statuses for a given Commit by ref
|
||||
func (c *Client) ListStatuses(owner, repo, ref string, opt ListStatusesOption) ([]*Status, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &ref); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
statuses := make([]*Status, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/statuses?%s", owner, repo, sha, opt.getURLQuery().Encode()), nil, nil, &statuses)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/statuses?%s", owner, repo, ref, opt.getURLQuery().Encode()), jsonHeader, nil, &statuses)
|
||||
return statuses, resp, err
|
||||
}
|
||||
|
||||
|
@ -85,8 +92,17 @@ type CombinedStatus struct {
|
|||
}
|
||||
|
||||
// GetCombinedStatus returns the CombinedStatus for a given Commit
|
||||
func (c *Client) GetCombinedStatus(owner, repo, sha string) (*CombinedStatus, *Response, error) {
|
||||
func (c *Client) GetCombinedStatus(owner, repo, ref string) (*CombinedStatus, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&owner, &repo, &ref); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
status := new(CombinedStatus)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/status", owner, repo, sha), nil, nil, status)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/status", owner, repo, ref), jsonHeader, nil, status)
|
||||
|
||||
// gitea api return empty body if nothing here jet
|
||||
if resp != nil && resp.StatusCode == 200 && err != nil {
|
||||
return status, resp, nil
|
||||
}
|
||||
|
||||
return status, resp, err
|
||||
}
|
||||
|
|
53
vendor/code.gitea.io/sdk/gitea/user.go
generated
vendored
53
vendor/code.gitea.io/sdk/gitea/user.go
generated
vendored
|
@ -6,6 +6,8 @@ package gitea
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -23,13 +25,37 @@ type User struct {
|
|||
// User locale
|
||||
Language string `json:"language"`
|
||||
// Is the user an administrator
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
LastLogin time.Time `json:"last_login,omitempty"`
|
||||
Created time.Time `json:"created,omitempty"`
|
||||
IsAdmin bool `json:"is_admin"`
|
||||
// Date and Time of last login
|
||||
LastLogin time.Time `json:"last_login"`
|
||||
// Date and Time of user creation
|
||||
Created time.Time `json:"created"`
|
||||
// Is user restricted
|
||||
Restricted bool `json:"restricted"`
|
||||
// Is user active
|
||||
IsActive bool `json:"active"`
|
||||
// Is user login prohibited
|
||||
ProhibitLogin bool `json:"prohibit_login"`
|
||||
// the user's location
|
||||
Location string `json:"location"`
|
||||
// the user's website
|
||||
Website string `json:"website"`
|
||||
// the user's description
|
||||
Description string `json:"description"`
|
||||
// User visibility level option
|
||||
Visibility VisibleType `json:"visibility"`
|
||||
|
||||
// user counts
|
||||
FollowerCount int `json:"followers_count"`
|
||||
FollowingCount int `json:"following_count"`
|
||||
StarredRepoCount int `json:"starred_repos_count"`
|
||||
}
|
||||
|
||||
// GetUserInfo get user info by user's name
|
||||
func (c *Client) GetUserInfo(user string) (*User, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
u := new(User)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u)
|
||||
return u, resp, err
|
||||
|
@ -41,3 +67,24 @@ func (c *Client) GetMyUserInfo() (*User, *Response, error) {
|
|||
resp, err := c.getParsedResponse("GET", "/user", nil, nil, u)
|
||||
return u, resp, err
|
||||
}
|
||||
|
||||
// GetUserByID returns user by a given user ID
|
||||
func (c *Client) GetUserByID(id int64) (*User, *Response, error) {
|
||||
if id < 0 {
|
||||
return nil, nil, fmt.Errorf("invalid user id %d", id)
|
||||
}
|
||||
|
||||
query := make(url.Values)
|
||||
query.Add("uid", strconv.FormatInt(id, 10))
|
||||
users, resp, err := c.searchUsers(query.Encode())
|
||||
|
||||
if err != nil {
|
||||
return nil, resp, err
|
||||
}
|
||||
|
||||
if len(users) == 1 {
|
||||
return users[0], resp, err
|
||||
}
|
||||
|
||||
return nil, resp, fmt.Errorf("user not found with id %d", id)
|
||||
}
|
||||
|
|
22
vendor/code.gitea.io/sdk/gitea/user_app.go
generated
vendored
22
vendor/code.gitea.io/sdk/gitea/user_app.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
|
@ -27,12 +28,15 @@ type ListAccessTokensOptions struct {
|
|||
|
||||
// ListAccessTokens lists all the access tokens of user
|
||||
func (c *Client) ListAccessTokens(opts ListAccessTokensOptions) ([]*AccessToken, *Response, error) {
|
||||
if len(c.username) == 0 {
|
||||
c.mutex.RLock()
|
||||
username := c.username
|
||||
c.mutex.RUnlock()
|
||||
if len(username) == 0 {
|
||||
return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
|
||||
}
|
||||
opts.setDefaults()
|
||||
tokens := make([]*AccessToken, 0, opts.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens?%s", c.username, opts.getURLQuery().Encode()), jsonHeader, nil, &tokens)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens?%s", url.PathEscape(username), opts.getURLQuery().Encode()), jsonHeader, nil, &tokens)
|
||||
return tokens, resp, err
|
||||
}
|
||||
|
||||
|
@ -43,7 +47,10 @@ type CreateAccessTokenOption struct {
|
|||
|
||||
// CreateAccessToken create one access token with options
|
||||
func (c *Client) CreateAccessToken(opt CreateAccessTokenOption) (*AccessToken, *Response, error) {
|
||||
if len(c.username) == 0 {
|
||||
c.mutex.RLock()
|
||||
username := c.username
|
||||
c.mutex.RUnlock()
|
||||
if len(username) == 0 {
|
||||
return nil, nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
|
@ -51,13 +58,16 @@ func (c *Client) CreateAccessToken(opt CreateAccessTokenOption) (*AccessToken, *
|
|||
return nil, nil, err
|
||||
}
|
||||
t := new(AccessToken)
|
||||
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", c.username), jsonHeader, bytes.NewReader(body), t)
|
||||
resp, err := c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", url.PathEscape(username)), jsonHeader, bytes.NewReader(body), t)
|
||||
return t, resp, err
|
||||
}
|
||||
|
||||
// DeleteAccessToken delete token, identified by ID and if not available by name
|
||||
func (c *Client) DeleteAccessToken(value interface{}) (*Response, error) {
|
||||
if len(c.username) == 0 {
|
||||
c.mutex.RLock()
|
||||
username := c.username
|
||||
c.mutex.RUnlock()
|
||||
if len(username) == 0 {
|
||||
return nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
|
||||
}
|
||||
|
||||
|
@ -75,6 +85,6 @@ func (c *Client) DeleteAccessToken(value interface{}) (*Response, error) {
|
|||
return nil, fmt.Errorf("only string and int64 supported")
|
||||
}
|
||||
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%s", c.username, token), jsonHeader, nil)
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%s", url.PathEscape(username), url.PathEscape(token)), jsonHeader, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
20
vendor/code.gitea.io/sdk/gitea/user_follow.go
generated
vendored
20
vendor/code.gitea.io/sdk/gitea/user_follow.go
generated
vendored
|
@ -21,6 +21,9 @@ func (c *Client) ListMyFollowers(opt ListFollowersOptions) ([]*User, *Response,
|
|||
|
||||
// ListFollowers list all the followers of one user
|
||||
func (c *Client) ListFollowers(user string, opt ListFollowersOptions) ([]*User, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
users := make([]*User, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
|
||||
|
@ -42,6 +45,9 @@ func (c *Client) ListMyFollowing(opt ListFollowingOptions) ([]*User, *Response,
|
|||
|
||||
// ListFollowing list all the users the user followed
|
||||
func (c *Client) ListFollowing(user string, opt ListFollowingOptions) ([]*User, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
users := make([]*User, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
|
||||
|
@ -50,24 +56,38 @@ func (c *Client) ListFollowing(user string, opt ListFollowingOptions) ([]*User,
|
|||
|
||||
// IsFollowing if current user followed the target
|
||||
func (c *Client) IsFollowing(target string) (bool, *Response) {
|
||||
if err := escapeValidatePathSegments(&target); err != nil {
|
||||
// ToDo return err
|
||||
return false, nil
|
||||
}
|
||||
_, resp, err := c.getResponse("GET", fmt.Sprintf("/user/following/%s", target), nil, nil)
|
||||
return err == nil, resp
|
||||
}
|
||||
|
||||
// IsUserFollowing if the user followed the target
|
||||
func (c *Client) IsUserFollowing(user, target string) (bool, *Response) {
|
||||
if err := escapeValidatePathSegments(&user, &target); err != nil {
|
||||
// ToDo return err
|
||||
return false, nil
|
||||
}
|
||||
_, resp, err := c.getResponse("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil)
|
||||
return err == nil, resp
|
||||
}
|
||||
|
||||
// Follow set current user follow the target
|
||||
func (c *Client) Follow(target string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&target); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
// Unfollow set current user unfollow the target
|
||||
func (c *Client) Unfollow(target string) (*Response, error) {
|
||||
if err := escapeValidatePathSegments(&target); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, resp, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil)
|
||||
return resp, err
|
||||
}
|
||||
|
|
3
vendor/code.gitea.io/sdk/gitea/user_gpgkey.go
generated
vendored
3
vendor/code.gitea.io/sdk/gitea/user_gpgkey.go
generated
vendored
|
@ -40,6 +40,9 @@ type ListGPGKeysOptions struct {
|
|||
|
||||
// ListGPGKeys list all the GPG keys of the user
|
||||
func (c *Client) ListGPGKeys(user string, opt ListGPGKeysOptions) ([]*GPGKey, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
keys := make([]*GPGKey, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/gpg_keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||
|
|
3
vendor/code.gitea.io/sdk/gitea/user_key.go
generated
vendored
3
vendor/code.gitea.io/sdk/gitea/user_key.go
generated
vendored
|
@ -31,6 +31,9 @@ type ListPublicKeysOptions struct {
|
|||
|
||||
// ListPublicKeys list all the public keys of the user
|
||||
func (c *Client) ListPublicKeys(user string, opt ListPublicKeysOptions) ([]*PublicKey, *Response, error) {
|
||||
if err := escapeValidatePathSegments(&user); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opt.setDefaults()
|
||||
keys := make([]*PublicKey, 0, opt.PageSize)
|
||||
resp, err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys)
|
||||
|
|
10
vendor/code.gitea.io/sdk/gitea/user_search.go
generated
vendored
10
vendor/code.gitea.io/sdk/gitea/user_search.go
generated
vendored
|
@ -34,11 +34,15 @@ func (opt *SearchUsersOption) QueryEncode() string {
|
|||
return query.Encode()
|
||||
}
|
||||
|
||||
// SearchUsers finds users by query
|
||||
func (c *Client) SearchUsers(opt SearchUsersOption) ([]*User, *Response, error) {
|
||||
func (c *Client) searchUsers(rawQuery string) ([]*User, *Response, error) {
|
||||
link, _ := url.Parse("/users/search")
|
||||
link.RawQuery = opt.QueryEncode()
|
||||
link.RawQuery = rawQuery
|
||||
userResp := new(searchUsersResponse)
|
||||
resp, err := c.getParsedResponse("GET", link.String(), nil, nil, &userResp)
|
||||
return userResp.Users, resp, err
|
||||
}
|
||||
|
||||
// SearchUsers finds users by query
|
||||
func (c *Client) SearchUsers(opt SearchUsersOption) ([]*User, *Response, error) {
|
||||
return c.searchUsers(opt.QueryEncode())
|
||||
}
|
||||
|
|
62
vendor/code.gitea.io/sdk/gitea/user_settings.go
generated
vendored
Normal file
62
vendor/code.gitea.io/sdk/gitea/user_settings.go
generated
vendored
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package gitea
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
// UserSettings represents user settings
|
||||
type UserSettings struct {
|
||||
FullName string `json:"full_name"`
|
||||
Website string `json:"website"`
|
||||
Description string `json:"description"`
|
||||
Location string `json:"location"`
|
||||
Language string `json:"language"`
|
||||
Theme string `json:"theme"`
|
||||
DiffViewStyle string `json:"diff_view_style"`
|
||||
// Privacy
|
||||
HideEmail bool `json:"hide_email"`
|
||||
HideActivity bool `json:"hide_activity"`
|
||||
}
|
||||
|
||||
// UserSettingsOptions represents options to change user settings
|
||||
type UserSettingsOptions struct {
|
||||
FullName *string `json:"full_name,omitempty"`
|
||||
Website *string `json:"website,omitempty"`
|
||||
Description *string `json:"description,omitempty"`
|
||||
Location *string `json:"location,omitempty"`
|
||||
Language *string `json:"language,omitempty"`
|
||||
Theme *string `json:"theme,omitempty"`
|
||||
DiffViewStyle *string `json:"diff_view_style,omitempty"`
|
||||
// Privacy
|
||||
HideEmail *bool `json:"hide_email,omitempty"`
|
||||
HideActivity *bool `json:"hide_activity,omitempty"`
|
||||
}
|
||||
|
||||
// GetUserSettings returns user settings
|
||||
func (c *Client) GetUserSettings() (*UserSettings, *Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
userConfig := new(UserSettings)
|
||||
resp, err := c.getParsedResponse("GET", "/user/settings", nil, nil, userConfig)
|
||||
return userConfig, resp, err
|
||||
}
|
||||
|
||||
// UpdateUserSettings returns user settings
|
||||
func (c *Client) UpdateUserSettings(opt UserSettingsOptions) (*UserSettings, *Response, error) {
|
||||
if err := c.checkServerVersionGreaterThanOrEqual(version1_15_0); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
body, err := json.Marshal(&opt)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
userConfig := new(UserSettings)
|
||||
resp, err := c.getParsedResponse("PATCH", "/user/settings", jsonHeader, bytes.NewReader(body), userConfig)
|
||||
return userConfig, resp, err
|
||||
}
|
11
vendor/code.gitea.io/sdk/gitea/version.go
generated
vendored
11
vendor/code.gitea.io/sdk/gitea/version.go
generated
vendored
|
@ -31,7 +31,10 @@ func (c *Client) CheckServerVersionConstraint(constraint string) error {
|
|||
return err
|
||||
}
|
||||
if !check.Check(c.serverVersion) {
|
||||
return fmt.Errorf("gitea server at %s does not satisfy version constraint %s", c.url, constraint)
|
||||
c.mutex.RLock()
|
||||
url := c.url
|
||||
c.mutex.RUnlock()
|
||||
return fmt.Errorf("gitea server at %s does not satisfy version constraint %s", url, constraint)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -42,6 +45,7 @@ var (
|
|||
version1_12_0, _ = version.NewVersion("1.12.0")
|
||||
version1_13_0, _ = version.NewVersion("1.13.0")
|
||||
version1_14_0, _ = version.NewVersion("1.14.0")
|
||||
version1_15_0, _ = version.NewVersion("1.15.0")
|
||||
)
|
||||
|
||||
// checkServerVersionGreaterThanOrEqual is internally used to speed up things and ignore issues with prerelease
|
||||
|
@ -51,7 +55,10 @@ func (c *Client) checkServerVersionGreaterThanOrEqual(v *version.Version) error
|
|||
}
|
||||
|
||||
if !c.serverVersion.GreaterThanOrEqual(v) {
|
||||
return fmt.Errorf("gitea server at %s is older than %s", c.url, v.Original())
|
||||
c.mutex.RLock()
|
||||
url := c.url
|
||||
c.mutex.RUnlock()
|
||||
return fmt.Errorf("gitea server at %s is older than %s", url, v.Original())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
459
vendor/gitea.com/noerw/unidiff-comments/changeset_reader.go
generated
vendored
Normal file
459
vendor/gitea.com/noerw/unidiff-comments/changeset_reader.go
generated
vendored
Normal file
|
@ -0,0 +1,459 @@
|
|||
package unidiff
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.com/noerw/unidiff-comments/types"
|
||||
)
|
||||
|
||||
const (
|
||||
stateStartOfDiff = "stateStartOfDiff"
|
||||
stateDiffHeader = "stateDiffHeader"
|
||||
stateHunkHeader = "stateHunkHeader"
|
||||
stateHunkBody = "stateHunkBody"
|
||||
stateComment = "stateComment"
|
||||
stateCommentDelim = "stateCommentDelim"
|
||||
stateCommentHeader = "stateCommentHeader"
|
||||
stateDiffComment = "stateDiffComment"
|
||||
stateDiffCommentDelim = "stateDiffCommentDelim"
|
||||
stateDiffCommentHeader = "stateDiffCommentHeader"
|
||||
|
||||
ignorePrefix = "###"
|
||||
)
|
||||
|
||||
var (
|
||||
reDiffHeader = regexp.MustCompile(
|
||||
`^--- |^\+\+\+ `)
|
||||
|
||||
reGitDiffHeader = regexp.MustCompile(
|
||||
`^diff |^index `)
|
||||
|
||||
reFromFile = regexp.MustCompile(
|
||||
`^--- (\S+)(\s+(.*))`)
|
||||
|
||||
reToFile = regexp.MustCompile(
|
||||
`^\+\+\+ (\S+)(\s+(.*))`)
|
||||
|
||||
reHunk = regexp.MustCompile(
|
||||
`^@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@`)
|
||||
|
||||
reSegmentContext = regexp.MustCompile(
|
||||
`^ `)
|
||||
|
||||
reSegmentAdded = regexp.MustCompile(
|
||||
`^\+`)
|
||||
|
||||
reSegmentRemoved = regexp.MustCompile(
|
||||
`^-`)
|
||||
|
||||
reCommentDelim = regexp.MustCompile(
|
||||
`^#\s+---`)
|
||||
|
||||
reCommentHeader = regexp.MustCompile(
|
||||
`^#\s+\[(\d+)@(\d+)\]\s+\|([^|]+)\|(.*)`)
|
||||
|
||||
reCommentText = regexp.MustCompile(
|
||||
`^#(\s*)(.*)\s*`)
|
||||
|
||||
reIndent = regexp.MustCompile(
|
||||
`^#(\s+)`)
|
||||
|
||||
reEmptyLine = regexp.MustCompile(
|
||||
`^\n$`)
|
||||
|
||||
reIgnoredLine = regexp.MustCompile(
|
||||
`^` + ignorePrefix)
|
||||
)
|
||||
|
||||
type parser struct {
|
||||
state string
|
||||
changeset types.Changeset
|
||||
diff *types.Diff
|
||||
hunk *types.Hunk
|
||||
segment *types.Segment
|
||||
comment *types.Comment
|
||||
line *types.Line
|
||||
lineNumber int
|
||||
|
||||
segmentType string
|
||||
commentsList []*types.Comment
|
||||
}
|
||||
|
||||
type Error struct {
|
||||
LineNumber int
|
||||
Message string
|
||||
}
|
||||
|
||||
func (err Error) Error() string {
|
||||
return fmt.Sprintf("line %d: %s", err.LineNumber, err.Message)
|
||||
}
|
||||
|
||||
func ReadChangeset(r io.Reader) (types.Changeset, error) {
|
||||
buffer := bufio.NewReader(r)
|
||||
|
||||
current := parser{}
|
||||
current.state = stateStartOfDiff
|
||||
|
||||
for {
|
||||
current.lineNumber++
|
||||
|
||||
line, err := buffer.ReadString('\n')
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if reIgnoredLine.MatchString(line) {
|
||||
continue
|
||||
}
|
||||
|
||||
err = current.switchState(line)
|
||||
if err != nil {
|
||||
return current.changeset, err
|
||||
}
|
||||
|
||||
err = current.createNodes(line)
|
||||
if err != nil {
|
||||
return current.changeset, err
|
||||
}
|
||||
|
||||
err = current.locateNodes(line)
|
||||
if err != nil {
|
||||
return current.changeset, err
|
||||
}
|
||||
|
||||
err = current.parseLine(line)
|
||||
if err != nil {
|
||||
return current.changeset, err
|
||||
}
|
||||
}
|
||||
|
||||
for _, comment := range current.commentsList {
|
||||
comment.Text = strings.TrimSpace(comment.Text)
|
||||
}
|
||||
|
||||
return current.changeset, nil
|
||||
}
|
||||
|
||||
func (current *parser) switchState(line string) error {
|
||||
inComment := false
|
||||
|
||||
switch current.state {
|
||||
case stateStartOfDiff:
|
||||
switch {
|
||||
case reDiffHeader.MatchString(line), reGitDiffHeader.MatchString(line):
|
||||
current.state = stateDiffHeader
|
||||
case reCommentText.MatchString(line):
|
||||
inComment = true
|
||||
case reEmptyLine.MatchString(line):
|
||||
// body intentionally left empty
|
||||
default:
|
||||
return Error{
|
||||
current.lineNumber,
|
||||
"expected diff header, but none found",
|
||||
}
|
||||
}
|
||||
case stateDiffHeader:
|
||||
switch {
|
||||
case reHunk.MatchString(line):
|
||||
current.state = stateHunkHeader
|
||||
}
|
||||
case stateDiffComment, stateDiffCommentDelim, stateDiffCommentHeader:
|
||||
switch {
|
||||
case reDiffHeader.MatchString(line), reGitDiffHeader.MatchString(line):
|
||||
current.state = stateDiffHeader
|
||||
case reCommentText.MatchString(line):
|
||||
inComment = true
|
||||
case reEmptyLine.MatchString(line):
|
||||
current.state = stateStartOfDiff
|
||||
}
|
||||
case stateHunkHeader:
|
||||
current.state = stateHunkBody
|
||||
fallthrough
|
||||
case stateHunkBody, stateComment, stateCommentDelim, stateCommentHeader:
|
||||
switch {
|
||||
case reSegmentContext.MatchString(line):
|
||||
current.state = stateHunkBody
|
||||
current.segmentType = types.SegmentTypeContext
|
||||
case reSegmentRemoved.MatchString(line):
|
||||
current.state = stateHunkBody
|
||||
current.segmentType = types.SegmentTypeRemoved
|
||||
case reSegmentAdded.MatchString(line):
|
||||
current.state = stateHunkBody
|
||||
current.segmentType = types.SegmentTypeAdded
|
||||
case reHunk.MatchString(line):
|
||||
current.state = stateHunkHeader
|
||||
case reCommentText.MatchString(line):
|
||||
inComment = true
|
||||
case reGitDiffHeader.MatchString(line):
|
||||
current.state = stateDiffHeader
|
||||
current.diff = nil
|
||||
current.hunk = nil
|
||||
current.segment = nil
|
||||
current.line = nil
|
||||
case reEmptyLine.MatchString(line):
|
||||
current.state = stateStartOfDiff
|
||||
current.diff = nil
|
||||
current.hunk = nil
|
||||
current.segment = nil
|
||||
current.line = nil
|
||||
}
|
||||
}
|
||||
|
||||
if !inComment {
|
||||
current.comment = nil
|
||||
} else {
|
||||
switch current.state {
|
||||
case stateStartOfDiff:
|
||||
fallthrough
|
||||
case stateDiffComment, stateDiffCommentDelim, stateDiffCommentHeader:
|
||||
switch {
|
||||
case reCommentDelim.MatchString(line):
|
||||
current.state = stateDiffCommentDelim
|
||||
case reCommentHeader.MatchString(line):
|
||||
current.state = stateDiffCommentHeader
|
||||
case reCommentText.MatchString(line):
|
||||
current.state = stateDiffComment
|
||||
}
|
||||
case stateHunkBody:
|
||||
fallthrough
|
||||
case stateComment, stateCommentDelim, stateCommentHeader:
|
||||
switch {
|
||||
case reCommentDelim.MatchString(line):
|
||||
current.state = stateCommentDelim
|
||||
case reCommentHeader.MatchString(line):
|
||||
current.state = stateCommentHeader
|
||||
case reCommentText.MatchString(line):
|
||||
current.state = stateComment
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Uncomment for debug state switching
|
||||
// fmt.Printf("%20s : %#v\n", current.state, line)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) createNodes(line string) error {
|
||||
switch current.state {
|
||||
case stateDiffComment:
|
||||
if current.comment != nil {
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case stateDiffCommentDelim, stateDiffCommentHeader:
|
||||
current.comment = &types.Comment{}
|
||||
fallthrough
|
||||
case stateDiffHeader:
|
||||
if current.diff == nil {
|
||||
current.diff = &types.Diff{}
|
||||
current.changeset.Diffs = append(current.changeset.Diffs,
|
||||
current.diff)
|
||||
}
|
||||
case stateHunkHeader:
|
||||
current.hunk = &types.Hunk{}
|
||||
current.segment = &types.Segment{}
|
||||
case stateCommentDelim, stateCommentHeader:
|
||||
current.comment = &types.Comment{}
|
||||
case stateComment:
|
||||
if current.comment == nil {
|
||||
current.comment = &types.Comment{}
|
||||
}
|
||||
case stateHunkBody:
|
||||
if current.segment.Type != current.segmentType {
|
||||
current.segment = &types.Segment{Type: current.segmentType}
|
||||
current.hunk.Segments = append(current.hunk.Segments,
|
||||
current.segment)
|
||||
}
|
||||
|
||||
current.line = &types.Line{}
|
||||
current.segment.Lines = append(current.segment.Lines, current.line)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) locateNodes(line string) error {
|
||||
switch current.state {
|
||||
case stateComment, stateDiffComment:
|
||||
current.locateComment(line)
|
||||
case stateHunkBody:
|
||||
current.locateLine(line)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) locateComment(line string) error {
|
||||
if current.comment.Parented || strings.TrimSpace(line) == "#" {
|
||||
return nil
|
||||
}
|
||||
|
||||
current.commentsList = append(current.commentsList, current.comment)
|
||||
current.comment.Parented = true
|
||||
|
||||
if current.hunk != nil {
|
||||
current.comment.Anchor.LineType = current.segment.Type
|
||||
current.comment.Anchor.Line = current.segment.GetLineNum(current.line)
|
||||
current.comment.Anchor.Path = current.diff.Destination.ToString
|
||||
current.comment.Anchor.SrcPath = current.diff.Source.ToString
|
||||
}
|
||||
|
||||
current.comment.Indent = getIndentSize(line)
|
||||
|
||||
parent := current.findParentComment(current.comment)
|
||||
if parent != nil {
|
||||
parent.Comments = append(parent.Comments, current.comment)
|
||||
} else {
|
||||
if current.line != nil {
|
||||
current.diff.LineComments = append(current.diff.LineComments,
|
||||
current.comment)
|
||||
current.line.Comments = append(current.line.Comments,
|
||||
current.comment)
|
||||
} else {
|
||||
current.diff.FileComments = append(current.diff.FileComments,
|
||||
current.comment)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) locateLine(line string) error {
|
||||
sourceOffset := current.hunk.SourceLine - 1
|
||||
destinationOffset := current.hunk.DestinationLine - 1
|
||||
if len(current.hunk.Segments) > 1 {
|
||||
prevSegment := current.hunk.Segments[len(current.hunk.Segments)-2]
|
||||
lastLine := prevSegment.Lines[len(prevSegment.Lines)-1]
|
||||
sourceOffset = lastLine.Source
|
||||
destinationOffset = lastLine.Destination
|
||||
}
|
||||
hunkLength := int64(len(current.segment.Lines))
|
||||
switch current.segment.Type {
|
||||
case types.SegmentTypeContext:
|
||||
current.line.Source = sourceOffset + hunkLength
|
||||
current.line.Destination = destinationOffset + hunkLength
|
||||
case types.SegmentTypeAdded:
|
||||
current.line.Source = sourceOffset
|
||||
current.line.Destination = destinationOffset + hunkLength
|
||||
case types.SegmentTypeRemoved:
|
||||
current.line.Source = sourceOffset + hunkLength
|
||||
current.line.Destination = destinationOffset
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) parseLine(line string) error {
|
||||
switch current.state {
|
||||
case stateDiffHeader:
|
||||
current.parseDiffHeader(line)
|
||||
case stateHunkHeader:
|
||||
current.parseHunkHeader(line)
|
||||
case stateHunkBody:
|
||||
current.parseHunkBody(line)
|
||||
case stateComment, stateDiffComment:
|
||||
current.parseComment(line)
|
||||
case stateCommentHeader, stateDiffCommentHeader:
|
||||
current.parseCommentHeader(line)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) parseDiffHeader(line string) error {
|
||||
switch {
|
||||
case reFromFile.MatchString(line):
|
||||
matches := reFromFile.FindStringSubmatch(line)
|
||||
current.changeset.Path = matches[1]
|
||||
current.diff.Source.ToString = matches[1]
|
||||
current.changeset.FromHash = matches[3]
|
||||
current.diff.Attributes.FromHash = []string{matches[3]}
|
||||
case reToFile.MatchString(line):
|
||||
matches := reToFile.FindStringSubmatch(line)
|
||||
current.diff.Destination.ToString = matches[1]
|
||||
current.changeset.ToHash = matches[3]
|
||||
current.diff.Attributes.ToHash = []string{matches[3]}
|
||||
default:
|
||||
return Error{
|
||||
current.lineNumber,
|
||||
"expected diff header, but not found",
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) parseHunkHeader(line string) error {
|
||||
matches := reHunk.FindStringSubmatch(line)
|
||||
current.hunk.SourceLine, _ = strconv.ParseInt(matches[1], 10, 64)
|
||||
current.hunk.SourceSpan, _ = strconv.ParseInt(matches[3], 10, 64)
|
||||
current.hunk.DestinationLine, _ = strconv.ParseInt(matches[4], 10, 64)
|
||||
current.hunk.DestinationSpan, _ = strconv.ParseInt(matches[6], 10, 64)
|
||||
current.diff.Hunks = append(current.diff.Hunks, current.hunk)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) parseHunkBody(line string) error {
|
||||
current.line.Line = line[1 : len(line)-1]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) parseCommentHeader(line string) error {
|
||||
matches := reCommentHeader.FindStringSubmatch(line)
|
||||
current.comment.Author.DisplayName = strings.TrimSpace(matches[3])
|
||||
current.comment.Id, _ = strconv.ParseInt(matches[1], 10, 64)
|
||||
updatedDate, _ := time.ParseInLocation(time.ANSIC,
|
||||
strings.TrimSpace(matches[4]),
|
||||
time.Local)
|
||||
current.comment.UpdatedDate = types.UnixTimestamp(updatedDate.Unix() * 1000)
|
||||
|
||||
version, _ := strconv.ParseInt(matches[2], 10, 64)
|
||||
current.comment.Version = int(version)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) parseComment(line string) error {
|
||||
matches := reCommentText.FindStringSubmatch(line)
|
||||
if len(matches[1]) < current.comment.Indent {
|
||||
return Error{
|
||||
LineNumber: current.lineNumber,
|
||||
Message: fmt.Sprintf(
|
||||
"unexpected indent, should be at least: %d",
|
||||
current.comment.Indent,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
indentedLine := matches[1][current.comment.Indent:] + matches[2]
|
||||
current.comment.Text += "\n" + indentedLine
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (current *parser) findParentComment(comment *types.Comment) *types.Comment {
|
||||
for i := len(current.commentsList) - 1; i >= 0; i-- {
|
||||
c := current.commentsList[i]
|
||||
if comment.Indent > c.Indent {
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getIndentSize(line string) int {
|
||||
matches := reIndent.FindStringSubmatch(line)
|
||||
if len(matches) == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(matches[1])
|
||||
}
|
5
vendor/gitea.com/noerw/unidiff-comments/go.mod
generated
vendored
Normal file
5
vendor/gitea.com/noerw/unidiff-comments/go.mod
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitea.com/noerw/unidiff-comments
|
||||
|
||||
go 1.15
|
||||
|
||||
require github.com/seletskiy/tplutil v0.0.0-20200921103632-f880f6245597
|
2
vendor/gitea.com/noerw/unidiff-comments/go.sum
generated
vendored
Normal file
2
vendor/gitea.com/noerw/unidiff-comments/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
github.com/seletskiy/tplutil v0.0.0-20200921103632-f880f6245597 h1:nZY1S2jo+VtDrUfjO9XYI137O41hhRkxZNV5Fb5ixCA=
|
||||
github.com/seletskiy/tplutil v0.0.0-20200921103632-f880f6245597/go.mod h1:F8CBHSOjnzjx9EeXyWJTAzJyVxN+Y8JH2WjLMn4utiw=
|
47
vendor/gitea.com/noerw/unidiff-comments/types/changeset.go
generated
vendored
Normal file
47
vendor/gitea.com/noerw/unidiff-comments/types/changeset.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
package types
|
||||
|
||||
type Changeset struct {
|
||||
FromHash string
|
||||
ToHash string
|
||||
Path string
|
||||
Whitespace string
|
||||
Diffs []*Diff
|
||||
}
|
||||
|
||||
func (r Changeset) ForEachComment(callback func(*Diff, *Comment, *Comment)) {
|
||||
for _, diff := range r.Diffs {
|
||||
stack := make([]*Comment, 0)
|
||||
parents := make(map[*Comment]*Comment)
|
||||
stack = append(stack, diff.FileComments...)
|
||||
stack = append(stack, diff.LineComments...)
|
||||
pos := 0
|
||||
|
||||
for pos < len(stack) {
|
||||
comment := stack[pos]
|
||||
|
||||
if comment.Comments != nil {
|
||||
stack = append(stack, comment.Comments...)
|
||||
for _, c := range comment.Comments {
|
||||
parents[c] = comment
|
||||
}
|
||||
}
|
||||
|
||||
callback(diff, comment, parents[comment])
|
||||
|
||||
pos++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r Changeset) ForEachLine(
|
||||
callback func(*Diff, *Hunk, *Segment, *Line) error,
|
||||
) error {
|
||||
for _, diff := range r.Diffs {
|
||||
err := diff.ForEachLine(callback)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
121
vendor/gitea.com/noerw/unidiff-comments/types/comment.go
generated
vendored
Normal file
121
vendor/gitea.com/noerw/unidiff-comments/types/comment.go
generated
vendored
Normal file
|
@ -0,0 +1,121 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UnixTimestamp int
|
||||
|
||||
func (u UnixTimestamp) String() string {
|
||||
return time.Unix(int64(u/1000), 0).Format(time.ANSIC)
|
||||
}
|
||||
|
||||
type Comment struct {
|
||||
Id int64
|
||||
Version int
|
||||
Text string
|
||||
CreatedDate UnixTimestamp
|
||||
UpdatedDate UnixTimestamp
|
||||
Comments CommentsTree
|
||||
Author struct {
|
||||
Name string
|
||||
EmailAddress string
|
||||
Id int
|
||||
DisplayName string
|
||||
Active bool
|
||||
Slug string
|
||||
Type string
|
||||
}
|
||||
|
||||
Anchor CommentAnchor
|
||||
|
||||
PermittedOperations struct {
|
||||
Editable bool
|
||||
Deletable bool
|
||||
}
|
||||
|
||||
Indent int
|
||||
Parented bool
|
||||
}
|
||||
|
||||
type CommentAnchor struct {
|
||||
FromHash string
|
||||
ToHash string
|
||||
Line int64 `json:"line"`
|
||||
LineType string `json:"lineType"`
|
||||
Path string `json:"path"`
|
||||
SrcPath string `json:"srcPath"`
|
||||
FileType string `json:"fileType"`
|
||||
}
|
||||
|
||||
type CommentsTree []*Comment
|
||||
|
||||
//const replyIndent = " "
|
||||
|
||||
var begOfLineRe = regexp.MustCompile("(?m)^")
|
||||
|
||||
//func (c Comment) String() string {
|
||||
// comments, _ := commentTpl.Execute(c)
|
||||
|
||||
// for _, reply := range c.Comments {
|
||||
// comments += reply.AsReply()
|
||||
// }
|
||||
|
||||
// return comments
|
||||
//}
|
||||
|
||||
//func (c Comment) AsReply() string {
|
||||
// return begOfLineRe.ReplaceAllString(
|
||||
// commentSpacing+c.String(),
|
||||
// replyIndent,
|
||||
// )
|
||||
//}
|
||||
|
||||
var reWhiteSpace = regexp.MustCompile(`\s+`)
|
||||
|
||||
func (c Comment) Short(length int) string {
|
||||
sticked := []rune(reWhiteSpace.ReplaceAllString(c.Text, " "))
|
||||
|
||||
if len(sticked) > length {
|
||||
return string(sticked[:length]) + "..."
|
||||
} else {
|
||||
return string(sticked)
|
||||
}
|
||||
}
|
||||
|
||||
const ignorePrefix = "###"
|
||||
|
||||
var reBeginningOfLine = regexp.MustCompile(`(?m)^`)
|
||||
var reIgnorePrefixSpace = regexp.MustCompile("(?m)^" + ignorePrefix + " $")
|
||||
|
||||
func Note(String string) string {
|
||||
return reIgnorePrefixSpace.ReplaceAllString(
|
||||
reBeginningOfLine.ReplaceAllString(String, ignorePrefix+" "),
|
||||
ignorePrefix)
|
||||
}
|
||||
|
||||
//const commentSpacing = "\n\n"
|
||||
//const commentPrefix = "# "
|
||||
|
||||
//func (comments CommentsTree) String() string {
|
||||
// res := ""
|
||||
|
||||
// if len(comments) > 0 {
|
||||
// res = "---" + commentSpacing
|
||||
// }
|
||||
|
||||
// for i, comment := range comments {
|
||||
// res += comment.String()
|
||||
// if i < len(comments)-1 {
|
||||
// res += commentSpacing
|
||||
// }
|
||||
// }
|
||||
|
||||
// if len(comments) > 0 {
|
||||
// return danglingSpacesRe.ReplaceAllString(
|
||||
// begOfLineRe.ReplaceAllString(res, "# "), "")
|
||||
// } else {
|
||||
// return ""
|
||||
// }
|
||||
//}
|
61
vendor/gitea.com/noerw/unidiff-comments/types/diff.go
generated
vendored
Normal file
61
vendor/gitea.com/noerw/unidiff-comments/types/diff.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
package types
|
||||
|
||||
type Diff struct {
|
||||
Truncated bool
|
||||
Source struct {
|
||||
Parent string
|
||||
Name string
|
||||
ToString string
|
||||
}
|
||||
Destination struct {
|
||||
Parent string
|
||||
Name string
|
||||
ToString string
|
||||
}
|
||||
Hunks []*Hunk
|
||||
|
||||
FileComments CommentsTree
|
||||
LineComments CommentsTree
|
||||
|
||||
Note string
|
||||
|
||||
// Lists made only for Stash API compatibility.
|
||||
// TODO: move it to `ash`.
|
||||
Attributes struct {
|
||||
FromHash []string
|
||||
ToHash []string
|
||||
}
|
||||
}
|
||||
|
||||
func (d Diff) GetHashFrom() string {
|
||||
if len(d.Attributes.FromHash) > 0 {
|
||||
return d.Attributes.FromHash[0]
|
||||
} else {
|
||||
return "???"
|
||||
}
|
||||
}
|
||||
|
||||
func (d Diff) GetHashTo() string {
|
||||
if len(d.Attributes.ToHash) > 0 {
|
||||
return d.Attributes.ToHash[0]
|
||||
} else {
|
||||
return "???"
|
||||
}
|
||||
}
|
||||
|
||||
func (d Diff) ForEachLine(
|
||||
callback func(*Diff, *Hunk, *Segment, *Line) error,
|
||||
) error {
|
||||
for _, hunk := range d.Hunks {
|
||||
for _, segment := range hunk.Segments {
|
||||
for _, line := range segment.Lines {
|
||||
err := callback(&d, hunk, segment, line)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
10
vendor/gitea.com/noerw/unidiff-comments/types/hunk.go
generated
vendored
Normal file
10
vendor/gitea.com/noerw/unidiff-comments/types/hunk.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
package types
|
||||
|
||||
type Hunk struct {
|
||||
SourceLine int64
|
||||
SourceSpan int64
|
||||
DestinationLine int64
|
||||
DestinationSpan int64
|
||||
Truncated bool
|
||||
Segments []*Segment
|
||||
}
|
29
vendor/gitea.com/noerw/unidiff-comments/types/line.go
generated
vendored
Normal file
29
vendor/gitea.com/noerw/unidiff-comments/types/line.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
package types
|
||||
|
||||
import "regexp"
|
||||
|
||||
type Line struct {
|
||||
Destination int64
|
||||
Source int64
|
||||
Line string
|
||||
Truncated bool
|
||||
ConflictMarker string
|
||||
CommentIds []int64
|
||||
Comments CommentsTree
|
||||
}
|
||||
|
||||
var danglingSpacesRe = regexp.MustCompile("(?m) +$")
|
||||
|
||||
//var lineTpl = tplutil.SparseTemplate("line", `
|
||||
//{{.Line}}
|
||||
|
||||
//{{if .Comments}}
|
||||
// {{"\n"}}
|
||||
// {{.Comments}}
|
||||
//{{end}}
|
||||
//`)
|
||||
|
||||
//func (l Line) String() string {
|
||||
// result, _ := lineTpl.Execute(l)
|
||||
// return result
|
||||
//}
|
39
vendor/gitea.com/noerw/unidiff-comments/types/segment.go
generated
vendored
Normal file
39
vendor/gitea.com/noerw/unidiff-comments/types/segment.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
package types
|
||||
|
||||
const (
|
||||
SegmentTypeContext = "CONTEXT"
|
||||
SegmentTypeRemoved = "REMOVED"
|
||||
SegmentTypeAdded = "ADDED"
|
||||
)
|
||||
|
||||
type Segment struct {
|
||||
Type string
|
||||
Truncated bool
|
||||
Lines []*Line
|
||||
}
|
||||
|
||||
func (s Segment) TextPrefix() string {
|
||||
switch s.Type {
|
||||
case SegmentTypeAdded:
|
||||
return "+"
|
||||
case SegmentTypeRemoved:
|
||||
return "-"
|
||||
case SegmentTypeContext:
|
||||
return " "
|
||||
default:
|
||||
return "?"
|
||||
}
|
||||
}
|
||||
|
||||
func (s Segment) GetLineNum(l *Line) int64 {
|
||||
switch s.Type {
|
||||
case SegmentTypeContext:
|
||||
fallthrough
|
||||
case SegmentTypeRemoved:
|
||||
return l.Source
|
||||
case SegmentTypeAdded:
|
||||
return l.Destination
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
2
vendor/github.com/AlecAivazis/survey/v2/go.mod
generated
vendored
2
vendor/github.com/AlecAivazis/survey/v2/go.mod
generated
vendored
|
@ -5,7 +5,7 @@ require (
|
|||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/kr/pty v1.1.4 // indirect
|
||||
github.com/kr/pty v1.1.4
|
||||
github.com/mattn/go-colorable v0.1.2 // indirect
|
||||
github.com/mattn/go-isatty v0.0.8
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
|
||||
|
|
12
vendor/github.com/AlecAivazis/survey/v2/input.go
generated
vendored
12
vendor/github.com/AlecAivazis/survey/v2/input.go
generated
vendored
|
@ -105,7 +105,8 @@ func (i *Input) OnChange(key rune, config *PromptConfig) (bool, error) {
|
|||
}
|
||||
} else if key == terminal.KeyDelete || key == terminal.KeyBackspace {
|
||||
if i.answer != "" {
|
||||
i.answer = i.answer[0 : len(i.answer)-1]
|
||||
runeAnswer := []rune(i.answer)
|
||||
i.answer = string(runeAnswer[0 : len(runeAnswer)-1])
|
||||
}
|
||||
} else if key >= terminal.KeySpace {
|
||||
i.answer += string(key)
|
||||
|
@ -190,13 +191,20 @@ func (i *Input) Prompt(config *PromptConfig) (interface{}, error) {
|
|||
}
|
||||
|
||||
func (i *Input) Cleanup(config *PromptConfig, val interface{}) error {
|
||||
// use the default answer when cleaning up the prompt if necessary
|
||||
ans := i.answer
|
||||
if ans == "" && i.Default != "" {
|
||||
ans = i.Default
|
||||
}
|
||||
|
||||
// render the cleanup
|
||||
return i.Render(
|
||||
InputQuestionTemplate,
|
||||
InputTemplateData{
|
||||
Input: *i,
|
||||
ShowAnswer: true,
|
||||
Config: config,
|
||||
Answer: i.answer,
|
||||
Answer: ans,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
8
vendor/github.com/AlecAivazis/survey/v2/multiselect.go
generated
vendored
8
vendor/github.com/AlecAivazis/survey/v2/multiselect.go
generated
vendored
|
@ -113,7 +113,8 @@ func (m *MultiSelect) OnChange(key rune, config *PromptConfig) {
|
|||
m.filter = ""
|
||||
} else if key == terminal.KeyDelete || key == terminal.KeyBackspace {
|
||||
if m.filter != "" {
|
||||
m.filter = m.filter[0 : len(m.filter)-1]
|
||||
runeFilter := []rune(m.filter)
|
||||
m.filter = string(runeFilter[0 : len(runeFilter)-1])
|
||||
}
|
||||
} else if key >= terminal.KeySpace {
|
||||
m.filter += string(key)
|
||||
|
@ -273,7 +274,10 @@ func (m *MultiSelect) Prompt(config *PromptConfig) (interface{}, error) {
|
|||
|
||||
// start waiting for input
|
||||
for {
|
||||
r, _, _ := rr.ReadRune()
|
||||
r, _, err := rr.ReadRune()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if r == '\r' || r == '\n' {
|
||||
break
|
||||
}
|
||||
|
|
11
vendor/github.com/AlecAivazis/survey/v2/renderer.go
generated
vendored
11
vendor/github.com/AlecAivazis/survey/v2/renderer.go
generated
vendored
|
@ -148,8 +148,15 @@ func (r *Renderer) countLines(buf bytes.Buffer) int {
|
|||
delim = len(bufBytes) // no new line found, read rest of text
|
||||
}
|
||||
|
||||
// account for word wrapping
|
||||
count += int(utf8.RuneCount(bufBytes[curr:delim]) / w)
|
||||
if lineWidth := utf8.RuneCount(bufBytes[curr:delim]); lineWidth > w {
|
||||
// account for word wrapping
|
||||
count += lineWidth / w
|
||||
if (lineWidth % w) == 0 {
|
||||
// content whose width is exactly a multiplier of available width should not
|
||||
// count as having wrapped on the last line
|
||||
count -= 1
|
||||
}
|
||||
}
|
||||
curr = delim + 1
|
||||
}
|
||||
|
||||
|
|
3
vendor/github.com/AlecAivazis/survey/v2/select.go
generated
vendored
3
vendor/github.com/AlecAivazis/survey/v2/select.go
generated
vendored
|
@ -114,8 +114,9 @@ func (s *Select) OnChange(key rune, config *PromptConfig) bool {
|
|||
} else if key == terminal.KeyDelete || key == terminal.KeyBackspace {
|
||||
// if there is content in the filter to delete
|
||||
if s.filter != "" {
|
||||
runeFilter := []rune(s.filter)
|
||||
// subtract a line from the current filter
|
||||
s.filter = s.filter[0 : len(s.filter)-1]
|
||||
s.filter = string(runeFilter[0 : len(runeFilter)-1])
|
||||
// we removed the last value in the filter
|
||||
}
|
||||
} else if key >= terminal.KeySpace {
|
||||
|
|
4
vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go
generated
vendored
4
vendor/github.com/AlecAivazis/survey/v2/terminal/cursor.go
generated
vendored
|
@ -42,12 +42,12 @@ func (c *Cursor) Back(n int) {
|
|||
|
||||
// NextLine moves cursor to beginning of the line n lines down.
|
||||
func (c *Cursor) NextLine(n int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%dE", n)
|
||||
c.Down(1)
|
||||
}
|
||||
|
||||
// PreviousLine moves cursor to beginning of the line n lines up.
|
||||
func (c *Cursor) PreviousLine(n int) {
|
||||
fmt.Fprintf(c.Out, "\x1b[%dF", n)
|
||||
c.Up(1)
|
||||
}
|
||||
|
||||
// HorizontalAbsolute moves cursor horizontally to x.
|
||||
|
|
11
vendor/github.com/AlecAivazis/survey/v2/transform.go
generated
vendored
11
vendor/github.com/AlecAivazis/survey/v2/transform.go
generated
vendored
|
@ -18,18 +18,21 @@ func TransformString(f func(s string) string) Transformer {
|
|||
return func(ans interface{}) interface{} {
|
||||
// if the answer value passed in is the zero value of the appropriate type
|
||||
if isZero(reflect.ValueOf(ans)) {
|
||||
// skip this `Transformer` by returning a nil value.
|
||||
// skip this `Transformer` by returning a zero value of string.
|
||||
// The original answer will be not affected,
|
||||
// see survey.go#L125.
|
||||
return nil
|
||||
// A zero value of string should be returned to be handled by
|
||||
// next Transformer in a composed Tranformer,
|
||||
// see tranform.go#L75
|
||||
return ""
|
||||
}
|
||||
|
||||
// "ans" is never nil here, so we don't have to check that
|
||||
// see survey.go#L97 for more.
|
||||
// see survey.go#L338 for more.
|
||||
// Make sure that the the answer's value was a typeof string.
|
||||
s, ok := ans.(string)
|
||||
if !ok {
|
||||
return nil
|
||||
return ""
|
||||
}
|
||||
|
||||
return f(s)
|
||||
|
|
2
vendor/github.com/Microsoft/go-winio/go.mod
generated
vendored
2
vendor/github.com/Microsoft/go-winio/go.mod
generated
vendored
|
@ -3,7 +3,7 @@ module github.com/Microsoft/go-winio
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/sirupsen/logrus v1.4.1
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3
|
||||
)
|
||||
|
|
6
vendor/github.com/Microsoft/go-winio/go.sum
generated
vendored
6
vendor/github.com/Microsoft/go-winio/go.sum
generated
vendored
|
@ -2,8 +2,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
|
@ -12,7 +12,5 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b h1:ag/x1USPSsqHud38I9BAC88qdNLDHHtQ4mlgQIZPPNA=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3 h1:7TYNF4UdlohbFwpNH04CoPMp1cHUZgO1Ebq5r2hIjfo=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
4
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
4
vendor/github.com/Microsoft/go-winio/pipe.go
generated
vendored
|
@ -429,10 +429,10 @@ type PipeConfig struct {
|
|||
// when the pipe is in message mode.
|
||||
MessageMode bool
|
||||
|
||||
// InputBufferSize specifies the size the input buffer, in bytes.
|
||||
// InputBufferSize specifies the size of the input buffer, in bytes.
|
||||
InputBufferSize int32
|
||||
|
||||
// OutputBufferSize specifies the size the input buffer, in bytes.
|
||||
// OutputBufferSize specifies the size of the output buffer, in bytes.
|
||||
OutputBufferSize int32
|
||||
}
|
||||
|
||||
|
|
168
vendor/github.com/adrg/xdg/README.md
generated
vendored
168
vendor/github.com/adrg/xdg/README.md
generated
vendored
|
@ -1,19 +1,52 @@
|
|||
xdg
|
||||
===
|
||||
<h1 align="center">
|
||||
<div>
|
||||
<img src="https://raw.githubusercontent.com/adrg/adrg.github.io/master/assets/projects/xdg/logo.png" height="80px" alt="xdg logo"/>
|
||||
</div>
|
||||
</h1>
|
||||
|
||||
[![Build Status](https://github.com/adrg/xdg/workflows/CI/badge.svg)](https://github.com/adrg/xdg/actions?query=workflow%3ACI)
|
||||
[![pkg.go.dev documentation](https://pkg.go.dev/badge/github.com/adrg/xdg)](https://pkg.go.dev/github.com/adrg/xdg)
|
||||
[![MIT license](https://img.shields.io/badge/license-MIT-red.svg?style=flat-square)](https://opensource.org/licenses/MIT)
|
||||
[![Go report card](https://goreportcard.com/badge/github.com/adrg/xdg)](https://goreportcard.com/report/github.com/adrg/xdg)
|
||||
<h4 align="center">Go implementation of the XDG Base Directory Specification and XDG user directories.</h4>
|
||||
|
||||
Provides an implementation of the [XDG Base Directory Specification](https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html).
|
||||
<p align="center">
|
||||
<a href="https://github.com/adrg/xdg/actions?query=workflow%3ACI">
|
||||
<img alt="Build status" src="https://github.com/adrg/xdg/workflows/CI/badge.svg">
|
||||
</a>
|
||||
<a href="https://app.codecov.io/gh/adrg/xdg">
|
||||
<img alt="Code coverage" src="https://codecov.io/gh/adrg/xdg/branch/master/graphs/badge.svg?branch=master">
|
||||
</a>
|
||||
<a href="https://pkg.go.dev/github.com/adrg/xdg">
|
||||
<img alt="pkg.go.dev documentation" src="https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white">
|
||||
</a>
|
||||
<a href="https://opensource.org/licenses/MIT" rel="nofollow">
|
||||
<img alt="MIT license" src="https://img.shields.io/github/license/adrg/xdg">
|
||||
</a>
|
||||
<br />
|
||||
<a href="https://goreportcard.com/report/github.com/adrg/xdg">
|
||||
<img alt="Go report card" src="https://goreportcard.com/badge/github.com/adrg/xdg">
|
||||
</a>
|
||||
<a href="https://github.com/avelino/awesome-go#configuration">
|
||||
<img alt="Awesome Go" src="https://awesome.re/mentioned-badge.svg">
|
||||
</a>
|
||||
<a href="https://github.com/adrg/xdg/graphs/contributors">
|
||||
<img alt="GitHub contributors" src="https://img.shields.io/github/contributors/adrg/xdg" />
|
||||
</a>
|
||||
<a href="https://github.com/adrg/xdg/issues">
|
||||
<img alt="GitHub open issues" src="https://img.shields.io/github/issues-raw/adrg/xdg">
|
||||
</a>
|
||||
<a href="https://ko-fi.com/T6T72WATK">
|
||||
<img alt="Buy me a coffee" src="https://img.shields.io/static/v1.svg?label=%20&message=Buy%20me%20a%20coffee&color=579fbf&logo=buy%20me%20a%20coffee&logoColor=white">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Provides an implementation of the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html).
|
||||
The specification defines a set of standard paths for storing application files,
|
||||
including data and configuration files. For portability and flexibility reasons,
|
||||
applications should use the XDG defined locations instead of hardcoding paths.
|
||||
The package also includes the locations of well known user directories.
|
||||
The current implementation supports Windows, Mac OS and most flavors of Unix.
|
||||
|
||||
Full documentation can be found at: https://godoc.org/github.com/adrg/xdg
|
||||
The package also includes the locations of well known [user directories](https://wiki.archlinux.org/index.php/XDG_user_directories)
|
||||
and an implementation of the [state directory](https://wiki.debian.org/XDGBaseDirectorySpecification#Proposal:_STATE_directory) proposal.
|
||||
Windows, macOS and most flavors of Unix are supported.
|
||||
|
||||
Full documentation can be found at: https://pkg.go.dev/github.com/adrg/xdg.
|
||||
|
||||
## Installation
|
||||
go get github.com/adrg/xdg
|
||||
|
@ -25,19 +58,19 @@ present in the environment.
|
|||
|
||||
#### XDG Base Directory
|
||||
|
||||
| | Unix | Mac OS | Windows |
|
||||
| :--- | :--- | :----- | :--- |
|
||||
| XDG_DATA_HOME | `~/.local/share` | `~/Library/Application Support` | `%LOCALAPPDATA%` |
|
||||
| XDG_DATA_DIRS | `/usr/local/share`<br/>`/usr/share` | `/Library/Application Support` | `%APPDATA%\Roaming`<br/>`%PROGRAMDATA%` |
|
||||
| XDG_CONFIG_HOME | `~/.config` | `~/Library/Preferences` | `%LOCALAPPDATA%` |
|
||||
| XDG_CONFIG_DIRS | `/etc/xdg` | `/Library/Preferences` | `%PROGRAMDATA%` |
|
||||
| XDG_CACHE_HOME | `~/.cache` | `~/Library/Caches` | `%LOCALAPPDATA%\cache` |
|
||||
| XDG_RUNTIME_DIR | `/run/user/UID` | `~/Library/Application Support` | `%LOCALAPPDATA%` |
|
||||
| | Unix | macOS | Windows |
|
||||
| :-------------- | :---------------------------------- | :------------------------------------------------------------------------------------ | :-------------------------------------- |
|
||||
| XDG_DATA_HOME | `~/.local/share` | `~/Library/Application Support` | `%LOCALAPPDATA%` |
|
||||
| XDG_DATA_DIRS | `/usr/local/share`<br/>`/usr/share` | `/Library/Application Support` | `%APPDATA%\Roaming`<br/>`%PROGRAMDATA%` |
|
||||
| XDG_CONFIG_HOME | `~/.config` | `~/Library/Application Support` | `%LOCALAPPDATA%` |
|
||||
| XDG_CONFIG_DIRS | `/etc/xdg` | `~/Library/Preferences`<br/>`/Library/Application Support`<br/>`/Library/Preferences` | `%PROGRAMDATA%` |
|
||||
| XDG_CACHE_HOME | `~/.cache` | `~/Library/Caches` | `%LOCALAPPDATA%\cache` |
|
||||
| XDG_RUNTIME_DIR | `/run/user/UID` | `~/Library/Application Support` | `%LOCALAPPDATA%` |
|
||||
|
||||
#### XDG user directories
|
||||
|
||||
| | Unix | Mac OS | Windows |
|
||||
| :--- | :--- | :----- | :--- |
|
||||
| | Unix | macOS | Windows |
|
||||
| :------------------ | :------------ | :------------ | :------------------------ |
|
||||
| XDG_DESKTOP_DIR | `~/Desktop` | `~/Desktop` | `%USERPROFILE%/Desktop` |
|
||||
| XDG_DOWNLOAD_DIR | `~/Downloads` | `~/Downloads` | `%USERPROFILE%/Downloads` |
|
||||
| XDG_DOCUMENTS_DIR | `~/Documents` | `~/Documents` | `%USERPROFILE%/Documents` |
|
||||
|
@ -49,43 +82,50 @@ present in the environment.
|
|||
|
||||
#### Non-standard directories
|
||||
|
||||
State directory
|
||||
|
||||
```
|
||||
Unix
|
||||
• ~/.local/state
|
||||
macOS
|
||||
• ~/Library/Application Support
|
||||
Windows
|
||||
• %LOCALAPPDATA%
|
||||
```
|
||||
|
||||
Application directories
|
||||
|
||||
```
|
||||
Unix:
|
||||
- $XDG_DATA_HOME/applications
|
||||
- ~/.local/share/applications
|
||||
- /usr/local/share/applications
|
||||
- /usr/share/applications
|
||||
- $XDG_DATA_DIRS/applications
|
||||
|
||||
Mac OS:
|
||||
- /Applications
|
||||
|
||||
Windows:
|
||||
- %APPDATA%\Roaming\Microsoft\Windows\Start Menu\Programs
|
||||
Unix
|
||||
• $XDG_DATA_HOME/applications
|
||||
• ~/.local/share/applications
|
||||
• /usr/local/share/applications
|
||||
• /usr/share/applications
|
||||
• $XDG_DATA_DIRS/applications
|
||||
macOS
|
||||
• /Applications
|
||||
Windows
|
||||
• %APPDATA%\Roaming\Microsoft\Windows\Start Menu\Programs
|
||||
```
|
||||
|
||||
Font Directories
|
||||
Font directories
|
||||
|
||||
```
|
||||
Unix:
|
||||
- $XDG_DATA_HOME/fonts
|
||||
- ~/.fonts
|
||||
- ~/.local/share/fonts
|
||||
- /usr/local/share/fonts
|
||||
- /usr/share/fonts
|
||||
- $XDG_DATA_DIRS/fonts
|
||||
|
||||
Mac OS:
|
||||
- ~/Library/Fonts
|
||||
- /Library/Fonts
|
||||
- /System/Library/Fonts
|
||||
- /Network/Library/Fonts
|
||||
|
||||
Windows:
|
||||
- %windir%\Fonts
|
||||
- %LOCALAPPDATA%\Microsoft\Windows\Fonts
|
||||
Unix
|
||||
• $XDG_DATA_HOME/fonts
|
||||
• ~/.fonts
|
||||
• ~/.local/share/fonts
|
||||
• /usr/local/share/fonts
|
||||
• /usr/share/fonts
|
||||
• $XDG_DATA_DIRS/fonts
|
||||
macOS
|
||||
• ~/Library/Fonts
|
||||
• /Library/Fonts
|
||||
• /System/Library/Fonts
|
||||
• /Network/Library/Fonts
|
||||
Windows
|
||||
• %windir%\Fonts
|
||||
• %LOCALAPPDATA%\Microsoft\Windows\Fonts
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
@ -103,7 +143,7 @@ import (
|
|||
|
||||
func main() {
|
||||
// XDG Base Directory paths.
|
||||
log.Println("Home config directory:", xdg.DataHome)
|
||||
log.Println("Home data directory:", xdg.DataHome)
|
||||
log.Println("Data directories:", xdg.DataDirs)
|
||||
log.Println("Home config directory:", xdg.ConfigHome)
|
||||
log.Println("Config directories:", xdg.ConfigDirs)
|
||||
|
@ -111,13 +151,14 @@ func main() {
|
|||
log.Println("Runtime directory:", xdg.RuntimeDir)
|
||||
|
||||
// Non-standard directories.
|
||||
log.Println("Home state directory:", xdg.StateHome)
|
||||
log.Println("Application directories:", xdg.ApplicationDirs)
|
||||
log.Println("Font directories:", xdg.FontDirs)
|
||||
|
||||
// Obtain a suitable location for application config files.
|
||||
// ConfigFile takes one parameter which must contain the name of the file,
|
||||
// but it can also contain a set of parent directories. If the directories
|
||||
// don't exists, they will be created relative to the base config directory.
|
||||
// don't exist, they will be created relative to the base config directory.
|
||||
configFilePath, err := xdg.ConfigFile("appname/config.yaml")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -128,6 +169,7 @@ func main() {
|
|||
// xdg.DataFile()
|
||||
// xdg.CacheFile()
|
||||
// xdg.RuntimeFile()
|
||||
// xdg.StateFile()
|
||||
|
||||
// Finding application config files.
|
||||
// SearchConfigFile takes one parameter which must contain the name of
|
||||
|
@ -143,6 +185,7 @@ func main() {
|
|||
// xdg.SearchDataFile()
|
||||
// xdg.SearchCacheFile()
|
||||
// xdg.SearchRuntimeFile()
|
||||
// xdg.SearchStateFile()
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -177,18 +220,27 @@ func main() {
|
|||
## Contributing
|
||||
|
||||
Contributions in the form of pull requests, issues or just general feedback,
|
||||
are always welcome.
|
||||
See [CONTRIBUTING.MD](https://github.com/adrg/xdg/blob/master/CONTRIBUTING.md).
|
||||
are always welcome.
|
||||
See [CONTRIBUTING.MD](CONTRIBUTING.md).
|
||||
|
||||
**Contributors**:
|
||||
[adrg](https://github.com/adrg),
|
||||
[wichert](https://github.com/wichert),
|
||||
[bouncepaw](https://github.com/bouncepaw),
|
||||
[gabriel-vasile](https://github.com/gabriel-vasile),
|
||||
[KalleDK](https://github.com/KalleDK).
|
||||
|
||||
## References
|
||||
|
||||
For more information see the
|
||||
[XDG Base Directory Specification](https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html) and
|
||||
[XDG user directories](https://wiki.archlinux.org/index.php/XDG_user_directories).
|
||||
For more information see:
|
||||
* [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html)
|
||||
* [XDG user directories](https://wiki.archlinux.org/index.php/XDG_user_directories)
|
||||
* [XDG state directory proposal](https://wiki.debian.org/XDGBaseDirectorySpecification#Proposal:_STATE_directory)
|
||||
* [XDG_STATE_HOME proposal](https://lists.freedesktop.org/archives/xdg/2016-December/013803.html)
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) 2014 Adrian-George Bostan.
|
||||
|
||||
This project is licensed under the [MIT license](https://opensource.org/licenses/MIT).
|
||||
See [LICENSE](https://github.com/adrg/xdg/blob/master/LICENSE) for more details.
|
||||
See [LICENSE](LICENSE) for more details.
|
||||
|
|
34
vendor/github.com/adrg/xdg/base_dirs.go
generated
vendored
34
vendor/github.com/adrg/xdg/base_dirs.go
generated
vendored
|
@ -1,15 +1,14 @@
|
|||
package xdg
|
||||
|
||||
import "os"
|
||||
|
||||
// XDG Base Directory environment variables.
|
||||
var (
|
||||
const (
|
||||
envDataHome = "XDG_DATA_HOME"
|
||||
envDataDirs = "XDG_DATA_DIRS"
|
||||
envConfigHome = "XDG_CONFIG_HOME"
|
||||
envConfigDirs = "XDG_CONFIG_DIRS"
|
||||
envCacheHome = "XDG_CACHE_HOME"
|
||||
envRuntimeDir = "XDG_RUNTIME_DIR"
|
||||
envStateHome = "XDG_STATE_HOME"
|
||||
)
|
||||
|
||||
type baseDirectories struct {
|
||||
|
@ -21,6 +20,7 @@ type baseDirectories struct {
|
|||
runtime string
|
||||
|
||||
// Non-standard directories.
|
||||
stateHome string
|
||||
fonts []string
|
||||
applications []string
|
||||
}
|
||||
|
@ -38,29 +38,13 @@ func (bd baseDirectories) cacheFile(relPath string) (string, error) {
|
|||
}
|
||||
|
||||
func (bd baseDirectories) runtimeFile(relPath string) (string, error) {
|
||||
fi, err := os.Lstat(bd.runtime)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return createPath(relPath, []string{bd.runtime})
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
|
||||
if fi.IsDir() {
|
||||
// The runtime directory must be owned by the user.
|
||||
if err = os.Chown(bd.runtime, os.Getuid(), os.Getgid()); err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
// For security reasons, the runtime directory cannot be a symlink.
|
||||
if err = os.Remove(bd.runtime); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
return createPath(relPath, []string{bd.runtime})
|
||||
}
|
||||
|
||||
func (bd baseDirectories) stateFile(relPath string) (string, error) {
|
||||
return createPath(relPath, []string{bd.stateHome})
|
||||
}
|
||||
|
||||
func (bd baseDirectories) searchDataFile(relPath string) (string, error) {
|
||||
return searchFile(relPath, append([]string{bd.dataHome}, bd.data...))
|
||||
}
|
||||
|
@ -76,3 +60,7 @@ func (bd baseDirectories) searchCacheFile(relPath string) (string, error) {
|
|||
func (bd baseDirectories) searchRuntimeFile(relPath string) (string, error) {
|
||||
return searchFile(relPath, []string{bd.runtime})
|
||||
}
|
||||
|
||||
func (bd baseDirectories) searchStateFile(relPath string) (string, error) {
|
||||
return searchFile(relPath, []string{bd.stateHome})
|
||||
}
|
||||
|
|
1
vendor/github.com/adrg/xdg/go.sum
generated
vendored
1
vendor/github.com/adrg/xdg/go.sum
generated
vendored
|
@ -5,6 +5,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
|||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
18
vendor/github.com/adrg/xdg/paths_darwin.go
generated
vendored
18
vendor/github.com/adrg/xdg/paths_darwin.go
generated
vendored
|
@ -5,15 +5,23 @@ import (
|
|||
)
|
||||
|
||||
func initBaseDirs(home string) {
|
||||
homeAppSupport := filepath.Join(home, "Library", "Application Support")
|
||||
rootAppSupport := "/Library/Application Support"
|
||||
|
||||
// Initialize base directories.
|
||||
baseDirs.dataHome = xdgPath(envDataHome, filepath.Join(home, "Library", "Application Support"))
|
||||
baseDirs.data = xdgPaths(envDataDirs, "/Library/Application Support")
|
||||
baseDirs.configHome = xdgPath(envConfigHome, filepath.Join(home, "Library", "Preferences"))
|
||||
baseDirs.config = xdgPaths(envConfigDirs, "/Library/Preferences")
|
||||
baseDirs.dataHome = xdgPath(envDataHome, homeAppSupport)
|
||||
baseDirs.data = xdgPaths(envDataDirs, rootAppSupport)
|
||||
baseDirs.configHome = xdgPath(envConfigHome, homeAppSupport)
|
||||
baseDirs.config = xdgPaths(envConfigDirs,
|
||||
filepath.Join(home, "Library", "Preferences"),
|
||||
rootAppSupport,
|
||||
"/Library/Preferences",
|
||||
)
|
||||
baseDirs.cacheHome = xdgPath(envCacheHome, filepath.Join(home, "Library", "Caches"))
|
||||
baseDirs.runtime = xdgPath(envRuntimeDir, filepath.Join(home, "Library", "Application Support"))
|
||||
baseDirs.runtime = xdgPath(envRuntimeDir, homeAppSupport)
|
||||
|
||||
// Initialize non-standard directories.
|
||||
baseDirs.stateHome = xdgPath(envStateHome, homeAppSupport)
|
||||
baseDirs.applications = []string{
|
||||
"/Applications",
|
||||
}
|
||||
|
|
1
vendor/github.com/adrg/xdg/paths_unix.go
generated
vendored
1
vendor/github.com/adrg/xdg/paths_unix.go
generated
vendored
|
@ -18,6 +18,7 @@ func initBaseDirs(home string) {
|
|||
baseDirs.runtime = xdgPath(envRuntimeDir, filepath.Join("/run/user", strconv.Itoa(os.Getuid())))
|
||||
|
||||
// Initialize non-standard directories.
|
||||
baseDirs.stateHome = xdgPath(envStateHome, filepath.Join(home, ".local", "state"))
|
||||
appDirs := []string{
|
||||
filepath.Join(baseDirs.dataHome, "applications"),
|
||||
filepath.Join(home, ".local/share/applications"),
|
||||
|
|
1
vendor/github.com/adrg/xdg/paths_windows.go
generated
vendored
1
vendor/github.com/adrg/xdg/paths_windows.go
generated
vendored
|
@ -43,6 +43,7 @@ func initBaseDirs(home string) {
|
|||
baseDirs.runtime = xdgPath(envRuntimeDir, localAppDataDir)
|
||||
|
||||
// Initialize non-standard directories.
|
||||
baseDirs.stateHome = xdgPath(envStateHome, localAppDataDir)
|
||||
baseDirs.applications = []string{
|
||||
filepath.Join(roamingAppDataDir, "Microsoft", "Windows", "Start Menu", "Programs"),
|
||||
}
|
||||
|
|
2
vendor/github.com/adrg/xdg/user_dirs.go
generated
vendored
2
vendor/github.com/adrg/xdg/user_dirs.go
generated
vendored
|
@ -1,7 +1,7 @@
|
|||
package xdg
|
||||
|
||||
// XDG user directories environment variables.
|
||||
var (
|
||||
const (
|
||||
envDesktopDir = "XDG_DESKTOP_DIR"
|
||||
envDownloadDir = "XDG_DOWNLOAD_DIR"
|
||||
envDocumentsDir = "XDG_DOCUMENTS_DIR"
|
||||
|
|
55
vendor/github.com/adrg/xdg/xdg.go
generated
vendored
55
vendor/github.com/adrg/xdg/xdg.go
generated
vendored
|
@ -12,6 +12,10 @@ flavors of Unix.
|
|||
|
||||
For more information regarding the XDG user directories see:
|
||||
https://wiki.archlinux.org/index.php/XDG_user_directories
|
||||
|
||||
For more information regarding the XDG state directory proposal see:
|
||||
https://wiki.debian.org/XDGBaseDirectorySpecification#Proposal:_STATE_directory
|
||||
https://lists.freedesktop.org/archives/xdg/2016-December/013803.html
|
||||
*/
|
||||
package xdg
|
||||
|
||||
|
@ -21,14 +25,14 @@ var (
|
|||
|
||||
// DataHome defines the base directory relative to which user-specific
|
||||
// data files should be stored. This directory is defined by the
|
||||
// environment variable $XDG_DATA_HOME. If this variable is not set,
|
||||
// $XDG_DATA_HOME environment variable. If the variable is not set,
|
||||
// a default equal to $HOME/.local/share should be used.
|
||||
DataHome string
|
||||
|
||||
// DataDirs defines the preference-ordered set of base directories to
|
||||
// search for data files in addition to the DataHome base directory.
|
||||
// This set of directories is defined by the environment variable
|
||||
// $XDG_DATA_DIRS. If this variable is not set, the default directories
|
||||
// This set of directories is defined by the $XDG_DATA_DIRS environment
|
||||
// variable. If the variable is not set, the default directories
|
||||
// to be used are /usr/local/share and /usr/share, in that order. The
|
||||
// DataHome directory is considered more important than any of the
|
||||
// directories defined by DataDirs. Therefore, user data files should be
|
||||
|
@ -37,30 +41,30 @@ var (
|
|||
|
||||
// ConfigHome defines the base directory relative to which user-specific
|
||||
// configuration files should be written. This directory is defined by
|
||||
// the environment variable $XDG_CONFIG_HOME. If this variable is not
|
||||
// the $XDG_CONFIG_HOME environment variable. If the variable is not
|
||||
// not set, a default equal to $HOME/.config should be used.
|
||||
ConfigHome string
|
||||
|
||||
// ConfigDirs defines the preference-ordered set of base directories to
|
||||
// search for configuration files in addition to the ConfigHome base
|
||||
// directory. This set of directories is defined by the environment
|
||||
// variable $XDG_CONFIG_DIRS. If this variable is not set, a default
|
||||
// equal to /etc/xdg should be used. The ConfigHome directory is
|
||||
// considered more important than any of the directories defined by
|
||||
// ConfigDirs. Therefore, user config files should be written
|
||||
// relative to the ConfigHome directory, if possible.
|
||||
// directory. This set of directories is defined by the $XDG_CONFIG_DIRS
|
||||
// environment variable. If the variable is not set, a default equal
|
||||
// to /etc/xdg should be used. The ConfigHome directory is considered
|
||||
// more important than any of the directories defined by ConfigDirs.
|
||||
// Therefore, user config files should be written relative to the
|
||||
// ConfigHome directory, if possible.
|
||||
ConfigDirs []string
|
||||
|
||||
// CacheHome defines the base directory relative to which user-specific
|
||||
// non-essential (cached) data should be written. This directory is
|
||||
// defined by the environment variable $XDG_CACHE_HOME. If this variable
|
||||
// defined by the $XDG_CACHE_HOME environment variable. If the variable
|
||||
// is not set, a default equal to $HOME/.cache should be used.
|
||||
CacheHome string
|
||||
|
||||
// RuntimeDir defines the base directory relative to which user-specific
|
||||
// non-essential runtime files and other file objects (such as sockets,
|
||||
// named pipes, etc.) should be stored. This directory is defined by the
|
||||
// environment variable $XDG_RUNTIME_DIR. If this variable is not set,
|
||||
// $XDG_RUNTIME_DIR environment variable. If the variable is not set,
|
||||
// applications should fall back to a replacement directory with similar
|
||||
// capabilities. Applications should use this directory for communication
|
||||
// and synchronization purposes and should not place larger files in it,
|
||||
|
@ -68,6 +72,12 @@ var (
|
|||
// swapped out to disk.
|
||||
RuntimeDir string
|
||||
|
||||
// StateHome defines the base directory relative to which user-specific
|
||||
// volatile data files should be stored. This directory is defined by
|
||||
// the non-standard $XDG_STATE_HOME environment variable. If the variable
|
||||
// is not set, a default equal to ~/.local/state should be used.
|
||||
StateHome string
|
||||
|
||||
// UserDirs defines the locations of well known user directories.
|
||||
UserDirs UserDirectories
|
||||
|
||||
|
@ -96,6 +106,7 @@ func Reload() {
|
|||
ConfigDirs = baseDirs.config
|
||||
CacheHome = baseDirs.cacheHome
|
||||
RuntimeDir = baseDirs.runtime
|
||||
StateHome = baseDirs.stateHome
|
||||
FontDirs = baseDirs.fonts
|
||||
ApplicationDirs = baseDirs.applications
|
||||
|
||||
|
@ -143,6 +154,18 @@ func RuntimeFile(relPath string) (string, error) {
|
|||
return baseDirs.runtimeFile(relPath)
|
||||
}
|
||||
|
||||
// StateFile returns a suitable location for the specified state file. State
|
||||
// files are usually volatile data files, not suitable to be stored relative
|
||||
// to the $XDG_DATA_HOME directory.
|
||||
// The relPath parameter must contain the name of the state file, and
|
||||
// optionally, a set of parent directories (e.g. appname/app.state).
|
||||
// If the specified directories do not exist, they will be created relative
|
||||
// to the base state directory. On failure, an error containing the
|
||||
// attempted paths is returned.
|
||||
func StateFile(relPath string) (string, error) {
|
||||
return baseDirs.stateFile(relPath)
|
||||
}
|
||||
|
||||
// SearchDataFile searches for specified file in the data search paths.
|
||||
// The relPath parameter must contain the name of the data file, and
|
||||
// optionally, a set of parent directories (e.g. appname/app.data). If the
|
||||
|
@ -175,6 +198,14 @@ func SearchRuntimeFile(relPath string) (string, error) {
|
|||
return baseDirs.searchRuntimeFile(relPath)
|
||||
}
|
||||
|
||||
// SearchStateFile searches for the specified file in the state search path.
|
||||
// The relPath parameter must contain the name of the state file, and
|
||||
// optionally, a set of parent directories (e.g. appname/app.state). If the
|
||||
// file cannot be found, an error specifying the searched path is returned.
|
||||
func SearchStateFile(relPath string) (string, error) {
|
||||
return baseDirs.searchStateFile(relPath)
|
||||
}
|
||||
|
||||
func init() {
|
||||
Reload()
|
||||
}
|
||||
|
|
31
vendor/github.com/araddon/dateparse/README.md
generated
vendored
31
vendor/github.com/araddon/dateparse/README.md
generated
vendored
|
@ -65,11 +65,11 @@ var examples = []string{
|
|||
"Mon, 02 Jan 2006 15:04:05 MST",
|
||||
"Tue, 11 Jul 2017 16:28:13 +0200 (CEST)",
|
||||
"Mon, 02 Jan 2006 15:04:05 -0700",
|
||||
"Thu, 4 Jan 2018 17:53:36 +0000",
|
||||
"Mon 30 Sep 2018 09:09:09 PM UTC",
|
||||
"Mon Aug 10 15:44:11 UTC+0100 2015",
|
||||
"Thu, 4 Jan 2018 17:53:36 +0000",
|
||||
"Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time)",
|
||||
"Sun, 3 Jan 2021 00:12:23 +0800 (GMT+08:00)",
|
||||
"September 17, 2012 10:09am",
|
||||
"September 17, 2012 at 10:09am PST-08",
|
||||
"September 17, 2012, 10:10:09",
|
||||
|
@ -77,11 +77,15 @@ var examples = []string{
|
|||
"October 7th, 1970",
|
||||
"12 Feb 2006, 19:17",
|
||||
"12 Feb 2006 19:17",
|
||||
"14 May 2019 19:11:40.164",
|
||||
"7 oct 70",
|
||||
"7 oct 1970",
|
||||
"03 February 2013",
|
||||
"1 July 2013",
|
||||
"2013-Feb-03",
|
||||
// dd/Mon/yyy alpha Months
|
||||
"06/Jan/2008:15:04:05 -0700",
|
||||
"06/Jan/2008 15:04:05 -0700",
|
||||
// mm/dd/yy
|
||||
"3/31/2014",
|
||||
"03/31/2014",
|
||||
|
@ -123,7 +127,10 @@ var examples = []string{
|
|||
"2006-01-02T15:04:05+0000",
|
||||
"2009-08-12T22:15:09-07:00",
|
||||
"2009-08-12T22:15:09",
|
||||
"2009-08-12T22:15:09.988",
|
||||
"2009-08-12T22:15:09Z",
|
||||
"2017-07-19T03:21:51:897+0100",
|
||||
"2019-05-29T08:41-04", // no seconds, 2 digit TZ offset
|
||||
// yyyy-mm-dd hh:mm:ss
|
||||
"2014-04-26 17:24:37.3186369",
|
||||
"2012-08-03 18:31:59.257000000",
|
||||
|
@ -147,6 +154,8 @@ var examples = []string{
|
|||
"2014-04",
|
||||
"2014",
|
||||
"2014-05-11 08:20:13,787",
|
||||
// yyyy-mm-dd-07:00
|
||||
"2020-07-20+08:00",
|
||||
// mm.dd.yy
|
||||
"3.31.2014",
|
||||
"03.31.2014",
|
||||
|
@ -156,6 +165,9 @@ var examples = []string{
|
|||
// yyyymmdd and similar
|
||||
"20140601",
|
||||
"20140722105203",
|
||||
// yymmdd hh:mm:yy mysql log
|
||||
// 080313 05:21:55 mysqld started
|
||||
"171113 14:14:20",
|
||||
// unix seconds, ms, micro, nano
|
||||
"1332151919",
|
||||
"1384216367189",
|
||||
|
@ -214,6 +226,7 @@ func main() {
|
|||
| Mon Aug 10 15:44:11 UTC+0100 2015 | 2015-08-10 15:44:11 +0000 UTC |
|
||||
| Thu, 4 Jan 2018 17:53:36 +0000 | 2018-01-04 17:53:36 +0000 UTC |
|
||||
| Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time) | 2015-07-03 18:04:07 +0100 GMT |
|
||||
| Sun, 3 Jan 2021 00:12:23 +0800 (GMT+08:00) | 2021-01-03 00:12:23 +0800 +0800 |
|
||||
| September 17, 2012 10:09am | 2012-09-17 10:09:00 +0000 UTC |
|
||||
| September 17, 2012 at 10:09am PST-08 | 2012-09-17 10:09:00 -0800 PST |
|
||||
| September 17, 2012, 10:10:09 | 2012-09-17 10:10:09 +0000 UTC |
|
||||
|
@ -221,11 +234,14 @@ func main() {
|
|||
| October 7th, 1970 | 1970-10-07 00:00:00 +0000 UTC |
|
||||
| 12 Feb 2006, 19:17 | 2006-02-12 19:17:00 +0000 UTC |
|
||||
| 12 Feb 2006 19:17 | 2006-02-12 19:17:00 +0000 UTC |
|
||||
| 14 May 2019 19:11:40.164 | 2019-05-14 19:11:40.164 +0000 UTC |
|
||||
| 7 oct 70 | 1970-10-07 00:00:00 +0000 UTC |
|
||||
| 7 oct 1970 | 1970-10-07 00:00:00 +0000 UTC |
|
||||
| 03 February 2013 | 2013-02-03 00:00:00 +0000 UTC |
|
||||
| 1 July 2013 | 2013-07-01 00:00:00 +0000 UTC |
|
||||
| 2013-Feb-03 | 2013-02-03 00:00:00 +0000 UTC |
|
||||
| 06/Jan/2008:15:04:05 -0700 | 2008-01-06 15:04:05 -0700 -0700 |
|
||||
| 06/Jan/2008 15:04:05 -0700 | 2008-01-06 15:04:05 -0700 -0700 |
|
||||
| 3/31/2014 | 2014-03-31 00:00:00 +0000 UTC |
|
||||
| 03/31/2014 | 2014-03-31 00:00:00 +0000 UTC |
|
||||
| 08/21/71 | 1971-08-21 00:00:00 +0000 UTC |
|
||||
|
@ -250,11 +266,22 @@ func main() {
|
|||
| 2014/4/02 03:00:51 | 2014-04-02 03:00:51 +0000 UTC |
|
||||
| 2012/03/19 10:11:59 | 2012-03-19 10:11:59 +0000 UTC |
|
||||
| 2012/03/19 10:11:59.3186369 | 2012-03-19 10:11:59.3186369 +0000 UTC |
|
||||
| 2014:3:31 | 2014-03-31 00:00:00 +0000 UTC |
|
||||
| 2014:03:31 | 2014-03-31 00:00:00 +0000 UTC |
|
||||
| 2014:4:8 22:05 | 2014-04-08 22:05:00 +0000 UTC |
|
||||
| 2014:04:08 22:05 | 2014-04-08 22:05:00 +0000 UTC |
|
||||
| 2014:04:2 03:00:51 | 2014-04-02 03:00:51 +0000 UTC |
|
||||
| 2014:4:02 03:00:51 | 2014-04-02 03:00:51 +0000 UTC |
|
||||
| 2012:03:19 10:11:59 | 2012-03-19 10:11:59 +0000 UTC |
|
||||
| 2012:03:19 10:11:59.3186369 | 2012-03-19 10:11:59.3186369 +0000 UTC |
|
||||
| 2014年04月08日 | 2014-04-08 00:00:00 +0000 UTC |
|
||||
| 2006-01-02T15:04:05+0000 | 2006-01-02 15:04:05 +0000 UTC |
|
||||
| 2009-08-12T22:15:09-07:00 | 2009-08-12 22:15:09 -0700 -0700 |
|
||||
| 2009-08-12T22:15:09 | 2009-08-12 22:15:09 +0000 UTC |
|
||||
| 2009-08-12T22:15:09.988 | 2009-08-12 22:15:09.988 +0000 UTC |
|
||||
| 2009-08-12T22:15:09Z | 2009-08-12 22:15:09 +0000 UTC |
|
||||
| 2017-07-19T03:21:51:897+0100 | 2017-07-19 03:21:51.897 +0100 +0100 |
|
||||
| 2019-05-29T08:41-04 | 2019-05-29 08:41:00 -0400 -0400 |
|
||||
| 2014-04-26 17:24:37.3186369 | 2014-04-26 17:24:37.3186369 +0000 UTC |
|
||||
| 2012-08-03 18:31:59.257000000 | 2012-08-03 18:31:59.257 +0000 UTC |
|
||||
| 2014-04-26 17:24:37.123 | 2014-04-26 17:24:37.123 +0000 UTC |
|
||||
|
@ -277,6 +304,7 @@ func main() {
|
|||
| 2014-04 | 2014-04-01 00:00:00 +0000 UTC |
|
||||
| 2014 | 2014-01-01 00:00:00 +0000 UTC |
|
||||
| 2014-05-11 08:20:13,787 | 2014-05-11 08:20:13.787 +0000 UTC |
|
||||
| 2020-07-20+08:00 | 2020-07-20 00:00:00 +0800 +0800 |
|
||||
| 3.31.2014 | 2014-03-31 00:00:00 +0000 UTC |
|
||||
| 03.31.2014 | 2014-03-31 00:00:00 +0000 UTC |
|
||||
| 08.21.71 | 1971-08-21 00:00:00 +0000 UTC |
|
||||
|
@ -284,6 +312,7 @@ func main() {
|
|||
| 2014.03.30 | 2014-03-30 00:00:00 +0000 UTC |
|
||||
| 20140601 | 2014-06-01 00:00:00 +0000 UTC |
|
||||
| 20140722105203 | 2014-07-22 10:52:03 +0000 UTC |
|
||||
| 171113 14:14:20 | 2017-11-13 14:14:20 +0000 UTC |
|
||||
| 1332151919 | 2012-03-19 10:11:59 +0000 UTC |
|
||||
| 1384216367189 | 2013-11-12 00:32:47.189 +0000 UTC |
|
||||
| 1384216367111222 | 2013-11-12 00:32:47.111222 +0000 UTC |
|
||||
|
|
4
vendor/github.com/araddon/dateparse/go.mod
generated
vendored
4
vendor/github.com/araddon/dateparse/go.mod
generated
vendored
|
@ -3,7 +3,7 @@ module github.com/araddon/dateparse
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.10 // indirect
|
||||
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
)
|
||||
|
|
11
vendor/github.com/araddon/dateparse/go.sum
generated
vendored
11
vendor/github.com/araddon/dateparse/go.sum
generated
vendored
|
@ -1,14 +1,17 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
|
||||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4 h1:8qmTC5ByIXO3GP/IzBkxcZ/99VITvnIETDhdFz/om7A=
|
||||
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
|
|
249
vendor/github.com/araddon/dateparse/parseany.go
generated
vendored
249
vendor/github.com/araddon/dateparse/parseany.go
generated
vendored
|
@ -55,37 +55,41 @@ type timeState uint8
|
|||
const (
|
||||
dateStart dateState = iota // 0
|
||||
dateDigit
|
||||
dateDigitSt
|
||||
dateYearDash
|
||||
dateYearDashAlphaDash
|
||||
dateYearDashDash
|
||||
dateYearDashDashWs // 5
|
||||
dateYearDashDashT
|
||||
dateYearDashDashOffset
|
||||
dateDigitDash
|
||||
dateDigitDashAlpha
|
||||
dateDigitDashAlphaDash
|
||||
dateDigitDot // 10
|
||||
dateDigitDashAlphaDash // 10
|
||||
dateDigitDot
|
||||
dateDigitDotDot
|
||||
dateDigitSlash
|
||||
dateDigitYearSlash
|
||||
dateDigitSlashAlpha // 15
|
||||
dateDigitColon
|
||||
dateDigitChineseYear
|
||||
dateDigitChineseYearWs // 15
|
||||
dateDigitChineseYearWs
|
||||
dateDigitWs
|
||||
dateDigitWsMoYear
|
||||
dateDigitWsMoYear // 20
|
||||
dateDigitWsMolong
|
||||
dateAlpha
|
||||
dateAlphaWs // 20
|
||||
dateAlphaWs
|
||||
dateAlphaWsDigit
|
||||
dateAlphaWsDigitMore
|
||||
dateAlphaWsDigitMore // 25
|
||||
dateAlphaWsDigitMoreWs
|
||||
dateAlphaWsDigitMoreWsYear
|
||||
dateAlphaWsMonth // 25
|
||||
dateAlphaWsMonth
|
||||
dateAlphaWsDigitYearmaybe
|
||||
dateAlphaWsMonthMore
|
||||
dateAlphaWsMonthSuffix
|
||||
dateAlphaWsMore
|
||||
dateAlphaWsAtTime // 30
|
||||
dateAlphaWsAtTime
|
||||
dateAlphaWsAlpha
|
||||
dateAlphaWsAlphaYearmaybe
|
||||
dateAlphaWsAlphaYearmaybe // 35
|
||||
dateAlphaPeriodWsDigit
|
||||
dateWeekdayComma
|
||||
dateWeekdayAbbrevComma
|
||||
|
@ -267,7 +271,7 @@ iterRunes:
|
|||
i += (bytesConsumed - 1)
|
||||
}
|
||||
|
||||
//gou.Debugf("i=%d r=%s state=%d %s", i, string(r), p.stateDate, datestr)
|
||||
// gou.Debugf("i=%d r=%s state=%d %s", i, string(r), p.stateDate, datestr)
|
||||
switch p.stateDate {
|
||||
case dateStart:
|
||||
if unicode.IsDigit(r) {
|
||||
|
@ -295,17 +299,37 @@ iterRunes:
|
|||
p.stateDate = dateDigitDash
|
||||
}
|
||||
case '/':
|
||||
// 08/May/2005
|
||||
// 03/31/2005
|
||||
// 2014/02/24
|
||||
p.stateDate = dateDigitSlash
|
||||
if i == 4 {
|
||||
p.yearlen = i
|
||||
// 2014/02/24 - Year first /
|
||||
p.yearlen = i // since it was start of datestr, i=len
|
||||
p.moi = i + 1
|
||||
p.setYear()
|
||||
p.stateDate = dateDigitYearSlash
|
||||
} else {
|
||||
// Either Ambiguous dd/mm vs mm/dd OR dd/month/yy
|
||||
// 08/May/2005
|
||||
// 03/31/2005
|
||||
// 31/03/2005
|
||||
if i+2 < len(p.datestr) && unicode.IsLetter(rune(datestr[i+1])) {
|
||||
// 08/May/2005
|
||||
p.stateDate = dateDigitSlashAlpha
|
||||
p.moi = i + 1
|
||||
p.daylen = 2
|
||||
p.dayi = 0
|
||||
p.setDay()
|
||||
continue
|
||||
}
|
||||
// Ambiguous dd/mm vs mm/dd the bane of date-parsing
|
||||
// 03/31/2005
|
||||
// 31/03/2005
|
||||
p.ambiguousMD = true
|
||||
if p.preferMonthFirst {
|
||||
if p.molen == 0 {
|
||||
// 03/31/2005
|
||||
p.molen = i
|
||||
p.setMonth()
|
||||
p.dayi = i + 1
|
||||
|
@ -317,6 +341,7 @@ iterRunes:
|
|||
p.moi = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case ':':
|
||||
|
@ -363,9 +388,13 @@ iterRunes:
|
|||
// 02 Jan 2018 23:59:34
|
||||
// 12 Feb 2006, 19:17
|
||||
// 12 Feb 2006, 19:17:22
|
||||
p.stateDate = dateDigitWs
|
||||
p.dayi = 0
|
||||
p.daylen = i
|
||||
if i == 6 {
|
||||
p.stateDate = dateDigitSt
|
||||
} else {
|
||||
p.stateDate = dateDigitWs
|
||||
p.dayi = 0
|
||||
p.daylen = i
|
||||
}
|
||||
case '年':
|
||||
// Chinese Year
|
||||
p.stateDate = dateDigitChineseYear
|
||||
|
@ -376,9 +405,15 @@ iterRunes:
|
|||
}
|
||||
p.part1Len = i
|
||||
|
||||
case dateDigitSt:
|
||||
p.set(0, "060102")
|
||||
i = i - 1
|
||||
p.stateTime = timeStart
|
||||
break iterRunes
|
||||
case dateYearDash:
|
||||
// dateYearDashDashT
|
||||
// 2006-01-02T15:04:05Z07:00
|
||||
// 2020-08-17T17:00:00:000+0100
|
||||
// dateYearDashDashWs
|
||||
// 2013-04-01 22:43:22
|
||||
// dateYearDashAlphaDash
|
||||
|
@ -400,7 +435,14 @@ iterRunes:
|
|||
// 2006-01-02T15:04:05Z07:00
|
||||
// dateYearDashDashWs
|
||||
// 2013-04-01 22:43:22
|
||||
// dateYearDashDashOffset
|
||||
// 2020-07-20+00:00
|
||||
switch r {
|
||||
case '+', '-':
|
||||
p.offseti = i
|
||||
p.daylen = i - p.dayi
|
||||
p.stateDate = dateYearDashDashOffset
|
||||
p.setDay()
|
||||
case ' ':
|
||||
p.daylen = i - p.dayi
|
||||
p.stateDate = dateYearDashDashWs
|
||||
|
@ -414,6 +456,21 @@ iterRunes:
|
|||
p.setDay()
|
||||
break iterRunes
|
||||
}
|
||||
|
||||
case dateYearDashDashT:
|
||||
// dateYearDashDashT
|
||||
// 2006-01-02T15:04:05Z07:00
|
||||
// 2020-08-17T17:00:00:000+0100
|
||||
|
||||
case dateYearDashDashOffset:
|
||||
// 2020-07-20+00:00
|
||||
switch r {
|
||||
case ':':
|
||||
p.set(p.offseti, "-07:00")
|
||||
// case ' ':
|
||||
// return nil, unknownErr(datestr)
|
||||
}
|
||||
|
||||
case dateYearDashAlphaDash:
|
||||
// 2013-Feb-03
|
||||
switch r {
|
||||
|
@ -446,7 +503,7 @@ iterRunes:
|
|||
case dateDigitDashAlphaDash:
|
||||
// 13-Feb-03 ambiguous
|
||||
// 28-Feb-03 ambiguous
|
||||
// 29-Jun-2016
|
||||
// 29-Jun-2016 dd-month(alpha)-yyyy
|
||||
switch r {
|
||||
case ' ':
|
||||
// we need to find if this was 4 digits, aka year
|
||||
|
@ -476,8 +533,49 @@ iterRunes:
|
|||
break iterRunes
|
||||
}
|
||||
|
||||
case dateDigitSlash:
|
||||
case dateDigitYearSlash:
|
||||
// 2014/07/10 06:55:38.156283
|
||||
// I honestly don't know if this format ever shows up as yyyy/
|
||||
|
||||
switch r {
|
||||
case ' ', ':':
|
||||
p.stateTime = timeStart
|
||||
if p.daylen == 0 {
|
||||
p.daylen = i - p.dayi
|
||||
p.setDay()
|
||||
}
|
||||
break iterRunes
|
||||
case '/':
|
||||
if p.molen == 0 {
|
||||
p.molen = i - p.moi
|
||||
p.setMonth()
|
||||
p.dayi = i + 1
|
||||
}
|
||||
}
|
||||
|
||||
case dateDigitSlashAlpha:
|
||||
// 06/May/2008
|
||||
|
||||
switch r {
|
||||
case '/':
|
||||
// |
|
||||
// 06/May/2008
|
||||
if p.molen == 0 {
|
||||
p.set(p.moi, "Jan")
|
||||
p.yeari = i + 1
|
||||
}
|
||||
// We aren't breaking because we are going to re-use this case
|
||||
// to find where the date starts, and possible time begins
|
||||
case ' ', ':':
|
||||
p.stateTime = timeStart
|
||||
if p.yearlen == 0 {
|
||||
p.yearlen = i - p.yeari
|
||||
p.setYear()
|
||||
}
|
||||
break iterRunes
|
||||
}
|
||||
|
||||
case dateDigitSlash:
|
||||
// 03/19/2012 10:11:59
|
||||
// 04/2/2014 03:00:37
|
||||
// 3/1/2012 10:11:59
|
||||
|
@ -488,25 +586,9 @@ iterRunes:
|
|||
// 1/2/06
|
||||
|
||||
switch r {
|
||||
case ' ':
|
||||
p.stateTime = timeStart
|
||||
if p.yearlen == 0 {
|
||||
p.yearlen = i - p.yeari
|
||||
p.setYear()
|
||||
} else if p.daylen == 0 {
|
||||
p.daylen = i - p.dayi
|
||||
p.setDay()
|
||||
}
|
||||
break iterRunes
|
||||
case '/':
|
||||
if p.yearlen > 0 {
|
||||
// 2014/07/10 06:55:38.156283
|
||||
if p.molen == 0 {
|
||||
p.molen = i - p.moi
|
||||
p.setMonth()
|
||||
p.dayi = i + 1
|
||||
}
|
||||
} else if p.preferMonthFirst {
|
||||
// This is the 2nd / so now we should know start pts of all of the dd, mm, yy
|
||||
if p.preferMonthFirst {
|
||||
if p.daylen == 0 {
|
||||
p.daylen = i - p.dayi
|
||||
p.setDay()
|
||||
|
@ -519,6 +601,15 @@ iterRunes:
|
|||
p.yeari = i + 1
|
||||
}
|
||||
}
|
||||
// Note no break, we are going to pass by and re-enter this dateDigitSlash
|
||||
// and look for ending (space) or not (just date)
|
||||
case ' ':
|
||||
p.stateTime = timeStart
|
||||
if p.yearlen == 0 {
|
||||
p.yearlen = i - p.yeari
|
||||
p.setYear()
|
||||
}
|
||||
break iterRunes
|
||||
}
|
||||
|
||||
case dateDigitColon:
|
||||
|
@ -718,8 +809,7 @@ iterRunes:
|
|||
|
||||
case r == ',':
|
||||
// Mon, 02 Jan 2006
|
||||
// p.moi = 0
|
||||
// p.molen = i
|
||||
|
||||
if i == 3 {
|
||||
p.stateDate = dateWeekdayAbbrevComma
|
||||
p.set(0, "Mon")
|
||||
|
@ -1039,7 +1129,7 @@ iterRunes:
|
|||
for ; i < len(datestr); i++ {
|
||||
r := rune(datestr[i])
|
||||
|
||||
//gou.Debugf("%d %s %d iterTimeRunes %s %s", i, string(r), p.stateTime, p.ds(), p.ts())
|
||||
// gou.Debugf("i=%d r=%s state=%d iterTimeRunes %s %s", i, string(r), p.stateTime, p.ds(), p.ts())
|
||||
|
||||
switch p.stateTime {
|
||||
case timeStart:
|
||||
|
@ -1096,7 +1186,12 @@ iterRunes:
|
|||
// 22:18+0530
|
||||
p.minlen = i - p.mini
|
||||
} else {
|
||||
p.seclen = i - p.seci
|
||||
if p.seclen == 0 {
|
||||
p.seclen = i - p.seci
|
||||
}
|
||||
if p.msi > 0 && p.mslen == 0 {
|
||||
p.mslen = i - p.msi
|
||||
}
|
||||
}
|
||||
p.offseti = i
|
||||
case '.':
|
||||
|
@ -1154,6 +1249,19 @@ iterRunes:
|
|||
} else if p.seci == 0 {
|
||||
p.seci = i + 1
|
||||
p.minlen = i - p.mini
|
||||
} else if p.seci > 0 {
|
||||
// 18:31:59:257 ms uses colon, wtf
|
||||
p.seclen = i - p.seci
|
||||
p.set(p.seci, "05")
|
||||
p.msi = i + 1
|
||||
|
||||
// gross, gross, gross. manipulating the datestr is horrible.
|
||||
// https://github.com/araddon/dateparse/issues/117
|
||||
// Could not get the parsing to work using golang time.Parse() without
|
||||
// replacing that colon with period.
|
||||
p.set(i, ".")
|
||||
datestr = datestr[0:i] + "." + datestr[i+1:]
|
||||
p.datestr = datestr
|
||||
}
|
||||
}
|
||||
case timeOffset:
|
||||
|
@ -1201,7 +1309,6 @@ iterRunes:
|
|||
// 17:57:51 MST 2009
|
||||
p.tzi = i
|
||||
p.stateTime = timeWsAlpha
|
||||
//break iterTimeRunes
|
||||
} else if unicode.IsDigit(r) {
|
||||
// 00:12:00 2008
|
||||
p.stateTime = timeWsYear
|
||||
|
@ -1231,6 +1338,7 @@ iterRunes:
|
|||
p.offseti = i
|
||||
case ' ':
|
||||
// 17:57:51 MST 2009
|
||||
// 17:57:51 MST
|
||||
p.tzlen = i - p.tzi
|
||||
if p.tzlen == 4 {
|
||||
p.set(p.tzi, " MST")
|
||||
|
@ -1333,7 +1441,7 @@ iterRunes:
|
|||
p.trimExtra()
|
||||
break
|
||||
}
|
||||
case '+', '-':
|
||||
case '+', '-', '(':
|
||||
// This really doesn't seem valid, but for some reason when round-tripping a go date
|
||||
// their is an extra +03 printed out. seems like go bug to me, but, parsing anyway.
|
||||
// 00:00:00 +0300 +03
|
||||
|
@ -1350,6 +1458,7 @@ iterRunes:
|
|||
p.setYear()
|
||||
}
|
||||
case unicode.IsLetter(r):
|
||||
// 15:04:05 -0700 MST
|
||||
if p.tzi == 0 {
|
||||
p.tzi = i
|
||||
}
|
||||
|
@ -1535,6 +1644,17 @@ iterRunes:
|
|||
}
|
||||
|
||||
switch p.stateTime {
|
||||
case timeWsAlpha:
|
||||
switch len(p.datestr) - p.tzi {
|
||||
case 3:
|
||||
// 13:31:51.999 +01:00 CET
|
||||
p.set(p.tzi, "MST")
|
||||
case 4:
|
||||
p.set(p.tzi, "MST")
|
||||
p.extra = len(p.datestr) - 1
|
||||
p.trimExtra()
|
||||
}
|
||||
|
||||
case timeWsAlphaWs:
|
||||
p.yearlen = i - p.yeari
|
||||
p.setYear()
|
||||
|
@ -1554,13 +1674,34 @@ iterRunes:
|
|||
case timePeriod:
|
||||
p.mslen = i - p.msi
|
||||
case timeOffset:
|
||||
// 19:55:00+0100
|
||||
p.set(p.offseti, "-0700")
|
||||
|
||||
switch len(p.datestr) - p.offseti {
|
||||
case 0, 1, 2, 4:
|
||||
return p, fmt.Errorf("TZ offset not recognized %q near %q (must be 2 or 4 digits optional colon)", datestr, string(datestr[p.offseti:]))
|
||||
case 3:
|
||||
// 19:55:00+01
|
||||
p.set(p.offseti, "-07")
|
||||
case 5:
|
||||
// 19:55:00+0100
|
||||
p.set(p.offseti, "-0700")
|
||||
}
|
||||
|
||||
case timeWsOffset:
|
||||
p.set(p.offseti, "-0700")
|
||||
case timeWsOffsetWs:
|
||||
// 17:57:51 -0700 2009
|
||||
// 00:12:00 +0000 UTC
|
||||
if p.tzi > 0 {
|
||||
switch len(p.datestr) - p.tzi {
|
||||
case 3:
|
||||
// 13:31:51.999 +01:00 CET
|
||||
p.set(p.tzi, "MST")
|
||||
case 4:
|
||||
// 13:31:51.999 +01:00 CEST
|
||||
p.set(p.tzi, "MST ")
|
||||
}
|
||||
|
||||
}
|
||||
case timeWsOffsetColon:
|
||||
// 17:57:51 -07:00
|
||||
p.set(p.offseti, "-07:00")
|
||||
|
@ -1638,6 +1779,9 @@ iterRunes:
|
|||
p.t = &t
|
||||
return p, nil
|
||||
}
|
||||
case dateDigitSt:
|
||||
// 171113 14:14:20
|
||||
return p, nil
|
||||
|
||||
case dateYearDash:
|
||||
// 2006-01
|
||||
|
@ -1650,6 +1794,16 @@ iterRunes:
|
|||
// 2006-01-2
|
||||
return p, nil
|
||||
|
||||
case dateYearDashDashOffset:
|
||||
/// 2020-07-20+00:00
|
||||
switch len(p.datestr) - p.offseti {
|
||||
case 5:
|
||||
p.set(p.offseti, "-0700")
|
||||
case 6:
|
||||
p.set(p.offseti, "-07:00")
|
||||
}
|
||||
return p, nil
|
||||
|
||||
case dateYearDashAlphaDash:
|
||||
// 2013-Feb-03
|
||||
// 2013-Feb-3
|
||||
|
@ -1757,6 +1911,13 @@ iterRunes:
|
|||
// 3/1/2014
|
||||
// 10/13/2014
|
||||
// 01/02/2006
|
||||
return p, nil
|
||||
|
||||
case dateDigitSlashAlpha:
|
||||
// 03/Jun/2014
|
||||
return p, nil
|
||||
|
||||
case dateDigitYearSlash:
|
||||
// 2014/10/13
|
||||
return p, nil
|
||||
|
||||
|
@ -2002,10 +2163,12 @@ func (p *parser) parse() (time.Time, error) {
|
|||
p.format = p.format[p.skip:]
|
||||
p.datestr = p.datestr[p.skip:]
|
||||
}
|
||||
//gou.Debugf("parse %q AS %q", p.datestr, string(p.format))
|
||||
|
||||
if p.loc == nil {
|
||||
// gou.Debugf("parse layout=%q input=%q \ntx, err := time.Parse(%q, %q)", string(p.format), p.datestr, string(p.format), p.datestr)
|
||||
return time.Parse(string(p.format), p.datestr)
|
||||
}
|
||||
//gou.Debugf("parse layout=%q input=%q \ntx, err := time.ParseInLocation(%q, %q, %v)", string(p.format), p.datestr, string(p.format), p.datestr, p.loc)
|
||||
return time.ParseInLocation(string(p.format), p.datestr, p.loc)
|
||||
}
|
||||
func isDay(alpha string) bool {
|
||||
|
|
26
vendor/github.com/charmbracelet/glamour/.golangci.yml
generated
vendored
Normal file
26
vendor/github.com/charmbracelet/glamour/.golangci.yml
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
run:
|
||||
tests: false
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
max-same-issues: 0
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- bodyclose
|
||||
- dupl
|
||||
- exportloopref
|
||||
- goconst
|
||||
- godot
|
||||
- godox
|
||||
- goimports
|
||||
- gomnd
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- misspell
|
||||
- prealloc
|
||||
- rowserrcheck
|
||||
- sqlclosecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- whitespace
|
31
vendor/github.com/charmbracelet/glamour/README.md
generated
vendored
31
vendor/github.com/charmbracelet/glamour/README.md
generated
vendored
|
@ -1,10 +1,13 @@
|
|||
# Glamour
|
||||
|
||||
[![Latest Release](https://img.shields.io/github/release/charmbracelet/glamour.svg)](https://github.com/charmbracelet/glamour/releases)
|
||||
[![GoDoc](https://godoc.org/github.com/golang/gddo?status.svg)](https://pkg.go.dev/github.com/charmbracelet/glamour?tab=doc)
|
||||
[![Build Status](https://github.com/charmbracelet/glamour/workflows/build/badge.svg)](https://github.com/charmbracelet/glamour/actions)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/charmbracelet/glamour/badge.svg?branch=master)](https://coveralls.io/github/charmbracelet/glamour?branch=master)
|
||||
[![Go ReportCard](http://goreportcard.com/badge/charmbracelet/glamour)](http://goreportcard.com/report/charmbracelet/glamour)
|
||||
<p>
|
||||
<img src="https://stuff.charm.sh/glamour/glamour-github-header.png" width="245" alt="Glamour Title Treatment"><br>
|
||||
<a href="https://github.com/charmbracelet/glamour/releases"><img src="https://img.shields.io/github/release/charmbracelet/glamour.svg" alt="Latest Release"></a>
|
||||
<a href="https://pkg.go.dev/github.com/charmbracelet/glamour?tab=doc"><img src="https://godoc.org/github.com/golang/gddo?status.svg" alt="GoDoc"></a>
|
||||
<a href="https://github.com/charmbracelet/glamour/actions"><img src="https://github.com/charmbracelet/glamour/workflows/build/badge.svg" alt="Build Status"></a>
|
||||
<a href="https://coveralls.io/github/charmbracelet/glamour?branch=master"><img src="https://coveralls.io/repos/github/charmbracelet/glamour/badge.svg?branch=master" alt="Coverage Status"></a>
|
||||
<a href="http://goreportcard.com/report/charmbracelet/glamour"><img src="http://goreportcard.com/badge/charmbracelet/glamour" alt="Go ReportCard"></a>
|
||||
</p>
|
||||
|
||||
Write handsome command-line tools with *glamour*!
|
||||
|
||||
|
@ -63,10 +66,22 @@ There are a few options for using a custom style:
|
|||
|
||||
## Glamourous Projects
|
||||
|
||||
Check out [Glow](https://github.com/charmbracelet/glow), a markdown renderer for
|
||||
the command-line, which uses `glamour`.
|
||||
|
||||
Check out these projects, which use `glamour`:
|
||||
- [Glow](https://github.com/charmbracelet/glow), a markdown renderer for
|
||||
the command-line.
|
||||
- [GitHub CLI](https://github.com/cli/cli), GitHub’s official command line tool.
|
||||
- [GLab](https://github.com/profclems/glab), An open source GitLab command line tool.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/charmbracelet/glamour/raw/master/LICENSE)
|
||||
|
||||
|
||||
***
|
||||
|
||||
Part of [Charm](https://charm.sh).
|
||||
|
||||
<a href="https://charm.sh/"><img alt="the Charm logo" src="https://stuff.charm.sh/charm-badge.jpg" width="400"></a>
|
||||
|
||||
Charm热爱开源! / Charm loves open source!
|
||||
|
||||
|
|
9
vendor/github.com/charmbracelet/glamour/ansi/elements.go
generated
vendored
9
vendor/github.com/charmbracelet/glamour/ansi/elements.go
generated
vendored
|
@ -7,6 +7,7 @@ import (
|
|||
"io"
|
||||
"strings"
|
||||
|
||||
east "github.com/yuin/goldmark-emoji/ast"
|
||||
"github.com/yuin/goldmark/ast"
|
||||
astext "github.com/yuin/goldmark/extension/ast"
|
||||
)
|
||||
|
@ -375,6 +376,14 @@ func (tr *ANSIRenderer) NewElement(node ast.Node, source []byte) Element {
|
|||
case ast.KindTextBlock:
|
||||
return Element{}
|
||||
|
||||
case east.KindEmoji:
|
||||
n := node.(*east.Emoji)
|
||||
return Element{
|
||||
Renderer: &BaseElement{
|
||||
Token: string(n.Value.Unicode),
|
||||
},
|
||||
}
|
||||
|
||||
// Unknown case
|
||||
default:
|
||||
fmt.Println("Warning: unhandled element", node.Kind().String())
|
||||
|
|
2
vendor/github.com/charmbracelet/glamour/ansi/image.go
generated
vendored
2
vendor/github.com/charmbracelet/glamour/ansi/image.go
generated
vendored
|
@ -25,7 +25,7 @@ func (e *ImageElement) Render(w io.Writer, ctx RenderContext) error {
|
|||
}
|
||||
if len(e.URL) > 0 {
|
||||
el := &BaseElement{
|
||||
Token: resolveRelativeURL(e.BaseURL, e.URL),
|
||||
Token: resolveURL(e.BaseURL, e.URL),
|
||||
Prefix: " ",
|
||||
Style: ctx.options.Styles.Image,
|
||||
}
|
||||
|
|
2
vendor/github.com/charmbracelet/glamour/ansi/link.go
generated
vendored
2
vendor/github.com/charmbracelet/glamour/ansi/link.go
generated
vendored
|
@ -64,7 +64,7 @@ func (e *LinkElement) Render(w io.Writer, ctx RenderContext) error {
|
|||
}
|
||||
|
||||
el := &BaseElement{
|
||||
Token: resolveRelativeURL(e.BaseURL, e.URL),
|
||||
Token: resolveURL(e.BaseURL, e.URL),
|
||||
Prefix: pre,
|
||||
Style: style,
|
||||
}
|
||||
|
|
10
vendor/github.com/charmbracelet/glamour/ansi/renderer.go
generated
vendored
10
vendor/github.com/charmbracelet/glamour/ansi/renderer.go
generated
vendored
|
@ -3,9 +3,9 @@ package ansi
|
|||
import (
|
||||
"io"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/muesli/termenv"
|
||||
east "github.com/yuin/goldmark-emoji/ast"
|
||||
"github.com/yuin/goldmark/ast"
|
||||
astext "github.com/yuin/goldmark/extension/ast"
|
||||
"github.com/yuin/goldmark/renderer"
|
||||
|
@ -72,13 +72,16 @@ func (r *ANSIRenderer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
|
|||
reg.Register(astext.KindFootnote, r.renderNode)
|
||||
reg.Register(astext.KindFootnoteList, r.renderNode)
|
||||
reg.Register(astext.KindFootnoteLink, r.renderNode)
|
||||
reg.Register(astext.KindFootnoteBackLink, r.renderNode)
|
||||
reg.Register(astext.KindFootnoteBacklink, r.renderNode)
|
||||
|
||||
// checkboxes
|
||||
reg.Register(astext.KindTaskCheckBox, r.renderNode)
|
||||
|
||||
// strikethrough
|
||||
reg.Register(astext.KindStrikethrough, r.renderNode)
|
||||
|
||||
// emoji
|
||||
reg.Register(east.KindEmoji, r.renderNode)
|
||||
}
|
||||
|
||||
func (r *ANSIRenderer) renderNode(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
|
||||
|
@ -145,7 +148,7 @@ func isChild(node ast.Node) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func resolveRelativeURL(baseURL string, rel string) string {
|
||||
func resolveURL(baseURL string, rel string) string {
|
||||
u, err := url.Parse(rel)
|
||||
if err != nil {
|
||||
return rel
|
||||
|
@ -153,7 +156,6 @@ func resolveRelativeURL(baseURL string, rel string) string {
|
|||
if u.IsAbs() {
|
||||
return rel
|
||||
}
|
||||
u.Path = strings.TrimPrefix(u.Path, "/")
|
||||
|
||||
base, err := url.Parse(baseURL)
|
||||
if err != nil {
|
||||
|
|
26
vendor/github.com/charmbracelet/glamour/glamour.go
generated
vendored
26
vendor/github.com/charmbracelet/glamour/glamour.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/muesli/termenv"
|
||||
"github.com/yuin/goldmark"
|
||||
emoji "github.com/yuin/goldmark-emoji"
|
||||
"github.com/yuin/goldmark/extension"
|
||||
"github.com/yuin/goldmark/parser"
|
||||
"github.com/yuin/goldmark/renderer"
|
||||
|
@ -135,20 +136,17 @@ func WithEnvironmentConfig() TermRendererOption {
|
|||
// standard style.
|
||||
func WithStylePath(stylePath string) TermRendererOption {
|
||||
return func(tr *TermRenderer) error {
|
||||
jsonBytes, err := ioutil.ReadFile(stylePath)
|
||||
switch {
|
||||
case err == nil:
|
||||
return json.Unmarshal(jsonBytes, &tr.ansiOptions.Styles)
|
||||
case os.IsNotExist(err):
|
||||
styles, err := getDefaultStyle(stylePath)
|
||||
styles, err := getDefaultStyle(stylePath)
|
||||
if err != nil {
|
||||
jsonBytes, err := ioutil.ReadFile(stylePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tr.ansiOptions.Styles = *styles
|
||||
return nil
|
||||
default:
|
||||
return err
|
||||
|
||||
return json.Unmarshal(jsonBytes, &tr.ansiOptions.Styles)
|
||||
}
|
||||
tr.ansiOptions.Styles = *styles
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,6 +185,14 @@ func WithWordWrap(wordWrap int) TermRendererOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithEmoji sets a TermRenderer's emoji rendering.
|
||||
func WithEmoji() TermRendererOption {
|
||||
return func(tr *TermRenderer) error {
|
||||
emoji.New().Extend(tr.md)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (tr *TermRenderer) Read(b []byte) (int, error) {
|
||||
return tr.renderBuf.Read(b)
|
||||
}
|
||||
|
|
11
vendor/github.com/charmbracelet/glamour/go.mod
generated
vendored
11
vendor/github.com/charmbracelet/glamour/go.mod
generated
vendored
|
@ -3,10 +3,11 @@ module github.com/charmbracelet/glamour
|
|||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/alecthomas/chroma v0.7.3
|
||||
github.com/microcosm-cc/bluemonday v1.0.2
|
||||
github.com/muesli/reflow v0.1.0
|
||||
github.com/muesli/termenv v0.6.0
|
||||
github.com/alecthomas/chroma v0.8.1
|
||||
github.com/microcosm-cc/bluemonday v1.0.4
|
||||
github.com/muesli/reflow v0.2.0
|
||||
github.com/muesli/termenv v0.7.4
|
||||
github.com/olekukonko/tablewriter v0.0.4
|
||||
github.com/yuin/goldmark v1.2.0
|
||||
github.com/yuin/goldmark v1.3.1
|
||||
github.com/yuin/goldmark-emoji v1.0.1
|
||||
)
|
||||
|
|
32
vendor/github.com/charmbracelet/glamour/go.sum
generated
vendored
32
vendor/github.com/charmbracelet/glamour/go.sum
generated
vendored
|
@ -1,12 +1,16 @@
|
|||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38 h1:smF2tmSOzy2Mm+0dGI2AIUHY+w0BUc+4tn40djz7+6U=
|
||||
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38/go.mod h1:r7bzyVFMNntcxPZXK3/+KdruV1H5KSlyVY0gc+NgInI=
|
||||
github.com/alecthomas/chroma v0.7.3 h1:NfdAERMy+esYQs8OXk0I868/qDxxCEo7FMz1WIqMAeI=
|
||||
github.com/alecthomas/chroma v0.7.3/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||
github.com/alecthomas/chroma v0.8.1 h1:ym20sbvyC6RXz45u4qDglcgr8E313oPROshcuCHqiEE=
|
||||
github.com/alecthomas/chroma v0.8.1/go.mod h1:sko8vR34/90zvl5QdcUdvzL3J8NKjAUx9va9jPuFNoM=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721 h1:JHZL0hZKJ1VENNfmXvHbgYlbUOvpzYzvy2aZU5gXVeo=
|
||||
github.com/alecthomas/colour v0.0.0-20160524082231-60882d9e2721/go.mod h1:QO9JBoKquHd+jz9nshCh40fOfO+JzsoXy8qTHF68zU0=
|
||||
github.com/alecthomas/kong v0.2.4/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE=
|
||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 h1:p9Sln00KOTlrYkxI1zYWl1QLnEqAqEARBEYa8FQnQcY=
|
||||
github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/chris-ramon/douceur v0.2.0 h1:IDMEdxlEUUBYBKE4z/mJnFyVXox+MjuEVDJNN27glkU=
|
||||
github.com/chris-ramon/douceur v0.2.0/go.mod h1:wDW5xjJdeoMm1mRt4sD4c/LbF/mWdEpRXQKjTR8nIBE=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
|
||||
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
@ -14,8 +18,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dlclark/regexp2 v1.2.0 h1:8sAhBGEM0dRWogWqWyQeIJnxjWO6oIjl8FKqREDsGfk=
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f h1:5CjVwnuUcp5adK4gmY6i72gpVFVnZDP2h5TmPScB6u4=
|
||||
github.com/google/goterm v0.0.0-20190703233501-fc88cf888a3f/go.mod h1:nOFQdrUlIlx6M6ODdSpBj1NVA+VgLC6kmw60mkw34H4=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
|
@ -25,12 +29,12 @@ github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+tw
|
|||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s=
|
||||
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
|
||||
github.com/muesli/reflow v0.1.0 h1:oQdpLfO56lr5pgLvqD0TcjW85rDjSYSBVdiG1Ch1ddM=
|
||||
github.com/muesli/reflow v0.1.0/go.mod h1:I9bWAt7QTg/que/qmUCJBGlj7wEq8OAFBjPNjc6xK4I=
|
||||
github.com/muesli/termenv v0.6.0 h1:zxvzTBmo4ZcxhNGGWeMz+Tttm51eF5bmPjfy4MCRYlk=
|
||||
github.com/muesli/termenv v0.6.0/go.mod h1:SohX91w6swWA4AYU+QmPx+aSgXhWO0juiyID9UZmbpA=
|
||||
github.com/microcosm-cc/bluemonday v1.0.4 h1:p0L+CTpo/PLFdkoPcJemLXG+fpMD7pYOoDEq1axMbGg=
|
||||
github.com/microcosm-cc/bluemonday v1.0.4/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
|
||||
github.com/muesli/reflow v0.2.0 h1:2o0UBJPHHH4fa2GCXU4Rg4DwOtWPMekCeyc5EWbAQp0=
|
||||
github.com/muesli/reflow v0.2.0/go.mod h1:qT22vjVmM9MIUeLgsVYe/Ye7eZlbv9dZjL3dVhUqLX8=
|
||||
github.com/muesli/termenv v0.7.4 h1:/pBqvU5CpkY53tU0vVn+xgs2ZTX63aH5nY+SSps5Xa8=
|
||||
github.com/muesli/termenv v0.7.4/go.mod h1:pZ7qY9l3F7e5xsAOS0zCew2tME+p7bWeBkotCEcIIcc=
|
||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
@ -43,8 +47,12 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/yuin/goldmark v1.2.0 h1:WOOcyaJPlzb8fZ8TloxFe8QZkhOOJx87leDa9MIT9dc=
|
||||
github.com/yuin/goldmark v1.2.0/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.1 h1:eVwehsLsZlCJCwXyGLgg+Q4iFWE/eTIMG0e8waCmm/I=
|
||||
github.com/yuin/goldmark v1.3.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os=
|
||||
github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3 h1:eH6Eip3UpmR+yM/qI9Ijluzb1bNv/cAU/n+6l8tRSis=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg=
|
||||
|
|
2
vendor/github.com/dlclark/regexp2/.travis.yml
generated
vendored
2
vendor/github.com/dlclark/regexp2/.travis.yml
generated
vendored
|
@ -1,5 +1,5 @@
|
|||
language: go
|
||||
|
||||
go:
|
||||
- 1.9
|
||||
- 1.5
|
||||
- tip
|
11
vendor/github.com/dlclark/regexp2/README.md
generated
vendored
11
vendor/github.com/dlclark/regexp2/README.md
generated
vendored
|
@ -43,8 +43,8 @@ The __last__ capture is embedded in each group, so `g.String()` will return the
|
|||
| Category | regexp | regexp2 |
|
||||
| --- | --- | --- |
|
||||
| Catastrophic backtracking possible | no, constant execution time guarantees | yes, if your pattern is at risk you can use the `re.MatchTimeout` field |
|
||||
| Python-style capture groups `(?P<name>re)` | yes | no (yes in RE2 compat mode) |
|
||||
| .NET-style capture groups `(?<name>re)` or `(?'name're)` | no | yes |
|
||||
| Python-style capture groups `(P<name>re)` | yes | no |
|
||||
| .NET-style capture groups `(<name>re)` or `('name're)` | no | yes |
|
||||
| comments `(?#comment)` | no | yes |
|
||||
| branch numbering reset `(?\|a\|b)` | no | no |
|
||||
| possessive match `(?>re)` | no | yes |
|
||||
|
@ -54,15 +54,14 @@ The __last__ capture is embedded in each group, so `g.String()` will return the
|
|||
| negative lookbehind `(?<!re)` | no | yes |
|
||||
| back reference `\1` | no | yes |
|
||||
| named back reference `\k'name'` | no | yes |
|
||||
| named ascii character class `[[:foo:]]`| yes | no (yes in RE2 compat mode) |
|
||||
| conditionals `(?(expr)yes\|no)` | no | yes |
|
||||
| named ascii character class `[[:foo:]]`| yes | no |
|
||||
| conditionals `((expr)yes\|no)` | no | yes |
|
||||
|
||||
## RE2 compatibility mode
|
||||
The default behavior of `regexp2` is to match the .NET regexp engine, however the `RE2` option is provided to change the parsing to increase compatibility with RE2. Using the `RE2` option when compiling a regexp will not take away any features, but will change the following behaviors:
|
||||
* add support for named ascii character classes (e.g. `[[:foo:]]`)
|
||||
* add support for python-style capture groups (e.g. `(P<name>re)`)
|
||||
* change singleline behavior for `$` to only match end of string (like RE2) (see [#24](https://github.com/dlclark/regexp2/issues/24))
|
||||
|
||||
|
||||
```go
|
||||
re := regexp2.MustCompile(`Your RE2-compatible pattern`, regexp2.RE2)
|
||||
if isMatch, _ := re.MatchString(`Something to match`); isMatch {
|
||||
|
|
11
vendor/github.com/dlclark/regexp2/regexp.go
generated
vendored
11
vendor/github.com/dlclark/regexp2/regexp.go
generated
vendored
|
@ -235,14 +235,17 @@ func (re *Regexp) getRunesAndStart(s string, startAt int) ([]rune, int) {
|
|||
ret[i] = r
|
||||
i++
|
||||
}
|
||||
if startAt == len(s) {
|
||||
runeIdx = i
|
||||
}
|
||||
return ret[:i], runeIdx
|
||||
}
|
||||
|
||||
func getRunes(s string) []rune {
|
||||
return []rune(s)
|
||||
ret := make([]rune, len(s))
|
||||
i := 0
|
||||
for _, r := range s {
|
||||
ret[i] = r
|
||||
i++
|
||||
}
|
||||
return ret[:i]
|
||||
}
|
||||
|
||||
// MatchRunes return true if the runes matches the regex
|
||||
|
|
19
vendor/github.com/dlclark/regexp2/runner.go
generated
vendored
19
vendor/github.com/dlclark/regexp2/runner.go
generated
vendored
|
@ -566,22 +566,9 @@ func (r *runner) execute() error {
|
|||
continue
|
||||
|
||||
case syntax.EndZ:
|
||||
rchars := r.rightchars()
|
||||
if rchars > 1 {
|
||||
if r.rightchars() > 1 || r.rightchars() == 1 && r.charAt(r.textPos()) != '\n' {
|
||||
break
|
||||
}
|
||||
// RE2 and EcmaScript define $ as "asserts position at the end of the string"
|
||||
// PCRE/.NET adds "or before the line terminator right at the end of the string (if any)"
|
||||
if (r.re.options & (RE2 | ECMAScript)) != 0 {
|
||||
// RE2/Ecmascript mode
|
||||
if rchars > 0 {
|
||||
break
|
||||
}
|
||||
} else if rchars == 1 && r.charAt(r.textPos()) != '\n' {
|
||||
// "regular" mode
|
||||
break
|
||||
}
|
||||
|
||||
r.advance(0)
|
||||
continue
|
||||
|
||||
|
@ -951,8 +938,8 @@ func (r *runner) advance(i int) {
|
|||
}
|
||||
|
||||
func (r *runner) goTo(newpos int) {
|
||||
// when branching backward or in place, ensure storage
|
||||
if newpos <= r.codepos {
|
||||
// when branching backward, ensure storage
|
||||
if newpos < r.codepos {
|
||||
r.ensureStorage()
|
||||
}
|
||||
|
||||
|
|
31
vendor/github.com/dlclark/regexp2/syntax/parser.go
generated
vendored
31
vendor/github.com/dlclark/regexp2/syntax/parser.go
generated
vendored
|
@ -1250,10 +1250,10 @@ func (p *parser) scanBasicBackslash(scanOnly bool) (*regexNode, error) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
if p.isCaptureSlot(capnum) {
|
||||
if p.useOptionE() || p.isCaptureSlot(capnum) {
|
||||
return newRegexNodeM(ntRef, p.options, capnum), nil
|
||||
}
|
||||
if capnum <= 9 && !p.useOptionE() {
|
||||
if capnum <= 9 {
|
||||
return nil, p.getErr(ErrUndefinedBackRef, capnum)
|
||||
}
|
||||
|
||||
|
@ -1648,7 +1648,7 @@ func (p *parser) scanOptions() {
|
|||
}
|
||||
|
||||
// Scans \ code for escape codes that map to single unicode chars.
|
||||
func (p *parser) scanCharEscape() (r rune, err error) {
|
||||
func (p *parser) scanCharEscape() (rune, error) {
|
||||
|
||||
ch := p.moveRightGetChar()
|
||||
|
||||
|
@ -1657,22 +1657,16 @@ func (p *parser) scanCharEscape() (r rune, err error) {
|
|||
return p.scanOctal(), nil
|
||||
}
|
||||
|
||||
pos := p.textpos()
|
||||
|
||||
switch ch {
|
||||
case 'x':
|
||||
// support for \x{HEX} syntax from Perl and PCRE
|
||||
if p.charsRight() > 0 && p.rightChar(0) == '{' {
|
||||
if p.useOptionE() {
|
||||
return ch, nil
|
||||
}
|
||||
p.moveRight(1)
|
||||
return p.scanHexUntilBrace()
|
||||
} else {
|
||||
r, err = p.scanHex(2)
|
||||
}
|
||||
return p.scanHex(2)
|
||||
case 'u':
|
||||
r, err = p.scanHex(4)
|
||||
return p.scanHex(4)
|
||||
case 'a':
|
||||
return '\u0007', nil
|
||||
case 'b':
|
||||
|
@ -1690,18 +1684,13 @@ func (p *parser) scanCharEscape() (r rune, err error) {
|
|||
case 'v':
|
||||
return '\u000B', nil
|
||||
case 'c':
|
||||
r, err = p.scanControl()
|
||||
return p.scanControl()
|
||||
default:
|
||||
if !p.useOptionE() && IsWordChar(ch) {
|
||||
return 0, p.getErr(ErrUnrecognizedEscape, string(ch))
|
||||
}
|
||||
return ch, nil
|
||||
}
|
||||
if err != nil && p.useOptionE() {
|
||||
p.textto(pos)
|
||||
return ch, nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Grabs and converts an ascii control character
|
||||
|
@ -1818,12 +1807,12 @@ func (p *parser) scanOctal() rune {
|
|||
//we know the first char is good because the caller had to check
|
||||
i := 0
|
||||
d := int(p.rightChar(0) - '0')
|
||||
for c > 0 && d <= 7 && d >= 0 {
|
||||
if i >= 0x20 && p.useOptionE() {
|
||||
break
|
||||
}
|
||||
for c > 0 && d <= 7 {
|
||||
i *= 8
|
||||
i += d
|
||||
if p.useOptionE() && i >= 0x20 {
|
||||
break
|
||||
}
|
||||
c--
|
||||
|
||||
p.moveRight(1)
|
||||
|
|
25
vendor/github.com/hashicorp/go-version/CHANGELOG.md
generated
vendored
Normal file
25
vendor/github.com/hashicorp/go-version/CHANGELOG.md
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
# 1.3.0 (March 31, 2021)
|
||||
|
||||
Please note that CHANGELOG.md does not exist in the source code prior to this release.
|
||||
|
||||
FEATURES:
|
||||
- Add `Core` function to return a version without prerelease or metadata ([#85](https://github.com/hashicorp/go-version/pull/85))
|
||||
|
||||
# 1.2.1 (June 17, 2020)
|
||||
|
||||
BUG FIXES:
|
||||
- Prevent `Version.Equal` method from panicking on `nil` encounter ([#73](https://github.com/hashicorp/go-version/pull/73))
|
||||
|
||||
# 1.2.0 (April 23, 2019)
|
||||
|
||||
FEATURES:
|
||||
- Add `GreaterThanOrEqual` and `LessThanOrEqual` helper methods ([#53](https://github.com/hashicorp/go-version/pull/53))
|
||||
|
||||
# 1.1.0 (Jan 07, 2019)
|
||||
|
||||
FEATURES:
|
||||
- Add `NewSemver` constructor ([#45](https://github.com/hashicorp/go-version/pull/45))
|
||||
|
||||
# 1.0.0 (August 24, 2018)
|
||||
|
||||
Initial release.
|
8
vendor/github.com/hashicorp/go-version/version.go
generated
vendored
8
vendor/github.com/hashicorp/go-version/version.go
generated
vendored
|
@ -278,6 +278,14 @@ func comparePrereleases(v string, other string) int {
|
|||
return 0
|
||||
}
|
||||
|
||||
// Core returns a new version constructed from only the MAJOR.MINOR.PATCH
|
||||
// segments of the version, without prerelease or metadata.
|
||||
func (v *Version) Core() *Version {
|
||||
segments := v.Segments64()
|
||||
segmentsOnly := fmt.Sprintf("%d.%d.%d", segments[0], segments[1], segments[2])
|
||||
return Must(NewVersion(segmentsOnly))
|
||||
}
|
||||
|
||||
// Equal tests if two versions are equal.
|
||||
func (v *Version) Equal(o *Version) bool {
|
||||
if v == nil || o == nil {
|
||||
|
|
121
vendor/github.com/lucasb-eyer/go-colorful/.gitignore
generated
vendored
121
vendor/github.com/lucasb-eyer/go-colorful/.gitignore
generated
vendored
|
@ -1,28 +1,101 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
# Created by https://www.toptal.com/developers/gitignore/api/code,go,linux,macos,windows
|
||||
# Edit at https://www.toptal.com/developers/gitignore?templates=code,go,linux,macos,windows
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Vim swap files
|
||||
.*.sw?
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
### Code ###
|
||||
.vscode/*
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
*.code-workspace
|
||||
|
||||
### Go ###
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Code coverage stuff
|
||||
coverage.out
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
### Go Patch ###
|
||||
/vendor/
|
||||
/Godeps/
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### Windows ###
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
Thumbs.db:encryptable
|
||||
ehthumbs.db
|
||||
ehthumbs_vista.db
|
||||
|
||||
# Dump file
|
||||
*.stackdump
|
||||
|
||||
# Folder config file
|
||||
[Dd]esktop.ini
|
||||
|
||||
# Recycle Bin used on file shares
|
||||
$RECYCLE.BIN/
|
||||
|
||||
# Windows Installer files
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# Windows shortcuts
|
||||
*.lnk
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/code,go,linux,macos,windows
|
||||
|
|
7
vendor/github.com/lucasb-eyer/go-colorful/.travis.yml
generated
vendored
7
vendor/github.com/lucasb-eyer/go-colorful/.travis.yml
generated
vendored
|
@ -1,7 +0,0 @@
|
|||
language: go
|
||||
install:
|
||||
- go get golang.org/x/tools/cmd/cover
|
||||
- go get github.com/mattn/goveralls
|
||||
script:
|
||||
- go test -v -covermode=count -coverprofile=coverage.out
|
||||
- if [[ "$TRAVIS_PULL_REQUEST" = "false" ]]; then $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci -repotoken $COVERALLS_TOKEN; fi
|
42
vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md
generated
vendored
Normal file
42
vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
The format of this file is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
but only releases after v1.0.3 properly adhere to it.
|
||||
|
||||
|
||||
## [1.2.0] - 2021-01-27
|
||||
### Added
|
||||
- HSLuv and HPLuv color spaces (#41, #51)
|
||||
- CIE LCh(uv) color space, called `LuvLCh` in code (#51)
|
||||
- JSON and envconfig serialization support for `HexColor` (#42)
|
||||
- `DistanceLinearRGB` (#53)
|
||||
|
||||
### Fixed
|
||||
- RGB to/from XYZ conversion is more accurate (#51)
|
||||
- A bug in `XYZToLuvWhiteRef` that only applied to very small values was fixed (#51)
|
||||
- `BlendHCL` output is clamped so that it's not invalid (#46)
|
||||
- Properly documented `DistanceCIE76` (#40)
|
||||
- Some small godoc fixes
|
||||
|
||||
|
||||
## [1.0.3] - 2019-11-11
|
||||
- Remove SQLMock dependency
|
||||
|
||||
|
||||
## [1.0.2] - 2019-04-07
|
||||
- Fixes SQLMock dependency
|
||||
|
||||
|
||||
## [1.0.1] - 2019-03-24
|
||||
- Adds support for Go Modules
|
||||
|
||||
|
||||
## [1.0.0] - 2018-05-26
|
||||
- API Breaking change in `MakeColor`: instead of `panic`ing when alpha is zero, it now returns a secondary, boolean return value indicating success. See [the color.Color interface](#the-colorcolor-interface) section and [this FAQ entry](#q-why-would-makecolor-ever-fail) for details.
|
||||
|
||||
|
||||
## [0.9.0] - 2018-05-26
|
||||
- Initial version number after having ignored versioning for a long time :)
|
42
vendor/github.com/lucasb-eyer/go-colorful/README.md
generated
vendored
42
vendor/github.com/lucasb-eyer/go-colorful/README.md
generated
vendored
|
@ -1,9 +1,9 @@
|
|||
go-colorful
|
||||
===========
|
||||
A library for playing with colors in go (golang).
|
||||
|
||||
[![Build Status](https://travis-ci.org/lucasb-eyer/go-colorful.svg?branch=master)](https://travis-ci.org/lucasb-eyer/go-colorful)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/lucasb-eyer/go-colorful/badge.svg?branch=master)](https://coveralls.io/github/lucasb-eyer/go-colorful?branch=master)
|
||||
[![go reportcard](https://goreportcard.com/badge/github.com/lucasb-eyer/go-colorful)](https://goreportcard.com/report/github.com/lucasb-eyer/go-colorful)
|
||||
|
||||
A library for playing with colors in Go. Supports Go 1.13 onwards.
|
||||
|
||||
Why?
|
||||
====
|
||||
|
@ -30,6 +30,9 @@ Go-Colorful stores colors in RGB and provides methods from converting these to v
|
|||
- **CIE-L\*a\*b\*:** A *perceptually uniform* color space, i.e. distances are meaningful. L\* in [0..1] and a\*, b\* almost in [-1..1].
|
||||
- **CIE-L\*u\*v\*:** Very similar to CIE-L\*a\*b\*, there is [no consensus](http://en.wikipedia.org/wiki/CIELUV#Historical_background) on which one is "better".
|
||||
- **CIE-L\*C\*h° (HCL):** This is generally the [most useful](http://vis4.net/blog/posts/avoid-equidistant-hsv-colors/) one; CIE-L\*a\*b\* space in polar coordinates, i.e. a *better* HSV. H° is in [0..360], C\* almost in [-1..1] and L\* as in CIE-L\*a\*b\*.
|
||||
- **CIE LCh(uv):** Called `LuvLCh` in code, this is a cylindrical transformation of the CIE-L\*u\*v\* color space. Like HCL above: H° is in [0..360], C\* almost in [-1..1] and L\* as in CIE-L\*u\*v\*.
|
||||
- **HSLuv:** The better alternative to HSL, see [here](https://www.hsluv.org/) and [here](https://www.kuon.ch/post/2020-03-08-hsluv/). Hue in [0..360], Saturation and Luminance in [0..1].
|
||||
- **HPLuv:** A variant of HSLuv. The color space is smoother, but only pastel colors can be included. Because the valid colors are limited, it's easy to get invalid Saturation values way above 1.0, indicating the color can't be represented in HPLuv beccause it's not pastel.
|
||||
|
||||
For the colorspaces where it makes sense (XYZ, Lab, Luv, HCl), the
|
||||
[D65](http://en.wikipedia.org/wiki/Illuminant_D65) is used as reference white
|
||||
|
@ -248,14 +251,14 @@ func main() {
|
|||
//c2, _ := colorful.Hex("#1E3140")
|
||||
|
||||
for i := 0 ; i < blocks ; i++ {
|
||||
draw.Draw(img, image.Rect(i*blockw, 0,(i+1)*blockw, 40), &image.Uniform{c1.BlendHsv(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src)
|
||||
draw.Draw(img, image.Rect(i*blockw, 40,(i+1)*blockw, 80), &image.Uniform{c1.BlendLuv(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src)
|
||||
draw.Draw(img, image.Rect(i*blockw, 80,(i+1)*blockw,120), &image.Uniform{c1.BlendRgb(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src)
|
||||
draw.Draw(img, image.Rect(i*blockw,120,(i+1)*blockw,160), &image.Uniform{c1.BlendLab(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src)
|
||||
draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1))}, image.ZP, draw.Src)
|
||||
draw.Draw(img, image.Rect(i*blockw, 0,(i+1)*blockw, 40), &image.Uniform{c1.BlendHsv(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)
|
||||
draw.Draw(img, image.Rect(i*blockw, 40,(i+1)*blockw, 80), &image.Uniform{c1.BlendLuv(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)
|
||||
draw.Draw(img, image.Rect(i*blockw, 80,(i+1)*blockw,120), &image.Uniform{c1.BlendRgb(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)
|
||||
draw.Draw(img, image.Rect(i*blockw,120,(i+1)*blockw,160), &image.Uniform{c1.BlendLab(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)
|
||||
draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src)
|
||||
|
||||
// This can be used to "fix" invalid colors in the gradient.
|
||||
//draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1)).Clamped()}, image.ZP, draw.Src)
|
||||
//draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1)).Clamped()}, image.Point{}, draw.Src)
|
||||
}
|
||||
|
||||
toimg, err := os.Create("colorblend.png")
|
||||
|
@ -468,25 +471,12 @@ section above.
|
|||
Who?
|
||||
====
|
||||
|
||||
This library has been developed by Lucas Beyer with contributions from
|
||||
This library was developed by Lucas Beyer with contributions from
|
||||
Bastien Dejean (@baskerville), Phil Kulak (@pkulak) and Christian Muehlhaeuser (@muesli).
|
||||
|
||||
Release Notes
|
||||
=============
|
||||
It is now maintained by makeworld (@makeworld-the-better-one).
|
||||
|
||||
### Version 1.0
|
||||
- API Breaking change in `MakeColor`: instead of `panic`ing when alpha is zero, it now returns a secondary, boolean return value indicating success. See [the color.Color interface](https://github.com/lucasb-eyer/go-colorful#the-colorcolor-interface) section and [this FAQ entry](https://github.com/lucasb-eyer/go-colorful#q-why-would-makecolor-ever-fail) for details.
|
||||
|
||||
### Version 0.9
|
||||
- Initial version number after having ignored versioning for a long time :)
|
||||
|
||||
License: MIT
|
||||
============
|
||||
Copyright (c) 2013 Lucas Beyer
|
||||
|
||||
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.
|
||||
## License
|
||||
|
||||
This repo is under the MIT license, see [LICENSE](LICENSE) for details.
|
||||
|
|
104
vendor/github.com/lucasb-eyer/go-colorful/colors.go
generated
vendored
104
vendor/github.com/lucasb-eyer/go-colorful/colors.go
generated
vendored
|
@ -48,6 +48,11 @@ func (col Color) RGB255() (r, g, b uint8) {
|
|||
return
|
||||
}
|
||||
|
||||
// Used to simplify HSLuv testing.
|
||||
func (col Color) values() (float64, float64, float64) {
|
||||
return col.R, col.G, col.B
|
||||
}
|
||||
|
||||
// This is the tolerance used when comparing colors using AlmostEqualRgb.
|
||||
const Delta = 1.0 / 255.0
|
||||
|
||||
|
@ -64,6 +69,7 @@ func (c Color) IsValid() bool {
|
|||
0.0 <= c.B && c.B <= 1.0
|
||||
}
|
||||
|
||||
// clamp01 clamps from 0 to 1.
|
||||
func clamp01(v float64) float64 {
|
||||
return math.Max(0.0, math.Min(v, 1.0))
|
||||
}
|
||||
|
@ -88,6 +94,15 @@ func (c1 Color) DistanceRgb(c2 Color) float64 {
|
|||
return math.Sqrt(sq(c1.R-c2.R) + sq(c1.G-c2.G) + sq(c1.B-c2.B))
|
||||
}
|
||||
|
||||
// DistanceLinearRGB computes the distance between two colors in linear RGB
|
||||
// space. This is not useful for measuring how humans perceive color, but
|
||||
// might be useful for other things, like dithering.
|
||||
func (c1 Color) DistanceLinearRGB(c2 Color) float64 {
|
||||
r1, g1, b1 := c1.LinearRgb()
|
||||
r2, g2, b2 := c2.LinearRgb()
|
||||
return math.Sqrt(sq(r1-r2) + sq(g1-g2) + sq(b1-b2))
|
||||
}
|
||||
|
||||
// Check for equality between colors within the tolerance Delta (1/255).
|
||||
func (c1 Color) AlmostEqualRgb(c2 Color) bool {
|
||||
return math.Abs(c1.R-c2.R)+
|
||||
|
@ -422,16 +437,16 @@ func FastLinearRgb(r, g, b float64) Color {
|
|||
|
||||
// XyzToLinearRgb converts from CIE XYZ-space to Linear RGB space.
|
||||
func XyzToLinearRgb(x, y, z float64) (r, g, b float64) {
|
||||
r = 3.2404542*x - 1.5371385*y - 0.4985314*z
|
||||
g = -0.9692660*x + 1.8760108*y + 0.0415560*z
|
||||
b = 0.0556434*x - 0.2040259*y + 1.0572252*z
|
||||
r = 3.2409699419045214*x - 1.5373831775700935*y - 0.49861076029300328*z
|
||||
g = -0.96924363628087983*x + 1.8759675015077207*y + 0.041555057407175613*z
|
||||
b = 0.055630079696993609*x - 0.20397695888897657*y + 1.0569715142428786*z
|
||||
return
|
||||
}
|
||||
|
||||
func LinearRgbToXyz(r, g, b float64) (x, y, z float64) {
|
||||
x = 0.4124564*r + 0.3575761*g + 0.1804375*b
|
||||
y = 0.2126729*r + 0.7151522*g + 0.0721750*b
|
||||
z = 0.0193339*r + 0.1191920*g + 0.9503041*b
|
||||
x = 0.41239079926595948*r + 0.35758433938387796*g + 0.18048078840183429*b
|
||||
y = 0.21263900587151036*r + 0.71516867876775593*g + 0.072192315360733715*b
|
||||
z = 0.019330818715591851*r + 0.11919477979462599*g + 0.95053215224966058*b
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -569,7 +584,7 @@ func (col Color) LabWhiteRef(wref [3]float64) (l, a, b float64) {
|
|||
|
||||
// Generates a color by using data given in CIE L*a*b* space using D65 as reference white.
|
||||
// WARNING: many combinations of `l`, `a`, and `b` values do not have corresponding
|
||||
// valid RGB values, check the FAQ in the README if you're unsure.
|
||||
// valid RGB values, check the FAQ in the README if you're unsure.
|
||||
func Lab(l, a, b float64) Color {
|
||||
return Xyz(LabToXyz(l, a, b))
|
||||
}
|
||||
|
@ -589,7 +604,7 @@ func (c1 Color) DistanceLab(c2 Color) float64 {
|
|||
return math.Sqrt(sq(l1-l2) + sq(a1-a2) + sq(b1-b2))
|
||||
}
|
||||
|
||||
// That's actually the same, but I don't want to break code.
|
||||
// DistanceCIE76 is the same as DistanceLab.
|
||||
func (c1 Color) DistanceCIE76(c2 Color) float64 {
|
||||
return c1.DistanceLab(c2)
|
||||
}
|
||||
|
@ -739,7 +754,7 @@ func XyzToLuv(x, y, z float64) (l, a, b float64) {
|
|||
|
||||
func XyzToLuvWhiteRef(x, y, z float64, wref [3]float64) (l, u, v float64) {
|
||||
if y/wref[1] <= 6.0/29.0*6.0/29.0*6.0/29.0 {
|
||||
l = y / wref[1] * 29.0 / 3.0 * 29.0 / 3.0 * 29.0 / 3.0
|
||||
l = y / wref[1] * (29.0 / 3.0 * 29.0 / 3.0 * 29.0 / 3.0) / 100.0
|
||||
} else {
|
||||
l = 1.16*math.Cbrt(y/wref[1]) - 0.16
|
||||
}
|
||||
|
@ -803,8 +818,8 @@ func (col Color) LuvWhiteRef(wref [3]float64) (l, u, v float64) {
|
|||
|
||||
// Generates a color by using data given in CIE L*u*v* space using D65 as reference white.
|
||||
// L* is in [0..1] and both u* and v* are in about [-1..1]
|
||||
// WARNING: many combinations of `l`, `a`, and `b` values do not have corresponding
|
||||
// valid RGB values, check the FAQ in the README if you're unsure.
|
||||
// WARNING: many combinations of `l`, `u`, and `v` values do not have corresponding
|
||||
// valid RGB values, check the FAQ in the README if you're unsure.
|
||||
func Luv(l, u, v float64) Color {
|
||||
return Xyz(LuvToXyz(l, u, v))
|
||||
}
|
||||
|
@ -870,8 +885,8 @@ func (col Color) HclWhiteRef(wref [3]float64) (h, c, l float64) {
|
|||
|
||||
// Generates a color by using data given in HCL space using D65 as reference white.
|
||||
// H values are in [0..360], C and L values are in [0..1]
|
||||
// WARNING: many combinations of `l`, `a`, and `b` values do not have corresponding
|
||||
// valid RGB values, check the FAQ in the README if you're unsure.
|
||||
// WARNING: many combinations of `h`, `c`, and `l` values do not have corresponding
|
||||
// valid RGB values, check the FAQ in the README if you're unsure.
|
||||
func Hcl(h, c, l float64) Color {
|
||||
return HclWhiteRef(h, c, l, D65)
|
||||
}
|
||||
|
@ -899,5 +914,66 @@ func (col1 Color) BlendHcl(col2 Color, t float64) Color {
|
|||
h2, c2, l2 := col2.Hcl()
|
||||
|
||||
// We know that h are both in [0..360]
|
||||
return Hcl(interp_angle(h1, h2, t), c1+t*(c2-c1), l1+t*(l2-l1))
|
||||
return Hcl(interp_angle(h1, h2, t), c1+t*(c2-c1), l1+t*(l2-l1)).Clamped()
|
||||
}
|
||||
|
||||
// LuvLch
|
||||
|
||||
// Converts the given color to LuvLCh space using D65 as reference white.
|
||||
// h values are in [0..360], C and L values are in [0..1] although C can overshoot 1.0
|
||||
func (col Color) LuvLCh() (l, c, h float64) {
|
||||
return col.LuvLChWhiteRef(D65)
|
||||
}
|
||||
|
||||
func LuvToLuvLCh(L, u, v float64) (l, c, h float64) {
|
||||
// Oops, floating point workaround necessary if u ~= v and both are very small (i.e. almost zero).
|
||||
if math.Abs(v-u) > 1e-4 && math.Abs(u) > 1e-4 {
|
||||
h = math.Mod(57.29577951308232087721*math.Atan2(v, u)+360.0, 360.0) // Rad2Deg
|
||||
} else {
|
||||
h = 0.0
|
||||
}
|
||||
l = L
|
||||
c = math.Sqrt(sq(u) + sq(v))
|
||||
return
|
||||
}
|
||||
|
||||
// Converts the given color to LuvLCh space, taking into account
|
||||
// a given reference white. (i.e. the monitor's white)
|
||||
// h values are in [0..360], c and l values are in [0..1]
|
||||
func (col Color) LuvLChWhiteRef(wref [3]float64) (l, c, h float64) {
|
||||
return LuvToLuvLCh(col.LuvWhiteRef(wref))
|
||||
}
|
||||
|
||||
// Generates a color by using data given in LuvLCh space using D65 as reference white.
|
||||
// h values are in [0..360], C and L values are in [0..1]
|
||||
// WARNING: many combinations of `l`, `c`, and `h` values do not have corresponding
|
||||
// valid RGB values, check the FAQ in the README if you're unsure.
|
||||
func LuvLCh(l, c, h float64) Color {
|
||||
return LuvLChWhiteRef(l, c, h, D65)
|
||||
}
|
||||
|
||||
func LuvLChToLuv(l, c, h float64) (L, u, v float64) {
|
||||
H := 0.01745329251994329576 * h // Deg2Rad
|
||||
u = c * math.Cos(H)
|
||||
v = c * math.Sin(H)
|
||||
L = l
|
||||
return
|
||||
}
|
||||
|
||||
// Generates a color by using data given in LuvLCh space, taking
|
||||
// into account a given reference white. (i.e. the monitor's white)
|
||||
// h values are in [0..360], C and L values are in [0..1]
|
||||
func LuvLChWhiteRef(l, c, h float64, wref [3]float64) Color {
|
||||
L, u, v := LuvLChToLuv(l, c, h)
|
||||
return LuvWhiteRef(L, u, v, wref)
|
||||
}
|
||||
|
||||
// BlendLuvLCh blends two colors in the cylindrical CIELUV color space.
|
||||
// t == 0 results in c1, t == 1 results in c2
|
||||
func (col1 Color) BlendLuvLCh(col2 Color, t float64) Color {
|
||||
l1, c1, h1 := col1.LuvLCh()
|
||||
l2, c2, h2 := col2.LuvLCh()
|
||||
|
||||
// We know that h are both in [0..360]
|
||||
return LuvLCh(l1+t*(l2-l1), c1+t*(c2-c1), interp_angle(h1, h2, t))
|
||||
}
|
||||
|
|
0
vendor/github.com/lucasb-eyer/go-colorful/go.sum
generated
vendored
0
vendor/github.com/lucasb-eyer/go-colorful/go.sum
generated
vendored
32
vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go
generated
vendored
32
vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go
generated
vendored
|
@ -2,12 +2,14 @@ package colorful
|
|||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// A HexColor is a Color stored as a hex string "#rrggbb". It implements the
|
||||
// database/sql.Scanner and database/sql/driver.Value interfaces.
|
||||
// database/sql.Scanner, database/sql/driver.Value,
|
||||
// encoding/json.Unmarshaler and encoding/json.Marshaler interfaces.
|
||||
type HexColor Color
|
||||
|
||||
type errUnsupportedType struct {
|
||||
|
@ -35,3 +37,31 @@ func (hc *HexColor) Value() (driver.Value, error) {
|
|||
func (e errUnsupportedType) Error() string {
|
||||
return fmt.Sprintf("unsupported type: got %v, want a %s", e.got, e.want)
|
||||
}
|
||||
|
||||
func (hc *HexColor) UnmarshalJSON(data []byte) error {
|
||||
var hexCode string
|
||||
if err := json.Unmarshal(data, &hexCode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var col, err = Hex(hexCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*hc = HexColor(col)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (hc HexColor) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(Color(hc).Hex())
|
||||
}
|
||||
|
||||
// Decode - deserialize function for https://github.com/kelseyhightower/envconfig
|
||||
func (hc *HexColor) Decode(hexCode string) error {
|
||||
var col, err = Hex(hexCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*hc = HexColor(col)
|
||||
return nil
|
||||
}
|
||||
|
|
1
vendor/github.com/lucasb-eyer/go-colorful/hsluv-snapshot-rev4.json
generated
vendored
Normal file
1
vendor/github.com/lucasb-eyer/go-colorful/hsluv-snapshot-rev4.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
207
vendor/github.com/lucasb-eyer/go-colorful/hsluv.go
generated
vendored
Normal file
207
vendor/github.com/lucasb-eyer/go-colorful/hsluv.go
generated
vendored
Normal file
|
@ -0,0 +1,207 @@
|
|||
package colorful
|
||||
|
||||
import "math"
|
||||
|
||||
// Source: https://github.com/hsluv/hsluv-go
|
||||
// Under MIT License
|
||||
// Modified so that Saturation and Luminance are in [0..1] instead of [0..100].
|
||||
|
||||
// HSLuv uses a rounded version of the D65. This has no impact on the final RGB
|
||||
// values, but to keep high levels of accuracy for internal operations and when
|
||||
// comparing to the test values, this modified white reference is used internally.
|
||||
//
|
||||
// See this GitHub thread for details on these values:
|
||||
// https://github.com/hsluv/hsluv/issues/79
|
||||
var hSLuvD65 = [3]float64{0.95045592705167, 1.0, 1.089057750759878}
|
||||
|
||||
func LuvLChToHSLuv(l, c, h float64) (float64, float64, float64) {
|
||||
// [-1..1] but the code expects it to be [-100..100]
|
||||
c *= 100.0
|
||||
l *= 100.0
|
||||
|
||||
var s, max float64
|
||||
if l > 99.9999999 || l < 0.00000001 {
|
||||
s = 0.0
|
||||
} else {
|
||||
max = maxChromaForLH(l, h)
|
||||
s = c / max * 100.0
|
||||
}
|
||||
return h, clamp01(s / 100.0), clamp01(l / 100.0)
|
||||
}
|
||||
|
||||
func HSLuvToLuvLCh(h, s, l float64) (float64, float64, float64) {
|
||||
l *= 100.0
|
||||
s *= 100.0
|
||||
|
||||
var c, max float64
|
||||
if l > 99.9999999 || l < 0.00000001 {
|
||||
c = 0.0
|
||||
} else {
|
||||
max = maxChromaForLH(l, h)
|
||||
c = max / 100.0 * s
|
||||
}
|
||||
|
||||
// c is [-100..100], but for LCh it's supposed to be almost [-1..1]
|
||||
return clamp01(l / 100.0), c / 100.0, h
|
||||
}
|
||||
|
||||
func LuvLChToHPLuv(l, c, h float64) (float64, float64, float64) {
|
||||
// [-1..1] but the code expects it to be [-100..100]
|
||||
c *= 100.0
|
||||
l *= 100.0
|
||||
|
||||
var s, max float64
|
||||
if l > 99.9999999 || l < 0.00000001 {
|
||||
s = 0.0
|
||||
} else {
|
||||
max = maxSafeChromaForL(l)
|
||||
s = c / max * 100.0
|
||||
}
|
||||
return h, s / 100.0, l / 100.0
|
||||
}
|
||||
|
||||
func HPLuvToLuvLCh(h, s, l float64) (float64, float64, float64) {
|
||||
// [-1..1] but the code expects it to be [-100..100]
|
||||
l *= 100.0
|
||||
s *= 100.0
|
||||
|
||||
var c, max float64
|
||||
if l > 99.9999999 || l < 0.00000001 {
|
||||
c = 0.0
|
||||
} else {
|
||||
max = maxSafeChromaForL(l)
|
||||
c = max / 100.0 * s
|
||||
}
|
||||
return l / 100.0, c / 100.0, h
|
||||
}
|
||||
|
||||
// HSLuv creates a new Color from values in the HSLuv color space.
|
||||
// Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1].
|
||||
//
|
||||
// The returned color values are clamped (using .Clamped), so this will never output
|
||||
// an invalid color.
|
||||
func HSLuv(h, s, l float64) Color {
|
||||
// HSLuv -> LuvLCh -> CIELUV -> CIEXYZ -> Linear RGB -> sRGB
|
||||
l, u, v := LuvLChToLuv(HSLuvToLuvLCh(h, s, l))
|
||||
return LinearRgb(XyzToLinearRgb(LuvToXyzWhiteRef(l, u, v, hSLuvD65))).Clamped()
|
||||
}
|
||||
|
||||
// HPLuv creates a new Color from values in the HPLuv color space.
|
||||
// Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1].
|
||||
//
|
||||
// The returned color values are clamped (using .Clamped), so this will never output
|
||||
// an invalid color.
|
||||
func HPLuv(h, s, l float64) Color {
|
||||
// HPLuv -> LuvLCh -> CIELUV -> CIEXYZ -> Linear RGB -> sRGB
|
||||
l, u, v := LuvLChToLuv(HPLuvToLuvLCh(h, s, l))
|
||||
return LinearRgb(XyzToLinearRgb(LuvToXyzWhiteRef(l, u, v, hSLuvD65))).Clamped()
|
||||
}
|
||||
|
||||
// HSLuv returns the Hue, Saturation and Luminance of the color in the HSLuv
|
||||
// color space. Hue in [0..360], a Saturation [0..1], and a Luminance
|
||||
// (lightness) in [0..1].
|
||||
func (col Color) HSLuv() (h, s, l float64) {
|
||||
// sRGB -> Linear RGB -> CIEXYZ -> CIELUV -> LuvLCh -> HSLuv
|
||||
return LuvLChToHSLuv(col.LuvLChWhiteRef(hSLuvD65))
|
||||
}
|
||||
|
||||
// HPLuv returns the Hue, Saturation and Luminance of the color in the HSLuv
|
||||
// color space. Hue in [0..360], a Saturation [0..1], and a Luminance
|
||||
// (lightness) in [0..1].
|
||||
//
|
||||
// Note that HPLuv can only represent pastel colors, and so the Saturation
|
||||
// value could be much larger than 1 for colors it can't represent.
|
||||
func (col Color) HPLuv() (h, s, l float64) {
|
||||
return LuvLChToHPLuv(col.LuvLChWhiteRef(hSLuvD65))
|
||||
}
|
||||
|
||||
// DistanceHSLuv calculates Euclidan distance in the HSLuv colorspace. No idea
|
||||
// how useful this is.
|
||||
//
|
||||
// The Hue value is divided by 100 before the calculation, so that H, S, and L
|
||||
// have the same relative ranges.
|
||||
func (c1 Color) DistanceHSLuv(c2 Color) float64 {
|
||||
h1, s1, l1 := c1.HSLuv()
|
||||
h2, s2, l2 := c2.HSLuv()
|
||||
return math.Sqrt(sq((h1-h2)/100.0) + sq(s1-s2) + sq(l1-l2))
|
||||
}
|
||||
|
||||
// DistanceHPLuv calculates Euclidean distance in the HPLuv colorspace. No idea
|
||||
// how useful this is.
|
||||
//
|
||||
// The Hue value is divided by 100 before the calculation, so that H, S, and L
|
||||
// have the same relative ranges.
|
||||
func (c1 Color) DistanceHPLuv(c2 Color) float64 {
|
||||
h1, s1, l1 := c1.HPLuv()
|
||||
h2, s2, l2 := c2.HPLuv()
|
||||
return math.Sqrt(sq((h1-h2)/100.0) + sq(s1-s2) + sq(l1-l2))
|
||||
}
|
||||
|
||||
var m = [3][3]float64{
|
||||
{3.2409699419045214, -1.5373831775700935, -0.49861076029300328},
|
||||
{-0.96924363628087983, 1.8759675015077207, 0.041555057407175613},
|
||||
{0.055630079696993609, -0.20397695888897657, 1.0569715142428786},
|
||||
}
|
||||
|
||||
const kappa = 903.2962962962963
|
||||
const epsilon = 0.0088564516790356308
|
||||
|
||||
func maxChromaForLH(l, h float64) float64 {
|
||||
hRad := h / 360.0 * math.Pi * 2.0
|
||||
minLength := math.MaxFloat64
|
||||
for _, line := range getBounds(l) {
|
||||
length := lengthOfRayUntilIntersect(hRad, line[0], line[1])
|
||||
if length > 0.0 && length < minLength {
|
||||
minLength = length
|
||||
}
|
||||
}
|
||||
return minLength
|
||||
}
|
||||
|
||||
func getBounds(l float64) [6][2]float64 {
|
||||
var sub2 float64
|
||||
var ret [6][2]float64
|
||||
sub1 := math.Pow(l+16.0, 3.0) / 1560896.0
|
||||
if sub1 > epsilon {
|
||||
sub2 = sub1
|
||||
} else {
|
||||
sub2 = l / kappa
|
||||
}
|
||||
for i := range m {
|
||||
for k := 0; k < 2; k++ {
|
||||
top1 := (284517.0*m[i][0] - 94839.0*m[i][2]) * sub2
|
||||
top2 := (838422.0*m[i][2]+769860.0*m[i][1]+731718.0*m[i][0])*l*sub2 - 769860.0*float64(k)*l
|
||||
bottom := (632260.0*m[i][2]-126452.0*m[i][1])*sub2 + 126452.0*float64(k)
|
||||
ret[i*2+k][0] = top1 / bottom
|
||||
ret[i*2+k][1] = top2 / bottom
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func lengthOfRayUntilIntersect(theta, x, y float64) (length float64) {
|
||||
length = y / (math.Sin(theta) - x*math.Cos(theta))
|
||||
return
|
||||
}
|
||||
|
||||
func maxSafeChromaForL(l float64) float64 {
|
||||
minLength := math.MaxFloat64
|
||||
for _, line := range getBounds(l) {
|
||||
m1 := line[0]
|
||||
b1 := line[1]
|
||||
x := intersectLineLine(m1, b1, -1.0/m1, 0.0)
|
||||
dist := distanceFromPole(x, b1+x*m1)
|
||||
if dist < minLength {
|
||||
minLength = dist
|
||||
}
|
||||
}
|
||||
return minLength
|
||||
}
|
||||
|
||||
func intersectLineLine(x1, y1, x2, y2 float64) float64 {
|
||||
return (y1 - y2) / (x2 - x1)
|
||||
}
|
||||
|
||||
func distanceFromPole(x, y float64) float64 {
|
||||
return math.Sqrt(math.Pow(x, 2.0) + math.Pow(y, 2.0))
|
||||
}
|
2
vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go
generated
vendored
2
vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go
generated
vendored
|
@ -61,7 +61,7 @@ func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, erro
|
|||
|
||||
// That would cause some infinite loops down there...
|
||||
if len(samples) < colorsCount {
|
||||
return nil, fmt.Errorf("palettegen: more colors requested (%v) than samples available (%v). Your requested color count may be wrong, you might want to use many samples or your constraint function makes the valid color space too small.", colorsCount, len(samples))
|
||||
return nil, fmt.Errorf("palettegen: more colors requested (%v) than samples available (%v). Your requested color count may be wrong, you might want to use many samples or your constraint function makes the valid color space too small", colorsCount, len(samples))
|
||||
} else if len(samples) == colorsCount {
|
||||
return labs2cols(samples), nil // Oops?
|
||||
}
|
||||
|
|
2
vendor/github.com/mattn/go-runewidth/go.mod
generated
vendored
2
vendor/github.com/mattn/go-runewidth/go.mod
generated
vendored
|
@ -1,3 +1,5 @@
|
|||
module github.com/mattn/go-runewidth
|
||||
|
||||
go 1.9
|
||||
|
||||
require github.com/rivo/uniseg v0.1.0
|
||||
|
|
2
vendor/github.com/mattn/go-runewidth/go.sum
generated
vendored
Normal file
2
vendor/github.com/mattn/go-runewidth/go.sum
generated
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
80
vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
80
vendor/github.com/mattn/go-runewidth/runewidth.go
generated
vendored
|
@ -2,6 +2,8 @@ package runewidth
|
|||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/rivo/uniseg"
|
||||
)
|
||||
|
||||
//go:generate go run script/generate.go
|
||||
|
@ -10,9 +12,6 @@ var (
|
|||
// EastAsianWidth will be set true if the current locale is CJK
|
||||
EastAsianWidth bool
|
||||
|
||||
// ZeroWidthJoiner is flag to set to use UTR#51 ZWJ
|
||||
ZeroWidthJoiner bool
|
||||
|
||||
// DefaultCondition is a condition in current locale
|
||||
DefaultCondition = &Condition{}
|
||||
)
|
||||
|
@ -30,7 +29,6 @@ func handleEnv() {
|
|||
}
|
||||
// update DefaultCondition
|
||||
DefaultCondition.EastAsianWidth = EastAsianWidth
|
||||
DefaultCondition.ZeroWidthJoiner = ZeroWidthJoiner
|
||||
}
|
||||
|
||||
type interval struct {
|
||||
|
@ -85,15 +83,13 @@ var nonprint = table{
|
|||
|
||||
// Condition have flag EastAsianWidth whether the current locale is CJK or not.
|
||||
type Condition struct {
|
||||
EastAsianWidth bool
|
||||
ZeroWidthJoiner bool
|
||||
EastAsianWidth bool
|
||||
}
|
||||
|
||||
// NewCondition return new instance of Condition which is current locale.
|
||||
func NewCondition() *Condition {
|
||||
return &Condition{
|
||||
EastAsianWidth: EastAsianWidth,
|
||||
ZeroWidthJoiner: ZeroWidthJoiner,
|
||||
EastAsianWidth: EastAsianWidth,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,38 +106,20 @@ func (c *Condition) RuneWidth(r rune) int {
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Condition) stringWidth(s string) (width int) {
|
||||
for _, r := range []rune(s) {
|
||||
width += c.RuneWidth(r)
|
||||
}
|
||||
return width
|
||||
}
|
||||
|
||||
func (c *Condition) stringWidthZeroJoiner(s string) (width int) {
|
||||
r1, r2 := rune(0), rune(0)
|
||||
for _, r := range []rune(s) {
|
||||
if r == 0xFE0E || r == 0xFE0F {
|
||||
continue
|
||||
}
|
||||
w := c.RuneWidth(r)
|
||||
if r2 == 0x200D && inTables(r, emoji) && inTables(r1, emoji) {
|
||||
if width < w {
|
||||
width = w
|
||||
}
|
||||
} else {
|
||||
width += w
|
||||
}
|
||||
r1, r2 = r2, r
|
||||
}
|
||||
return width
|
||||
}
|
||||
|
||||
// StringWidth return width as you can see
|
||||
func (c *Condition) StringWidth(s string) (width int) {
|
||||
if c.ZeroWidthJoiner {
|
||||
return c.stringWidthZeroJoiner(s)
|
||||
g := uniseg.NewGraphemes(s)
|
||||
for g.Next() {
|
||||
var chWidth int
|
||||
for _, r := range g.Runes() {
|
||||
chWidth = c.RuneWidth(r)
|
||||
if chWidth > 0 {
|
||||
break // Our best guess at this point is to use the width of the first non-zero-width rune.
|
||||
}
|
||||
}
|
||||
width += chWidth
|
||||
}
|
||||
return c.stringWidth(s)
|
||||
return
|
||||
}
|
||||
|
||||
// Truncate return string truncated with w cells
|
||||
|
@ -149,19 +127,25 @@ func (c *Condition) Truncate(s string, w int, tail string) string {
|
|||
if c.StringWidth(s) <= w {
|
||||
return s
|
||||
}
|
||||
r := []rune(s)
|
||||
tw := c.StringWidth(tail)
|
||||
w -= tw
|
||||
width := 0
|
||||
i := 0
|
||||
for ; i < len(r); i++ {
|
||||
cw := c.RuneWidth(r[i])
|
||||
if width+cw > w {
|
||||
w -= c.StringWidth(tail)
|
||||
var width int
|
||||
pos := len(s)
|
||||
g := uniseg.NewGraphemes(s)
|
||||
for g.Next() {
|
||||
var chWidth int
|
||||
for _, r := range g.Runes() {
|
||||
chWidth = c.RuneWidth(r)
|
||||
if chWidth > 0 {
|
||||
break // See StringWidth() for details.
|
||||
}
|
||||
}
|
||||
if width+chWidth > w {
|
||||
pos, _ = g.Positions()
|
||||
break
|
||||
}
|
||||
width += cw
|
||||
width += chWidth
|
||||
}
|
||||
return string(r[0:i]) + tail
|
||||
return s[:pos] + tail
|
||||
}
|
||||
|
||||
// Wrap return string wrapped with w cells
|
||||
|
@ -169,7 +153,7 @@ func (c *Condition) Wrap(s string, w int) string {
|
|||
width := 0
|
||||
out := ""
|
||||
for _, r := range []rune(s) {
|
||||
cw := RuneWidth(r)
|
||||
cw := c.RuneWidth(r)
|
||||
if r == '\n' {
|
||||
out += string(r)
|
||||
width = 0
|
||||
|
|
14
vendor/github.com/olekukonko/tablewriter/.travis.yml
generated
vendored
14
vendor/github.com/olekukonko/tablewriter/.travis.yml
generated
vendored
|
@ -1,8 +1,8 @@
|
|||
language: go
|
||||
|
||||
arch:
|
||||
- ppc64le
|
||||
- amd64
|
||||
go:
|
||||
- 1.1
|
||||
- 1.2
|
||||
- 1.3
|
||||
- 1.4
|
||||
- 1.5
|
||||
|
@ -12,3 +12,11 @@ go:
|
|||
- 1.9
|
||||
- "1.10"
|
||||
- tip
|
||||
jobs:
|
||||
exclude :
|
||||
- arch : ppc64le
|
||||
go :
|
||||
- 1.3
|
||||
- arch : ppc64le
|
||||
go :
|
||||
- 1.4
|
||||
|
|
47
vendor/github.com/olekukonko/tablewriter/README.md
generated
vendored
47
vendor/github.com/olekukonko/tablewriter/README.md
generated
vendored
|
@ -25,7 +25,7 @@ Generate ASCII table on the fly ... Installation is simple as
|
|||
- Set custom footer support
|
||||
- Optional identical cells merging
|
||||
- Set custom caption
|
||||
- Optional reflowing of paragrpahs in multi-line cells.
|
||||
- Optional reflowing of paragraphs in multi-line cells.
|
||||
|
||||
#### Example 1 - Basic
|
||||
```go
|
||||
|
@ -197,6 +197,41 @@ table.Render()
|
|||
+----------+--------------------------+-------+---------+
|
||||
```
|
||||
|
||||
#### Example 7 - Identical cells merging (specify the column index to merge)
|
||||
```go
|
||||
data := [][]string{
|
||||
[]string{"1/1/2014", "Domain name", "1234", "$10.98"},
|
||||
[]string{"1/1/2014", "January Hosting", "1234", "$10.98"},
|
||||
[]string{"1/4/2014", "February Hosting", "3456", "$51.00"},
|
||||
[]string{"1/4/2014", "February Extra Bandwidth", "4567", "$30.00"},
|
||||
}
|
||||
|
||||
table := tablewriter.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Date", "Description", "CV2", "Amount"})
|
||||
table.SetFooter([]string{"", "", "Total", "$146.93"})
|
||||
table.SetAutoMergeCellsByColumnIndex([]int{2, 3})
|
||||
table.SetRowLine(true)
|
||||
table.AppendBulk(data)
|
||||
table.Render()
|
||||
```
|
||||
|
||||
##### Output 7
|
||||
```
|
||||
+----------+--------------------------+-------+---------+
|
||||
| DATE | DESCRIPTION | CV2 | AMOUNT |
|
||||
+----------+--------------------------+-------+---------+
|
||||
| 1/1/2014 | Domain name | 1234 | $10.98 |
|
||||
+----------+--------------------------+ + +
|
||||
| 1/1/2014 | January Hosting | | |
|
||||
+----------+--------------------------+-------+---------+
|
||||
| 1/4/2014 | February Hosting | 3456 | $51.00 |
|
||||
+----------+--------------------------+-------+---------+
|
||||
| 1/4/2014 | February Extra Bandwidth | 4567 | $30.00 |
|
||||
+----------+--------------------------+-------+---------+
|
||||
| TOTAL | $146.93 |
|
||||
+----------+--------------------------+-------+---------+
|
||||
```
|
||||
|
||||
|
||||
#### Table with color
|
||||
```go
|
||||
|
@ -233,7 +268,7 @@ table.Render()
|
|||
#### Table with color Output
|
||||
![Table with Color](https://cloud.githubusercontent.com/assets/6460392/21101956/bbc7b356-c0a1-11e6-9f36-dba694746efc.png)
|
||||
|
||||
#### Example - 7 Table Cells with Color
|
||||
#### Example - 8 Table Cells with Color
|
||||
|
||||
Individual Cell Colors from `func Rich` take precedence over Column Colors
|
||||
|
||||
|
@ -289,7 +324,7 @@ table.Render()
|
|||
##### Table cells with color Output
|
||||
![Table cells with Color](https://user-images.githubusercontent.com/9064687/63969376-bcd88d80-ca6f-11e9-9466-c3d954700b25.png)
|
||||
|
||||
#### Example 8 - Set table caption
|
||||
#### Example 9 - Set table caption
|
||||
```go
|
||||
data := [][]string{
|
||||
[]string{"A", "The Good", "500"},
|
||||
|
@ -310,7 +345,7 @@ table.Render() // Send output
|
|||
|
||||
Note: Caption text will wrap with total width of rendered table.
|
||||
|
||||
##### Output 7
|
||||
##### Output 9
|
||||
```
|
||||
+------+-----------------------+--------+
|
||||
| NAME | SIGN | RATING |
|
||||
|
@ -323,7 +358,7 @@ Note: Caption text will wrap with total width of rendered table.
|
|||
Movie ratings.
|
||||
```
|
||||
|
||||
#### Example 8 - Set NoWhiteSpace and TablePadding option
|
||||
#### Example 10 - Set NoWhiteSpace and TablePadding option
|
||||
```go
|
||||
data := [][]string{
|
||||
{"node1.example.com", "Ready", "compute", "1.11"},
|
||||
|
@ -349,7 +384,7 @@ table.AppendBulk(data) // Add Bulk Data
|
|||
table.Render()
|
||||
```
|
||||
|
||||
##### Output 8
|
||||
##### Output 10
|
||||
```
|
||||
NAME STATUS ROLE VERSION
|
||||
node1.example.com Ready compute 1.11
|
||||
|
|
2
vendor/github.com/olekukonko/tablewriter/go.mod
generated
vendored
2
vendor/github.com/olekukonko/tablewriter/go.mod
generated
vendored
|
@ -2,4 +2,4 @@ module github.com/olekukonko/tablewriter
|
|||
|
||||
go 1.12
|
||||
|
||||
require github.com/mattn/go-runewidth v0.0.7
|
||||
require github.com/mattn/go-runewidth v0.0.9
|
||||
|
|
4
vendor/github.com/olekukonko/tablewriter/go.sum
generated
vendored
4
vendor/github.com/olekukonko/tablewriter/go.sum
generated
vendored
|
@ -1,2 +1,2 @@
|
|||
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
|
|
94
vendor/github.com/olekukonko/tablewriter/table.go
generated
vendored
94
vendor/github.com/olekukonko/tablewriter/table.go
generated
vendored
|
@ -48,39 +48,40 @@ type Border struct {
|
|||
}
|
||||
|
||||
type Table struct {
|
||||
out io.Writer
|
||||
rows [][]string
|
||||
lines [][][]string
|
||||
cs map[int]int
|
||||
rs map[int]int
|
||||
headers [][]string
|
||||
footers [][]string
|
||||
caption bool
|
||||
captionText string
|
||||
autoFmt bool
|
||||
autoWrap bool
|
||||
reflowText bool
|
||||
mW int
|
||||
pCenter string
|
||||
pRow string
|
||||
pColumn string
|
||||
tColumn int
|
||||
tRow int
|
||||
hAlign int
|
||||
fAlign int
|
||||
align int
|
||||
newLine string
|
||||
rowLine bool
|
||||
autoMergeCells bool
|
||||
noWhiteSpace bool
|
||||
tablePadding string
|
||||
hdrLine bool
|
||||
borders Border
|
||||
colSize int
|
||||
headerParams []string
|
||||
columnsParams []string
|
||||
footerParams []string
|
||||
columnsAlign []int
|
||||
out io.Writer
|
||||
rows [][]string
|
||||
lines [][][]string
|
||||
cs map[int]int
|
||||
rs map[int]int
|
||||
headers [][]string
|
||||
footers [][]string
|
||||
caption bool
|
||||
captionText string
|
||||
autoFmt bool
|
||||
autoWrap bool
|
||||
reflowText bool
|
||||
mW int
|
||||
pCenter string
|
||||
pRow string
|
||||
pColumn string
|
||||
tColumn int
|
||||
tRow int
|
||||
hAlign int
|
||||
fAlign int
|
||||
align int
|
||||
newLine string
|
||||
rowLine bool
|
||||
autoMergeCells bool
|
||||
columnsToAutoMergeCells map[int]bool
|
||||
noWhiteSpace bool
|
||||
tablePadding string
|
||||
hdrLine bool
|
||||
borders Border
|
||||
colSize int
|
||||
headerParams []string
|
||||
columnsParams []string
|
||||
footerParams []string
|
||||
columnsAlign []int
|
||||
}
|
||||
|
||||
// Start New Table
|
||||
|
@ -276,6 +277,21 @@ func (t *Table) SetAutoMergeCells(auto bool) {
|
|||
t.autoMergeCells = auto
|
||||
}
|
||||
|
||||
// Set Auto Merge Cells By Column Index
|
||||
// This would enable / disable the merge of cells with identical values for specific columns
|
||||
// If cols is empty, it is the same as `SetAutoMergeCells(true)`.
|
||||
func (t *Table) SetAutoMergeCellsByColumnIndex(cols []int) {
|
||||
t.autoMergeCells = true
|
||||
|
||||
if len(cols) > 0 {
|
||||
m := make(map[int]bool)
|
||||
for _, col := range cols {
|
||||
m[col] = true
|
||||
}
|
||||
t.columnsToAutoMergeCells = m
|
||||
}
|
||||
}
|
||||
|
||||
// Set Table Border
|
||||
// This would enable / disable line around the table
|
||||
func (t *Table) SetBorder(border bool) {
|
||||
|
@ -830,9 +846,19 @@ func (t *Table) printRowMergeCells(writer io.Writer, columns [][]string, rowIdx
|
|||
}
|
||||
|
||||
if t.autoMergeCells {
|
||||
var mergeCell bool
|
||||
if t.columnsToAutoMergeCells != nil {
|
||||
// Check to see if the column index is in columnsToAutoMergeCells.
|
||||
if t.columnsToAutoMergeCells[y] {
|
||||
mergeCell = true
|
||||
}
|
||||
} else {
|
||||
// columnsToAutoMergeCells was not set.
|
||||
mergeCell = true
|
||||
}
|
||||
//Store the full line to merge mutli-lines cells
|
||||
fullLine := strings.TrimRight(strings.Join(columns[y], " "), " ")
|
||||
if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" {
|
||||
if len(previousLine) > y && fullLine == previousLine[y] && fullLine != "" && mergeCell {
|
||||
// If this cell is identical to the one above but not empty, we don't display the border and keep the cell empty.
|
||||
displayCellBorder = append(displayCellBorder, false)
|
||||
str = ""
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user