21 Commits

Author SHA1 Message Date
8372dad929 Changelog v0.4.1 (#176)
Changelog v0.4.1

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/176
Reviewed-by: Andrew Thornton <art27@cantab.net>
Reviewed-by: Gary Kim <gary@garykim.dev>
2020-09-13 21:48:36 +00:00
edd180a8f5 Fix notification: --all dont relay on a repo (#159)
fix nil pointer exeption

make notifications work outside a repo

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/159
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: mrsdizzie <info@mrsdizzie.com>
2020-07-20 03:09:34 +00:00
a979df1070 Changelog v0.4.0 (#157)
Changelog for v0.4.0

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/157
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: appleboy <appleboy.tw@gmail.com>
2020-07-18 10:57:18 +00:00
08a9a9a8ab Bugfixes for initCommand (#156)
respect --login parameter again

🚀

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/156
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: Andrew Thornton <art27@cantab.net>
2020-07-18 10:43:56 +00:00
2135af0304 Fix Login Detection By Repo Param (#151)
Fix login detection by Repo param

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/151
Reviewed-by: lafriks <lafriks@noreply.gitea.io>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
2020-07-17 16:36:48 +00:00
19ee32168e Add notifications subcomand (#148)
rm Aliase news for now

show read notifications not supported jet

add notifications subcomand

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/148
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: mrsdizzie <info@mrsdizzie.com>
2020-07-17 15:30:02 +00:00
12ea1ad35c Subcomand Login Show List By Default (#152)
tea login list by default

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/152
Reviewed-by: techknowlogick <techknowlogick@gitea.io>
Reviewed-by: lafriks <lafriks@noreply.gitea.io>
2020-07-17 07:16:38 +00:00
3a382e73b1 Fix Login List Output (#150)
fix output

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/150
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: techknowlogick <techknowlogick@gitea.io>
2020-07-16 16:12:22 +00:00
f1801f39a6 Add subcomand 'pulls create' (#144)
wordings

print pull URL

change title required mesage

inform User on push error

fix body

🚀

finish

impruve

fix help menue of pull create

refactor

Add pull-request command

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: Sandro Santilli <strk@kbt.io>
Reviewed-on: https://gitea.com/gitea/tea/pulls/144
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: lafriks <lafriks@noreply.gitea.io>
2020-07-16 15:00:51 +00:00
66947bcf09 Update Vendors (#145)
vendor

go update vendors

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/145
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: techknowlogick <techknowlogick@gitea.io>
2020-07-13 22:38:05 +00:00
85e1244db8 Add note for alpine/arch-linux package (#143)
add note for archlinux TEA package

add note for alpine linux TEA package

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/143
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: techknowlogick <techknowlogick@gitea.io>
2020-07-05 18:36:21 +00:00
618eeb9029 Add Changelog for v0.3.1 (#139) (#140)
Add Changelog for v0.3.1 (#139)

Add Changelog for v0.3.1

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/139
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>

Reviewed-on: https://gitea.com/gitea/tea/pulls/140
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: John Olheiser <john.olheiser@gmail.com>
2020-06-15 20:17:45 +00:00
b2efb45f64 --ssh-key should be string not bool (#135)
--ssh-key should be string not bool

Fix #134

Reviewed-on: https://gitea.com/gitea/tea/pulls/135
Reviewed-by: 6543 <6543@noreply.gitea.io>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
2020-06-12 02:43:55 +00:00
59fe58577a Migrate gitea-sdk to v0.12.0 (#133)
Migrate

Update code.gitea.io/sdk/gitea to v0.12.0.

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/133
Reviewed-by: Andrew Thornton <art27@cantab.net>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
2020-05-27 13:48:09 +00:00
3c312cb409 Update Vendors: (#129)
* github.com/araddon/dateparse upgrade => v0.0.0-20200409225146-d820a6159ab1
* code.gitea.io/sdk/gitea upgrade => v0.11.3
* github.com/olekukonko/tablewriter upgrade => v0.0.4
* github.com/mattn/go-runewidth upgrade => v0.0.9
* github.com/stretchr/testify upgrade => v1.5.1
* github.com/davecgh/go-spew upgrade => v1.1.1
* github.com/urfave/cli/v2 upgrade => v2.2.0

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/129
Reviewed-by: techknowlogick <techknowlogick@gitea.io>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
2020-04-30 10:54:11 +00:00
6cff3b1cc7 migrate src-d/go-git -> go-git/go-git (#128)
Merge branch 'master' into vendor-migrate-go-git

Merge branch 'master' into vendor-migrate-go-git

migrate src-d/go-git -> go-git/go-git

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/128
Reviewed-by: techknowlogick <techknowlogick@gitea.io>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
2020-04-30 02:02:15 +00:00
4b059770ea Add gitea-vet (#121)
Close #119

Co-authored-by: 6543 <6543@obermui.de>
Co-authored-by: jolheiser <john.olheiser@gmail.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/121
Reviewed-by: John Olheiser <john.olheiser@gmail.com>
Reviewed-by: Andrew Thornton <art27@cantab.net>
2020-04-28 13:02:21 +00:00
a35fcb682b migrate yaml lib (#130)
vendor

migrate imports

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/130
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
Reviewed-by: techknowlogick <techknowlogick@gitea.io>
2020-04-28 03:39:36 +00:00
8bbeeae327 Update Readme & add demo GIF (#125)
add suggestions from reviews & remove alias from subcomand list

gif is now on cdn & add review suggestion

Add ICON & Name

update description & co

add demo gif

fix newline becaues of new markdown roule

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/125
Reviewed-by: lafriks <lafriks@noreply.gitea.io>
Reviewed-by: Gary Kim <gary@garykim.dev>
2020-04-25 12:04:05 +00:00
35ad046d8d modules/git: fix dropped error (#127)
modules/git: fix dropped error

Co-authored-by: Lars Lehtonen <lars.lehtonen@gmail.com>
Reviewed-on: https://gitea.com/gitea/tea/pulls/127
Reviewed-by: 6543 <6543@noreply.gitea.io>
Reviewed-by: Lunny Xiao <xiaolunwen@gmail.com>
2020-04-25 02:35:22 +00:00
e9dee07459 Issues details: add missing newline (#126)
add missing newline

Co-authored-by: 6543 <6543@obermui.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/126
Reviewed-by: techknowlogick <techknowlogick@gitea.io>
Reviewed-by: mrsdizzie <info@mrsdizzie.com>
2020-04-23 00:28:54 +00:00
685 changed files with 35521 additions and 101997 deletions

2
.gitignore vendored
View File

@ -1,4 +1,6 @@
tea tea
/gitea-vet
.idea/ .idea/
.history/ .history/
dist/ dist/

View File

@ -1,5 +1,34 @@
# Changelog # Changelog
## [v0.4.1](https://gitea.com/gitea/tea/releases/tag/v0.4.1) - 2020-09-13
* BUGFIXES
* Notification don't relay on a repo (#159)
## [v0.4.0](https://gitea.com/gitea/tea/pulls?q=&type=all&state=closed&milestone=1264) - 2020-07-18
* FEATURES
* Add notifications subcomand (#148)
* Add subcomand 'pulls create' (#144)
* BUGFIXES
* Fix Login Detection By Repo Param (#151)
* Fix Login List Output (#150)
* Fix --ssh-key Option (#135)
* ENHANCEMENTS
* Subcomand Login Show List By Default (#152)
* BUILD
* Migrate src-d/go-git to go-git/go-git (#128)
* Migrate gitea-sdk to v0.12.0 (#133)
* Migrate yaml lib (#130)
* Add gitea-vet (#121)
## [v0.3.1](https://gitea.com/gitea/tea/pulls?q=&type=all&state=closed&milestone=1265) - 2020-06-15
* BUGFIXES
* --ssh-key should be string not bool (#135) (#137)
* modules/git: fix dropped error (#127)
* Issues details: add missing newline (#126)
## [v0.3.0](https://gitea.com/gitea/tea/pulls?q=&type=all&state=closed&milestone=1227) - 2020-04-22 ## [v0.3.0](https://gitea.com/gitea/tea/pulls?q=&type=all&state=closed&milestone=1227) - 2020-04-22
* FEATURES * FEATURES

View File

@ -68,7 +68,11 @@ fmt:
.PHONY: vet .PHONY: vet
vet: vet:
# Default vet
$(GO) vet -mod=vendor $(PACKAGES) $(GO) vet -mod=vendor $(PACKAGES)
# Custom vet
$(GO) build -mod=vendor gitea.com/jolheiser/gitea-vet
$(GO) vet -vettool=gitea-vet $(PACKAGES)
.PHONY: lint .PHONY: lint
lint: lint:

View File

@ -1,38 +1,35 @@
# Gitea Command Line Tool for Go # <img alt='' src='https://gitea.com/repo-avatars/550-80a3a8c2ab0e2c2d69f296b7f8582485' height="40"/> *T E A*
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![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)
[![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)
This project acts as a command line tool for operating one or multiple Gitea instances. It depends on [code.gitea.io/sdk](https://code.gitea.io/sdk) client SDK implementation written in Go to interact with ## The official CLI interface for gitea
the Gitea API implementation.
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](https://dl.gitea.io/screenshots/tea_demo.gif)
## Installation ## Installation
Currently no prebuilt binaries are provided. You can use the prebuilt binaries from [dl.gitea.io](https://dl.gitea.io/tea/)
To install, a Go installation is needed.
To install from source, go 1.12 or newer is required:
```sh ```sh
go get code.gitea.io/tea go get code.gitea.io/tea
go install code.gitea.io/tea go install code.gitea.io/tea
``` ```
If the `tea` executable is not found, you might need to set up your `$GOPATH` and `$PATH` variables first:
```sh If you have `brew` installed, you can install `tea` via:
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
```
If you have `brew` installed, you can install tea version via:
```sh ```sh
brew tap gitea/tap https://gitea.com/gitea/homebrew-gitea brew tap gitea/tap https://gitea.com/gitea/homebrew-gitea
brew install --devel tea 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))**
## Usage ## Usage
First of all, you have to create a token on your `personal settings -> application` page of your gitea instance. First of all, you have to create a token on your `personal settings -> application` page of your gitea instance.
@ -42,23 +39,32 @@ Use this token to login with `tea`:
tea login add --name=try --url=https://try.gitea.io --token=xxxxxx tea login add --name=try --url=https://try.gitea.io --token=xxxxxx
``` ```
Now you can use the `tea` commands: Now you can use the following `tea` subcommands.
Detailed usage information is available via `tea <command> --help`.
```sh ```sh
tea issues login Log in to a Gitea server
tea releases logout Log out from a Gitea server
issues List, create and update issues
pulls List, checkout and clean pull requests
releases Create 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
``` ```
To fetch issues from different repos, use the `--remote` flag (when inside a gitea repository directory) or `--login` & `--repo` flags. To fetch issues from different repos, use the `--remote` flag (when inside a gitea repository directory) or `--login` & `--repo` flags.
## Compilation ## Compilation
Make sure you have installed a current go version.
To compile the sources yourself run the following: To compile the sources yourself run the following:
```sh ```sh
go get code.gitea.io/tea git clone https://gitea.com/gitea/tea.git
cd "${GOPATH}/src/code.gitea.io/tea" cd tea
go build make
``` ```
## Contributing ## Contributing

14
build.go Normal file
View File

@ -0,0 +1,14 @@
// 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.
//+build vendor
package main
// Libraries that are included to vendor utilities used during build.
// These libraries will not be included in a normal compilation.
import (
// for vet
_ "gitea.com/jolheiser/gitea-vet"
)

View File

@ -21,7 +21,7 @@ import (
"code.gitea.io/tea/modules/git" "code.gitea.io/tea/modules/git"
"code.gitea.io/tea/modules/utils" "code.gitea.io/tea/modules/utils"
"github.com/go-gitea/yaml" "gopkg.in/yaml.v2"
) )
// Login represents a login to a gitea server, you even could add multiple logins for one gitea server // Login represents a login to a gitea server, you even could add multiple logins for one gitea server
@ -189,10 +189,16 @@ func saveConfig(ymlPath string) error {
return ioutil.WriteFile(ymlPath, bs, 0660) return ioutil.WriteFile(ymlPath, bs, 0660)
} }
func curGitRepoPath() (*Login, string, error) { func curGitRepoPath(path string) (*Login, string, error) {
repo, err := git.RepoForWorkdir() var err error
var repo *git.TeaRepo
if len(path) == 0 {
repo, err = git.RepoForWorkdir()
} else {
repo, err = git.RepoFromPath(path)
}
if err != nil { if err != nil {
return nil, "", errors.New("No Gitea login found") return nil, "", err
} }
gitConfig, err := repo.Config() gitConfig, err := repo.Config()
if err != nil { if err != nil {

View File

@ -81,15 +81,21 @@ var AllDefaultFlags = append([]cli.Flag{
// initCommand returns repository and *Login based on flags // initCommand returns repository and *Login based on flags
func initCommand() (*Login, string, string) { func initCommand() (*Login, string, string) {
login := initCommandLoginOnly() err := loadConfig(yamlConfigPath)
if err != nil {
log.Fatal("load config file failed ", yamlConfigPath)
}
var err error login, repoPath, err := curGitRepoPath(repoValue)
repoPath := repoValue
if repoPath == "" {
login, repoPath, err = curGitRepoPath()
if err != nil { if err != nil {
log.Fatal(err.Error()) log.Fatal(err.Error())
} }
if loginValue != "" {
login = getLoginByName(loginValue)
if login == nil {
log.Fatal("Login name " + loginValue + " does not exist")
}
} }
owner, repo := splitRepo(repoPath) owner, repo := splitRepo(repoPath)

View File

@ -64,7 +64,7 @@ func runIssueDetail(ctx *cli.Context, index string) error {
return err return err
} }
fmt.Printf("#%d %s\n%s created %s\n\n%s", issue.Index, fmt.Printf("#%d %s\n%s created %s\n\n%s\n", issue.Index,
issue.Title, issue.Title,
issue.Poster.UserName, issue.Poster.UserName,
issue.Created.Format("2006-01-02 15:04:05"), issue.Created.Format("2006-01-02 15:04:05"),
@ -87,8 +87,7 @@ func runIssuesList(ctx *cli.Context) error {
} }
issues, err := login.Client().ListRepoIssues(owner, repo, gitea.ListIssueOption{ issues, err := login.Client().ListRepoIssues(owner, repo, gitea.ListIssueOption{
Page: 0, State: state,
State: string(state),
Type: gitea.IssueTypeIssue, Type: gitea.IssueTypeIssue,
}) })
@ -182,7 +181,7 @@ var CmdIssuesReopen = cli.Command{
Description: `Change state of an issue to 'open'`, Description: `Change state of an issue to 'open'`,
ArgsUsage: "<issue index>", ArgsUsage: "<issue index>",
Action: func(ctx *cli.Context) error { Action: func(ctx *cli.Context) error {
var s = string(gitea.StateOpen) var s = gitea.StateOpen
return editIssueState(ctx, gitea.EditIssueOption{State: &s}) return editIssueState(ctx, gitea.EditIssueOption{State: &s})
}, },
Flags: AllDefaultFlags, Flags: AllDefaultFlags,
@ -195,7 +194,7 @@ var CmdIssuesClose = cli.Command{
Description: `Change state of an issue to 'closed'`, Description: `Change state of an issue to 'closed'`,
ArgsUsage: "<issue index>", ArgsUsage: "<issue index>",
Action: func(ctx *cli.Context) error { Action: func(ctx *cli.Context) error {
var s = string(gitea.StateClosed) var s = gitea.StateClosed
return editIssueState(ctx, gitea.EditIssueOption{State: &s}) return editIssueState(ctx, gitea.EditIssueOption{State: &s})
}, },
Flags: AllDefaultFlags, Flags: AllDefaultFlags,

View File

@ -49,7 +49,7 @@ func runLabels(ctx *cli.Context) error {
var values [][]string var values [][]string
labels, err := login.Client().ListRepoLabels(owner, repo) labels, err := login.Client().ListRepoLabels(owner, repo, gitea.ListLabelsOptions{})
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -21,6 +21,7 @@ var CmdLogin = cli.Command{
Name: "login", Name: "login",
Usage: "Log in to a Gitea server", Usage: "Log in to a Gitea server",
Description: `Log in to a Gitea server`, Description: `Log in to a Gitea server`,
Action: runLoginList,
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
&cmdLoginList, &cmdLoginList,
&cmdLoginAdd, &cmdLoginAdd,
@ -55,7 +56,7 @@ var cmdLoginAdd = cli.Command{
Usage: "Access token. Can be obtained from Settings > Applications", Usage: "Access token. Can be obtained from Settings > Applications",
Required: true, Required: true,
}, },
&cli.BoolFlag{ &cli.StringFlag{
Name: "ssh-key", Name: "ssh-key",
Aliases: []string{"s"}, Aliases: []string{"s"},
Usage: "Path to a SSH key to use for pull/push operations", Usage: "Path to a SSH key to use for pull/push operations",
@ -129,6 +130,7 @@ var cmdLoginList = cli.Command{
Usage: "List Gitea logins", Usage: "List Gitea logins",
Description: `List Gitea logins`, Description: `List Gitea logins`,
Action: runLoginList, Action: runLoginList,
Flags: []cli.Flag{&OutputFlag},
} }
func runLoginList(ctx *cli.Context) error { func runLoginList(ctx *cli.Context) error {
@ -137,10 +139,23 @@ func runLoginList(ctx *cli.Context) error {
log.Fatal("Unable to load config file " + yamlConfigPath) log.Fatal("Unable to load config file " + yamlConfigPath)
} }
fmt.Printf("Name\tURL\tSSHHost\n") headers := []string{
for _, l := range config.Logins { "Name",
fmt.Printf("%s\t%s\t%s\n", l.Name, l.URL, l.GetSSHHost()) "URL",
"SSHHost",
} }
var values [][]string
for _, l := range config.Logins {
values = append(values, []string{
l.Name,
l.URL,
l.GetSSHHost(),
})
}
Output(outputValue, headers, values)
return nil return nil
} }

109
cmd/notifications.go Normal file
View File

@ -0,0 +1,109 @@
// 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 (
"log"
"strings"
"code.gitea.io/sdk/gitea"
"github.com/urfave/cli/v2"
)
// CmdNotifications is the main command to operate with notifications
var CmdNotifications = cli.Command{
Name: "notifications",
Usage: "show notifications",
Description: "show notifications, by default based of the current repo and unread one",
Action: runNotifications,
Flags: append([]cli.Flag{
&cli.BoolFlag{
Name: "all",
Aliases: []string{"a"},
Usage: "show all notifications of related gitea instance",
},
/* // not supported jet
&cli.BoolFlag{
Name: "read",
Aliases: []string{"rd"},
Usage: "show read notifications instead unread",
},
*/
&cli.IntFlag{
Name: "page",
Aliases: []string{"p"},
Usage: "specify page, default is 1",
Value: 1,
},
&cli.IntFlag{
Name: "limit",
Aliases: []string{"lm"},
Usage: "specify limit of items per page",
},
}, AllDefaultFlags...),
}
func runNotifications(ctx *cli.Context) error {
var news []*gitea.NotificationThread
var err error
listOpts := gitea.ListOptions{
Page: ctx.Int("page"),
PageSize: ctx.Int("limit"),
}
if ctx.Bool("all") {
login := initCommandLoginOnly()
news, err = login.Client().ListNotifications(gitea.ListNotificationOptions{
ListOptions: listOpts,
})
} else {
login, owner, repo := initCommand()
news, err = login.Client().ListRepoNotifications(owner, repo, gitea.ListNotificationOptions{
ListOptions: listOpts,
})
}
if err != nil {
log.Fatal(err)
}
headers := []string{
"Type",
"Index",
"Title",
}
if ctx.Bool("all") {
headers = append(headers, "Repository")
}
var values [][]string
for _, n := range news {
if n.Subject == nil {
continue
}
// if pull or Issue get Index
var index string
if n.Subject.Type == "Issue" || n.Subject.Type == "Pull" {
index = n.Subject.URL
urlParts := strings.Split(n.Subject.URL, "/")
if len(urlParts) != 0 {
index = urlParts[len(urlParts)-1]
}
index = "#" + index
}
item := []string{n.Subject.Type, index, n.Subject.Title}
if ctx.Bool("all") {
item = append(item, n.Repository.FullName)
}
values = append(values, item)
}
if len(values) != 0 {
Output(outputValue, headers, values)
}
return nil
}

View File

@ -13,9 +13,9 @@ import (
local_git "code.gitea.io/tea/modules/git" local_git "code.gitea.io/tea/modules/git"
"code.gitea.io/sdk/gitea" "code.gitea.io/sdk/gitea"
"github.com/go-git/go-git/v5"
git_config "github.com/go-git/go-git/v5/config"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"gopkg.in/src-d/go-git.v4"
git_config "gopkg.in/src-d/go-git.v4/config"
) )
// CmdPulls is the main command to operate on PRs // CmdPulls is the main command to operate on PRs
@ -35,6 +35,7 @@ var CmdPulls = cli.Command{
Subcommands: []*cli.Command{ Subcommands: []*cli.Command{
&CmdPullsCheckout, &CmdPullsCheckout,
&CmdPullsClean, &CmdPullsClean,
&CmdPullsCreate,
}, },
} }
@ -52,8 +53,7 @@ func runPulls(ctx *cli.Context) error {
} }
prs, err := login.Client().ListRepoPullRequests(owner, repo, gitea.ListPullRequestsOptions{ prs, err := login.Client().ListRepoPullRequests(owner, repo, gitea.ListPullRequestsOptions{
Page: 0, State: state,
State: string(state),
}) })
if err != nil { if err != nil {
@ -265,6 +265,111 @@ call me again with the --ignore-sha flag`, pr.Head.Ref)
return r.TeaDeleteBranch(branch, pr.Head.Ref, auth) return r.TeaDeleteBranch(branch, pr.Head.Ref, auth)
} }
// CmdPullsCreate creates a pull request
var CmdPullsCreate = cli.Command{
Name: "create",
Usage: "Create a pull-request",
Description: "Create a pull-request",
Action: runPullsCreate,
Flags: append([]cli.Flag{
&cli.StringFlag{
Name: "head",
Usage: "Set head branch (default is current one)",
},
&cli.StringFlag{
Name: "base",
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",
},
}, AllDefaultFlags...),
}
func runPullsCreate(ctx *cli.Context) error {
login, ownerArg, repoArg := initCommand()
client := login.Client()
repo, err := login.Client().GetRepo(ownerArg, repoArg)
if err != nil {
log.Fatal(err)
}
// open local git repo
localRepo, err := local_git.RepoForWorkdir()
if err != nil {
log.Fatal(err)
}
base := ctx.String("base")
// default is default branch
if len(base) == 0 {
base = repo.DefaultBranch
}
head := ctx.String("head")
// default is current one
if len(head) == 0 {
head, err = localRepo.TeaGetCurrentBranchName()
if err != nil {
log.Fatal(err)
}
}
title := ctx.String("title")
// default is head branch name
if len(title) == 0 {
title = head
if strings.Contains(title, ":") {
title = strings.SplitN(title, ":", 2)[1]
}
title = strings.Replace(title, "-", " ", -1)
title = strings.Replace(title, "_", " ", -1)
title = strings.Title(strings.ToLower(title))
}
// title is required
if len(title) == 0 {
fmt.Printf("Title is required")
return nil
}
// push if possible
err = localRepo.Push(&git.PushOptions{})
if err != nil {
fmt.Printf("Error occurred during 'git push':\n%s\n", err.Error())
}
pr, err := client.CreatePullRequest(ownerArg, repoArg, gitea.CreatePullRequestOption{
Head: head,
Base: base,
Title: title,
Body: ctx.String("description"),
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("#%d %s\n%s created %s\n", pr.Index,
pr.Title,
pr.Poster.UserName,
pr.Created.Format("2006-01-02 15:04:05"),
)
if len(pr.Body) != 0 {
fmt.Printf("\n%s\n", pr.Body)
}
fmt.Println(pr.HTMLURL)
return nil
}
func argToIndex(arg string) (int64, error) { func argToIndex(arg string) (int64, error) {
if strings.HasPrefix(arg, "#") { if strings.HasPrefix(arg, "#") {
arg = arg[1:] arg = arg[1:]

View File

@ -29,7 +29,7 @@ var CmdReleases = cli.Command{
func runReleases(ctx *cli.Context) error { func runReleases(ctx *cli.Context) error {
login, owner, repo := initCommand() login, owner, repo := initCommand()
releases, err := login.Client().ListReleases(owner, repo) releases, err := login.Client().ListReleases(owner, repo, gitea.ListReleasesOptions{})
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -58,11 +58,11 @@ func runReposList(ctx *cli.Context) error {
var err error var err error
if org != "" { if org != "" {
rps, err = login.Client().ListOrgRepos(org) rps, err = login.Client().ListOrgRepos(org, gitea.ListOrgReposOptions{})
} else if user != "" { } else if user != "" {
rps, err = login.Client().ListUserRepos(user) rps, err = login.Client().ListUserRepos(user, gitea.ListReposOptions{})
} else { } else {
rps, err = login.Client().ListMyRepos() rps, err = login.Client().ListMyRepos(gitea.ListReposOptions{})
} }
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

View File

@ -73,7 +73,7 @@ func runTrackedTimes(ctx *cli.Context) error {
if err != nil { if err != nil {
return err return err
} }
times, err = client.ListTrackedTimes(owner, repo, issue) times, err = client.ListTrackedTimes(owner, repo, issue, gitea.ListTrackedTimesOptions{})
} else { } else {
// get all tracked times by the specified user // get all tracked times by the specified user
times, err = client.GetUserTrackedTimes(owner, repo, user) times, err = client.GetUserTrackedTimes(owner, repo, user)

24
go.mod
View File

@ -3,16 +3,20 @@ module code.gitea.io/tea
go 1.12 go 1.12
require ( require (
code.gitea.io/sdk/gitea v0.11.2 code.gitea.io/sdk/gitea v0.12.1
github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195 gitea.com/jolheiser/gitea-vet v0.1.0
github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/go-gitea/yaml v0.0.0-20170812160011-eb3733d160e7 github.com/go-git/go-git/v5 v5.1.0
github.com/mattn/go-runewidth v0.0.4 // indirect github.com/hashicorp/go-version v1.2.1 // indirect
github.com/olekukonko/tablewriter v0.0.1 github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/olekukonko/tablewriter v0.0.4
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.5.1
github.com/urfave/cli/v2 v2.1.1 github.com/urfave/cli/v2 v2.2.0
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
gopkg.in/src-d/go-git.v4 v4.13.1 golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect
gopkg.in/yaml.v2 v2.2.7 // indirect golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed // indirect
gopkg.in/yaml.v2 v2.3.0
) )

116
go.sum
View File

@ -1,19 +1,21 @@
code.gitea.io/sdk/gitea v0.11.2 h1:D0xIRlHv3IckzdYOWzHK1bPvlkXdA4LD909UYyBdi1o= code.gitea.io/sdk/gitea v0.12.1 h1:bMgjEqPnNX/i6TpVwXwpjJtFOnUSuC9P6yy/jjy8sjY=
code.gitea.io/sdk/gitea v0.11.2/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= code.gitea.io/sdk/gitea v0.12.1/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
gitea.com/jolheiser/gitea-vet v0.1.0 h1:gJEms9YWbIcrPOEmDOJ+5JZXCYFxNpwxlI73uRulAi4=
gitea.com/jolheiser/gitea-vet v0.1.0/go.mod h1:2Oa6TAdEp1N/38oBNh3ZeiSEER60D/CeDaBFv2sdH58=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= 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/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= 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/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195 h1:c4mLfegoDw6OhSJXTd2jUEQgZUQuJWtocudb97Qn9EM= github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 h1:TEBmxO80TM04L8IuMWk77SGL1HomBmKTdzdJLLWznxI=
github.com/araddon/dateparse v0.0.0-20190622164848-0fb0a474d195/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= 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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
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 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-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 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -23,12 +25,22 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjr
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-gitea/yaml v0.0.0-20170812160011-eb3733d160e7 h1:/FEVbfrJ50yBk73Lyq1oCZ4VaCc0g1xd9xLHjz+Znf8= github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
github.com/go-gitea/yaml v0.0.0-20170812160011-eb3733d160e7/go.mod h1:WjJPyqjAk/UMv+Fk/ZRjEOh5SXszSALnSzKqICd7pNg= github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E=
github.com/go-git/go-billy/v5 v5.0.0 h1:7NQHvd9FVid8VL4qVUMm8XifBK+2xCoZ2lSk0agRrHM=
github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0=
github.com/go-git/go-git-fixtures/v4 v4.0.1 h1:q+IFMfLx200Q3scvt2hN79JsEzy4AmBTp/pqnefH+Bc=
github.com/go-git/go-git-fixtures/v4 v4.0.1/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw=
github.com/go-git/go-git/v5 v5.1.0 h1:HxJn9g/E7eYvKW3Fm7Jt4ee8LXfPOm/H1cdDu8vEssk=
github.com/go-git/go-git/v5 v5.1.0/go.mod h1:ZKfuPUoY1ZqIG4QG9BDBh3G4gLM5zvPuSJAozQrZuyM=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= 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/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= 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.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/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg=
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
@ -37,72 +49,96 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 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/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.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 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.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
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/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= 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/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= 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 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 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.8.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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 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 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= 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/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
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 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/urfave/cli/v2 v2.1.1 h1:Qt8FeAtxE/vfdrLmR3rxR6JRE0RoVmbXu8+6kZtYU4k= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4=
github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= 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.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 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-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/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-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg=
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
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=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/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-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20200625203802-6e8e738ad208/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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 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 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= 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-20200713011307-fd294ab11aed h1:+qzWo37K31KxduIYaBeMqJ8MUOyTayOQKpH9aDPLMSY=
golang.org/x/tools v0.0.0-20200713011307-fd294ab11aed/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE=
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 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 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/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=

View File

@ -43,6 +43,7 @@ func main() {
&cmd.CmdLabels, &cmd.CmdLabels,
&cmd.CmdTrackedTimes, &cmd.CmdTrackedTimes,
&cmd.CmdOpen, &cmd.CmdOpen,
&cmd.CmdNotifications,
} }
app.EnableBashCompletion = true app.EnableBashCompletion = true
err := app.Run(os.Args) err := app.Run(os.Args)

View File

@ -14,11 +14,11 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
git_transport "github.com/go-git/go-git/v5/plumbing/transport"
gogit_http "github.com/go-git/go-git/v5/plumbing/transport/http"
gogit_ssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal" "golang.org/x/crypto/ssh/terminal"
git_transport "gopkg.in/src-d/go-git.v4/plumbing/transport"
gogit_http "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
gogit_ssh "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
) )
// GetAuthForURL returns the appropriate AuthMethod to be used in Push() / Pull() // GetAuthForURL returns the appropriate AuthMethod to be used in Push() / Pull()
@ -81,6 +81,9 @@ func readSSHPrivKey(keyFile string) (sig ssh.Signer, err error) {
sig, err = ssh.ParsePrivateKey(sshKey) sig, err = ssh.ParsePrivateKey(sshKey)
if err != nil { if err != nil {
pass, err := promptPass(keyFile) pass, err := promptPass(keyFile)
if err != nil {
return nil, err
}
sig, err = ssh.ParsePrivateKeyWithPassphrase(sshKey, []byte(pass)) sig, err = ssh.ParsePrivateKeyWithPassphrase(sshKey, []byte(pass))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -8,10 +8,10 @@ import (
"fmt" "fmt"
"strings" "strings"
"gopkg.in/src-d/go-git.v4" "github.com/go-git/go-git/v5"
git_config "gopkg.in/src-d/go-git.v4/config" git_config "github.com/go-git/go-git/v5/config"
git_plumbing "gopkg.in/src-d/go-git.v4/plumbing" git_plumbing "github.com/go-git/go-git/v5/plumbing"
git_transport "gopkg.in/src-d/go-git.v4/plumbing/transport" git_transport "github.com/go-git/go-git/v5/plumbing/transport"
) )
// TeaCreateBranch creates a new branch in the repo, tracking from another branch. // TeaCreateBranch creates a new branch in the repo, tracking from another branch.
@ -175,3 +175,17 @@ func (r TeaRepo) TeaFindBranchByName(branchName, repoURL string) (b *git_config.
} }
return b, b.Validate() return b, b.Validate()
} }
// TeaGetCurrentBranchName return the name of the branch witch is currently active
func (r TeaRepo) TeaGetCurrentBranchName() (string, error) {
localHead, err := r.Head()
if err != nil {
return "", err
}
if !localHead.Name().IsBranch() {
return "", fmt.Errorf("active ref is no branch")
}
return strings.TrimLeft(localHead.Name().String(), "refs/heads/"), nil
}

View File

@ -8,8 +8,8 @@ import (
"fmt" "fmt"
"net/url" "net/url"
"gopkg.in/src-d/go-git.v4" "github.com/go-git/go-git/v5"
git_config "gopkg.in/src-d/go-git.v4/config" git_config "github.com/go-git/go-git/v5/config"
) )
// GetRemote tries to match a Remote of the repo via the given URL. // GetRemote tries to match a Remote of the repo via the given URL.

View File

@ -5,7 +5,7 @@
package git package git
import ( import (
"gopkg.in/src-d/go-git.v4" "github.com/go-git/go-git/v5"
) )
// TeaRepo is a go-git Repository, with an extended high level interface. // TeaRepo is a go-git Repository, with an extended high level interface.
@ -25,3 +25,15 @@ func RepoForWorkdir() (*TeaRepo, error) {
return &TeaRepo{repo}, nil return &TeaRepo{repo}, nil
} }
// RepoFromPath tries to open the git repository by path
func RepoFromPath(path string) (*TeaRepo, error) {
repo, err := git.PlainOpenWithOptions(path, &git.PlainOpenOptions{
DetectDotGit: true,
})
if err != nil {
return nil, err
}
return &TeaRepo{repo}, nil
}

View File

@ -11,10 +11,16 @@ import (
"fmt" "fmt"
) )
// AdminListOrgsOptions options for listing admin's organizations
type AdminListOrgsOptions struct {
ListOptions
}
// AdminListOrgs lists all orgs // AdminListOrgs lists all orgs
func (c *Client) AdminListOrgs() ([]*Organization, error) { func (c *Client) AdminListOrgs(opt AdminListOrgsOptions) ([]*Organization, error) {
orgs := make([]*Organization, 0, 10) opt.setDefaults()
return orgs, c.getParsedResponse("GET", "/admin/orgs", nil, nil, &orgs) orgs := make([]*Organization, 0, opt.PageSize)
return orgs, c.getParsedResponse("GET", fmt.Sprintf("/admin/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs)
} }
// AdminCreateOrg create an organization // AdminCreateOrg create an organization

View File

@ -11,10 +11,16 @@ import (
"fmt" "fmt"
) )
// AdminListUsersOptions options for listing admin users
type AdminListUsersOptions struct {
ListOptions
}
// AdminListUsers lists all users // AdminListUsers lists all users
func (c *Client) AdminListUsers() ([]*User, error) { func (c *Client) AdminListUsers(opt AdminListUsersOptions) ([]*User, error) {
users := make([]*User, 0, 10) opt.setDefaults()
return users, c.getParsedResponse("GET", "/admin/users", nil, nil, &users) users := make([]*User, 0, opt.PageSize)
return users, c.getParsedResponse("GET", fmt.Sprintf("/admin/users?%s", opt.getURLQuery().Encode()), nil, nil, &users)
} }
// CreateUserOption create user options // CreateUserOption create user options

View File

@ -24,11 +24,17 @@ type Attachment struct {
DownloadURL string `json:"browser_download_url"` DownloadURL string `json:"browser_download_url"`
} }
// ListReleaseAttachmentsOptions options for listing release's attachments
type ListReleaseAttachmentsOptions struct {
ListOptions
}
// ListReleaseAttachments list release's attachments // ListReleaseAttachments list release's attachments
func (c *Client) ListReleaseAttachments(user, repo string, release int64) ([]*Attachment, error) { func (c *Client) ListReleaseAttachments(user, repo string, release int64, opt ListReleaseAttachmentsOptions) ([]*Attachment, error) {
attachments := make([]*Attachment, 0, 10) opt.setDefaults()
attachments := make([]*Attachment, 0, opt.PageSize)
err := c.getParsedResponse("GET", err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases/%d/assets", user, repo, release), fmt.Sprintf("/repos/%s/%s/releases/%d/assets?%s", user, repo, release, opt.getURLQuery().Encode()),
nil, nil, &attachments) nil, nil, &attachments)
return attachments, err return attachments, err
} }

View File

@ -22,7 +22,7 @@ var jsonHeader = http.Header{"content-type": []string{"application/json"}}
// Version return the library version // Version return the library version
func Version() string { func Version() string {
return "0.11.1" return "0.12.0"
} }
// Client represents a Gitea API client. // Client represents a Gitea API client.
@ -31,6 +31,7 @@ type Client struct {
accessToken string accessToken string
username string username string
password string password string
otp string
sudo string sudo string
client *http.Client client *http.Client
serverVersion *version.Version serverVersion *version.Version
@ -58,6 +59,11 @@ func (c *Client) SetBasicAuth(username, password string) {
c.username, c.password = username, password c.username, c.password = username, password
} }
// SetOTP sets OTP for 2FA
func (c *Client) SetOTP(otp string) {
c.otp = otp
}
// SetHTTPClient replaces default http.Client with user given one. // SetHTTPClient replaces default http.Client with user given one.
func (c *Client) SetHTTPClient(client *http.Client) { func (c *Client) SetHTTPClient(client *http.Client) {
c.client = client c.client = client
@ -76,10 +82,13 @@ func (c *Client) doRequest(method, path string, header http.Header, body io.Read
if len(c.accessToken) != 0 { if len(c.accessToken) != 0 {
req.Header.Set("Authorization", "token "+c.accessToken) req.Header.Set("Authorization", "token "+c.accessToken)
} }
if len(c.otp) != 0 {
req.Header.Set("X-GITEA-OTP", c.otp)
}
if len(c.username) != 0 { if len(c.username) != 0 {
req.SetBasicAuth(c.username, c.password) req.SetBasicAuth(c.username, c.password)
} }
if c.sudo != "" { if len(c.sudo) != 0 {
req.Header.Set("Sudo", c.sudo) req.Header.Set("Sudo", c.sudo)
} }
for k, v := range header { for k, v := range header {
@ -110,8 +119,6 @@ func (c *Client) getResponse(method, path string, header http.Header, body io.Re
return nil, errors.New("409 Conflict") return nil, errors.New("409 Conflict")
case 422: case 422:
return nil, fmt.Errorf("422 Unprocessable Entity: %s", string(data)) return nil, fmt.Errorf("422 Unprocessable Entity: %s", string(data))
case 500:
return nil, fmt.Errorf("500 Internal Server Error, request: '%s' with '%s' method and '%s' header", path, method, header)
} }
if resp.StatusCode/100 != 2 { if resp.StatusCode/100 != 2 {
@ -119,7 +126,7 @@ func (c *Client) getResponse(method, path string, header http.Header, body io.Re
if err = json.Unmarshal(data, &errMap); err != nil { if err = json.Unmarshal(data, &errMap); err != nil {
// when the JSON can't be parsed, data was probably empty or a plain string, // when the JSON can't be parsed, data was probably empty or a plain string,
// so we try to return a helpful error anyway // so we try to return a helpful error anyway
return nil, fmt.Errorf("Unknown API Error: %d %s", resp.StatusCode, string(data)) return nil, fmt.Errorf("Unknown API Error: %d\nRequest: '%s' with '%s' method '%s' header and '%s' body", resp.StatusCode, path, method, header, string(data))
} }
return nil, errors.New(errMap["message"].(string)) return nil, errors.New(errMap["message"].(string))
} }

View File

@ -10,13 +10,18 @@ import (
"fmt" "fmt"
) )
// ListForksOptions options for listing repository's forks
type ListForksOptions struct {
ListOptions
}
// ListForks list a repository's forks // ListForks list a repository's forks
func (c *Client) ListForks(user, repo string) ([]*Repository, error) { func (c *Client) ListForks(user string, repo string, opt ListForksOptions) ([]*Repository, error) {
forks := make([]*Repository, 10) opt.setDefaults()
err := c.getParsedResponse("GET", forks := make([]*Repository, opt.PageSize)
fmt.Sprintf("/repos/%s/%s/forks", user, repo), return forks, c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/forks?%s", user, repo, opt.getURLQuery().Encode()),
nil, nil, &forks) nil, nil, &forks)
return forks, err
} }
// CreateForkOption options for creating a fork // CreateForkOption options for creating a fork
@ -32,8 +37,5 @@ func (c *Client) CreateFork(user, repo string, form CreateForkOption) (*Reposito
return nil, err return nil, err
} }
fork := new(Repository) fork := new(Repository)
err = c.getParsedResponse("POST", return fork, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/forks", user, repo), jsonHeader, bytes.NewReader(body), &fork)
fmt.Sprintf("/repos/%s/%s/forks", user, repo),
jsonHeader, bytes.NewReader(body), &fork)
return fork, err
} }

View File

@ -17,10 +17,16 @@ type GitHook struct {
Content string `json:"content,omitempty"` Content string `json:"content,omitempty"`
} }
// ListRepoGitHooksOptions options for listing repository's githooks
type ListRepoGitHooksOptions struct {
ListOptions
}
// ListRepoGitHooks list all the Git hooks of one repository // ListRepoGitHooks list all the Git hooks of one repository
func (c *Client) ListRepoGitHooks(user, repo string) ([]*GitHook, error) { func (c *Client) ListRepoGitHooks(user, repo string, opt ListRepoGitHooksOptions) ([]*GitHook, error) {
hooks := make([]*GitHook, 0, 10) opt.setDefaults()
return hooks, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git", user, repo), nil, nil, &hooks) hooks := make([]*GitHook, 0, opt.PageSize)
return hooks, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks/git?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
} }
// GetRepoGitHook get a Git hook of a repository // GetRepoGitHook get a Git hook of a repository

View File

@ -24,16 +24,23 @@ type Hook struct {
Created time.Time `json:"created_at"` Created time.Time `json:"created_at"`
} }
// ListHooksOptions options for listing hooks
type ListHooksOptions struct {
ListOptions
}
// ListOrgHooks list all the hooks of one organization // ListOrgHooks list all the hooks of one organization
func (c *Client) ListOrgHooks(org string) ([]*Hook, error) { func (c *Client) ListOrgHooks(org string, opt ListHooksOptions) ([]*Hook, error) {
hooks := make([]*Hook, 0, 10) opt.setDefaults()
return hooks, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks", org), nil, nil, &hooks) hooks := make([]*Hook, 0, opt.PageSize)
return hooks, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/hooks?%s", org, opt.getURLQuery().Encode()), nil, nil, &hooks)
} }
// ListRepoHooks list all the hooks of one repository // ListRepoHooks list all the hooks of one repository
func (c *Client) ListRepoHooks(user, repo string) ([]*Hook, error) { func (c *Client) ListRepoHooks(user, repo string, opt ListHooksOptions) ([]*Hook, error) {
hooks := make([]*Hook, 0, 10) opt.setDefaults()
return hooks, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), nil, nil, &hooks) hooks := make([]*Hook, 0, opt.PageSize)
return hooks, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &hooks)
} }
// GetOrgHook get a hook of an organization // GetOrgHook get a hook of an organization

View File

@ -10,6 +10,7 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url" "net/url"
"strings"
"time" "time"
) )
@ -19,6 +20,14 @@ type PullRequestMeta struct {
Merged *time.Time `json:"merged_at"` Merged *time.Time `json:"merged_at"`
} }
// RepositoryMeta basic repository information
type RepositoryMeta struct {
ID int64 `json:"id"`
Name string `json:"name"`
Owner string `json:"owner"`
FullName string `json:"full_name"`
}
// Issue represents an issue in a repository // Issue represents an issue in a repository
type Issue struct { type Issue struct {
ID int64 `json:"id"` ID int64 `json:"id"`
@ -41,18 +50,31 @@ type Issue struct {
Closed *time.Time `json:"closed_at"` Closed *time.Time `json:"closed_at"`
Deadline *time.Time `json:"due_date"` Deadline *time.Time `json:"due_date"`
PullRequest *PullRequestMeta `json:"pull_request"` PullRequest *PullRequestMeta `json:"pull_request"`
Repository *RepositoryMeta `json:"repository"`
} }
// ListIssueOption list issue options // ListIssueOption list issue options
type ListIssueOption struct { type ListIssueOption struct {
Page int ListOptions
// open, closed, all State StateType
State string
Type IssueType Type IssueType
Labels []string Labels []string
Milestones []string
KeyWord string KeyWord string
} }
// StateType issue state type
type StateType string
const (
// StateOpen pr/issue is opend
StateOpen StateType = "open"
// StateClosed pr/issue is closed
StateClosed StateType = "closed"
// StateAll is all
StateAll StateType = "all"
)
// IssueType is issue a pull or only an issue // IssueType is issue a pull or only an issue
type IssueType string type IssueType string
@ -67,79 +89,73 @@ const (
// QueryEncode turns options into querystring argument // QueryEncode turns options into querystring argument
func (opt *ListIssueOption) QueryEncode() string { func (opt *ListIssueOption) QueryEncode() string {
query := make(url.Values) query := opt.getURLQuery()
if opt.Page > 0 {
query.Add("page", fmt.Sprintf("%d", opt.Page))
}
if len(opt.State) > 0 { if len(opt.State) > 0 {
query.Add("state", opt.State) query.Add("state", string(opt.State))
} }
if opt.Page > 0 {
query.Add("page", fmt.Sprintf("%d", opt.Page))
}
if len(opt.State) > 0 {
query.Add("state", opt.State)
}
if len(opt.Labels) > 0 { if len(opt.Labels) > 0 {
var lq string query.Add("labels", strings.Join(opt.Labels, ","))
for _, l := range opt.Labels {
if len(lq) > 0 {
lq += ","
}
lq += l
}
query.Add("labels", lq)
} }
if len(opt.KeyWord) > 0 { if len(opt.KeyWord) > 0 {
query.Add("q", opt.KeyWord) query.Add("q", opt.KeyWord)
} }
query.Add("type", string(opt.Type)) query.Add("type", string(opt.Type))
if len(opt.Milestones) > 0 {
query.Add("milestones", strings.Join(opt.Milestones, ","))
}
return query.Encode() return query.Encode()
} }
// ListIssues returns all issues assigned the authenticated user // ListIssues returns all issues assigned the authenticated user
func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, error) { func (c *Client) ListIssues(opt ListIssueOption) ([]*Issue, error) {
link, _ := url.Parse("/repos/issues/search") opt.setDefaults()
issues := make([]*Issue, 0, 10) issues := make([]*Issue, 0, opt.PageSize)
link.RawQuery = opt.QueryEncode()
return issues, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues)
}
// ListUserIssues returns all issues assigned to the authenticated user link, _ := url.Parse("/repos/issues/search")
func (c *Client) ListUserIssues(opt ListIssueOption) ([]*Issue, error) { link.RawQuery = opt.QueryEncode()
// WARNING: "/user/issues" API is not implemented jet! err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues)
allIssues, err := c.ListIssues(opt) if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil {
if err != nil { for i := 0; i < len(issues); i++ {
return nil, err if issues[i].Repository != nil {
} issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0]
user, err := c.GetMyUserInfo()
if err != nil {
return nil, err
}
// Workaround: client sort out non user related issues
issues := make([]*Issue, 0, 10)
for _, i := range allIssues {
if i.ID == user.ID {
issues = append(issues, i)
} }
} }
return issues, nil }
return issues, err
} }
// ListRepoIssues returns all issues for a given repository // ListRepoIssues returns all issues for a given repository
func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, error) { func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, error) {
opt.setDefaults()
issues := make([]*Issue, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues", owner, repo)) link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues", owner, repo))
issues := make([]*Issue, 0, 10)
link.RawQuery = opt.QueryEncode() link.RawQuery = opt.QueryEncode()
return issues, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues) err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &issues)
if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil {
for i := 0; i < len(issues); i++ {
if issues[i].Repository != nil {
issues[i].Repository.Owner = strings.Split(issues[i].Repository.FullName, "/")[0]
}
}
}
return issues, err
} }
// GetIssue returns a single issue for a given repository // GetIssue returns a single issue for a given repository
func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, error) { func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, error) {
issue := new(Issue) issue := new(Issue)
return issue, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue) err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue)
if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil && issue.Repository != nil {
issue.Repository.Owner = strings.Split(issue.Repository.FullName, "/")[0]
}
return issue, err
} }
// CreateIssueOption options to create one issue // CreateIssueOption options to create one issue
@ -175,7 +191,7 @@ type EditIssueOption struct {
Assignee *string `json:"assignee"` Assignee *string `json:"assignee"`
Assignees []string `json:"assignees"` Assignees []string `json:"assignees"`
Milestone *int64 `json:"milestone"` Milestone *int64 `json:"milestone"`
State *string `json:"state"` State *StateType `json:"state"`
Deadline *time.Time `json:"due_date"` Deadline *time.Time `json:"due_date"`
} }

View File

@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"time" "time"
) )
@ -25,16 +26,50 @@ type Comment struct {
Updated time.Time `json:"updated_at"` Updated time.Time `json:"updated_at"`
} }
// ListIssueCommentOptions list comment options
type ListIssueCommentOptions struct {
ListOptions
Since time.Time
Before time.Time
}
// QueryEncode turns options into querystring argument
func (opt *ListIssueCommentOptions) 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))
}
return query.Encode()
}
// ListIssueComments list comments on an issue. // ListIssueComments list comments on an issue.
func (c *Client) ListIssueComments(owner, repo string, index int64) ([]*Comment, error) { func (c *Client) ListIssueComments(owner, repo string, index int64, opt ListIssueCommentOptions) ([]*Comment, error) {
comments := make([]*Comment, 0, 10) opt.setDefaults()
return comments, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), nil, nil, &comments) link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index))
link.RawQuery = opt.QueryEncode()
comments := make([]*Comment, 0, opt.PageSize)
return comments, c.getParsedResponse("GET", link.String(), nil, nil, &comments)
} }
// ListRepoIssueComments list comments for a given repo. // ListRepoIssueComments list comments for a given repo.
func (c *Client) ListRepoIssueComments(owner, repo string) ([]*Comment, error) { func (c *Client) ListRepoIssueComments(owner, repo string, opt ListIssueCommentOptions) ([]*Comment, error) {
comments := make([]*Comment, 0, 10) opt.setDefaults()
return comments, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo), nil, nil, &comments) link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/issues/comments", owner, repo))
link.RawQuery = opt.QueryEncode()
comments := make([]*Comment, 0, opt.PageSize)
return comments, c.getParsedResponse("GET", link.String(), nil, nil, &comments)
}
// GetIssueComment get a comment for a given repo by id.
func (c *Client) GetIssueComment(owner, repo string, id int64) (*Comment, error) {
comment := new(Comment)
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return comment, err
}
return comment, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/comments/%d", owner, repo, id), nil, nil, &comment)
} }
// CreateIssueCommentOption options for creating a comment on an issue // CreateIssueCommentOption options for creating a comment on an issue

View File

@ -20,10 +20,16 @@ type Label struct {
URL string `json:"url"` URL string `json:"url"`
} }
// ListLabelsOptions options for listing repository's labels
type ListLabelsOptions struct {
ListOptions
}
// ListRepoLabels list labels of one repository // ListRepoLabels list labels of one repository
func (c *Client) ListRepoLabels(owner, repo string) ([]*Label, error) { func (c *Client) ListRepoLabels(owner, repo string, opt ListLabelsOptions) ([]*Label, error) {
labels := make([]*Label, 0, 10) opt.setDefaults()
return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels", owner, repo), nil, nil, &labels) labels := make([]*Label, 0, opt.PageSize)
return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels?%s", owner, repo, opt.getURLQuery().Encode()), nil, nil, &labels)
} }
// GetRepoLabel get one label of repository by repo it // GetRepoLabel get one label of repository by repo it
@ -43,6 +49,11 @@ type CreateLabelOption struct {
// CreateLabel create one label of repository // CreateLabel create one label of repository
func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, error) { func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, error) {
if len(opt.Color) == 6 {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
opt.Color = "#" + opt.Color
}
}
body, err := json.Marshal(&opt) body, err := json.Marshal(&opt)
if err != nil { if err != nil {
return nil, err return nil, err
@ -77,9 +88,9 @@ func (c *Client) DeleteLabel(owner, repo string, id int64) error {
} }
// GetIssueLabels get labels of one issue via issue id // GetIssueLabels get labels of one issue via issue id
func (c *Client) GetIssueLabels(owner, repo string, index int64) ([]*Label, error) { func (c *Client) GetIssueLabels(owner, repo string, index int64, opts ListLabelsOptions) ([]*Label, error) {
labels := make([]*Label, 0, 5) labels := make([]*Label, 0, 5)
return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil, &labels) return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels?%s", owner, repo, index, opts.getURLQuery().Encode()), nil, nil, &labels)
} }
// IssueLabelsOption a collection of labels // IssueLabelsOption a collection of labels

View File

@ -8,21 +8,10 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"time" "time"
) )
// StateType issue state type
type StateType string
const (
// StateOpen pr is opend
StateOpen StateType = "open"
// StateClosed pr is closed
StateClosed StateType = "closed"
// StateAll is all
StateAll StateType = "all"
)
// Milestone milestone is a collection of issues on one repository // Milestone milestone is a collection of issues on one repository
type Milestone struct { type Milestone struct {
ID int64 `json:"id"` ID int64 `json:"id"`
@ -35,10 +24,30 @@ type Milestone struct {
Deadline *time.Time `json:"due_on"` Deadline *time.Time `json:"due_on"`
} }
// ListMilestoneOption list milestone options
type ListMilestoneOption struct {
ListOptions
// open, closed, all
State StateType
}
// QueryEncode turns options into querystring argument
func (opt *ListMilestoneOption) QueryEncode() string {
query := opt.getURLQuery()
if opt.State != "" {
query.Add("state", string(opt.State))
}
return query.Encode()
}
// ListRepoMilestones list all the milestones of one repository // ListRepoMilestones list all the milestones of one repository
func (c *Client) ListRepoMilestones(owner, repo string) ([]*Milestone, error) { func (c *Client) ListRepoMilestones(owner, repo string, opt ListMilestoneOption) ([]*Milestone, error) {
milestones := make([]*Milestone, 0, 10) opt.setDefaults()
return milestones, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), nil, nil, &milestones) milestones := make([]*Milestone, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/milestones", owner, repo))
link.RawQuery = opt.QueryEncode()
return milestones, c.getParsedResponse("GET", link.String(), nil, nil, &milestones)
} }
// GetMilestone get one milestone by repo name and milestone id // GetMilestone get one milestone by repo name and milestone id
@ -51,6 +60,7 @@ func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, error)
type CreateMilestoneOption struct { type CreateMilestoneOption struct {
Title string `json:"title"` Title string `json:"title"`
Description string `json:"description"` Description string `json:"description"`
State StateType `json:"state"`
Deadline *time.Time `json:"due_on"` Deadline *time.Time `json:"due_on"`
} }
@ -61,7 +71,18 @@ func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption)
return nil, err return nil, err
} }
milestone := new(Milestone) milestone := new(Milestone)
return milestone, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone) err = c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone)
// make creating closed milestones need gitea >= v1.13.0
// this make it backwards compatible
if err == nil && opt.State == StateClosed && milestone.State != StateClosed {
closed := "closed"
return c.EditMilestone(owner, repo, milestone.ID, EditMilestoneOption{
State: &closed,
})
}
return milestone, err
} }
// EditMilestoneOption options for editing a milestone // EditMilestoneOption options for editing a milestone

View File

@ -6,6 +6,7 @@ package gitea
import ( import (
"fmt" "fmt"
"net/http"
) )
// GetIssueSubscribers get list of users who subscribed on an issue // GetIssueSubscribers get list of users who subscribed on an issue
@ -22,8 +23,17 @@ func (c *Client) AddIssueSubscription(owner, repo string, index int64, user stri
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return err return err
} }
_, err := c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil) status, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
if err != nil {
return err return err
}
if status == http.StatusCreated {
return nil
}
if status == http.StatusOK {
return fmt.Errorf("already subscribed")
}
return fmt.Errorf("unexpected Status: %d", status)
} }
// DeleteIssueSubscription unsubscribe user from issue // DeleteIssueSubscription unsubscribe user from issue
@ -31,8 +41,26 @@ func (c *Client) DeleteIssueSubscription(owner, repo string, index int64, user s
if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil { if err := c.CheckServerVersionConstraint(">=1.11.0"); err != nil {
return err return err
} }
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil) status, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/%s", owner, repo, index, user), nil, nil)
if err != nil {
return err return err
}
if status == http.StatusCreated {
return nil
}
if status == http.StatusOK {
return fmt.Errorf("already unsubscribed")
}
return fmt.Errorf("unexpected Status: %d", status)
}
// CheckIssueSubscription check if current user is subscribed to an issue
func (c *Client) CheckIssueSubscription(owner, repo string, index int64) (*WatchInfo, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
wi := new(WatchInfo)
return wi, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/subscriptions/check", owner, repo, index), nil, nil, wi)
} }
// IssueSubscribe subscribe current user to an issue // IssueSubscribe subscribe current user to an issue

View File

@ -37,12 +37,6 @@ func (c *Client) GetRepoTrackedTimes(owner, repo string) ([]*TrackedTime, error)
return times, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/times", owner, repo), nil, nil, &times) return times, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/times", owner, repo), nil, nil, &times)
} }
// ListTrackedTimes list tracked times of a single issue for a given repository
func (c *Client) ListTrackedTimes(owner, repo string, index int64) ([]*TrackedTime, error) {
times := make([]*TrackedTime, 0, 10)
return times, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), nil, nil, &times)
}
// GetMyTrackedTimes list tracked times of the current user // GetMyTrackedTimes list tracked times of the current user
func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, error) { func (c *Client) GetMyTrackedTimes() ([]*TrackedTime, error) {
times := make([]*TrackedTime, 0, 10) times := make([]*TrackedTime, 0, 10)
@ -70,6 +64,18 @@ func (c *Client) AddTime(owner, repo string, index int64, opt AddTimeOption) (*T
jsonHeader, bytes.NewReader(body), t) jsonHeader, bytes.NewReader(body), t)
} }
// 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, error) {
opt.setDefaults()
times := make([]*TrackedTime, 0, opt.PageSize)
return times, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/times?%s", owner, repo, index, opt.getURLQuery().Encode()), nil, nil, &times)
}
// ResetIssueTime reset tracked time of a single issue for a given repository // ResetIssueTime reset tracked time of a single issue for a given repository
func (c *Client) ResetIssueTime(owner, repo string, index int64) error { func (c *Client) ResetIssueTime(owner, repo string, index int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), nil, nil) _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/times", owner, repo, index), nil, nil)

37
vendor/code.gitea.io/sdk/gitea/list_options.go generated vendored Normal file
View 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 gitea
import (
"fmt"
"net/url"
)
const defaultPageSize = 10
const maxPageSize = 50
// ListOptions options for using Gitea's API pagination
type ListOptions struct {
Page int
PageSize int
}
func (o ListOptions) getURLQuery() url.Values {
query := make(url.Values)
query.Add("page", fmt.Sprintf("%d", o.Page))
query.Add("limit", fmt.Sprintf("%d", o.PageSize))
return query
}
func (o ListOptions) setDefaults() {
if o.Page < 1 {
o.Page = 1
}
if o.PageSize < 0 || o.PageSize > maxPageSize {
o.PageSize = defaultPageSize
}
}

137
vendor/code.gitea.io/sdk/gitea/notifications.go generated vendored Normal file
View File

@ -0,0 +1,137 @@
// 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 gitea
import (
"fmt"
"net/url"
"time"
)
// NotificationThread expose Notification on API
type NotificationThread struct {
ID int64 `json:"id"`
Repository *Repository `json:"repository"`
Subject *NotificationSubject `json:"subject"`
Unread bool `json:"unread"`
Pinned bool `json:"pinned"`
UpdatedAt time.Time `json:"updated_at"`
URL string `json:"url"`
}
// 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" binding:"In(Issue,Pull,Commit)"`
}
// ListNotificationOptions represents the filter options
type ListNotificationOptions struct {
ListOptions
Since time.Time
Before time.Time
}
// MarkNotificationOptions represents the filter options
type MarkNotificationOptions struct {
LastReadAt time.Time
}
// QueryEncode encode options to url query
func (opt *ListNotificationOptions) 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))
}
return query.Encode()
}
// QueryEncode encode options to url query
func (opt *MarkNotificationOptions) QueryEncode() string {
query := make(url.Values)
if !opt.LastReadAt.IsZero() {
query.Add("last_read_at", opt.LastReadAt.Format(time.RFC3339))
}
return query.Encode()
}
// CheckNotifications list users's notification threads
func (c *Client) CheckNotifications() (int64, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return 0, err
}
new := struct {
New int64 `json:"new"`
}{}
return new.New, c.getParsedResponse("GET", "/notifications/new", jsonHeader, nil, &new)
}
// GetNotification get notification thread by ID
func (c *Client) GetNotification(id int64) (*NotificationThread, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
thread := new(NotificationThread)
return thread, c.getParsedResponse("GET", fmt.Sprintf("/notifications/threads/%d", id), nil, nil, thread)
}
// ReadNotification mark notification thread as read by ID
func (c *Client) ReadNotification(id int64) error {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return err
}
_, err := c.getResponse("PATCH", fmt.Sprintf("/notifications/threads/%d", id), nil, nil)
return err
}
// ListNotifications list users's notification threads
func (c *Client) ListNotifications(opt ListNotificationOptions) ([]*NotificationThread, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
link, _ := url.Parse("/notifications")
link.RawQuery = opt.QueryEncode()
threads := make([]*NotificationThread, 0, 10)
return threads, c.getParsedResponse("GET", link.String(), nil, nil, &threads)
}
// ReadNotifications mark notification threads as read
func (c *Client) ReadNotifications(opt MarkNotificationOptions) error {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return err
}
link, _ := url.Parse("/notifications")
link.RawQuery = opt.QueryEncode()
_, err := c.getResponse("PUT", link.String(), nil, nil)
return err
}
// ListRepoNotifications list users's notification threads on a specific repo
func (c *Client) ListRepoNotifications(owner, reponame string, opt ListNotificationOptions) ([]*NotificationThread, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, reponame))
link.RawQuery = opt.QueryEncode()
threads := make([]*NotificationThread, 0, 10)
return threads, c.getParsedResponse("GET", link.String(), nil, nil, &threads)
}
// ReadRepoNotifications mark notification threads as read on a specific repo
func (c *Client) ReadRepoNotifications(owner, reponame string, opt MarkNotificationOptions) error {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return err
}
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/notifications", owner, reponame))
link.RawQuery = opt.QueryEncode()
_, err := c.getResponse("PUT", link.String(), nil, nil)
return err
}

87
vendor/code.gitea.io/sdk/gitea/oauth2.go generated vendored Normal file
View File

@ -0,0 +1,87 @@
// 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 gitea
import (
"bytes"
"encoding/json"
"fmt"
"time"
)
// Oauth2 represents an Oauth2 Application
type Oauth2 struct {
ID int64 `json:"id"`
Name string `json:"name"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
RedirectURIs []string `json:"redirect_uris"`
Created time.Time `json:"created"`
}
// ListOauth2Option for listing Oauth2 Applications
type ListOauth2Option struct {
ListOptions
}
// CreateOauth2Option required options for creating an Application
type CreateOauth2Option struct {
Name string `json:"name"`
RedirectURIs []string `json:"redirect_uris"`
}
// CreateOauth2 create an Oauth2 Application and returns a completed Oauth2 object.
func (c *Client) CreateOauth2(opt CreateOauth2Option) (*Oauth2, error) {
if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil {
return nil, e
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
oauth := new(Oauth2)
return oauth, c.getParsedResponse("POST", "/user/applications/oauth2", jsonHeader, bytes.NewReader(body), oauth)
}
// UpdateOauth2 a specific Oauth2 Application by ID and return a completed Oauth2 object.
func (c *Client) UpdateOauth2(oauth2id int64, opt CreateOauth2Option) (*Oauth2, error) {
if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil {
return nil, e
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
oauth := new(Oauth2)
return oauth, c.getParsedResponse("PATCH", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), jsonHeader, bytes.NewReader(body), oauth)
}
// GetOauth2 a specific Oauth2 Application by ID.
func (c *Client) GetOauth2(oauth2id int64) (*Oauth2, error) {
if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil {
return nil, e
}
oauth2s := &Oauth2{}
return oauth2s, c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil, &oauth2s)
}
// ListOauth2 all of your Oauth2 Applications.
func (c *Client) ListOauth2(opt ListOauth2Option) ([]*Oauth2, error) {
if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil {
return nil, e
}
opt.setDefaults()
oauth2s := make([]*Oauth2, 0, opt.PageSize)
return oauth2s, c.getParsedResponse("GET", fmt.Sprintf("/user/applications/oauth2?%s", opt.getURLQuery().Encode()), nil, nil, &oauth2s)
}
// DeleteOauth2 delete an Oauth2 application by ID
func (c *Client) DeleteOauth2(oauth2id int64) error {
if e := c.CheckServerVersionConstraint(">=1.12.0"); e != nil {
return e
}
_, err := c.getResponse("DELETE", fmt.Sprintf("/user/applications/oauth2/%d", oauth2id), nil, nil)
return err
}

View File

@ -23,16 +23,23 @@ type Organization struct {
Visibility string `json:"visibility"` Visibility string `json:"visibility"`
} }
// ListOrgsOptions options for listing organizations
type ListOrgsOptions struct {
ListOptions
}
// ListMyOrgs list all of current user's organizations // ListMyOrgs list all of current user's organizations
func (c *Client) ListMyOrgs() ([]*Organization, error) { func (c *Client) ListMyOrgs(opt ListOrgsOptions) ([]*Organization, error) {
orgs := make([]*Organization, 0, 5) opt.setDefaults()
return orgs, c.getParsedResponse("GET", "/user/orgs", nil, nil, &orgs) orgs := make([]*Organization, 0, opt.PageSize)
return orgs, c.getParsedResponse("GET", fmt.Sprintf("/user/orgs?%s", opt.getURLQuery().Encode()), nil, nil, &orgs)
} }
// ListUserOrgs list all of some user's organizations // ListUserOrgs list all of some user's organizations
func (c *Client) ListUserOrgs(user string) ([]*Organization, error) { func (c *Client) ListUserOrgs(user string, opt ListOrgsOptions) ([]*Organization, error) {
orgs := make([]*Organization, 0, 5) opt.setDefaults()
return orgs, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs", user), nil, nil, &orgs) orgs := make([]*Organization, 0, opt.PageSize)
return orgs, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs?%s", user, opt.getURLQuery().Encode()), nil, nil, &orgs)
} }
// GetOrg get one organization by name // GetOrg get one organization by name

View File

@ -1,26 +1,98 @@
// Copyright 2016 The Gogs Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package gitea package gitea
import ( import (
"bytes"
"encoding/json"
"fmt" "fmt"
"net/http"
"net/url"
) )
// AddOrgMembershipOption add user to organization options // DeleteOrgMembership remove a member from an organization
type AddOrgMembershipOption struct { func (c *Client) DeleteOrgMembership(org, user string) error {
Role string `json:"role"` _, err := c.getResponse("DELETE", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
return err
} }
// AddOrgMembership add some one to an organization's member // ListOrgMembershipOption list OrgMembership options
func (c *Client) AddOrgMembership(org, user string, opt AddOrgMembershipOption) error { type ListOrgMembershipOption struct {
body, err := json.Marshal(&opt) ListOptions
}
// ListOrgMembership list an organization's members
func (c *Client) ListOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, error) {
opt.setDefaults()
users := make([]*User, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/members", url.PathEscape(org)))
link.RawQuery = opt.getURLQuery().Encode()
return users, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
}
// ListPublicOrgMembership list an organization's members
func (c *Client) ListPublicOrgMembership(org string, opt ListOrgMembershipOption) ([]*User, error) {
opt.setDefaults()
users := make([]*User, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/orgs/%s/public_members", url.PathEscape(org)))
link.RawQuery = opt.getURLQuery().Encode()
return users, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &users)
}
// CheckOrgMembership Check if a user is a member of an organization
func (c *Client) CheckOrgMembership(org, user string) (bool, error) {
status, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
if err != nil {
return false, err
}
switch status {
case http.StatusNoContent:
return true, nil
case http.StatusNotFound:
return false, nil
default:
return false, fmt.Errorf("unexpected Status: %d", status)
}
}
// CheckPublicOrgMembership Check if a user is a member of an organization
func (c *Client) CheckPublicOrgMembership(org, user string) (bool, error) {
status, err := c.getStatusCode("GET", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
if err != nil {
return false, err
}
switch status {
case http.StatusNoContent:
return true, nil
case http.StatusNotFound:
return false, nil
default:
return false, fmt.Errorf("unexpected Status: %d", status)
}
}
// SetPublicOrgMembership publicize/conceal a user's membership
func (c *Client) SetPublicOrgMembership(org, user string, visible bool) error {
var (
status int
err error
)
if visible {
status, err = c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
} else {
status, err = c.getStatusCode("DELETE", fmt.Sprintf("/orgs/%s/public_members/%s", url.PathEscape(org), url.PathEscape(user)), nil, nil)
}
if err != nil { if err != nil {
return err return err
} }
_, err = c.getResponse("PUT", fmt.Sprintf("/orgs/%s/membership/%s", org, user), jsonHeader, bytes.NewReader(body)) switch status {
return err case http.StatusNoContent:
return nil
case http.StatusNotFound:
return fmt.Errorf("forbidden")
default:
return fmt.Errorf("unexpected Status: %d", status)
}
} }

View File

@ -22,16 +22,23 @@ type Team struct {
Units []string `json:"units"` Units []string `json:"units"`
} }
// ListTeamsOptions options for listing teams
type ListTeamsOptions struct {
ListOptions
}
// ListOrgTeams lists all teams of an organization // ListOrgTeams lists all teams of an organization
func (c *Client) ListOrgTeams(org string) ([]*Team, error) { func (c *Client) ListOrgTeams(org string, opt ListTeamsOptions) ([]*Team, error) {
teams := make([]*Team, 0, 10) opt.setDefaults()
return teams, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams", org), nil, nil, &teams) teams := make([]*Team, 0, opt.PageSize)
return teams, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/teams?%s", org, opt.getURLQuery().Encode()), nil, nil, &teams)
} }
// ListMyTeams lists all the teams of the current user // ListMyTeams lists all the teams of the current user
func (c *Client) ListMyTeams() ([]*Team, error) { func (c *Client) ListMyTeams(opt *ListTeamsOptions) ([]*Team, error) {
teams := make([]*Team, 0, 10) opt.setDefaults()
return teams, c.getParsedResponse("GET", "/user/teams", nil, nil, &teams) teams := make([]*Team, 0, opt.PageSize)
return teams, c.getParsedResponse("GET", fmt.Sprintf("/user/teams?%s", opt.getURLQuery().Encode()), nil, nil, &teams)
} }
// GetTeam gets a team by ID // GetTeam gets a team by ID
@ -86,10 +93,16 @@ func (c *Client) DeleteTeam(id int64) error {
return err return err
} }
// ListTeamMembersOptions options for listing team's members
type ListTeamMembersOptions struct {
ListOptions
}
// ListTeamMembers lists all members of a team // ListTeamMembers lists all members of a team
func (c *Client) ListTeamMembers(id int64) ([]*User, error) { func (c *Client) ListTeamMembers(id int64, opt ListTeamMembersOptions) ([]*User, error) {
members := make([]*User, 0, 10) opt.setDefaults()
return members, c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members", id), nil, nil, &members) members := make([]*User, 0, opt.PageSize)
return members, c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/members?%s", id, opt.getURLQuery().Encode()), nil, nil, &members)
} }
// GetTeamMember gets a member of a team // GetTeamMember gets a member of a team
@ -110,10 +123,16 @@ func (c *Client) RemoveTeamMember(id int64, user string) error {
return err return err
} }
// ListTeamRepositoriesOptions options for listing team's repositories
type ListTeamRepositoriesOptions struct {
ListOptions
}
// ListTeamRepositories lists all repositories of a team // ListTeamRepositories lists all repositories of a team
func (c *Client) ListTeamRepositories(id int64) ([]*Repository, error) { func (c *Client) ListTeamRepositories(id int64, opt ListTeamRepositoriesOptions) ([]*Repository, error) {
repos := make([]*Repository, 0, 10) opt.setDefaults()
return repos, c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/repos", id), nil, nil, &repos) repos := make([]*Repository, 0, opt.PageSize)
return repos, c.getParsedResponse("GET", fmt.Sprintf("/teams/%d/repos?%s", id, opt.getURLQuery().Encode()), nil, nil, &repos)
} }
// AddTeamRepository adds a repository to a team // AddTeamRepository adds a repository to a team

View File

@ -59,26 +59,32 @@ type PullRequest struct {
// ListPullRequestsOptions options for listing pull requests // ListPullRequestsOptions options for listing pull requests
type ListPullRequestsOptions struct { type ListPullRequestsOptions struct {
Page int `json:"page"` ListOptions
// open, closed, all State StateType `json:"state"`
State string `json:"state"`
// oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority // oldest, recentupdate, leastupdate, mostcomment, leastcomment, priority
Sort string `json:"sort"` Sort string
Milestone int64 `json:"milestone"` Milestone int64
} }
// ListRepoPullRequests list PRs of one repository // MergeStyle is used specify how a pull is merged
func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, error) { type MergeStyle string
// declare variables
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls", owner, repo)) const (
prs := make([]*PullRequest, 0, 10) // MergeStyleMerge merge pull as usual
query := make(url.Values) MergeStyleMerge MergeStyle = "merge"
// add options to query // MergeStyleRebase rebase pull
if opt.Page > 0 { MergeStyleRebase MergeStyle = "rebase"
query.Add("page", fmt.Sprintf("%d", opt.Page)) // MergeStyleRebaseMerge rebase and merge pull
} MergeStyleRebaseMerge MergeStyle = "rebase-merge"
// MergeStyleSquash squash and merge pull
MergeStyleSquash MergeStyle = "squash"
)
// QueryEncode turns options into querystring argument
func (opt *ListPullRequestsOptions) QueryEncode() string {
query := opt.getURLQuery()
if len(opt.State) > 0 { if len(opt.State) > 0 {
query.Add("state", opt.State) query.Add("state", string(opt.State))
} }
if len(opt.Sort) > 0 { if len(opt.Sort) > 0 {
query.Add("sort", opt.Sort) query.Add("sort", opt.Sort)
@ -86,8 +92,16 @@ func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOp
if opt.Milestone > 0 { if opt.Milestone > 0 {
query.Add("milestone", fmt.Sprintf("%d", opt.Milestone)) query.Add("milestone", fmt.Sprintf("%d", opt.Milestone))
} }
link.RawQuery = query.Encode() return query.Encode()
// request }
// ListRepoPullRequests list PRs of one repository
func (c *Client) ListRepoPullRequests(owner, repo string, opt ListPullRequestsOptions) ([]*PullRequest, error) {
opt.setDefaults()
prs := make([]*PullRequest, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls", owner, repo))
link.RawQuery = opt.QueryEncode()
return prs, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &prs) return prs, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &prs)
} }
@ -125,11 +139,12 @@ func (c *Client) CreatePullRequest(owner, repo string, opt CreatePullRequestOpti
type EditPullRequestOption struct { type EditPullRequestOption struct {
Title string `json:"title"` Title string `json:"title"`
Body string `json:"body"` Body string `json:"body"`
Base string `json:"base"`
Assignee string `json:"assignee"` Assignee string `json:"assignee"`
Assignees []string `json:"assignees"` Assignees []string `json:"assignees"`
Milestone int64 `json:"milestone"` Milestone int64 `json:"milestone"`
Labels []int64 `json:"labels"` Labels []int64 `json:"labels"`
State *string `json:"state"` State *StateType `json:"state"`
Deadline *time.Time `json:"due_date"` Deadline *time.Time `json:"due_date"`
} }
@ -146,26 +161,27 @@ func (c *Client) EditPullRequest(owner, repo string, index int64, opt EditPullRe
// MergePullRequestOption options when merging a pull request // MergePullRequestOption options when merging a pull request
type MergePullRequestOption struct { type MergePullRequestOption struct {
// required: true Style MergeStyle `json:"Do"`
// enum: merge,rebase,rebase-merge,squash Title string `json:"MergeTitleField"`
Do string `json:"Do" binding:"Required;In(merge,rebase,rebase-merge,squash)"` Message string `json:"MergeMessageField"`
MergeTitleField string `json:"MergeTitleField"`
MergeMessageField string `json:"MergeMessageField"`
}
// MergePullRequestResponse response when merging a pull request
type MergePullRequestResponse struct {
} }
// MergePullRequest merge a PR to repository by PR id // MergePullRequest merge a PR to repository by PR id
func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePullRequestOption) (*MergePullRequestResponse, error) { func (c *Client) MergePullRequest(owner, repo string, index int64, opt MergePullRequestOption) (bool, error) {
if opt.Style == MergeStyleSquash {
if err := c.CheckServerVersionConstraint(">=1.11.5"); err != nil {
return false, err
}
}
body, err := json.Marshal(&opt) body, err := json.Marshal(&opt)
if err != nil { if err != nil {
return nil, err return false, err
} }
response := new(MergePullRequestResponse) status, err := c.getStatusCode("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), jsonHeader, bytes.NewReader(body))
return response, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index), if err != nil {
jsonHeader, bytes.NewReader(body), response) return false, err
}
return status == 200, nil
} }
// IsPullRequestMerged test if one PR is merged to one repository // IsPullRequestMerged test if one PR is merged to one repository

184
vendor/code.gitea.io/sdk/gitea/pull_review.go generated vendored Normal file
View File

@ -0,0 +1,184 @@
// 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 gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"time"
)
// ReviewStateType review state type
type ReviewStateType string
const (
// ReviewStateApproved pr is approved
ReviewStateApproved ReviewStateType = "APPROVED"
// ReviewStatePending pr state is pending
ReviewStatePending ReviewStateType = "PENDING"
// ReviewStateComment is a comment review
ReviewStateComment ReviewStateType = "COMMENT"
// ReviewStateRequestChanges changes for pr are requested
ReviewStateRequestChanges ReviewStateType = "REQUEST_CHANGES"
// ReviewStateRequestReview review is requested from user
ReviewStateRequestReview ReviewStateType = "REQUEST_REVIEW"
// ReviewStateUnknown state of pr is unknown
ReviewStateUnknown ReviewStateType = ""
)
// 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"`
// swagger:strfmt date-time
Submitted time.Time `json:"submitted_at"`
HTMLURL string `json:"html_url"`
HTMLPullURL string `json:"pull_request_url"`
}
// PullReviewComment represents a comment on a pull request review
type PullReviewComment struct {
ID int64 `json:"id"`
Body string `json:"body"`
Reviewer *User `json:"user"`
ReviewID int64 `json:"pull_request_review_id"`
// swagger:strfmt date-time
Created time.Time `json:"created_at"`
// swagger:strfmt date-time
Updated time.Time `json:"updated_at"`
Path string `json:"path"`
CommitID string `json:"commit_id"`
OrigCommitID string `json:"original_commit_id"`
DiffHunk string `json:"diff_hunk"`
LineNum uint64 `json:"position"`
OldLineNum uint64 `json:"original_position"`
HTMLURL string `json:"html_url"`
HTMLPullURL string `json:"pull_request_url"`
}
// CreatePullReviewOptions are options to create a pull review
type CreatePullReviewOptions struct {
State ReviewStateType `json:"event"`
Body string `json:"body"`
CommitID string `json:"commit_id"`
Comments []CreatePullReviewComment `json:"comments"`
}
// CreatePullReviewComment represent a review comment for creation api
type CreatePullReviewComment struct {
// the tree path
Path string `json:"path"`
Body string `json:"body"`
// if comment to old file line or 0
OldLineNum int64 `json:"old_position"`
// if comment to new file line or 0
NewLineNum int64 `json:"new_position"`
}
// SubmitPullReviewOptions are options to submit a pending pull review
type SubmitPullReviewOptions struct {
State ReviewStateType `json:"event"`
Body string `json:"body"`
}
// ListPullReviewsOptions options for listing PullReviews
type ListPullReviewsOptions struct {
ListOptions
}
// ListPullReviews lists all reviews of a pull request
func (c *Client) ListPullReviews(owner, repo string, index int64, opt ListPullReviewsOptions) ([]*PullReview, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
opt.setDefaults()
rs := make([]*PullReview, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index))
link.RawQuery = opt.ListOptions.getURLQuery().Encode()
return rs, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rs)
}
// GetPullReview gets a specific review of a pull request
func (c *Client) GetPullReview(owner, repo string, index, id int64) (*PullReview, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
r := new(PullReview)
return r, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil, &r)
}
// ListPullReviewsCommentsOptions options for listing PullReviewsComments
type ListPullReviewsCommentsOptions struct {
ListOptions
}
// ListPullReviewComments lists all comments of a pull request review
func (c *Client) ListPullReviewComments(owner, repo string, index, id int64, opt ListPullReviewsCommentsOptions) ([]*PullReviewComment, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
opt.setDefaults()
rcl := make([]*PullReviewComment, 0, opt.PageSize)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d/comments", owner, repo, index, id))
link.RawQuery = opt.ListOptions.getURLQuery().Encode()
return rcl, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &rcl)
}
// DeletePullReview delete a specific review from a pull request
func (c *Client) DeletePullReview(owner, repo string, index, id int64) error {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return err
}
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id), jsonHeader, nil)
return err
}
// CreatePullReview create a review to an pull request
func (c *Client) CreatePullReview(owner, repo string, index int64, opt CreatePullReviewOptions) (*PullReview, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
r := new(PullReview)
return r, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews", owner, repo, index),
jsonHeader, bytes.NewReader(body), r)
}
// SubmitPullReview submit a pending review to an pull request
func (c *Client) SubmitPullReview(owner, repo string, index, id int64, opt SubmitPullReviewOptions) (*PullReview, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
r := new(PullReview)
return r, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/pulls/%d/reviews/%d", owner, repo, index, id),
jsonHeader, bytes.NewReader(body), r)
}

View File

@ -29,11 +29,17 @@ type Release struct {
Attachments []*Attachment `json:"assets"` Attachments []*Attachment `json:"assets"`
} }
// ListReleasesOptions options for listing repository's releases
type ListReleasesOptions struct {
ListOptions
}
// ListReleases list releases of a repository // ListReleases list releases of a repository
func (c *Client) ListReleases(user, repo string) ([]*Release, error) { func (c *Client) ListReleases(user, repo string, opt ListReleasesOptions) ([]*Release, error) {
releases := make([]*Release, 0, 10) opt.setDefaults()
releases := make([]*Release, 0, opt.PageSize)
err := c.getParsedResponse("GET", err := c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/releases", user, repo), fmt.Sprintf("/repos/%s/%s/releases?%s", user, repo, opt.getURLQuery().Encode()),
nil, nil, &releases) nil, nil, &releases)
return releases, err return releases, err
} }

View File

@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"time" "time"
) )
@ -56,22 +57,105 @@ type Repository struct {
AvatarURL string `json:"avatar_url"` AvatarURL string `json:"avatar_url"`
} }
// ListReposOptions options for listing repositories
type ListReposOptions struct {
ListOptions
}
// ListMyRepos lists all repositories for the authenticated user that has access to. // ListMyRepos lists all repositories for the authenticated user that has access to.
func (c *Client) ListMyRepos() ([]*Repository, error) { func (c *Client) ListMyRepos(opt ListReposOptions) ([]*Repository, error) {
repos := make([]*Repository, 0, 10) opt.setDefaults()
return repos, c.getParsedResponse("GET", "/user/repos", nil, nil, &repos) repos := make([]*Repository, 0, opt.PageSize)
return repos, c.getParsedResponse("GET", fmt.Sprintf("/user/repos?%s", opt.getURLQuery().Encode()), nil, nil, &repos)
} }
// ListUserRepos list all repositories of one user by user's name // ListUserRepos list all repositories of one user by user's name
func (c *Client) ListUserRepos(user string) ([]*Repository, error) { func (c *Client) ListUserRepos(user string, opt ListReposOptions) ([]*Repository, error) {
repos := make([]*Repository, 0, 10) opt.setDefaults()
return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos", user), nil, nil, &repos) repos := make([]*Repository, 0, opt.PageSize)
return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos?%s", user, opt.getURLQuery().Encode()), nil, nil, &repos)
}
// ListOrgReposOptions options for a organization's repositories
type ListOrgReposOptions struct {
ListOptions
} }
// ListOrgRepos list all repositories of one organization by organization's name // ListOrgRepos list all repositories of one organization by organization's name
func (c *Client) ListOrgRepos(org string) ([]*Repository, error) { func (c *Client) ListOrgRepos(org string, opt ListOrgReposOptions) ([]*Repository, error) {
repos := make([]*Repository, 0, 10) opt.setDefaults()
return repos, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos", org), nil, nil, &repos) repos := make([]*Repository, 0, opt.PageSize)
return repos, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos?%s", org, opt.getURLQuery().Encode()), nil, nil, &repos)
}
// SearchRepoOptions options for searching repositories
type SearchRepoOptions struct {
ListOptions
Keyword string
Topic bool
IncludeDesc bool
UID int64
PriorityOwnerID int64
StarredBy int64
Private bool
Template bool
Mode string
Exclusive bool
Sort string
}
// QueryEncode turns options into querystring argument
func (opt *SearchRepoOptions) QueryEncode() string {
query := opt.getURLQuery()
if opt.Keyword != "" {
query.Add("q", opt.Keyword)
}
query.Add("topic", fmt.Sprintf("%t", opt.Topic))
query.Add("includeDesc", fmt.Sprintf("%t", opt.IncludeDesc))
if opt.UID > 0 {
query.Add("uid", fmt.Sprintf("%d", opt.UID))
}
if opt.PriorityOwnerID > 0 {
query.Add("priority_owner_id", fmt.Sprintf("%d", opt.PriorityOwnerID))
}
if opt.StarredBy > 0 {
query.Add("starredBy", fmt.Sprintf("%d", opt.StarredBy))
}
query.Add("private", fmt.Sprintf("%t", opt.Private))
query.Add("template", fmt.Sprintf("%t", opt.Template))
if opt.Mode != "" {
query.Add("mode", opt.Mode)
}
query.Add("exclusive", fmt.Sprintf("%t", opt.Exclusive))
if opt.Sort != "" {
query.Add("sort", opt.Sort)
}
return query.Encode()
}
type searchRepoResponse struct {
Repos []*Repository `json:"data"`
}
// SearchRepos searches for repositories matching the given filters
func (c *Client) SearchRepos(opt SearchRepoOptions) ([]*Repository, error) {
opt.setDefaults()
resp := new(searchRepoResponse)
link, _ := url.Parse("/repos/search")
link.RawQuery = opt.QueryEncode()
err := c.getParsedResponse("GET", link.String(), nil, nil, &resp)
return resp.Repos, err
} }
// CreateRepoOption options when creating repository // CreateRepoOption options when creating repository
@ -93,6 +177,8 @@ type CreateRepoOption struct {
License string `json:"license"` License string `json:"license"`
// Readme of the repository to create // Readme of the repository to create
Readme string `json:"readme"` Readme string `json:"readme"`
// DefaultBranch of the repository (used when initializes and in template)
DefaultBranch string `json:"default_branch"`
} }
// CreateRepo creates a repository for authenticated user. // CreateRepo creates a repository for authenticated user.

View File

@ -1,4 +1,5 @@
// Copyright 2016 The Gogs Authors. All rights reserved. // Copyright 2016 The Gogs Authors. All rights reserved.
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style // Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
@ -47,16 +48,44 @@ type PayloadCommitVerification struct {
type Branch struct { type Branch struct {
Name string `json:"name"` Name string `json:"name"`
Commit *PayloadCommit `json:"commit"` Commit *PayloadCommit `json:"commit"`
Protected bool `json:"protected"`
RequiredApprovals int64 `json:"required_approvals"`
EnableStatusCheck bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
UserCanPush bool `json:"user_can_push"`
UserCanMerge bool `json:"user_can_merge"`
EffectiveBranchProtectionName string `json:"effective_branch_protection_name"`
}
// ListRepoBranchesOptions options for listing a repository's branches
type ListRepoBranchesOptions struct {
ListOptions
} }
// ListRepoBranches list all the branches of one repository // ListRepoBranches list all the branches of one repository
func (c *Client) ListRepoBranches(user, repo string) ([]*Branch, error) { func (c *Client) ListRepoBranches(user, repo string, opt ListRepoBranchesOptions) ([]*Branch, error) {
branches := make([]*Branch, 0, 10) opt.setDefaults()
return branches, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches", user, repo), nil, nil, &branches) branches := make([]*Branch, 0, opt.PageSize)
return branches, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &branches)
} }
// GetRepoBranch get one branch's information of one repository // GetRepoBranch get one branch's information of one repository
func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, error) { func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, error) {
b := new(Branch) b := new(Branch)
return b, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b) if err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b); err != nil {
return nil, err
}
return b, nil
}
// DeleteRepoBranch delete a branch in a repository
func (c *Client) DeleteRepoBranch(user, repo, branch string) (bool, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return false, err
}
status, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil)
if err != nil {
return false, err
}
return status == 204, nil
} }

View File

@ -0,0 +1,148 @@
// 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 gitea
import (
"bytes"
"encoding/json"
"fmt"
"net/url"
"time"
)
// 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"`
// swagger:strfmt date-time
Created time.Time `json:"created_at"`
// swagger:strfmt date-time
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"`
}
// 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"`
}
// ListBranchProtectionsOptions list branch protection options
type ListBranchProtectionsOptions struct {
ListOptions
}
// ListBranchProtections list branch protections for a repo
func (c *Client) ListBranchProtections(owner, repo string, opt ListBranchProtectionsOptions) ([]*BranchProtection, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
bps := make([]*BranchProtection, 0, 5)
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo))
link.RawQuery = opt.getURLQuery().Encode()
return bps, c.getParsedResponse("GET", link.String(), jsonHeader, nil, &bps)
}
// GetBranchProtection gets a branch protection
func (c *Client) GetBranchProtection(owner, repo, name string) (*BranchProtection, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
bp := new(BranchProtection)
return bp, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil, bp)
}
// CreateBranchProtection creates a branch protection for a repo
func (c *Client) CreateBranchProtection(owner, repo string, opt CreateBranchProtectionOption) (*BranchProtection, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
bp := new(BranchProtection)
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
return bp, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/branch_protections", owner, repo), jsonHeader, bytes.NewReader(body), bp)
}
// EditBranchProtection edits a branch protection for a repo
func (c *Client) EditBranchProtection(owner, repo, name string, opt EditBranchProtectionOption) (*BranchProtection, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
bp := new(BranchProtection)
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
return bp, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, bytes.NewReader(body), bp)
}
// DeleteBranchProtection deletes a branch protection for a repo
func (c *Client) DeleteBranchProtection(owner, repo, name string) error {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return err
}
_, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/branch_protections/%s", owner, repo, name), jsonHeader, nil)
return err
}

View File

@ -10,20 +10,23 @@ import (
"fmt" "fmt"
) )
// ListCollaboratorsOptions options for listing a repository's collaborators
type ListCollaboratorsOptions struct {
ListOptions
}
// ListCollaborators list a repository's collaborators // ListCollaborators list a repository's collaborators
func (c *Client) ListCollaborators(user, repo string) ([]*User, error) { func (c *Client) ListCollaborators(user, repo string, opt ListCollaboratorsOptions) ([]*User, error) {
collaborators := make([]*User, 0, 10) opt.setDefaults()
err := c.getParsedResponse("GET", collaborators := make([]*User, 0, opt.PageSize)
fmt.Sprintf("/repos/%s/%s/collaborators", user, repo), return collaborators, c.getParsedResponse("GET",
fmt.Sprintf("/repos/%s/%s/collaborators?%s", user, repo, opt.getURLQuery().Encode()),
nil, nil, &collaborators) nil, nil, &collaborators)
return collaborators, err
} }
// IsCollaborator check if a user is a collaborator of a repository // IsCollaborator check if a user is a collaborator of a repository
func (c *Client) IsCollaborator(user, repo, collaborator string) (bool, error) { func (c *Client) IsCollaborator(user, repo, collaborator string) (bool, error) {
status, err := c.getStatusCode("GET", status, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator),
nil, nil)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -44,14 +47,13 @@ func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollabo
if err != nil { if err != nil {
return err return err
} }
_, err = c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, bytes.NewReader(body)) _, err = c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), jsonHeader, bytes.NewReader(body))
return err return err
} }
// DeleteCollaborator remove a collaborator from a repository // DeleteCollaborator remove a collaborator from a repository
func (c *Client) DeleteCollaborator(user, repo, collaborator string) error { func (c *Client) DeleteCollaborator(user, repo, collaborator string) error {
_, err := c.getResponse("DELETE", _, err := c.getResponse("DELETE",
fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, nil)
nil, nil)
return err return err
} }

View File

@ -7,6 +7,8 @@ package gitea
import ( import (
"fmt" "fmt"
"net/url"
"time"
) )
// Identity for a person's identity like an author or committer // Identity for a person's identity like an author or committer
@ -46,8 +48,39 @@ type Commit struct {
Parents []*CommitMeta `json:"parents"` Parents []*CommitMeta `json:"parents"`
} }
// CommitDateOptions store dates for GIT_AUTHOR_DATE and GIT_COMMITTER_DATE
type CommitDateOptions struct {
Author time.Time `json:"author"`
Committer time.Time `json:"committer"`
}
// GetSingleCommit returns a single commit // GetSingleCommit returns a single commit
func (c *Client) GetSingleCommit(user, repo, commitID string) (*Commit, error) { func (c *Client) GetSingleCommit(user, repo, commitID string) (*Commit, error) {
commit := new(Commit) commit := new(Commit)
return commit, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s", user, repo, commitID), nil, nil, &commit) return commit, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/git/commits/%s", user, repo, commitID), nil, nil, &commit)
} }
// ListCommitOptions list commit options
type ListCommitOptions struct {
ListOptions
//SHA or branch to start listing commits from (usually 'master')
SHA string
}
// QueryEncode turns options into querystring argument
func (opt *ListCommitOptions) QueryEncode() string {
query := opt.ListOptions.getURLQuery()
if opt.SHA != "" {
query.Add("sha", opt.SHA)
}
return query.Encode()
}
// ListRepoCommits return list of commits from a repo
func (c *Client) ListRepoCommits(user, repo string, opt ListCommitOptions) ([]*Commit, error) {
link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/commits", user, repo))
opt.setDefaults()
commits := make([]*Commit, 0, opt.PageSize)
link.RawQuery = opt.QueryEncode()
return commits, c.getParsedResponse("GET", link.String(), nil, nil, &commits)
}

View File

@ -6,11 +6,187 @@
package gitea package gitea
import ( import (
"bytes"
"encoding/json"
"fmt" "fmt"
) )
// FileOptions options for all file APIs
type FileOptions struct {
// message (optional) for the commit of this file. if not supplied, a default message will be used
Message string `json:"message"`
// branch (optional) to base this file from. if not given, the default branch is used
BranchName string `json:"branch"`
// new_branch (optional) will make a new branch from `branch` before creating the file
NewBranchName string `json:"new_branch"`
// `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
Author Identity `json:"author"`
Committer Identity `json:"committer"`
Dates CommitDateOptions `json:"dates"`
}
// CreateFileOptions options for creating files
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
type CreateFileOptions struct {
FileOptions
// content must be base64 encoded
// required: true
Content string `json:"content"`
}
// DeleteFileOptions options for deleting files (used for other File structs below)
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
type DeleteFileOptions struct {
FileOptions
// sha is the SHA for the file that already exists
// required: true
SHA string `json:"sha"`
}
// UpdateFileOptions options for updating files
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
type UpdateFileOptions struct {
FileOptions
// sha is the SHA for the file that already exists
// required: true
SHA string `json:"sha"`
// content must be base64 encoded
// required: true
Content string `json:"content"`
// from_path (optional) is the path of the original file which will be moved/renamed to the path in the URL
FromPath string `json:"from_path"`
}
// FileLinksResponse contains the links for a repo's file
type FileLinksResponse struct {
Self *string `json:"self"`
GitURL *string `json:"git"`
HTMLURL *string `json:"html"`
}
// ContentsResponse contains information about a repo's entry's (dir, file, symlink, submodule) metadata and content
type ContentsResponse struct {
Name string `json:"name"`
Path string `json:"path"`
SHA string `json:"sha"`
// `type` will be `file`, `dir`, `symlink`, or `submodule`
Type string `json:"type"`
Size int64 `json:"size"`
// `encoding` is populated when `type` is `file`, otherwise null
Encoding *string `json:"encoding"`
// `content` is populated when `type` is `file`, otherwise null
Content *string `json:"content"`
// `target` is populated when `type` is `symlink`, otherwise null
Target *string `json:"target"`
URL *string `json:"url"`
HTMLURL *string `json:"html_url"`
GitURL *string `json:"git_url"`
DownloadURL *string `json:"download_url"`
// `submodule_git_url` is populated when `type` is `submodule`, otherwise null
SubmoduleGitURL *string `json:"submodule_git_url"`
Links *FileLinksResponse `json:"_links"`
}
// FileCommitResponse contains information generated from a Git commit for a repo's file.
type FileCommitResponse struct {
CommitMeta
HTMLURL string `json:"html_url"`
Author *CommitUser `json:"author"`
Committer *CommitUser `json:"committer"`
Parents []*CommitMeta `json:"parents"`
Message string `json:"message"`
Tree *CommitMeta `json:"tree"`
}
// FileResponse contains information about a repo's file
type FileResponse struct {
Content *ContentsResponse `json:"content"`
Commit *FileCommitResponse `json:"commit"`
Verification *PayloadCommitVerification `json:"verification"`
}
// FileDeleteResponse contains information about a repo's file that was deleted
type FileDeleteResponse struct {
Content interface{} `json:"content"` // to be set to nil
Commit *FileCommitResponse `json:"commit"`
Verification *PayloadCommitVerification `json:"verification"`
}
// GetFile downloads a file of repository, ref can be branch/tag/commit. // GetFile downloads a file of repository, ref can be branch/tag/commit.
// e.g.: ref -> master, tree -> macaron.go(no leading slash) // e.g.: ref -> master, tree -> macaron.go(no leading slash)
func (c *Client) GetFile(user, repo, ref, tree string) ([]byte, error) { func (c *Client) GetFile(user, repo, ref, tree string) ([]byte, error) {
return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", user, repo, ref, tree), nil, nil) return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", user, repo, ref, tree), 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
// ref is optional
func (c *Client) GetContents(owner, repo, ref, filepath string) (*ContentsResponse, error) {
cr := new(ContentsResponse)
return cr, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/contents/%s?ref=%s", owner, repo, filepath, ref), jsonHeader, nil, cr)
}
// CreateFile create a file in a repository
func (c *Client) CreateFile(owner, repo, filepath string, opt CreateFileOptions) (*FileResponse, error) {
var err error
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
fr := new(FileResponse)
return fr, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr)
}
// UpdateFile update a file in a repository
func (c *Client) UpdateFile(owner, repo, filepath string, opt UpdateFileOptions) (*FileResponse, error) {
var err error
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
fr := new(FileResponse)
return fr, c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body), fr)
}
// DeleteFile delete a file from repository
func (c *Client) DeleteFile(owner, repo, filepath string, opt DeleteFileOptions) error {
var err error
if opt.BranchName, err = c.setDefaultBranchForOldVersions(owner, repo, opt.BranchName); err != nil {
return err
}
body, err := json.Marshal(&opt)
if err != nil {
return err
}
status, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/contents/%s", owner, repo, filepath), jsonHeader, bytes.NewReader(body))
if err != nil {
return err
}
if status != 200 && status != 204 {
return fmt.Errorf("unexpected Status: %d", status)
}
return nil
}
func (c *Client) setDefaultBranchForOldVersions(owner, repo, branch string) (string, error) {
if len(branch) == 0 {
// Gitea >= 1.12.0 Use DefaultBranch on "", mimic this for older versions
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
r, err := c.GetRepo(owner, repo)
if err != nil {
return "", err
}
return r.DefaultBranch, nil
}
}
return branch, nil
}

View File

@ -8,6 +8,7 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/url"
"time" "time"
) )
@ -24,10 +25,32 @@ type DeployKey struct {
Repository *Repository `json:"repository,omitempty"` Repository *Repository `json:"repository,omitempty"`
} }
// ListDeployKeysOptions options for listing a repository's deploy keys
type ListDeployKeysOptions struct {
ListOptions
KeyID int64
Fingerprint string
}
// QueryEncode turns options into querystring argument
func (opt *ListDeployKeysOptions) QueryEncode() string {
query := opt.getURLQuery()
if opt.KeyID > 0 {
query.Add("key_id", fmt.Sprintf("%d", opt.KeyID))
}
if len(opt.Fingerprint) > 0 {
query.Add("fingerprint", opt.Fingerprint)
}
return query.Encode()
}
// ListDeployKeys list all the deploy keys of one repository // ListDeployKeys list all the deploy keys of one repository
func (c *Client) ListDeployKeys(user, repo string) ([]*DeployKey, error) { func (c *Client) ListDeployKeys(user, repo string, opt ListDeployKeysOptions) ([]*DeployKey, error) {
keys := make([]*DeployKey, 0, 10) link, _ := url.Parse(fmt.Sprintf("/repos/%s/%s/keys", user, repo))
return keys, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys", user, repo), nil, nil, &keys) opt.setDefaults()
link.RawQuery = opt.QueryEncode()
keys := make([]*DeployKey, 0, opt.PageSize)
return keys, c.getParsedResponse("GET", link.String(), nil, nil, &keys)
} }
// GetDeployKey get one deploy key with key id // GetDeployKey get one deploy key with key id

View File

@ -17,8 +17,14 @@ type Tag struct {
TarballURL string `json:"tarball_url"` TarballURL string `json:"tarball_url"`
} }
// ListRepoTags list all the branches of one repository // ListRepoTagsOptions options for listing a repository's tags
func (c *Client) ListRepoTags(user, repo string) ([]*Tag, error) { type ListRepoTagsOptions struct {
tags := make([]*Tag, 0, 10) ListOptions
return tags, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags", user, repo), nil, nil, &tags) }
// ListRepoTags list all the branches of one repository
func (c *Client) ListRepoTags(user, repo string, opt ListRepoTagsOptions) ([]*Tag, error) {
opt.setDefaults()
tags := make([]*Tag, 0, opt.PageSize)
return tags, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/tags?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, &tags)
} }

View File

@ -10,24 +10,37 @@ import (
"fmt" "fmt"
) )
// TopicsList represents a list of repo's topics // ListRepoTopicsOptions options for listing repo's topics
type TopicsList struct { type ListRepoTopicsOptions struct {
ListOptions
}
// topicsList represents a list of repo's topics
type topicsList struct {
Topics []string `json:"topics"` Topics []string `json:"topics"`
} }
// ListRepoTopics list all repository's topics // ListRepoTopics list all repository's topics
func (c *Client) ListRepoTopics(user, repo string) (*TopicsList, error) { func (c *Client) ListRepoTopics(user, repo string, opt ListRepoTopicsOptions) ([]string, error) {
var list TopicsList opt.setDefaults()
return &list, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/topics", user, repo), nil, nil, &list)
list := new(topicsList)
err := c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/topics?%s", user, repo, opt.getURLQuery().Encode()), nil, nil, list)
if err != nil {
return nil, err
}
return list.Topics, nil
} }
// SetRepoTopics replaces the list of repo's topics // SetRepoTopics replaces the list of repo's topics
func (c *Client) SetRepoTopics(user, repo string, list TopicsList) error { func (c *Client) SetRepoTopics(user, repo string, list []string) error {
body, err := json.Marshal(&list)
l := topicsList{Topics: list}
body, err := json.Marshal(&l)
if err != nil { if err != nil {
return err return err
} }
_, err = c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics", user, repo), jsonHeader, bytes.NewReader(body)) _, err = c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/topics", user, repo), jsonHeader, bytes.NewReader(body))
return err return err
} }

32
vendor/code.gitea.io/sdk/gitea/repo_transfer.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
// 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 gitea
import (
"bytes"
"encoding/json"
"fmt"
)
// TransferRepoOption options when transfer a repository's ownership
type TransferRepoOption struct {
// required: true
NewOwner string `json:"new_owner"`
// ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories.
TeamIDs *[]int64 `json:"team_ids"`
}
// TransferRepo transfers the ownership of a repository
func (c *Client) TransferRepo(owner, reponame string, opt TransferRepoOption) (*Repository, error) {
if err := c.CheckServerVersionConstraint(">=1.12.0"); err != nil {
return nil, err
}
body, err := json.Marshal(&opt)
if err != nil {
return nil, err
}
repo := new(Repository)
return repo, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/transfer", owner, reponame), jsonHeader, bytes.NewReader(body), repo)
}

View File

@ -31,11 +31,10 @@ type GitTreeResponse struct {
// GetTrees downloads a file of repository, ref can be branch/tag/commit. // GetTrees downloads a file of repository, ref can be branch/tag/commit.
// e.g.: ref -> master, tree -> macaron.go(no leading slash) // e.g.: ref -> master, tree -> macaron.go(no leading slash)
func (c *Client) GetTrees(user, repo, ref string, recursive bool) (*GitTreeResponse, error) { func (c *Client) GetTrees(user, repo, ref string, recursive bool) (*GitTreeResponse, error) {
var trees GitTreeResponse trees := new(GitTreeResponse)
var path = fmt.Sprintf("/repos/%s/%s/git/trees/%s", user, repo, ref) var path = fmt.Sprintf("/repos/%s/%s/git/trees/%s", user, repo, ref)
if recursive { if recursive {
path += "?recursive=1" path += "?recursive=1"
} }
err := c.getParsedResponse("GET", path, nil, nil, &trees) return trees, c.getParsedResponse("GET", path, nil, nil, trees)
return &trees, err
} }

View File

@ -21,21 +21,53 @@ type WatchInfo struct {
} }
// GetWatchedRepos list all the watched repos of user // GetWatchedRepos list all the watched repos of user
func (c *Client) GetWatchedRepos(user, pass string) ([]*Repository, error) { func (c *Client) GetWatchedRepos(user string) ([]*Repository, error) {
repos := make([]*Repository, 0, 10) repos := make([]*Repository, 0, 10)
return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/subscriptions", user), return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/subscriptions", user), nil, nil, &repos)
http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil, &repos) }
// GetMyWatchedRepos list repositories watched by the authenticated user
func (c *Client) GetMyWatchedRepos() ([]*Repository, error) {
repos := make([]*Repository, 0, 10)
return repos, c.getParsedResponse("GET", fmt.Sprintf("/user/subscriptions"), nil, nil, &repos)
}
// CheckRepoWatch check if the current user is watching a repo
func (c *Client) CheckRepoWatch(repoUser, repoName string) (bool, error) {
status, err := c.getStatusCode("GET", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil)
if err != nil {
return false, err
}
switch status {
case http.StatusNotFound:
return false, nil
case http.StatusOK:
return true, nil
default:
return false, fmt.Errorf("unexpected Status: %d", status)
}
} }
// WatchRepo start to watch a repository // WatchRepo start to watch a repository
func (c *Client) WatchRepo(user, pass, repoUser, repoName string) (*WatchInfo, error) { func (c *Client) WatchRepo(repoUser, repoName string) error {
i := new(WatchInfo) status, err := c.getStatusCode("PUT", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil)
return i, c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), if err != nil {
http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil, i) return err
}
if status == http.StatusOK {
return nil
}
return fmt.Errorf("unexpected Status: %d", status)
} }
// UnWatchRepo start to watch a repository // UnWatchRepo stop to watch a repository
func (c *Client) UnWatchRepo(user, pass, repoUser, repoName string) (int, error) { func (c *Client) UnWatchRepo(repoUser, repoName string) error {
return c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), status, err := c.getStatusCode("DELETE", fmt.Sprintf("/repos/%s/%s/subscription", repoUser, repoName), nil, nil)
http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil) if err != nil {
return err
}
if status == http.StatusNoContent {
return nil
}
return fmt.Errorf("unexpected Status: %d", status)
} }

View File

@ -50,29 +50,25 @@ type CreateStatusOption struct {
} }
// CreateStatus creates a new Status for a given Commit // CreateStatus creates a new Status for a given Commit
//
// POST /repos/:owner/:repo/statuses/:sha
func (c *Client) CreateStatus(owner, repo, sha string, opts CreateStatusOption) (*Status, error) { func (c *Client) CreateStatus(owner, repo, sha string, opts CreateStatusOption) (*Status, error) {
body, err := json.Marshal(&opts) body, err := json.Marshal(&opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
status := &Status{} status := new(Status)
return status, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/statuses/%s", owner, repo, sha), return status, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/statuses/%s", owner, repo, sha), jsonHeader, bytes.NewReader(body), status)
jsonHeader, bytes.NewReader(body), status)
} }
// ListStatusesOption holds pagination information // ListStatusesOption options for listing a repository's commit's statuses
type ListStatusesOption struct { type ListStatusesOption struct {
Page int ListOptions
} }
// ListStatuses returns all statuses for a given Commit // ListStatuses returns all statuses for a given Commit
// func (c *Client) ListStatuses(owner, repo, sha string, opt ListStatusesOption) ([]*Status, error) {
// GET /repos/:owner/:repo/commits/:ref/statuses opt.setDefaults()
func (c *Client) ListStatuses(owner, repo, sha string, opts ListStatusesOption) ([]*Status, error) { statuses := make([]*Status, 0, opt.PageSize)
statuses := make([]*Status, 0, 10) return statuses, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/statuses?%s", owner, repo, sha, opt.getURLQuery().Encode()), nil, nil, &statuses)
return statuses, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/statuses?page=%d", owner, repo, sha, opts.Page), nil, nil, &statuses)
} }
// CombinedStatus holds the combined state of several statuses for a single commit // CombinedStatus holds the combined state of several statuses for a single commit
@ -87,9 +83,7 @@ type CombinedStatus struct {
} }
// GetCombinedStatus returns the CombinedStatus for a given Commit // GetCombinedStatus returns the CombinedStatus for a given Commit
//
// GET /repos/:owner/:repo/commits/:ref/status
func (c *Client) GetCombinedStatus(owner, repo, sha string) (*CombinedStatus, error) { func (c *Client) GetCombinedStatus(owner, repo, sha string) (*CombinedStatus, error) {
status := &CombinedStatus{} status := new(CombinedStatus)
return status, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/status", owner, repo, sha), nil, nil, status) return status, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/commits/%s/status", owner, repo, sha), nil, nil, status)
} }

View File

@ -7,17 +7,10 @@ package gitea
import ( import (
"bytes" "bytes"
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http"
) )
// BasicAuthEncode generate base64 of basic auth head
func BasicAuthEncode(user, pass string) string {
return base64.StdEncoding.EncodeToString([]byte(user + ":" + pass))
}
// AccessToken represents an API access token. // AccessToken represents an API access token.
type AccessToken struct { type AccessToken struct {
ID int64 `json:"id"` ID int64 `json:"id"`
@ -26,11 +19,19 @@ type AccessToken struct {
TokenLastEight string `json:"token_last_eight"` TokenLastEight string `json:"token_last_eight"`
} }
// ListAccessTokens lista all the access tokens of user // ListAccessTokensOptions options for listing a users's access tokens
func (c *Client) ListAccessTokens(user, pass string) ([]*AccessToken, error) { type ListAccessTokensOptions struct {
tokens := make([]*AccessToken, 0, 10) ListOptions
return tokens, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens", user), }
http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil, &tokens)
// ListAccessTokens lists all the access tokens of user
func (c *Client) ListAccessTokens(opts ListAccessTokensOptions) ([]*AccessToken, error) {
if len(c.username) == 0 {
return nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
}
opts.setDefaults()
tokens := make([]*AccessToken, 0, opts.PageSize)
return tokens, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens?%s", c.username, opts.getURLQuery().Encode()), jsonHeader, nil, &tokens)
} }
// CreateAccessTokenOption options when create access token // CreateAccessTokenOption options when create access token
@ -39,22 +40,23 @@ type CreateAccessTokenOption struct {
} }
// CreateAccessToken create one access token with options // CreateAccessToken create one access token with options
func (c *Client) CreateAccessToken(user, pass string, opt CreateAccessTokenOption) (*AccessToken, error) { func (c *Client) CreateAccessToken(opt CreateAccessTokenOption) (*AccessToken, error) {
if len(c.username) == 0 {
return nil, fmt.Errorf("\"username\" not set: only BasicAuth allowed")
}
body, err := json.Marshal(&opt) body, err := json.Marshal(&opt)
if err != nil { if err != nil {
return nil, err return nil, err
} }
t := new(AccessToken) t := new(AccessToken)
return t, c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", user), return t, c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", c.username), jsonHeader, bytes.NewReader(body), t)
http.Header{
"content-type": []string{"application/json"},
"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}},
bytes.NewReader(body), t)
} }
// DeleteAccessToken delete token with key id // DeleteAccessToken delete token with key id
func (c *Client) DeleteAccessToken(user string, keyID int64) error { func (c *Client) DeleteAccessToken(keyID int64) error {
_, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%d", user, keyID), if len(c.username) == 0 {
http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, c.password)}}, nil) return fmt.Errorf("\"username\" not set: only BasicAuth allowed")
}
_, err := c.getResponse("DELETE", fmt.Sprintf("/users/%s/tokens/%d", c.username, keyID), jsonHeader, nil)
return err return err
} }

View File

@ -7,6 +7,7 @@ package gitea
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
) )
// Email an email address belonging to a user // Email an email address belonging to a user
@ -16,10 +17,16 @@ type Email struct {
Primary bool `json:"primary"` Primary bool `json:"primary"`
} }
// ListEmailsOptions options for listing current's user emails
type ListEmailsOptions struct {
ListOptions
}
// ListEmails all the email addresses of user // ListEmails all the email addresses of user
func (c *Client) ListEmails() ([]*Email, error) { func (c *Client) ListEmails(opt ListEmailsOptions) ([]*Email, error) {
emails := make([]*Email, 0, 3) opt.setDefaults()
return emails, c.getParsedResponse("GET", "/user/emails", nil, nil, &emails) emails := make([]*Email, 0, opt.PageSize)
return emails, c.getParsedResponse("GET", fmt.Sprintf("/user/emails?%s", opt.getURLQuery().Encode()), nil, nil, &emails)
} }
// CreateEmailOption options when creating email addresses // CreateEmailOption options when creating email addresses

View File

@ -6,28 +6,42 @@ package gitea
import "fmt" import "fmt"
// ListFollowersOptions options for listing followers
type ListFollowersOptions struct {
ListOptions
}
// ListMyFollowers list all the followers of current user // ListMyFollowers list all the followers of current user
func (c *Client) ListMyFollowers(page int) ([]*User, error) { func (c *Client) ListMyFollowers(opt ListFollowersOptions) ([]*User, error) {
users := make([]*User, 0, 10) opt.setDefaults()
return users, c.getParsedResponse("GET", fmt.Sprintf("/user/followers?page=%d", page), nil, nil, &users) users := make([]*User, 0, opt.PageSize)
return users, c.getParsedResponse("GET", fmt.Sprintf("/user/followers?%s", opt.getURLQuery().Encode()), nil, nil, &users)
} }
// ListFollowers list all the followers of one user // ListFollowers list all the followers of one user
func (c *Client) ListFollowers(user string, page int) ([]*User, error) { func (c *Client) ListFollowers(user string, opt ListFollowersOptions) ([]*User, error) {
users := make([]*User, 0, 10) opt.setDefaults()
return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?page=%d", user, page), nil, nil, &users) users := make([]*User, 0, opt.PageSize)
return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
}
// ListFollowingOptions options for listing a user's users being followed
type ListFollowingOptions struct {
ListOptions
} }
// ListMyFollowing list all the users current user followed // ListMyFollowing list all the users current user followed
func (c *Client) ListMyFollowing(page int) ([]*User, error) { func (c *Client) ListMyFollowing(opt ListFollowingOptions) ([]*User, error) {
users := make([]*User, 0, 10) opt.setDefaults()
return users, c.getParsedResponse("GET", fmt.Sprintf("/user/following?page=%d", page), nil, nil, &users) users := make([]*User, 0, opt.PageSize)
return users, c.getParsedResponse("GET", fmt.Sprintf("/user/following?%s", opt.getURLQuery().Encode()), nil, nil, &users)
} }
// ListFollowing list all the users the user followed // ListFollowing list all the users the user followed
func (c *Client) ListFollowing(user string, page int) ([]*User, error) { func (c *Client) ListFollowing(user string, opt ListFollowingOptions) ([]*User, error) {
users := make([]*User, 0, 10) opt.setDefaults()
return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?page=%d", user, page), nil, nil, &users) users := make([]*User, 0, opt.PageSize)
return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?%s", user, opt.getURLQuery().Encode()), nil, nil, &users)
} }
// IsFollowing if current user followed the target // IsFollowing if current user followed the target

View File

@ -33,16 +33,23 @@ type GPGKeyEmail struct {
Verified bool `json:"verified"` Verified bool `json:"verified"`
} }
// ListGPGKeysOptions options for listing a user's GPGKeys
type ListGPGKeysOptions struct {
ListOptions
}
// ListGPGKeys list all the GPG keys of the user // ListGPGKeys list all the GPG keys of the user
func (c *Client) ListGPGKeys(user string) ([]*GPGKey, error) { func (c *Client) ListGPGKeys(user string, opt ListGPGKeysOptions) ([]*GPGKey, error) {
keys := make([]*GPGKey, 0, 10) opt.setDefaults()
return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/gpg_keys", user), nil, nil, &keys) keys := make([]*GPGKey, 0, opt.PageSize)
return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/gpg_keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys)
} }
// ListMyGPGKeys list all the GPG keys of current user // ListMyGPGKeys list all the GPG keys of current user
func (c *Client) ListMyGPGKeys() ([]*GPGKey, error) { func (c *Client) ListMyGPGKeys(opt *ListGPGKeysOptions) ([]*GPGKey, error) {
keys := make([]*GPGKey, 0, 10) opt.setDefaults()
return keys, c.getParsedResponse("GET", "/user/gpg_keys", nil, nil, &keys) keys := make([]*GPGKey, 0, opt.PageSize)
return keys, c.getParsedResponse("GET", fmt.Sprintf("/user/gpg_keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys)
} }
// GetGPGKey get current user's GPG key by key id // GetGPGKey get current user's GPG key by key id

View File

@ -24,16 +24,23 @@ type PublicKey struct {
KeyType string `json:"key_type,omitempty"` KeyType string `json:"key_type,omitempty"`
} }
// ListPublicKeysOptions options for listing a user's PublicKeys
type ListPublicKeysOptions struct {
ListOptions
}
// ListPublicKeys list all the public keys of the user // ListPublicKeys list all the public keys of the user
func (c *Client) ListPublicKeys(user string) ([]*PublicKey, error) { func (c *Client) ListPublicKeys(user string, opt ListPublicKeysOptions) ([]*PublicKey, error) {
keys := make([]*PublicKey, 0, 10) opt.setDefaults()
return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys", user), nil, nil, &keys) keys := make([]*PublicKey, 0, opt.PageSize)
return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys?%s", user, opt.getURLQuery().Encode()), nil, nil, &keys)
} }
// ListMyPublicKeys list all the public keys of current user // ListMyPublicKeys list all the public keys of current user
func (c *Client) ListMyPublicKeys() ([]*PublicKey, error) { func (c *Client) ListMyPublicKeys(opt ListPublicKeysOptions) ([]*PublicKey, error) {
keys := make([]*PublicKey, 0, 10) opt.setDefaults()
return keys, c.getParsedResponse("GET", "/user/keys", nil, nil, &keys) keys := make([]*PublicKey, 0, opt.PageSize)
return keys, c.getParsedResponse("GET", fmt.Sprintf("/user/keys?%s", opt.getURLQuery().Encode()), nil, nil, &keys)
} }
// GetPublicKey get current user's public key by key id // GetPublicKey get current user's public key by key id

View File

@ -1,14 +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 gitea package gitea
import "fmt" import (
"fmt"
"net/url"
)
type searchUsersResponse struct { type searchUsersResponse struct {
Users []*User `json:"data"` Users []*User `json:"data"`
} }
// SearchUsersOption options for SearchUsers
type SearchUsersOption struct {
ListOptions
KeyWord string
}
// QueryEncode turns options into querystring argument
func (opt *SearchUsersOption) QueryEncode() string {
query := make(url.Values)
if opt.Page > 0 {
query.Add("page", fmt.Sprintf("%d", opt.Page))
}
if opt.PageSize > 0 {
query.Add("limit", fmt.Sprintf("%d", opt.PageSize))
}
if len(opt.KeyWord) > 0 {
query.Add("q", opt.KeyWord)
}
return query.Encode()
}
// SearchUsers finds users by query // SearchUsers finds users by query
func (c *Client) SearchUsers(query string, limit int) ([]*User, error) { func (c *Client) SearchUsers(opt SearchUsersOption) ([]*User, error) {
link, _ := url.Parse("/users/search")
link.RawQuery = opt.QueryEncode()
resp := new(searchUsersResponse) resp := new(searchUsersResponse)
err := c.getParsedResponse("GET", fmt.Sprintf("/users/search?q=%s&limit=%d", query, limit), nil, nil, &resp) err := c.getParsedResponse("GET", link.String(), nil, nil, &resp)
return resp.Users, err return resp.Users, err
} }

5
vendor/gitea.com/jolheiser/gitea-vet/.gitignore generated vendored Normal file
View File

@ -0,0 +1,5 @@
# GoLand
.idea/
# Binaries
/gitea-vet*

19
vendor/gitea.com/jolheiser/gitea-vet/LICENSE generated vendored Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2020 The Gitea Authors
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.

7
vendor/gitea.com/jolheiser/gitea-vet/Makefile generated vendored Normal file
View File

@ -0,0 +1,7 @@
.PHONY: build
build:
go build
.PHONY: fmt
fmt:
go fmt ./...

7
vendor/gitea.com/jolheiser/gitea-vet/README.md generated vendored Normal file
View File

@ -0,0 +1,7 @@
# gitea-vet
`go vet` tool for Gitea
| Analyzer | Description |
|----------|---------------------------------------------------------------------|
| Imports | Checks for import sorting. stdlib->code.gitea.io->other |
| License | Checks file headers for some form of `Copyright...YYYY...Gitea/Gogs`|

54
vendor/gitea.com/jolheiser/gitea-vet/checks/imports.go generated vendored Normal file
View 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 checks
import (
"strings"
"golang.org/x/tools/go/analysis"
)
var Imports = &analysis.Analyzer{
Name: "imports",
Doc: "check for import order.",
Run: runImports,
}
func runImports(pass *analysis.Pass) (interface{}, error) {
for _, file := range pass.Files {
level := 0
for _, im := range file.Imports {
var lvl int
val := im.Path.Value
if importHasPrefix(val, "code.gitea.io") {
lvl = 2
} else if strings.Contains(val, ".") {
lvl = 3
} else {
lvl = 1
}
if lvl < level {
pass.Reportf(file.Pos(), "Imports are sorted wrong")
break
}
level = lvl
}
}
return nil, nil
}
func importHasPrefix(s, p string) bool {
return strings.HasPrefix(s, "\""+p)
}
func sliceHasPrefix(s string, prefixes ...string) bool {
for _, p := range prefixes {
if importHasPrefix(s, p) {
return true
}
}
return false
}

73
vendor/gitea.com/jolheiser/gitea-vet/checks/license.go generated vendored Normal file
View File

@ -0,0 +1,73 @@
// 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 checks
import (
"regexp"
"strings"
"golang.org/x/tools/go/analysis"
)
var (
header = regexp.MustCompile(`.*Copyright.*\d{4}.*(Gitea|Gogs)`)
goGenerate = "//go:generate"
buildTag = "// +build"
)
var License = &analysis.Analyzer{
Name: "license",
Doc: "check for a copyright header.",
Run: runLicense,
}
func runLicense(pass *analysis.Pass) (interface{}, error) {
for _, file := range pass.Files {
if len(file.Comments) == 0 {
pass.Reportf(file.Pos(), "Copyright not found")
continue
}
if len(file.Comments[0].List) == 0 {
pass.Reportf(file.Pos(), "Copyright not found or wrong")
continue
}
commentGroup := 0
if strings.HasPrefix(file.Comments[0].List[0].Text, goGenerate) {
if len(file.Comments[0].List) > 1 {
pass.Reportf(file.Pos(), "Must be an empty line between the go:generate and the Copyright")
continue
}
commentGroup++
}
if strings.HasPrefix(file.Comments[0].List[0].Text, buildTag) {
commentGroup++
}
if len(file.Comments) < commentGroup+1 {
pass.Reportf(file.Pos(), "Copyright not found")
continue
}
if len(file.Comments[commentGroup].List) < 1 {
pass.Reportf(file.Pos(), "Copyright not found or wrong")
continue
}
var check bool
for _, comment := range file.Comments[commentGroup].List {
if header.MatchString(comment.Text) {
check = true
}
}
if !check {
pass.Reportf(file.Pos(), "Copyright did not match check")
}
}
return nil, nil
}

5
vendor/gitea.com/jolheiser/gitea-vet/go.mod generated vendored Normal file
View File

@ -0,0 +1,5 @@
module gitea.com/jolheiser/gitea-vet
go 1.14
require golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224

20
vendor/gitea.com/jolheiser/gitea-vet/go.sum generated vendored Normal file
View File

@ -0,0 +1,20 @@
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 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

17
vendor/gitea.com/jolheiser/gitea-vet/main.go generated vendored Normal file
View File

@ -0,0 +1,17 @@
// 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 main
import (
"gitea.com/jolheiser/gitea-vet/checks"
"golang.org/x/tools/go/analysis/unitchecker"
)
func main() {
unitchecker.Main(
checks.Imports,
checks.License,
)
}

View File

@ -48,7 +48,7 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/apcera/termtables" "github.com/scylladb/termtables"
"github.com/araddon/dateparse" "github.com/araddon/dateparse"
) )

View File

@ -142,4 +142,4 @@
// - make error context accessible programmatically? // - make error context accessible programmatically?
// - limit input size? // - limit input size?
// //
package gcfg // import "github.com/src-d/gcfg" package gcfg // import "github.com/go-git/gcfg"

View File

@ -7,8 +7,8 @@ import (
"os" "os"
"strings" "strings"
"github.com/src-d/gcfg/scanner" "github.com/go-git/gcfg/scanner"
"github.com/src-d/gcfg/token" "github.com/go-git/gcfg/token"
"gopkg.in/warnings.v0" "gopkg.in/warnings.v0"
) )

View File

@ -11,7 +11,7 @@ import (
) )
import ( import (
"github.com/src-d/gcfg/token" "github.com/go-git/gcfg/token"
) )
// In an ErrorList, an error is represented by an *Error. // In an ErrorList, an error is represented by an *Error.

View File

@ -19,7 +19,7 @@ import (
) )
import ( import (
"github.com/src-d/gcfg/token" "github.com/go-git/gcfg/token"
) )
// An ErrorHandler may be provided to Scanner.Init. If a syntax error is // An ErrorHandler may be provided to Scanner.Init. If a syntax error is

View File

@ -10,7 +10,7 @@ import (
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
"github.com/src-d/gcfg/types" "github.com/go-git/gcfg/types"
"gopkg.in/warnings.v0" "gopkg.in/warnings.v0"
) )

View File

@ -1,20 +1,21 @@
# go-billy [![GoDoc](https://godoc.org/gopkg.in/src-d/go-billy.v4?status.svg)](https://godoc.org/gopkg.in/src-d/go-billy.v4) [![Build Status](https://travis-ci.com/src-d/go-billy.svg)](https://travis-ci.com/src-d/go-billy) [![Build status](https://ci.appveyor.com/api/projects/status/vx2qn6vlakbi724t?svg=true)](https://ci.appveyor.com/project/mcuadros/go-billy) [![codecov](https://codecov.io/gh/src-d/go-billy/branch/master/graph/badge.svg)](https://codecov.io/gh/src-d/go-billy) # go-billy [![GoDoc](https://godoc.org/gopkg.in/go-git/go-billy.v5?status.svg)](https://pkg.go.dev/github.com/go-git/go-billy) [![Test](https://github.com/go-git/go-billy/workflows/Test/badge.svg)](https://github.com/go-git/go-billy/actions?query=workflow%3ATest)
The missing interface filesystem abstraction for Go. The missing interface filesystem abstraction for Go.
Billy implements an interface based on the `os` standard library, allowing to develop applications without dependency on the underlying storage. Makes it virtually free to implement mocks and testing over filesystem operations. Billy implements an interface based on the `os` standard library, allowing to develop applications without dependency on the underlying storage. Makes it virtually free to implement mocks and testing over filesystem operations.
Billy was born as part of [src-d/go-git](https://github.com/src-d/go-git) project. Billy was born as part of [go-git/go-git](https://github.com/go-git/go-git) project.
## Installation ## Installation
```go ```go
go get -u gopkg.in/src-d/go-billy.v4/... import "github.com/go-git/go-billy/v5" // with go modules enabled (GO111MODULE=on or outside GOPATH)
import "github.com/go-git/go-billy" // with go modules disabled
``` ```
## Usage ## Usage
Billy exposes filesystems using the Billy exposes filesystems using the
[`Filesystem` interface](https://godoc.org/github.com/src-d/go-billy#Filesystem). [`Filesystem` interface](https://pkg.go.dev/github.com/go-git/go-billy/v5?tab=doc#Filesystem).
Each filesystem implementation gives you a `New` method, whose arguments depend on Each filesystem implementation gives you a `New` method, whose arguments depend on
the implementation itself, that returns a new `Filesystem`. the implementation itself, that returns a new `Filesystem`.

10
vendor/github.com/go-git/go-billy/v5/go.mod generated vendored Normal file
View File

@ -0,0 +1,10 @@
module github.com/go-git/go-billy/v5
require (
github.com/kr/text v0.2.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f
)
go 1.13

14
vendor/github.com/go-git/go-billy/v5/go.sum generated vendored Normal file
View File

@ -0,0 +1,14 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/go-git/go-billy v1.0.0 h1:bXR6Zu3opPSg0R4dDxqaLglY4rxw7ja7wS16qSpOKL4=
github.com/go-git/go-billy v3.1.0+incompatible h1:dwrJ8G2Jt1srYgIJs+lRjA36qBY68O2Lg5idKG8ef5M=
github.com/kr/pty v1.1.1/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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
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=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -5,8 +5,8 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"gopkg.in/src-d/go-billy.v4" "github.com/go-git/go-billy/v5"
"gopkg.in/src-d/go-billy.v4/helper/polyfill" "github.com/go-git/go-billy/v5/helper/polyfill"
) )
// ChrootHelper is a helper to implement billy.Chroot. // ChrootHelper is a helper to implement billy.Chroot.

View File

@ -4,7 +4,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"gopkg.in/src-d/go-billy.v4" "github.com/go-git/go-billy/v5"
) )
// Polyfill is a helper that implements all missing method from billy.Filesystem. // Polyfill is a helper that implements all missing method from billy.Filesystem.

View File

@ -1,5 +1,5 @@
// Package osfs provides a billy filesystem for the OS. // Package osfs provides a billy filesystem for the OS.
package osfs // import "gopkg.in/src-d/go-billy.v4/osfs" package osfs // import "github.com/go-git/go-billy/v5/osfs"
import ( import (
"io/ioutil" "io/ioutil"
@ -7,8 +7,8 @@ import (
"path/filepath" "path/filepath"
"sync" "sync"
"gopkg.in/src-d/go-billy.v4" "github.com/go-git/go-billy/v5"
"gopkg.in/src-d/go-billy.v4/helper/chroot" "github.com/go-git/go-billy/v5/helper/chroot"
) )
const ( const (
@ -72,7 +72,7 @@ func (fs *OS) Rename(from, to string) error {
return err return err
} }
return os.Rename(from, to) return rename(from, to)
} }
func (fs *OS) MkdirAll(path string, perm os.FileMode) error { func (fs *OS) MkdirAll(path string, perm os.FileMode) error {

Some files were not shown because too many files have changed in this diff Show More