Adds simple integration with github library and test with publish github

This commit is contained in:
Miguel de la Cruz 2020-03-07 13:08:03 +01:00
parent d5815e4e6a
commit fdaf72aac4
206 changed files with 63806 additions and 2 deletions

View file

@ -2,10 +2,12 @@ package cmd
import (
"fmt"
"context"
"git.ctrlz.es/mgdelacroix/campaigner/campaign"
"git.ctrlz.es/mgdelacroix/campaigner/config"
"git.ctrlz.es/mgdelacroix/campaigner/jira"
"git.ctrlz.es/mgdelacroix/campaigner/github"
"github.com/spf13/cobra"
)
@ -13,7 +15,7 @@ import (
func JiraPublishCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "jira",
Short: "Publishes the campaign tickets in JIRA",
Short: "Publishes the campaign tickets in jira",
Args: cobra.NoArgs,
RunE: jiraPublishCmdF,
}
@ -25,6 +27,21 @@ func JiraPublishCmd() *cobra.Command {
return cmd
}
func GithubPublishCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "github",
Short: "Publishes the campaign tickets in github",
Args: cobra.NoArgs,
Run: githubPublishCmdF,
}
cmd.Flags().BoolP("all", "a", false, "Publish all the tickets of the campaign")
cmd.Flags().IntP("batch", "b", 0, "Number of tickets to publish")
cmd.Flags().Bool("dry-run", false, "Print the tickets information instead of publishing them")
return cmd
}
func PublishCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "publish",
@ -32,6 +49,7 @@ func PublishCmd() *cobra.Command {
}
cmd.AddCommand(
GithubPublishCmd(),
JiraPublishCmd(),
)
@ -77,3 +95,26 @@ func jiraPublishCmdF(cmd *cobra.Command, _ []string) error {
return nil
}
func githubPublishCmdF(cmd *cobra.Command, _ []string) {
cfg, err := config.ReadConfig()
if err != nil {
ErrorAndExit(cmd, err)
}
// cmp, err := campaign.Read()
// if err != nil {
// ErrorAndExit(cmd, err)
// }
githubClient := github.NewClient("my/repo", cfg.GithubToken)
repos, _, err := githubClient.Repositories.List(context.Background(), "", nil)
if err != nil {
ErrorAndExit(cmd, err)
}
for _, repo := range repos {
cmd.Println(*repo.Name)
}
}

25
github/github.go Normal file
View file

@ -0,0 +1,25 @@
package github
import (
"context"
"golang.org/x/oauth2"
"github.com/google/go-github/v29/github"
)
type GithubClient struct {
*github.Client
Repo string
}
func NewClient(repo, token string) *GithubClient {
ctx := context.Background()
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
tc := oauth2.NewClient(ctx, ts)
client := github.NewClient(tc)
return &GithubClient{
Client: client,
Repo: repo,
}
}

4
go.mod
View file

@ -3,9 +3,11 @@ module git.ctrlz.es/mgdelacroix/campaigner
go 1.13
require (
github.com/fatih/color v1.9.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/go-github/v29 v29.0.3
github.com/spf13/cobra v0.0.6
github.com/trivago/tgo v1.0.7 // indirect
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
gopkg.in/andygrunwald/go-jira.v1 v1.8.0
)

19
go.sum
View file

@ -17,6 +17,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@ -32,8 +34,13 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github/v29 v29.0.3 h1:IktKCTwU//aFHnpA+2SLIi7Oo9uhAzgsdZNbcAqhgdc=
github.com/google/go-github/v29 v29.0.3/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@ -53,6 +60,11 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
@ -98,6 +110,7 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
@ -105,7 +118,9 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092 h1:4QSRKanuywn15aTZvI/mIDEgPQpswuFndXpOj3rKEco=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -115,11 +130,15 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=

3
vendor/github.com/golang/protobuf/AUTHORS generated vendored Normal file
View file

@ -0,0 +1,3 @@
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at http://tip.golang.org/AUTHORS.

3
vendor/github.com/golang/protobuf/CONTRIBUTORS generated vendored Normal file
View file

@ -0,0 +1,3 @@
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at http://tip.golang.org/CONTRIBUTORS.

28
vendor/github.com/golang/protobuf/LICENSE generated vendored Normal file
View file

@ -0,0 +1,28 @@
Copyright 2010 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

253
vendor/github.com/golang/protobuf/proto/clone.go generated vendored Normal file
View file

@ -0,0 +1,253 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2011 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Protocol buffer deep copy and merge.
// TODO: RawMessage.
package proto
import (
"fmt"
"log"
"reflect"
"strings"
)
// Clone returns a deep copy of a protocol buffer.
func Clone(src Message) Message {
in := reflect.ValueOf(src)
if in.IsNil() {
return src
}
out := reflect.New(in.Type().Elem())
dst := out.Interface().(Message)
Merge(dst, src)
return dst
}
// Merger is the interface representing objects that can merge messages of the same type.
type Merger interface {
// Merge merges src into this message.
// Required and optional fields that are set in src will be set to that value in dst.
// Elements of repeated fields will be appended.
//
// Merge may panic if called with a different argument type than the receiver.
Merge(src Message)
}
// generatedMerger is the custom merge method that generated protos will have.
// We must add this method since a generate Merge method will conflict with
// many existing protos that have a Merge data field already defined.
type generatedMerger interface {
XXX_Merge(src Message)
}
// Merge merges src into dst.
// Required and optional fields that are set in src will be set to that value in dst.
// Elements of repeated fields will be appended.
// Merge panics if src and dst are not the same type, or if dst is nil.
func Merge(dst, src Message) {
if m, ok := dst.(Merger); ok {
m.Merge(src)
return
}
in := reflect.ValueOf(src)
out := reflect.ValueOf(dst)
if out.IsNil() {
panic("proto: nil destination")
}
if in.Type() != out.Type() {
panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
}
if in.IsNil() {
return // Merge from nil src is a noop
}
if m, ok := dst.(generatedMerger); ok {
m.XXX_Merge(src)
return
}
mergeStruct(out.Elem(), in.Elem())
}
func mergeStruct(out, in reflect.Value) {
sprop := GetProperties(in.Type())
for i := 0; i < in.NumField(); i++ {
f := in.Type().Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
continue
}
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
}
if emIn, err := extendable(in.Addr().Interface()); err == nil {
emOut, _ := extendable(out.Addr().Interface())
mIn, muIn := emIn.extensionsRead()
if mIn != nil {
mOut := emOut.extensionsWrite()
muIn.Lock()
mergeExtension(mOut, mIn)
muIn.Unlock()
}
}
uf := in.FieldByName("XXX_unrecognized")
if !uf.IsValid() {
return
}
uin := uf.Bytes()
if len(uin) > 0 {
out.FieldByName("XXX_unrecognized").SetBytes(append([]byte(nil), uin...))
}
}
// mergeAny performs a merge between two values of the same type.
// viaPtr indicates whether the values were indirected through a pointer (implying proto2).
// prop is set if this is a struct field (it may be nil).
func mergeAny(out, in reflect.Value, viaPtr bool, prop *Properties) {
if in.Type() == protoMessageType {
if !in.IsNil() {
if out.IsNil() {
out.Set(reflect.ValueOf(Clone(in.Interface().(Message))))
} else {
Merge(out.Interface().(Message), in.Interface().(Message))
}
}
return
}
switch in.Kind() {
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
reflect.String, reflect.Uint32, reflect.Uint64:
if !viaPtr && isProto3Zero(in) {
return
}
out.Set(in)
case reflect.Interface:
// Probably a oneof field; copy non-nil values.
if in.IsNil() {
return
}
// Allocate destination if it is not set, or set to a different type.
// Otherwise we will merge as normal.
if out.IsNil() || out.Elem().Type() != in.Elem().Type() {
out.Set(reflect.New(in.Elem().Elem().Type())) // interface -> *T -> T -> new(T)
}
mergeAny(out.Elem(), in.Elem(), false, nil)
case reflect.Map:
if in.Len() == 0 {
return
}
if out.IsNil() {
out.Set(reflect.MakeMap(in.Type()))
}
// For maps with value types of *T or []byte we need to deep copy each value.
elemKind := in.Type().Elem().Kind()
for _, key := range in.MapKeys() {
var val reflect.Value
switch elemKind {
case reflect.Ptr:
val = reflect.New(in.Type().Elem().Elem())
mergeAny(val, in.MapIndex(key), false, nil)
case reflect.Slice:
val = in.MapIndex(key)
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
default:
val = in.MapIndex(key)
}
out.SetMapIndex(key, val)
}
case reflect.Ptr:
if in.IsNil() {
return
}
if out.IsNil() {
out.Set(reflect.New(in.Elem().Type()))
}
mergeAny(out.Elem(), in.Elem(), true, nil)
case reflect.Slice:
if in.IsNil() {
return
}
if in.Type().Elem().Kind() == reflect.Uint8 {
// []byte is a scalar bytes field, not a repeated field.
// Edge case: if this is in a proto3 message, a zero length
// bytes field is considered the zero value, and should not
// be merged.
if prop != nil && prop.proto3 && in.Len() == 0 {
return
}
// Make a deep copy.
// Append to []byte{} instead of []byte(nil) so that we never end up
// with a nil result.
out.SetBytes(append([]byte{}, in.Bytes()...))
return
}
n := in.Len()
if out.IsNil() {
out.Set(reflect.MakeSlice(in.Type(), 0, n))
}
switch in.Type().Elem().Kind() {
case reflect.Bool, reflect.Float32, reflect.Float64, reflect.Int32, reflect.Int64,
reflect.String, reflect.Uint32, reflect.Uint64:
out.Set(reflect.AppendSlice(out, in))
default:
for i := 0; i < n; i++ {
x := reflect.Indirect(reflect.New(in.Type().Elem()))
mergeAny(x, in.Index(i), false, nil)
out.Set(reflect.Append(out, x))
}
}
case reflect.Struct:
mergeStruct(out, in)
default:
// unknown type, so not a protocol buffer
log.Printf("proto: don't know how to copy %v", in)
}
}
func mergeExtension(out, in map[int32]Extension) {
for extNum, eIn := range in {
eOut := Extension{desc: eIn.desc}
if eIn.value != nil {
v := reflect.New(reflect.TypeOf(eIn.value)).Elem()
mergeAny(v, reflect.ValueOf(eIn.value), false, nil)
eOut.value = v.Interface()
}
if eIn.enc != nil {
eOut.enc = make([]byte, len(eIn.enc))
copy(eOut.enc, eIn.enc)
}
out[extNum] = eOut
}
}

427
vendor/github.com/golang/protobuf/proto/decode.go generated vendored Normal file
View file

@ -0,0 +1,427 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
/*
* Routines for decoding protocol buffer data to construct in-memory representations.
*/
import (
"errors"
"fmt"
"io"
)
// errOverflow is returned when an integer is too large to be represented.
var errOverflow = errors.New("proto: integer overflow")
// ErrInternalBadWireType is returned by generated code when an incorrect
// wire type is encountered. It does not get returned to user code.
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
// DecodeVarint reads a varint-encoded integer from the slice.
// It returns the integer and the number of bytes consumed, or
// zero if there is not enough.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func DecodeVarint(buf []byte) (x uint64, n int) {
for shift := uint(0); shift < 64; shift += 7 {
if n >= len(buf) {
return 0, 0
}
b := uint64(buf[n])
n++
x |= (b & 0x7F) << shift
if (b & 0x80) == 0 {
return x, n
}
}
// The number is too large to represent in a 64-bit value.
return 0, 0
}
func (p *Buffer) decodeVarintSlow() (x uint64, err error) {
i := p.index
l := len(p.buf)
for shift := uint(0); shift < 64; shift += 7 {
if i >= l {
err = io.ErrUnexpectedEOF
return
}
b := p.buf[i]
i++
x |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
p.index = i
return
}
}
// The number is too large to represent in a 64-bit value.
err = errOverflow
return
}
// DecodeVarint reads a varint-encoded integer from the Buffer.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func (p *Buffer) DecodeVarint() (x uint64, err error) {
i := p.index
buf := p.buf
if i >= len(buf) {
return 0, io.ErrUnexpectedEOF
} else if buf[i] < 0x80 {
p.index++
return uint64(buf[i]), nil
} else if len(buf)-i < 10 {
return p.decodeVarintSlow()
}
var b uint64
// we already checked the first byte
x = uint64(buf[i]) - 0x80
i++
b = uint64(buf[i])
i++
x += b << 7
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 7
b = uint64(buf[i])
i++
x += b << 14
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 14
b = uint64(buf[i])
i++
x += b << 21
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 21
b = uint64(buf[i])
i++
x += b << 28
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 28
b = uint64(buf[i])
i++
x += b << 35
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 35
b = uint64(buf[i])
i++
x += b << 42
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 42
b = uint64(buf[i])
i++
x += b << 49
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 49
b = uint64(buf[i])
i++
x += b << 56
if b&0x80 == 0 {
goto done
}
x -= 0x80 << 56
b = uint64(buf[i])
i++
x += b << 63
if b&0x80 == 0 {
goto done
}
return 0, errOverflow
done:
p.index = i
return x, nil
}
// DecodeFixed64 reads a 64-bit integer from the Buffer.
// This is the format for the
// fixed64, sfixed64, and double protocol buffer types.
func (p *Buffer) DecodeFixed64() (x uint64, err error) {
// x, err already 0
i := p.index + 8
if i < 0 || i > len(p.buf) {
err = io.ErrUnexpectedEOF
return
}
p.index = i
x = uint64(p.buf[i-8])
x |= uint64(p.buf[i-7]) << 8
x |= uint64(p.buf[i-6]) << 16
x |= uint64(p.buf[i-5]) << 24
x |= uint64(p.buf[i-4]) << 32
x |= uint64(p.buf[i-3]) << 40
x |= uint64(p.buf[i-2]) << 48
x |= uint64(p.buf[i-1]) << 56
return
}
// DecodeFixed32 reads a 32-bit integer from the Buffer.
// This is the format for the
// fixed32, sfixed32, and float protocol buffer types.
func (p *Buffer) DecodeFixed32() (x uint64, err error) {
// x, err already 0
i := p.index + 4
if i < 0 || i > len(p.buf) {
err = io.ErrUnexpectedEOF
return
}
p.index = i
x = uint64(p.buf[i-4])
x |= uint64(p.buf[i-3]) << 8
x |= uint64(p.buf[i-2]) << 16
x |= uint64(p.buf[i-1]) << 24
return
}
// DecodeZigzag64 reads a zigzag-encoded 64-bit integer
// from the Buffer.
// This is the format used for the sint64 protocol buffer type.
func (p *Buffer) DecodeZigzag64() (x uint64, err error) {
x, err = p.DecodeVarint()
if err != nil {
return
}
x = (x >> 1) ^ uint64((int64(x&1)<<63)>>63)
return
}
// DecodeZigzag32 reads a zigzag-encoded 32-bit integer
// from the Buffer.
// This is the format used for the sint32 protocol buffer type.
func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
x, err = p.DecodeVarint()
if err != nil {
return
}
x = uint64((uint32(x) >> 1) ^ uint32((int32(x&1)<<31)>>31))
return
}
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
// This is the format used for the bytes protocol buffer
// type and for embedded messages.
func (p *Buffer) DecodeRawBytes(alloc bool) (buf []byte, err error) {
n, err := p.DecodeVarint()
if err != nil {
return nil, err
}
nb := int(n)
if nb < 0 {
return nil, fmt.Errorf("proto: bad byte length %d", nb)
}
end := p.index + nb
if end < p.index || end > len(p.buf) {
return nil, io.ErrUnexpectedEOF
}
if !alloc {
// todo: check if can get more uses of alloc=false
buf = p.buf[p.index:end]
p.index += nb
return
}
buf = make([]byte, nb)
copy(buf, p.buf[p.index:])
p.index += nb
return
}
// DecodeStringBytes reads an encoded string from the Buffer.
// This is the format used for the proto2 string type.
func (p *Buffer) DecodeStringBytes() (s string, err error) {
buf, err := p.DecodeRawBytes(false)
if err != nil {
return
}
return string(buf), nil
}
// Unmarshaler is the interface representing objects that can
// unmarshal themselves. The argument points to data that may be
// overwritten, so implementations should not keep references to the
// buffer.
// Unmarshal implementations should not clear the receiver.
// Any unmarshaled data should be merged into the receiver.
// Callers of Unmarshal that do not want to retain existing data
// should Reset the receiver before calling Unmarshal.
type Unmarshaler interface {
Unmarshal([]byte) error
}
// newUnmarshaler is the interface representing objects that can
// unmarshal themselves. The semantics are identical to Unmarshaler.
//
// This exists to support protoc-gen-go generated messages.
// The proto package will stop type-asserting to this interface in the future.
//
// DO NOT DEPEND ON THIS.
type newUnmarshaler interface {
XXX_Unmarshal([]byte) error
}
// Unmarshal parses the protocol buffer representation in buf and places the
// decoded result in pb. If the struct underlying pb does not match
// the data in buf, the results can be unpredictable.
//
// Unmarshal resets pb before starting to unmarshal, so any
// existing data in pb is always removed. Use UnmarshalMerge
// to preserve and append to existing data.
func Unmarshal(buf []byte, pb Message) error {
pb.Reset()
if u, ok := pb.(newUnmarshaler); ok {
return u.XXX_Unmarshal(buf)
}
if u, ok := pb.(Unmarshaler); ok {
return u.Unmarshal(buf)
}
return NewBuffer(buf).Unmarshal(pb)
}
// UnmarshalMerge parses the protocol buffer representation in buf and
// writes the decoded result to pb. If the struct underlying pb does not match
// the data in buf, the results can be unpredictable.
//
// UnmarshalMerge merges into existing data in pb.
// Most code should use Unmarshal instead.
func UnmarshalMerge(buf []byte, pb Message) error {
if u, ok := pb.(newUnmarshaler); ok {
return u.XXX_Unmarshal(buf)
}
if u, ok := pb.(Unmarshaler); ok {
// NOTE: The history of proto have unfortunately been inconsistent
// whether Unmarshaler should or should not implicitly clear itself.
// Some implementations do, most do not.
// Thus, calling this here may or may not do what people want.
//
// See https://github.com/golang/protobuf/issues/424
return u.Unmarshal(buf)
}
return NewBuffer(buf).Unmarshal(pb)
}
// DecodeMessage reads a count-delimited message from the Buffer.
func (p *Buffer) DecodeMessage(pb Message) error {
enc, err := p.DecodeRawBytes(false)
if err != nil {
return err
}
return NewBuffer(enc).Unmarshal(pb)
}
// DecodeGroup reads a tag-delimited group from the Buffer.
// StartGroup tag is already consumed. This function consumes
// EndGroup tag.
func (p *Buffer) DecodeGroup(pb Message) error {
b := p.buf[p.index:]
x, y := findEndGroup(b)
if x < 0 {
return io.ErrUnexpectedEOF
}
err := Unmarshal(b[:x], pb)
p.index += y
return err
}
// Unmarshal parses the protocol buffer representation in the
// Buffer and places the decoded result in pb. If the struct
// underlying pb does not match the data in the buffer, the results can be
// unpredictable.
//
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
func (p *Buffer) Unmarshal(pb Message) error {
// If the object can unmarshal itself, let it.
if u, ok := pb.(newUnmarshaler); ok {
err := u.XXX_Unmarshal(p.buf[p.index:])
p.index = len(p.buf)
return err
}
if u, ok := pb.(Unmarshaler); ok {
// NOTE: The history of proto have unfortunately been inconsistent
// whether Unmarshaler should or should not implicitly clear itself.
// Some implementations do, most do not.
// Thus, calling this here may or may not do what people want.
//
// See https://github.com/golang/protobuf/issues/424
err := u.Unmarshal(p.buf[p.index:])
p.index = len(p.buf)
return err
}
// Slow workaround for messages that aren't Unmarshalers.
// This includes some hand-coded .pb.go files and
// bootstrap protos.
// TODO: fix all of those and then add Unmarshal to
// the Message interface. Then:
// The cast above and code below can be deleted.
// The old unmarshaler can be deleted.
// Clients can call Unmarshal directly (can already do that, actually).
var info InternalMessageInfo
err := info.Unmarshal(pb, p.buf[p.index:])
p.index = len(p.buf)
return err
}

63
vendor/github.com/golang/protobuf/proto/deprecated.go generated vendored Normal file
View file

@ -0,0 +1,63 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2018 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
import "errors"
// Deprecated: do not use.
type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
// Deprecated: do not use.
func GetStats() Stats { return Stats{} }
// Deprecated: do not use.
func MarshalMessageSet(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSet([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func MarshalMessageSetJSON(interface{}) ([]byte, error) {
return nil, errors.New("proto: not implemented")
}
// Deprecated: do not use.
func UnmarshalMessageSetJSON([]byte, interface{}) error {
return errors.New("proto: not implemented")
}
// Deprecated: do not use.
func RegisterMessageSetType(Message, int32, string) {}

350
vendor/github.com/golang/protobuf/proto/discard.go generated vendored Normal file
View file

@ -0,0 +1,350 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2017 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
import (
"fmt"
"reflect"
"strings"
"sync"
"sync/atomic"
)
type generatedDiscarder interface {
XXX_DiscardUnknown()
}
// DiscardUnknown recursively discards all unknown fields from this message
// and all embedded messages.
//
// When unmarshaling a message with unrecognized fields, the tags and values
// of such fields are preserved in the Message. This allows a later call to
// marshal to be able to produce a message that continues to have those
// unrecognized fields. To avoid this, DiscardUnknown is used to
// explicitly clear the unknown fields after unmarshaling.
//
// For proto2 messages, the unknown fields of message extensions are only
// discarded from messages that have been accessed via GetExtension.
func DiscardUnknown(m Message) {
if m, ok := m.(generatedDiscarder); ok {
m.XXX_DiscardUnknown()
return
}
// TODO: Dynamically populate a InternalMessageInfo for legacy messages,
// but the master branch has no implementation for InternalMessageInfo,
// so it would be more work to replicate that approach.
discardLegacy(m)
}
// DiscardUnknown recursively discards all unknown fields.
func (a *InternalMessageInfo) DiscardUnknown(m Message) {
di := atomicLoadDiscardInfo(&a.discard)
if di == nil {
di = getDiscardInfo(reflect.TypeOf(m).Elem())
atomicStoreDiscardInfo(&a.discard, di)
}
di.discard(toPointer(&m))
}
type discardInfo struct {
typ reflect.Type
initialized int32 // 0: only typ is valid, 1: everything is valid
lock sync.Mutex
fields []discardFieldInfo
unrecognized field
}
type discardFieldInfo struct {
field field // Offset of field, guaranteed to be valid
discard func(src pointer)
}
var (
discardInfoMap = map[reflect.Type]*discardInfo{}
discardInfoLock sync.Mutex
)
func getDiscardInfo(t reflect.Type) *discardInfo {
discardInfoLock.Lock()
defer discardInfoLock.Unlock()
di := discardInfoMap[t]
if di == nil {
di = &discardInfo{typ: t}
discardInfoMap[t] = di
}
return di
}
func (di *discardInfo) discard(src pointer) {
if src.isNil() {
return // Nothing to do.
}
if atomic.LoadInt32(&di.initialized) == 0 {
di.computeDiscardInfo()
}
for _, fi := range di.fields {
sfp := src.offset(fi.field)
fi.discard(sfp)
}
// For proto2 messages, only discard unknown fields in message extensions
// that have been accessed via GetExtension.
if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
// Ignore lock since DiscardUnknown is not concurrency safe.
emm, _ := em.extensionsRead()
for _, mx := range emm {
if m, ok := mx.value.(Message); ok {
DiscardUnknown(m)
}
}
}
if di.unrecognized.IsValid() {
*src.offset(di.unrecognized).toBytes() = nil
}
}
func (di *discardInfo) computeDiscardInfo() {
di.lock.Lock()
defer di.lock.Unlock()
if di.initialized != 0 {
return
}
t := di.typ
n := t.NumField()
for i := 0; i < n; i++ {
f := t.Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
continue
}
dfi := discardFieldInfo{field: toField(&f)}
tf := f.Type
// Unwrap tf to get its most basic type.
var isPointer, isSlice bool
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
isSlice = true
tf = tf.Elem()
}
if tf.Kind() == reflect.Ptr {
isPointer = true
tf = tf.Elem()
}
if isPointer && isSlice && tf.Kind() != reflect.Struct {
panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
}
switch tf.Kind() {
case reflect.Struct:
switch {
case !isPointer:
panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
case isSlice: // E.g., []*pb.T
di := getDiscardInfo(tf)
dfi.discard = func(src pointer) {
sps := src.getPointerSlice()
for _, sp := range sps {
if !sp.isNil() {
di.discard(sp)
}
}
}
default: // E.g., *pb.T
di := getDiscardInfo(tf)
dfi.discard = func(src pointer) {
sp := src.getPointer()
if !sp.isNil() {
di.discard(sp)
}
}
}
case reflect.Map:
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
default: // E.g., map[K]V
if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
dfi.discard = func(src pointer) {
sm := src.asPointerTo(tf).Elem()
if sm.Len() == 0 {
return
}
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
DiscardUnknown(val.Interface().(Message))
}
}
} else {
dfi.discard = func(pointer) {} // Noop
}
}
case reflect.Interface:
// Must be oneof field.
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
default: // E.g., interface{}
// TODO: Make this faster?
dfi.discard = func(src pointer) {
su := src.asPointerTo(tf).Elem()
if !su.IsNil() {
sv := su.Elem().Elem().Field(0)
if sv.Kind() == reflect.Ptr && sv.IsNil() {
return
}
switch sv.Type().Kind() {
case reflect.Ptr: // Proto struct (e.g., *T)
DiscardUnknown(sv.Interface().(Message))
}
}
}
}
default:
continue
}
di.fields = append(di.fields, dfi)
}
di.unrecognized = invalidField
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
if f.Type != reflect.TypeOf([]byte{}) {
panic("expected XXX_unrecognized to be of type []byte")
}
di.unrecognized = toField(&f)
}
atomic.StoreInt32(&di.initialized, 1)
}
func discardLegacy(m Message) {
v := reflect.ValueOf(m)
if v.Kind() != reflect.Ptr || v.IsNil() {
return
}
v = v.Elem()
if v.Kind() != reflect.Struct {
return
}
t := v.Type()
for i := 0; i < v.NumField(); i++ {
f := t.Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
continue
}
vf := v.Field(i)
tf := f.Type
// Unwrap tf to get its most basic type.
var isPointer, isSlice bool
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
isSlice = true
tf = tf.Elem()
}
if tf.Kind() == reflect.Ptr {
isPointer = true
tf = tf.Elem()
}
if isPointer && isSlice && tf.Kind() != reflect.Struct {
panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
}
switch tf.Kind() {
case reflect.Struct:
switch {
case !isPointer:
panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
case isSlice: // E.g., []*pb.T
for j := 0; j < vf.Len(); j++ {
discardLegacy(vf.Index(j).Interface().(Message))
}
default: // E.g., *pb.T
discardLegacy(vf.Interface().(Message))
}
case reflect.Map:
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
default: // E.g., map[K]V
tv := vf.Type().Elem()
if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
for _, key := range vf.MapKeys() {
val := vf.MapIndex(key)
discardLegacy(val.Interface().(Message))
}
}
}
case reflect.Interface:
// Must be oneof field.
switch {
case isPointer || isSlice:
panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
default: // E.g., test_proto.isCommunique_Union interface
if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
vf = vf.Elem() // E.g., *test_proto.Communique_Msg
if !vf.IsNil() {
vf = vf.Elem() // E.g., test_proto.Communique_Msg
vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
if vf.Kind() == reflect.Ptr {
discardLegacy(vf.Interface().(Message))
}
}
}
}
}
}
if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
if vf.Type() != reflect.TypeOf([]byte{}) {
panic("expected XXX_unrecognized to be of type []byte")
}
vf.Set(reflect.ValueOf([]byte(nil)))
}
// For proto2 messages, only discard unknown fields in message extensions
// that have been accessed via GetExtension.
if em, err := extendable(m); err == nil {
// Ignore lock since discardLegacy is not concurrency safe.
emm, _ := em.extensionsRead()
for _, mx := range emm {
if m, ok := mx.value.(Message); ok {
discardLegacy(m)
}
}
}
}

203
vendor/github.com/golang/protobuf/proto/encode.go generated vendored Normal file
View file

@ -0,0 +1,203 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
/*
* Routines for encoding data into the wire format for protocol buffers.
*/
import (
"errors"
"reflect"
)
var (
// errRepeatedHasNil is the error returned if Marshal is called with
// a struct with a repeated field containing a nil element.
errRepeatedHasNil = errors.New("proto: repeated field has nil element")
// errOneofHasNil is the error returned if Marshal is called with
// a struct with a oneof field containing a nil element.
errOneofHasNil = errors.New("proto: oneof field has nil value")
// ErrNil is the error returned if Marshal is called with nil.
ErrNil = errors.New("proto: Marshal called with nil")
// ErrTooLarge is the error returned if Marshal is called with a
// message that encodes to >2GB.
ErrTooLarge = errors.New("proto: message encodes to over 2 GB")
)
// The fundamental encoders that put bytes on the wire.
// Those that take integer types all accept uint64 and are
// therefore of type valueEncoder.
const maxVarintBytes = 10 // maximum length of a varint
// EncodeVarint returns the varint encoding of x.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
// Not used by the package itself, but helpful to clients
// wishing to use the same encoding.
func EncodeVarint(x uint64) []byte {
var buf [maxVarintBytes]byte
var n int
for n = 0; x > 127; n++ {
buf[n] = 0x80 | uint8(x&0x7F)
x >>= 7
}
buf[n] = uint8(x)
n++
return buf[0:n]
}
// EncodeVarint writes a varint-encoded integer to the Buffer.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
// protocol buffer types.
func (p *Buffer) EncodeVarint(x uint64) error {
for x >= 1<<7 {
p.buf = append(p.buf, uint8(x&0x7f|0x80))
x >>= 7
}
p.buf = append(p.buf, uint8(x))
return nil
}
// SizeVarint returns the varint encoding size of an integer.
func SizeVarint(x uint64) int {
switch {
case x < 1<<7:
return 1
case x < 1<<14:
return 2
case x < 1<<21:
return 3
case x < 1<<28:
return 4
case x < 1<<35:
return 5
case x < 1<<42:
return 6
case x < 1<<49:
return 7
case x < 1<<56:
return 8
case x < 1<<63:
return 9
}
return 10
}
// EncodeFixed64 writes a 64-bit integer to the Buffer.
// This is the format for the
// fixed64, sfixed64, and double protocol buffer types.
func (p *Buffer) EncodeFixed64(x uint64) error {
p.buf = append(p.buf,
uint8(x),
uint8(x>>8),
uint8(x>>16),
uint8(x>>24),
uint8(x>>32),
uint8(x>>40),
uint8(x>>48),
uint8(x>>56))
return nil
}
// EncodeFixed32 writes a 32-bit integer to the Buffer.
// This is the format for the
// fixed32, sfixed32, and float protocol buffer types.
func (p *Buffer) EncodeFixed32(x uint64) error {
p.buf = append(p.buf,
uint8(x),
uint8(x>>8),
uint8(x>>16),
uint8(x>>24))
return nil
}
// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
// to the Buffer.
// This is the format used for the sint64 protocol buffer type.
func (p *Buffer) EncodeZigzag64(x uint64) error {
// use signed number to get arithmetic right shift.
return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
// to the Buffer.
// This is the format used for the sint32 protocol buffer type.
func (p *Buffer) EncodeZigzag32(x uint64) error {
// use signed number to get arithmetic right shift.
return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
}
// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
// This is the format used for the bytes protocol buffer
// type and for embedded messages.
func (p *Buffer) EncodeRawBytes(b []byte) error {
p.EncodeVarint(uint64(len(b)))
p.buf = append(p.buf, b...)
return nil
}
// EncodeStringBytes writes an encoded string to the Buffer.
// This is the format used for the proto2 string type.
func (p *Buffer) EncodeStringBytes(s string) error {
p.EncodeVarint(uint64(len(s)))
p.buf = append(p.buf, s...)
return nil
}
// Marshaler is the interface representing objects that can marshal themselves.
type Marshaler interface {
Marshal() ([]byte, error)
}
// EncodeMessage writes the protocol buffer to the Buffer,
// prefixed by a varint-encoded length.
func (p *Buffer) EncodeMessage(pb Message) error {
siz := Size(pb)
p.EncodeVarint(uint64(siz))
return p.Marshal(pb)
}
// All protocol buffer fields are nillable, but be careful.
func isNil(v reflect.Value) bool {
switch v.Kind() {
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return v.IsNil()
}
return false
}

301
vendor/github.com/golang/protobuf/proto/equal.go generated vendored Normal file
View file

@ -0,0 +1,301 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2011 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Protocol buffer comparison.
package proto
import (
"bytes"
"log"
"reflect"
"strings"
)
/*
Equal returns true iff protocol buffers a and b are equal.
The arguments must both be pointers to protocol buffer structs.
Equality is defined in this way:
- Two messages are equal iff they are the same type,
corresponding fields are equal, unknown field sets
are equal, and extensions sets are equal.
- Two set scalar fields are equal iff their values are equal.
If the fields are of a floating-point type, remember that
NaN != x for all x, including NaN. If the message is defined
in a proto3 .proto file, fields are not "set"; specifically,
zero length proto3 "bytes" fields are equal (nil == {}).
- Two repeated fields are equal iff their lengths are the same,
and their corresponding elements are equal. Note a "bytes" field,
although represented by []byte, is not a repeated field and the
rule for the scalar fields described above applies.
- Two unset fields are equal.
- Two unknown field sets are equal if their current
encoded state is equal.
- Two extension sets are equal iff they have corresponding
elements that are pairwise equal.
- Two map fields are equal iff their lengths are the same,
and they contain the same set of elements. Zero-length map
fields are equal.
- Every other combination of things are not equal.
The return value is undefined if a and b are not protocol buffers.
*/
func Equal(a, b Message) bool {
if a == nil || b == nil {
return a == b
}
v1, v2 := reflect.ValueOf(a), reflect.ValueOf(b)
if v1.Type() != v2.Type() {
return false
}
if v1.Kind() == reflect.Ptr {
if v1.IsNil() {
return v2.IsNil()
}
if v2.IsNil() {
return false
}
v1, v2 = v1.Elem(), v2.Elem()
}
if v1.Kind() != reflect.Struct {
return false
}
return equalStruct(v1, v2)
}
// v1 and v2 are known to have the same type.
func equalStruct(v1, v2 reflect.Value) bool {
sprop := GetProperties(v1.Type())
for i := 0; i < v1.NumField(); i++ {
f := v1.Type().Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
continue
}
f1, f2 := v1.Field(i), v2.Field(i)
if f.Type.Kind() == reflect.Ptr {
if n1, n2 := f1.IsNil(), f2.IsNil(); n1 && n2 {
// both unset
continue
} else if n1 != n2 {
// set/unset mismatch
return false
}
f1, f2 = f1.Elem(), f2.Elem()
}
if !equalAny(f1, f2, sprop.Prop[i]) {
return false
}
}
if em1 := v1.FieldByName("XXX_InternalExtensions"); em1.IsValid() {
em2 := v2.FieldByName("XXX_InternalExtensions")
if !equalExtensions(v1.Type(), em1.Interface().(XXX_InternalExtensions), em2.Interface().(XXX_InternalExtensions)) {
return false
}
}
if em1 := v1.FieldByName("XXX_extensions"); em1.IsValid() {
em2 := v2.FieldByName("XXX_extensions")
if !equalExtMap(v1.Type(), em1.Interface().(map[int32]Extension), em2.Interface().(map[int32]Extension)) {
return false
}
}
uf := v1.FieldByName("XXX_unrecognized")
if !uf.IsValid() {
return true
}
u1 := uf.Bytes()
u2 := v2.FieldByName("XXX_unrecognized").Bytes()
return bytes.Equal(u1, u2)
}
// v1 and v2 are known to have the same type.
// prop may be nil.
func equalAny(v1, v2 reflect.Value, prop *Properties) bool {
if v1.Type() == protoMessageType {
m1, _ := v1.Interface().(Message)
m2, _ := v2.Interface().(Message)
return Equal(m1, m2)
}
switch v1.Kind() {
case reflect.Bool:
return v1.Bool() == v2.Bool()
case reflect.Float32, reflect.Float64:
return v1.Float() == v2.Float()
case reflect.Int32, reflect.Int64:
return v1.Int() == v2.Int()
case reflect.Interface:
// Probably a oneof field; compare the inner values.
n1, n2 := v1.IsNil(), v2.IsNil()
if n1 || n2 {
return n1 == n2
}
e1, e2 := v1.Elem(), v2.Elem()
if e1.Type() != e2.Type() {
return false
}
return equalAny(e1, e2, nil)
case reflect.Map:
if v1.Len() != v2.Len() {
return false
}
for _, key := range v1.MapKeys() {
val2 := v2.MapIndex(key)
if !val2.IsValid() {
// This key was not found in the second map.
return false
}
if !equalAny(v1.MapIndex(key), val2, nil) {
return false
}
}
return true
case reflect.Ptr:
// Maps may have nil values in them, so check for nil.
if v1.IsNil() && v2.IsNil() {
return true
}
if v1.IsNil() != v2.IsNil() {
return false
}
return equalAny(v1.Elem(), v2.Elem(), prop)
case reflect.Slice:
if v1.Type().Elem().Kind() == reflect.Uint8 {
// short circuit: []byte
// Edge case: if this is in a proto3 message, a zero length
// bytes field is considered the zero value.
if prop != nil && prop.proto3 && v1.Len() == 0 && v2.Len() == 0 {
return true
}
if v1.IsNil() != v2.IsNil() {
return false
}
return bytes.Equal(v1.Interface().([]byte), v2.Interface().([]byte))
}
if v1.Len() != v2.Len() {
return false
}
for i := 0; i < v1.Len(); i++ {
if !equalAny(v1.Index(i), v2.Index(i), prop) {
return false
}
}
return true
case reflect.String:
return v1.Interface().(string) == v2.Interface().(string)
case reflect.Struct:
return equalStruct(v1, v2)
case reflect.Uint32, reflect.Uint64:
return v1.Uint() == v2.Uint()
}
// unknown type, so not a protocol buffer
log.Printf("proto: don't know how to compare %v", v1)
return false
}
// base is the struct type that the extensions are based on.
// x1 and x2 are InternalExtensions.
func equalExtensions(base reflect.Type, x1, x2 XXX_InternalExtensions) bool {
em1, _ := x1.extensionsRead()
em2, _ := x2.extensionsRead()
return equalExtMap(base, em1, em2)
}
func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
if len(em1) != len(em2) {
return false
}
for extNum, e1 := range em1 {
e2, ok := em2[extNum]
if !ok {
return false
}
m1 := extensionAsLegacyType(e1.value)
m2 := extensionAsLegacyType(e2.value)
if m1 == nil && m2 == nil {
// Both have only encoded form.
if bytes.Equal(e1.enc, e2.enc) {
continue
}
// The bytes are different, but the extensions might still be
// equal. We need to decode them to compare.
}
if m1 != nil && m2 != nil {
// Both are unencoded.
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
return false
}
continue
}
// At least one is encoded. To do a semantically correct comparison
// we need to unmarshal them first.
var desc *ExtensionDesc
if m := extensionMaps[base]; m != nil {
desc = m[extNum]
}
if desc == nil {
// If both have only encoded form and the bytes are the same,
// it is handled above. We get here when the bytes are different.
// We don't know how to decode it, so just compare them as byte
// slices.
log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
return false
}
var err error
if m1 == nil {
m1, err = decodeExtension(e1.enc, desc)
}
if m2 == nil && err == nil {
m2, err = decodeExtension(e2.enc, desc)
}
if err != nil {
// The encoded form is invalid.
log.Printf("proto: badly encoded extension %d of %v: %v", extNum, base, err)
return false
}
if !equalAny(reflect.ValueOf(m1), reflect.ValueOf(m2), nil) {
return false
}
}
return true
}

607
vendor/github.com/golang/protobuf/proto/extensions.go generated vendored Normal file
View file

@ -0,0 +1,607 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
/*
* Types and routines for supporting protocol buffer extensions.
*/
import (
"errors"
"fmt"
"io"
"reflect"
"strconv"
"sync"
)
// ErrMissingExtension is the error returned by GetExtension if the named extension is not in the message.
var ErrMissingExtension = errors.New("proto: missing extension")
// ExtensionRange represents a range of message extensions for a protocol buffer.
// Used in code generated by the protocol compiler.
type ExtensionRange struct {
Start, End int32 // both inclusive
}
// extendableProto is an interface implemented by any protocol buffer generated by the current
// proto compiler that may be extended.
type extendableProto interface {
Message
ExtensionRangeArray() []ExtensionRange
extensionsWrite() map[int32]Extension
extensionsRead() (map[int32]Extension, sync.Locker)
}
// extendableProtoV1 is an interface implemented by a protocol buffer generated by the previous
// version of the proto compiler that may be extended.
type extendableProtoV1 interface {
Message
ExtensionRangeArray() []ExtensionRange
ExtensionMap() map[int32]Extension
}
// extensionAdapter is a wrapper around extendableProtoV1 that implements extendableProto.
type extensionAdapter struct {
extendableProtoV1
}
func (e extensionAdapter) extensionsWrite() map[int32]Extension {
return e.ExtensionMap()
}
func (e extensionAdapter) extensionsRead() (map[int32]Extension, sync.Locker) {
return e.ExtensionMap(), notLocker{}
}
// notLocker is a sync.Locker whose Lock and Unlock methods are nops.
type notLocker struct{}
func (n notLocker) Lock() {}
func (n notLocker) Unlock() {}
// extendable returns the extendableProto interface for the given generated proto message.
// If the proto message has the old extension format, it returns a wrapper that implements
// the extendableProto interface.
func extendable(p interface{}) (extendableProto, error) {
switch p := p.(type) {
case extendableProto:
if isNilPtr(p) {
return nil, fmt.Errorf("proto: nil %T is not extendable", p)
}
return p, nil
case extendableProtoV1:
if isNilPtr(p) {
return nil, fmt.Errorf("proto: nil %T is not extendable", p)
}
return extensionAdapter{p}, nil
}
// Don't allocate a specific error containing %T:
// this is the hot path for Clone and MarshalText.
return nil, errNotExtendable
}
var errNotExtendable = errors.New("proto: not an extendable proto.Message")
func isNilPtr(x interface{}) bool {
v := reflect.ValueOf(x)
return v.Kind() == reflect.Ptr && v.IsNil()
}
// XXX_InternalExtensions is an internal representation of proto extensions.
//
// Each generated message struct type embeds an anonymous XXX_InternalExtensions field,
// thus gaining the unexported 'extensions' method, which can be called only from the proto package.
//
// The methods of XXX_InternalExtensions are not concurrency safe in general,
// but calls to logically read-only methods such as has and get may be executed concurrently.
type XXX_InternalExtensions struct {
// The struct must be indirect so that if a user inadvertently copies a
// generated message and its embedded XXX_InternalExtensions, they
// avoid the mayhem of a copied mutex.
//
// The mutex serializes all logically read-only operations to p.extensionMap.
// It is up to the client to ensure that write operations to p.extensionMap are
// mutually exclusive with other accesses.
p *struct {
mu sync.Mutex
extensionMap map[int32]Extension
}
}
// extensionsWrite returns the extension map, creating it on first use.
func (e *XXX_InternalExtensions) extensionsWrite() map[int32]Extension {
if e.p == nil {
e.p = new(struct {
mu sync.Mutex
extensionMap map[int32]Extension
})
e.p.extensionMap = make(map[int32]Extension)
}
return e.p.extensionMap
}
// extensionsRead returns the extensions map for read-only use. It may be nil.
// The caller must hold the returned mutex's lock when accessing Elements within the map.
func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Locker) {
if e.p == nil {
return nil, nil
}
return e.p.extensionMap, &e.p.mu
}
// ExtensionDesc represents an extension specification.
// Used in generated code from the protocol compiler.
type ExtensionDesc struct {
ExtendedType Message // nil pointer to the type that is being extended
ExtensionType interface{} // nil pointer to the extension type
Field int32 // field number
Name string // fully-qualified name of extension, for text formatting
Tag string // protobuf tag style
Filename string // name of the file in which the extension is defined
}
func (ed *ExtensionDesc) repeated() bool {
t := reflect.TypeOf(ed.ExtensionType)
return t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
}
// Extension represents an extension in a message.
type Extension struct {
// When an extension is stored in a message using SetExtension
// only desc and value are set. When the message is marshaled
// enc will be set to the encoded form of the message.
//
// When a message is unmarshaled and contains extensions, each
// extension will have only enc set. When such an extension is
// accessed using GetExtension (or GetExtensions) desc and value
// will be set.
desc *ExtensionDesc
// value is a concrete value for the extension field. Let the type of
// desc.ExtensionType be the "API type" and the type of Extension.value
// be the "storage type". The API type and storage type are the same except:
// * For scalars (except []byte), the API type uses *T,
// while the storage type uses T.
// * For repeated fields, the API type uses []T, while the storage type
// uses *[]T.
//
// The reason for the divergence is so that the storage type more naturally
// matches what is expected of when retrieving the values through the
// protobuf reflection APIs.
//
// The value may only be populated if desc is also populated.
value interface{}
// enc is the raw bytes for the extension field.
enc []byte
}
// SetRawExtension is for testing only.
func SetRawExtension(base Message, id int32, b []byte) {
epb, err := extendable(base)
if err != nil {
return
}
extmap := epb.extensionsWrite()
extmap[id] = Extension{enc: b}
}
// isExtensionField returns true iff the given field number is in an extension range.
func isExtensionField(pb extendableProto, field int32) bool {
for _, er := range pb.ExtensionRangeArray() {
if er.Start <= field && field <= er.End {
return true
}
}
return false
}
// checkExtensionTypes checks that the given extension is valid for pb.
func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
var pbi interface{} = pb
// Check the extended type.
if ea, ok := pbi.(extensionAdapter); ok {
pbi = ea.extendableProtoV1
}
if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
}
// Check the range.
if !isExtensionField(pb, extension.Field) {
return errors.New("proto: bad extension number; not in declared ranges")
}
return nil
}
// extPropKey is sufficient to uniquely identify an extension.
type extPropKey struct {
base reflect.Type
field int32
}
var extProp = struct {
sync.RWMutex
m map[extPropKey]*Properties
}{
m: make(map[extPropKey]*Properties),
}
func extensionProperties(ed *ExtensionDesc) *Properties {
key := extPropKey{base: reflect.TypeOf(ed.ExtendedType), field: ed.Field}
extProp.RLock()
if prop, ok := extProp.m[key]; ok {
extProp.RUnlock()
return prop
}
extProp.RUnlock()
extProp.Lock()
defer extProp.Unlock()
// Check again.
if prop, ok := extProp.m[key]; ok {
return prop
}
prop := new(Properties)
prop.Init(reflect.TypeOf(ed.ExtensionType), "unknown_name", ed.Tag, nil)
extProp.m[key] = prop
return prop
}
// HasExtension returns whether the given extension is present in pb.
func HasExtension(pb Message, extension *ExtensionDesc) bool {
// TODO: Check types, field numbers, etc.?
epb, err := extendable(pb)
if err != nil {
return false
}
extmap, mu := epb.extensionsRead()
if extmap == nil {
return false
}
mu.Lock()
_, ok := extmap[extension.Field]
mu.Unlock()
return ok
}
// ClearExtension removes the given extension from pb.
func ClearExtension(pb Message, extension *ExtensionDesc) {
epb, err := extendable(pb)
if err != nil {
return
}
// TODO: Check types, field numbers, etc.?
extmap := epb.extensionsWrite()
delete(extmap, extension.Field)
}
// GetExtension retrieves a proto2 extended field from pb.
//
// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
// then GetExtension parses the encoded field and returns a Go value of the specified type.
// If the field is not present, then the default value is returned (if one is specified),
// otherwise ErrMissingExtension is reported.
//
// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
// then GetExtension returns the raw encoded bytes of the field extension.
func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
epb, err := extendable(pb)
if err != nil {
return nil, err
}
if extension.ExtendedType != nil {
// can only check type if this is a complete descriptor
if err := checkExtensionTypes(epb, extension); err != nil {
return nil, err
}
}
emap, mu := epb.extensionsRead()
if emap == nil {
return defaultExtensionValue(extension)
}
mu.Lock()
defer mu.Unlock()
e, ok := emap[extension.Field]
if !ok {
// defaultExtensionValue returns the default value or
// ErrMissingExtension if there is no default.
return defaultExtensionValue(extension)
}
if e.value != nil {
// Already decoded. Check the descriptor, though.
if e.desc != extension {
// This shouldn't happen. If it does, it means that
// GetExtension was called twice with two different
// descriptors with the same field number.
return nil, errors.New("proto: descriptor conflict")
}
return extensionAsLegacyType(e.value), nil
}
if extension.ExtensionType == nil {
// incomplete descriptor
return e.enc, nil
}
v, err := decodeExtension(e.enc, extension)
if err != nil {
return nil, err
}
// Remember the decoded version and drop the encoded version.
// That way it is safe to mutate what we return.
e.value = extensionAsStorageType(v)
e.desc = extension
e.enc = nil
emap[extension.Field] = e
return extensionAsLegacyType(e.value), nil
}
// defaultExtensionValue returns the default value for extension.
// If no default for an extension is defined ErrMissingExtension is returned.
func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
if extension.ExtensionType == nil {
// incomplete descriptor, so no default
return nil, ErrMissingExtension
}
t := reflect.TypeOf(extension.ExtensionType)
props := extensionProperties(extension)
sf, _, err := fieldDefault(t, props)
if err != nil {
return nil, err
}
if sf == nil || sf.value == nil {
// There is no default value.
return nil, ErrMissingExtension
}
if t.Kind() != reflect.Ptr {
// We do not need to return a Ptr, we can directly return sf.value.
return sf.value, nil
}
// We need to return an interface{} that is a pointer to sf.value.
value := reflect.New(t).Elem()
value.Set(reflect.New(value.Type().Elem()))
if sf.kind == reflect.Int32 {
// We may have an int32 or an enum, but the underlying data is int32.
// Since we can't set an int32 into a non int32 reflect.value directly
// set it as a int32.
value.Elem().SetInt(int64(sf.value.(int32)))
} else {
value.Elem().Set(reflect.ValueOf(sf.value))
}
return value.Interface(), nil
}
// decodeExtension decodes an extension encoded in b.
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
t := reflect.TypeOf(extension.ExtensionType)
unmarshal := typeUnmarshaler(t, extension.Tag)
// t is a pointer to a struct, pointer to basic type or a slice.
// Allocate space to store the pointer/slice.
value := reflect.New(t).Elem()
var err error
for {
x, n := decodeVarint(b)
if n == 0 {
return nil, io.ErrUnexpectedEOF
}
b = b[n:]
wire := int(x) & 7
b, err = unmarshal(b, valToPointer(value.Addr()), wire)
if err != nil {
return nil, err
}
if len(b) == 0 {
break
}
}
return value.Interface(), nil
}
// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
// The returned slice has the same length as es; missing extensions will appear as nil elements.
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
epb, err := extendable(pb)
if err != nil {
return nil, err
}
extensions = make([]interface{}, len(es))
for i, e := range es {
extensions[i], err = GetExtension(epb, e)
if err == ErrMissingExtension {
err = nil
}
if err != nil {
return
}
}
return
}
// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
// just the Field field, which defines the extension's field number.
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
epb, err := extendable(pb)
if err != nil {
return nil, err
}
registeredExtensions := RegisteredExtensions(pb)
emap, mu := epb.extensionsRead()
if emap == nil {
return nil, nil
}
mu.Lock()
defer mu.Unlock()
extensions := make([]*ExtensionDesc, 0, len(emap))
for extid, e := range emap {
desc := e.desc
if desc == nil {
desc = registeredExtensions[extid]
if desc == nil {
desc = &ExtensionDesc{Field: extid}
}
}
extensions = append(extensions, desc)
}
return extensions, nil
}
// SetExtension sets the specified extension of pb to the specified value.
func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
epb, err := extendable(pb)
if err != nil {
return err
}
if err := checkExtensionTypes(epb, extension); err != nil {
return err
}
typ := reflect.TypeOf(extension.ExtensionType)
if typ != reflect.TypeOf(value) {
return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
}
// nil extension values need to be caught early, because the
// encoder can't distinguish an ErrNil due to a nil extension
// from an ErrNil due to a missing field. Extensions are
// always optional, so the encoder would just swallow the error
// and drop all the extensions from the encoded message.
if reflect.ValueOf(value).IsNil() {
return fmt.Errorf("proto: SetExtension called with nil value of type %T", value)
}
extmap := epb.extensionsWrite()
extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
return nil
}
// ClearAllExtensions clears all extensions from pb.
func ClearAllExtensions(pb Message) {
epb, err := extendable(pb)
if err != nil {
return
}
m := epb.extensionsWrite()
for k := range m {
delete(m, k)
}
}
// A global registry of extensions.
// The generated code will register the generated descriptors by calling RegisterExtension.
var extensionMaps = make(map[reflect.Type]map[int32]*ExtensionDesc)
// RegisterExtension is called from the generated code.
func RegisterExtension(desc *ExtensionDesc) {
st := reflect.TypeOf(desc.ExtendedType).Elem()
m := extensionMaps[st]
if m == nil {
m = make(map[int32]*ExtensionDesc)
extensionMaps[st] = m
}
if _, ok := m[desc.Field]; ok {
panic("proto: duplicate extension registered: " + st.String() + " " + strconv.Itoa(int(desc.Field)))
}
m[desc.Field] = desc
}
// RegisteredExtensions returns a map of the registered extensions of a
// protocol buffer struct, indexed by the extension number.
// The argument pb should be a nil pointer to the struct type.
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
return extensionMaps[reflect.TypeOf(pb).Elem()]
}
// extensionAsLegacyType converts an value in the storage type as the API type.
// See Extension.value.
func extensionAsLegacyType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
// Represent primitive types as a pointer to the value.
rv2 := reflect.New(rv.Type())
rv2.Elem().Set(rv)
v = rv2.Interface()
case reflect.Ptr:
// Represent slice types as the value itself.
switch rv.Type().Elem().Kind() {
case reflect.Slice:
if rv.IsNil() {
v = reflect.Zero(rv.Type().Elem()).Interface()
} else {
v = rv.Elem().Interface()
}
}
}
return v
}
// extensionAsStorageType converts an value in the API type as the storage type.
// See Extension.value.
func extensionAsStorageType(v interface{}) interface{} {
switch rv := reflect.ValueOf(v); rv.Kind() {
case reflect.Ptr:
// Represent slice types as the value itself.
switch rv.Type().Elem().Kind() {
case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
if rv.IsNil() {
v = reflect.Zero(rv.Type().Elem()).Interface()
} else {
v = rv.Elem().Interface()
}
}
case reflect.Slice:
// Represent slice types as a pointer to the value.
if rv.Type().Elem().Kind() != reflect.Uint8 {
rv2 := reflect.New(rv.Type())
rv2.Elem().Set(rv)
v = rv2.Interface()
}
}
return v
}

965
vendor/github.com/golang/protobuf/proto/lib.go generated vendored Normal file
View file

@ -0,0 +1,965 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
Package proto converts data structures to and from the wire format of
protocol buffers. It works in concert with the Go source code generated
for .proto files by the protocol compiler.
A summary of the properties of the protocol buffer interface
for a protocol buffer variable v:
- Names are turned from camel_case to CamelCase for export.
- There are no methods on v to set fields; just treat
them as structure fields.
- There are getters that return a field's value if set,
and return the field's default value if unset.
The getters work even if the receiver is a nil message.
- The zero value for a struct is its correct initialization state.
All desired fields must be set before marshaling.
- A Reset() method will restore a protobuf struct to its zero state.
- Non-repeated fields are pointers to the values; nil means unset.
That is, optional or required field int32 f becomes F *int32.
- Repeated fields are slices.
- Helper functions are available to aid the setting of fields.
msg.Foo = proto.String("hello") // set field
- Constants are defined to hold the default values of all fields that
have them. They have the form Default_StructName_FieldName.
Because the getter methods handle defaulted values,
direct use of these constants should be rare.
- Enums are given type names and maps from names to values.
Enum values are prefixed by the enclosing message's name, or by the
enum's type name if it is a top-level enum. Enum types have a String
method, and a Enum method to assist in message construction.
- Nested messages, groups and enums have type names prefixed with the name of
the surrounding message type.
- Extensions are given descriptor names that start with E_,
followed by an underscore-delimited list of the nested messages
that contain it (if any) followed by the CamelCased name of the
extension field itself. HasExtension, ClearExtension, GetExtension
and SetExtension are functions for manipulating extensions.
- Oneof field sets are given a single field in their message,
with distinguished wrapper types for each possible field value.
- Marshal and Unmarshal are functions to encode and decode the wire format.
When the .proto file specifies `syntax="proto3"`, there are some differences:
- Non-repeated fields of non-message type are values instead of pointers.
- Enum types do not get an Enum method.
The simplest way to describe this is to see an example.
Given file test.proto, containing
package example;
enum FOO { X = 17; }
message Test {
required string label = 1;
optional int32 type = 2 [default=77];
repeated int64 reps = 3;
optional group OptionalGroup = 4 {
required string RequiredField = 5;
}
oneof union {
int32 number = 6;
string name = 7;
}
}
The resulting file, test.pb.go, is:
package example
import proto "github.com/golang/protobuf/proto"
import math "math"
type FOO int32
const (
FOO_X FOO = 17
)
var FOO_name = map[int32]string{
17: "X",
}
var FOO_value = map[string]int32{
"X": 17,
}
func (x FOO) Enum() *FOO {
p := new(FOO)
*p = x
return p
}
func (x FOO) String() string {
return proto.EnumName(FOO_name, int32(x))
}
func (x *FOO) UnmarshalJSON(data []byte) error {
value, err := proto.UnmarshalJSONEnum(FOO_value, data)
if err != nil {
return err
}
*x = FOO(value)
return nil
}
type Test struct {
Label *string `protobuf:"bytes,1,req,name=label" json:"label,omitempty"`
Type *int32 `protobuf:"varint,2,opt,name=type,def=77" json:"type,omitempty"`
Reps []int64 `protobuf:"varint,3,rep,name=reps" json:"reps,omitempty"`
Optionalgroup *Test_OptionalGroup `protobuf:"group,4,opt,name=OptionalGroup" json:"optionalgroup,omitempty"`
// Types that are valid to be assigned to Union:
// *Test_Number
// *Test_Name
Union isTest_Union `protobuf_oneof:"union"`
XXX_unrecognized []byte `json:"-"`
}
func (m *Test) Reset() { *m = Test{} }
func (m *Test) String() string { return proto.CompactTextString(m) }
func (*Test) ProtoMessage() {}
type isTest_Union interface {
isTest_Union()
}
type Test_Number struct {
Number int32 `protobuf:"varint,6,opt,name=number"`
}
type Test_Name struct {
Name string `protobuf:"bytes,7,opt,name=name"`
}
func (*Test_Number) isTest_Union() {}
func (*Test_Name) isTest_Union() {}
func (m *Test) GetUnion() isTest_Union {
if m != nil {
return m.Union
}
return nil
}
const Default_Test_Type int32 = 77
func (m *Test) GetLabel() string {
if m != nil && m.Label != nil {
return *m.Label
}
return ""
}
func (m *Test) GetType() int32 {
if m != nil && m.Type != nil {
return *m.Type
}
return Default_Test_Type
}
func (m *Test) GetOptionalgroup() *Test_OptionalGroup {
if m != nil {
return m.Optionalgroup
}
return nil
}
type Test_OptionalGroup struct {
RequiredField *string `protobuf:"bytes,5,req" json:"RequiredField,omitempty"`
}
func (m *Test_OptionalGroup) Reset() { *m = Test_OptionalGroup{} }
func (m *Test_OptionalGroup) String() string { return proto.CompactTextString(m) }
func (m *Test_OptionalGroup) GetRequiredField() string {
if m != nil && m.RequiredField != nil {
return *m.RequiredField
}
return ""
}
func (m *Test) GetNumber() int32 {
if x, ok := m.GetUnion().(*Test_Number); ok {
return x.Number
}
return 0
}
func (m *Test) GetName() string {
if x, ok := m.GetUnion().(*Test_Name); ok {
return x.Name
}
return ""
}
func init() {
proto.RegisterEnum("example.FOO", FOO_name, FOO_value)
}
To create and play with a Test object:
package main
import (
"log"
"github.com/golang/protobuf/proto"
pb "./example.pb"
)
func main() {
test := &pb.Test{
Label: proto.String("hello"),
Type: proto.Int32(17),
Reps: []int64{1, 2, 3},
Optionalgroup: &pb.Test_OptionalGroup{
RequiredField: proto.String("good bye"),
},
Union: &pb.Test_Name{"fred"},
}
data, err := proto.Marshal(test)
if err != nil {
log.Fatal("marshaling error: ", err)
}
newTest := &pb.Test{}
err = proto.Unmarshal(data, newTest)
if err != nil {
log.Fatal("unmarshaling error: ", err)
}
// Now test and newTest contain the same data.
if test.GetLabel() != newTest.GetLabel() {
log.Fatalf("data mismatch %q != %q", test.GetLabel(), newTest.GetLabel())
}
// Use a type switch to determine which oneof was set.
switch u := test.Union.(type) {
case *pb.Test_Number: // u.Number contains the number.
case *pb.Test_Name: // u.Name contains the string.
}
// etc.
}
*/
package proto
import (
"encoding/json"
"fmt"
"log"
"reflect"
"sort"
"strconv"
"sync"
)
// RequiredNotSetError is an error type returned by either Marshal or Unmarshal.
// Marshal reports this when a required field is not initialized.
// Unmarshal reports this when a required field is missing from the wire data.
type RequiredNotSetError struct{ field string }
func (e *RequiredNotSetError) Error() string {
if e.field == "" {
return fmt.Sprintf("proto: required field not set")
}
return fmt.Sprintf("proto: required field %q not set", e.field)
}
func (e *RequiredNotSetError) RequiredNotSet() bool {
return true
}
type invalidUTF8Error struct{ field string }
func (e *invalidUTF8Error) Error() string {
if e.field == "" {
return "proto: invalid UTF-8 detected"
}
return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field)
}
func (e *invalidUTF8Error) InvalidUTF8() bool {
return true
}
// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8.
// This error should not be exposed to the external API as such errors should
// be recreated with the field information.
var errInvalidUTF8 = &invalidUTF8Error{}
// isNonFatal reports whether the error is either a RequiredNotSet error
// or a InvalidUTF8 error.
func isNonFatal(err error) bool {
if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() {
return true
}
if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() {
return true
}
return false
}
type nonFatal struct{ E error }
// Merge merges err into nf and reports whether it was successful.
// Otherwise it returns false for any fatal non-nil errors.
func (nf *nonFatal) Merge(err error) (ok bool) {
if err == nil {
return true // not an error
}
if !isNonFatal(err) {
return false // fatal error
}
if nf.E == nil {
nf.E = err // store first instance of non-fatal error
}
return true
}
// Message is implemented by generated protocol buffer messages.
type Message interface {
Reset()
String() string
ProtoMessage()
}
// A Buffer is a buffer manager for marshaling and unmarshaling
// protocol buffers. It may be reused between invocations to
// reduce memory usage. It is not necessary to use a Buffer;
// the global functions Marshal and Unmarshal create a
// temporary Buffer and are fine for most applications.
type Buffer struct {
buf []byte // encode/decode byte stream
index int // read point
deterministic bool
}
// NewBuffer allocates a new Buffer and initializes its internal data to
// the contents of the argument slice.
func NewBuffer(e []byte) *Buffer {
return &Buffer{buf: e}
}
// Reset resets the Buffer, ready for marshaling a new protocol buffer.
func (p *Buffer) Reset() {
p.buf = p.buf[0:0] // for reading/writing
p.index = 0 // for reading
}
// SetBuf replaces the internal buffer with the slice,
// ready for unmarshaling the contents of the slice.
func (p *Buffer) SetBuf(s []byte) {
p.buf = s
p.index = 0
}
// Bytes returns the contents of the Buffer.
func (p *Buffer) Bytes() []byte { return p.buf }
// SetDeterministic sets whether to use deterministic serialization.
//
// Deterministic serialization guarantees that for a given binary, equal
// messages will always be serialized to the same bytes. This implies:
//
// - Repeated serialization of a message will return the same bytes.
// - Different processes of the same binary (which may be executing on
// different machines) will serialize equal messages to the same bytes.
//
// Note that the deterministic serialization is NOT canonical across
// languages. It is not guaranteed to remain stable over time. It is unstable
// across different builds with schema changes due to unknown fields.
// Users who need canonical serialization (e.g., persistent storage in a
// canonical form, fingerprinting, etc.) should define their own
// canonicalization specification and implement their own serializer rather
// than relying on this API.
//
// If deterministic serialization is requested, map entries will be sorted
// by keys in lexographical order. This is an implementation detail and
// subject to change.
func (p *Buffer) SetDeterministic(deterministic bool) {
p.deterministic = deterministic
}
/*
* Helper routines for simplifying the creation of optional fields of basic type.
*/
// Bool is a helper routine that allocates a new bool value
// to store v and returns a pointer to it.
func Bool(v bool) *bool {
return &v
}
// Int32 is a helper routine that allocates a new int32 value
// to store v and returns a pointer to it.
func Int32(v int32) *int32 {
return &v
}
// Int is a helper routine that allocates a new int32 value
// to store v and returns a pointer to it, but unlike Int32
// its argument value is an int.
func Int(v int) *int32 {
p := new(int32)
*p = int32(v)
return p
}
// Int64 is a helper routine that allocates a new int64 value
// to store v and returns a pointer to it.
func Int64(v int64) *int64 {
return &v
}
// Float32 is a helper routine that allocates a new float32 value
// to store v and returns a pointer to it.
func Float32(v float32) *float32 {
return &v
}
// Float64 is a helper routine that allocates a new float64 value
// to store v and returns a pointer to it.
func Float64(v float64) *float64 {
return &v
}
// Uint32 is a helper routine that allocates a new uint32 value
// to store v and returns a pointer to it.
func Uint32(v uint32) *uint32 {
return &v
}
// Uint64 is a helper routine that allocates a new uint64 value
// to store v and returns a pointer to it.
func Uint64(v uint64) *uint64 {
return &v
}
// String is a helper routine that allocates a new string value
// to store v and returns a pointer to it.
func String(v string) *string {
return &v
}
// EnumName is a helper function to simplify printing protocol buffer enums
// by name. Given an enum map and a value, it returns a useful string.
func EnumName(m map[int32]string, v int32) string {
s, ok := m[v]
if ok {
return s
}
return strconv.Itoa(int(v))
}
// UnmarshalJSONEnum is a helper function to simplify recovering enum int values
// from their JSON-encoded representation. Given a map from the enum's symbolic
// names to its int values, and a byte buffer containing the JSON-encoded
// value, it returns an int32 that can be cast to the enum type by the caller.
//
// The function can deal with both JSON representations, numeric and symbolic.
func UnmarshalJSONEnum(m map[string]int32, data []byte, enumName string) (int32, error) {
if data[0] == '"' {
// New style: enums are strings.
var repr string
if err := json.Unmarshal(data, &repr); err != nil {
return -1, err
}
val, ok := m[repr]
if !ok {
return 0, fmt.Errorf("unrecognized enum %s value %q", enumName, repr)
}
return val, nil
}
// Old style: enums are ints.
var val int32
if err := json.Unmarshal(data, &val); err != nil {
return 0, fmt.Errorf("cannot unmarshal %#q into enum %s", data, enumName)
}
return val, nil
}
// DebugPrint dumps the encoded data in b in a debugging format with a header
// including the string s. Used in testing but made available for general debugging.
func (p *Buffer) DebugPrint(s string, b []byte) {
var u uint64
obuf := p.buf
index := p.index
p.buf = b
p.index = 0
depth := 0
fmt.Printf("\n--- %s ---\n", s)
out:
for {
for i := 0; i < depth; i++ {
fmt.Print(" ")
}
index := p.index
if index == len(p.buf) {
break
}
op, err := p.DecodeVarint()
if err != nil {
fmt.Printf("%3d: fetching op err %v\n", index, err)
break out
}
tag := op >> 3
wire := op & 7
switch wire {
default:
fmt.Printf("%3d: t=%3d unknown wire=%d\n",
index, tag, wire)
break out
case WireBytes:
var r []byte
r, err = p.DecodeRawBytes(false)
if err != nil {
break out
}
fmt.Printf("%3d: t=%3d bytes [%d]", index, tag, len(r))
if len(r) <= 6 {
for i := 0; i < len(r); i++ {
fmt.Printf(" %.2x", r[i])
}
} else {
for i := 0; i < 3; i++ {
fmt.Printf(" %.2x", r[i])
}
fmt.Printf(" ..")
for i := len(r) - 3; i < len(r); i++ {
fmt.Printf(" %.2x", r[i])
}
}
fmt.Printf("\n")
case WireFixed32:
u, err = p.DecodeFixed32()
if err != nil {
fmt.Printf("%3d: t=%3d fix32 err %v\n", index, tag, err)
break out
}
fmt.Printf("%3d: t=%3d fix32 %d\n", index, tag, u)
case WireFixed64:
u, err = p.DecodeFixed64()
if err != nil {
fmt.Printf("%3d: t=%3d fix64 err %v\n", index, tag, err)
break out
}
fmt.Printf("%3d: t=%3d fix64 %d\n", index, tag, u)
case WireVarint:
u, err = p.DecodeVarint()
if err != nil {
fmt.Printf("%3d: t=%3d varint err %v\n", index, tag, err)
break out
}
fmt.Printf("%3d: t=%3d varint %d\n", index, tag, u)
case WireStartGroup:
fmt.Printf("%3d: t=%3d start\n", index, tag)
depth++
case WireEndGroup:
depth--
fmt.Printf("%3d: t=%3d end\n", index, tag)
}
}
if depth != 0 {
fmt.Printf("%3d: start-end not balanced %d\n", p.index, depth)
}
fmt.Printf("\n")
p.buf = obuf
p.index = index
}
// SetDefaults sets unset protocol buffer fields to their default values.
// It only modifies fields that are both unset and have defined defaults.
// It recursively sets default values in any non-nil sub-messages.
func SetDefaults(pb Message) {
setDefaults(reflect.ValueOf(pb), true, false)
}
// v is a pointer to a struct.
func setDefaults(v reflect.Value, recur, zeros bool) {
v = v.Elem()
defaultMu.RLock()
dm, ok := defaults[v.Type()]
defaultMu.RUnlock()
if !ok {
dm = buildDefaultMessage(v.Type())
defaultMu.Lock()
defaults[v.Type()] = dm
defaultMu.Unlock()
}
for _, sf := range dm.scalars {
f := v.Field(sf.index)
if !f.IsNil() {
// field already set
continue
}
dv := sf.value
if dv == nil && !zeros {
// no explicit default, and don't want to set zeros
continue
}
fptr := f.Addr().Interface() // **T
// TODO: Consider batching the allocations we do here.
switch sf.kind {
case reflect.Bool:
b := new(bool)
if dv != nil {
*b = dv.(bool)
}
*(fptr.(**bool)) = b
case reflect.Float32:
f := new(float32)
if dv != nil {
*f = dv.(float32)
}
*(fptr.(**float32)) = f
case reflect.Float64:
f := new(float64)
if dv != nil {
*f = dv.(float64)
}
*(fptr.(**float64)) = f
case reflect.Int32:
// might be an enum
if ft := f.Type(); ft != int32PtrType {
// enum
f.Set(reflect.New(ft.Elem()))
if dv != nil {
f.Elem().SetInt(int64(dv.(int32)))
}
} else {
// int32 field
i := new(int32)
if dv != nil {
*i = dv.(int32)
}
*(fptr.(**int32)) = i
}
case reflect.Int64:
i := new(int64)
if dv != nil {
*i = dv.(int64)
}
*(fptr.(**int64)) = i
case reflect.String:
s := new(string)
if dv != nil {
*s = dv.(string)
}
*(fptr.(**string)) = s
case reflect.Uint8:
// exceptional case: []byte
var b []byte
if dv != nil {
db := dv.([]byte)
b = make([]byte, len(db))
copy(b, db)
} else {
b = []byte{}
}
*(fptr.(*[]byte)) = b
case reflect.Uint32:
u := new(uint32)
if dv != nil {
*u = dv.(uint32)
}
*(fptr.(**uint32)) = u
case reflect.Uint64:
u := new(uint64)
if dv != nil {
*u = dv.(uint64)
}
*(fptr.(**uint64)) = u
default:
log.Printf("proto: can't set default for field %v (sf.kind=%v)", f, sf.kind)
}
}
for _, ni := range dm.nested {
f := v.Field(ni)
// f is *T or []*T or map[T]*T
switch f.Kind() {
case reflect.Ptr:
if f.IsNil() {
continue
}
setDefaults(f, recur, zeros)
case reflect.Slice:
for i := 0; i < f.Len(); i++ {
e := f.Index(i)
if e.IsNil() {
continue
}
setDefaults(e, recur, zeros)
}
case reflect.Map:
for _, k := range f.MapKeys() {
e := f.MapIndex(k)
if e.IsNil() {
continue
}
setDefaults(e, recur, zeros)
}
}
}
}
var (
// defaults maps a protocol buffer struct type to a slice of the fields,
// with its scalar fields set to their proto-declared non-zero default values.
defaultMu sync.RWMutex
defaults = make(map[reflect.Type]defaultMessage)
int32PtrType = reflect.TypeOf((*int32)(nil))
)
// defaultMessage represents information about the default values of a message.
type defaultMessage struct {
scalars []scalarField
nested []int // struct field index of nested messages
}
type scalarField struct {
index int // struct field index
kind reflect.Kind // element type (the T in *T or []T)
value interface{} // the proto-declared default value, or nil
}
// t is a struct type.
func buildDefaultMessage(t reflect.Type) (dm defaultMessage) {
sprop := GetProperties(t)
for _, prop := range sprop.Prop {
fi, ok := sprop.decoderTags.get(prop.Tag)
if !ok {
// XXX_unrecognized
continue
}
ft := t.Field(fi).Type
sf, nested, err := fieldDefault(ft, prop)
switch {
case err != nil:
log.Print(err)
case nested:
dm.nested = append(dm.nested, fi)
case sf != nil:
sf.index = fi
dm.scalars = append(dm.scalars, *sf)
}
}
return dm
}
// fieldDefault returns the scalarField for field type ft.
// sf will be nil if the field can not have a default.
// nestedMessage will be true if this is a nested message.
// Note that sf.index is not set on return.
func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMessage bool, err error) {
var canHaveDefault bool
switch ft.Kind() {
case reflect.Ptr:
if ft.Elem().Kind() == reflect.Struct {
nestedMessage = true
} else {
canHaveDefault = true // proto2 scalar field
}
case reflect.Slice:
switch ft.Elem().Kind() {
case reflect.Ptr:
nestedMessage = true // repeated message
case reflect.Uint8:
canHaveDefault = true // bytes field
}
case reflect.Map:
if ft.Elem().Kind() == reflect.Ptr {
nestedMessage = true // map with message values
}
}
if !canHaveDefault {
if nestedMessage {
return nil, true, nil
}
return nil, false, nil
}
// We now know that ft is a pointer or slice.
sf = &scalarField{kind: ft.Elem().Kind()}
// scalar fields without defaults
if !prop.HasDefault {
return sf, false, nil
}
// a scalar field: either *T or []byte
switch ft.Elem().Kind() {
case reflect.Bool:
x, err := strconv.ParseBool(prop.Default)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default bool %q: %v", prop.Default, err)
}
sf.value = x
case reflect.Float32:
x, err := strconv.ParseFloat(prop.Default, 32)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default float32 %q: %v", prop.Default, err)
}
sf.value = float32(x)
case reflect.Float64:
x, err := strconv.ParseFloat(prop.Default, 64)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default float64 %q: %v", prop.Default, err)
}
sf.value = x
case reflect.Int32:
x, err := strconv.ParseInt(prop.Default, 10, 32)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default int32 %q: %v", prop.Default, err)
}
sf.value = int32(x)
case reflect.Int64:
x, err := strconv.ParseInt(prop.Default, 10, 64)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default int64 %q: %v", prop.Default, err)
}
sf.value = x
case reflect.String:
sf.value = prop.Default
case reflect.Uint8:
// []byte (not *uint8)
sf.value = []byte(prop.Default)
case reflect.Uint32:
x, err := strconv.ParseUint(prop.Default, 10, 32)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default uint32 %q: %v", prop.Default, err)
}
sf.value = uint32(x)
case reflect.Uint64:
x, err := strconv.ParseUint(prop.Default, 10, 64)
if err != nil {
return nil, false, fmt.Errorf("proto: bad default uint64 %q: %v", prop.Default, err)
}
sf.value = x
default:
return nil, false, fmt.Errorf("proto: unhandled def kind %v", ft.Elem().Kind())
}
return sf, false, nil
}
// mapKeys returns a sort.Interface to be used for sorting the map keys.
// Map fields may have key types of non-float scalars, strings and enums.
func mapKeys(vs []reflect.Value) sort.Interface {
s := mapKeySorter{vs: vs}
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
if len(vs) == 0 {
return s
}
switch vs[0].Kind() {
case reflect.Int32, reflect.Int64:
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
case reflect.Uint32, reflect.Uint64:
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
case reflect.Bool:
s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
case reflect.String:
s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
default:
panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
}
return s
}
type mapKeySorter struct {
vs []reflect.Value
less func(a, b reflect.Value) bool
}
func (s mapKeySorter) Len() int { return len(s.vs) }
func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
func (s mapKeySorter) Less(i, j int) bool {
return s.less(s.vs[i], s.vs[j])
}
// isProto3Zero reports whether v is a zero proto3 value.
func isProto3Zero(v reflect.Value) bool {
switch v.Kind() {
case reflect.Bool:
return !v.Bool()
case reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint32, reflect.Uint64:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.String:
return v.String() == ""
}
return false
}
const (
// ProtoPackageIsVersion3 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion3 = true
// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion2 = true
// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
// to assert that that code is compatible with this version of the proto package.
ProtoPackageIsVersion1 = true
)
// InternalMessageInfo is a type used internally by generated .pb.go files.
// This type is not intended to be used by non-generated code.
// This type is not subject to any compatibility guarantee.
type InternalMessageInfo struct {
marshal *marshalInfo
unmarshal *unmarshalInfo
merge *mergeInfo
discard *discardInfo
}

181
vendor/github.com/golang/protobuf/proto/message_set.go generated vendored Normal file
View file

@ -0,0 +1,181 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
/*
* Support for message sets.
*/
import (
"errors"
)
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
// A message type ID is required for storing a protocol buffer in a message set.
var errNoMessageTypeID = errors.New("proto does not have a message type ID")
// The first two types (_MessageSet_Item and messageSet)
// model what the protocol compiler produces for the following protocol message:
// message MessageSet {
// repeated group Item = 1 {
// required int32 type_id = 2;
// required string message = 3;
// };
// }
// That is the MessageSet wire format. We can't use a proto to generate these
// because that would introduce a circular dependency between it and this package.
type _MessageSet_Item struct {
TypeId *int32 `protobuf:"varint,2,req,name=type_id"`
Message []byte `protobuf:"bytes,3,req,name=message"`
}
type messageSet struct {
Item []*_MessageSet_Item `protobuf:"group,1,rep"`
XXX_unrecognized []byte
// TODO: caching?
}
// Make sure messageSet is a Message.
var _ Message = (*messageSet)(nil)
// messageTypeIder is an interface satisfied by a protocol buffer type
// that may be stored in a MessageSet.
type messageTypeIder interface {
MessageTypeId() int32
}
func (ms *messageSet) find(pb Message) *_MessageSet_Item {
mti, ok := pb.(messageTypeIder)
if !ok {
return nil
}
id := mti.MessageTypeId()
for _, item := range ms.Item {
if *item.TypeId == id {
return item
}
}
return nil
}
func (ms *messageSet) Has(pb Message) bool {
return ms.find(pb) != nil
}
func (ms *messageSet) Unmarshal(pb Message) error {
if item := ms.find(pb); item != nil {
return Unmarshal(item.Message, pb)
}
if _, ok := pb.(messageTypeIder); !ok {
return errNoMessageTypeID
}
return nil // TODO: return error instead?
}
func (ms *messageSet) Marshal(pb Message) error {
msg, err := Marshal(pb)
if err != nil {
return err
}
if item := ms.find(pb); item != nil {
// reuse existing item
item.Message = msg
return nil
}
mti, ok := pb.(messageTypeIder)
if !ok {
return errNoMessageTypeID
}
mtid := mti.MessageTypeId()
ms.Item = append(ms.Item, &_MessageSet_Item{
TypeId: &mtid,
Message: msg,
})
return nil
}
func (ms *messageSet) Reset() { *ms = messageSet{} }
func (ms *messageSet) String() string { return CompactTextString(ms) }
func (*messageSet) ProtoMessage() {}
// Support for the message_set_wire_format message option.
func skipVarint(buf []byte) []byte {
i := 0
for ; buf[i]&0x80 != 0; i++ {
}
return buf[i+1:]
}
// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
func unmarshalMessageSet(buf []byte, exts interface{}) error {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
m = exts.extensionsWrite()
case map[int32]Extension:
m = exts
default:
return errors.New("proto: not an extension map")
}
ms := new(messageSet)
if err := Unmarshal(buf, ms); err != nil {
return err
}
for _, item := range ms.Item {
id := *item.TypeId
msg := item.Message
// Restore wire type and field number varint, plus length varint.
// Be careful to preserve duplicate items.
b := EncodeVarint(uint64(id)<<3 | WireBytes)
if ext, ok := m[id]; ok {
// Existing data; rip off the tag and length varint
// so we join the new data correctly.
// We can assume that ext.enc is set because we are unmarshaling.
o := ext.enc[len(b):] // skip wire type and field number
_, n := DecodeVarint(o) // calculate length of length varint
o = o[n:] // skip length varint
msg = append(o, msg...) // join old data and new data
}
b = append(b, EncodeVarint(uint64(len(msg)))...)
b = append(b, msg...)
m[id] = Extension{enc: b}
}
return nil
}

View file

@ -0,0 +1,360 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2012 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build purego appengine js
// This file contains an implementation of proto field accesses using package reflect.
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
// be used on App Engine.
package proto
import (
"reflect"
"sync"
)
const unsafeAllowed = false
// A field identifies a field in a struct, accessible from a pointer.
// In this implementation, a field is identified by the sequence of field indices
// passed to reflect's FieldByIndex.
type field []int
// toField returns a field equivalent to the given reflect field.
func toField(f *reflect.StructField) field {
return f.Index
}
// invalidField is an invalid field identifier.
var invalidField = field(nil)
// zeroField is a noop when calling pointer.offset.
var zeroField = field([]int{})
// IsValid reports whether the field identifier is valid.
func (f field) IsValid() bool { return f != nil }
// The pointer type is for the table-driven decoder.
// The implementation here uses a reflect.Value of pointer type to
// create a generic pointer. In pointer_unsafe.go we use unsafe
// instead of reflect to implement the same (but faster) interface.
type pointer struct {
v reflect.Value
}
// toPointer converts an interface of pointer type to a pointer
// that points to the same target.
func toPointer(i *Message) pointer {
return pointer{v: reflect.ValueOf(*i)}
}
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
v := reflect.ValueOf(*i)
u := reflect.New(v.Type())
u.Elem().Set(v)
if deref {
u = u.Elem()
}
return pointer{v: u}
}
// valToPointer converts v to a pointer. v must be of pointer type.
func valToPointer(v reflect.Value) pointer {
return pointer{v: v}
}
// offset converts from a pointer to a structure to a pointer to
// one of its fields.
func (p pointer) offset(f field) pointer {
return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
}
func (p pointer) isNil() bool {
return p.v.IsNil()
}
// grow updates the slice s in place to make it one element longer.
// s must be addressable.
// Returns the (addressable) new element.
func grow(s reflect.Value) reflect.Value {
n, m := s.Len(), s.Cap()
if n < m {
s.SetLen(n + 1)
} else {
s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
}
return s.Index(n)
}
func (p pointer) toInt64() *int64 {
return p.v.Interface().(*int64)
}
func (p pointer) toInt64Ptr() **int64 {
return p.v.Interface().(**int64)
}
func (p pointer) toInt64Slice() *[]int64 {
return p.v.Interface().(*[]int64)
}
var int32ptr = reflect.TypeOf((*int32)(nil))
func (p pointer) toInt32() *int32 {
return p.v.Convert(int32ptr).Interface().(*int32)
}
// The toInt32Ptr/Slice methods don't work because of enums.
// Instead, we must use set/get methods for the int32ptr/slice case.
/*
func (p pointer) toInt32Ptr() **int32 {
return p.v.Interface().(**int32)
}
func (p pointer) toInt32Slice() *[]int32 {
return p.v.Interface().(*[]int32)
}
*/
func (p pointer) getInt32Ptr() *int32 {
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
// raw int32 type
return p.v.Elem().Interface().(*int32)
}
// an enum
return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
}
func (p pointer) setInt32Ptr(v int32) {
// Allocate value in a *int32. Possibly convert that to a *enum.
// Then assign it to a **int32 or **enum.
// Note: we can convert *int32 to *enum, but we can't convert
// **int32 to **enum!
p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
}
// getInt32Slice copies []int32 from p as a new slice.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) getInt32Slice() []int32 {
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
// raw int32 type
return p.v.Elem().Interface().([]int32)
}
// an enum
// Allocate a []int32, then assign []enum's values into it.
// Note: we can't convert []enum to []int32.
slice := p.v.Elem()
s := make([]int32, slice.Len())
for i := 0; i < slice.Len(); i++ {
s[i] = int32(slice.Index(i).Int())
}
return s
}
// setInt32Slice copies []int32 into p as a new slice.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) setInt32Slice(v []int32) {
if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
// raw int32 type
p.v.Elem().Set(reflect.ValueOf(v))
return
}
// an enum
// Allocate a []enum, then assign []int32's values into it.
// Note: we can't convert []enum to []int32.
slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
for i, x := range v {
slice.Index(i).SetInt(int64(x))
}
p.v.Elem().Set(slice)
}
func (p pointer) appendInt32Slice(v int32) {
grow(p.v.Elem()).SetInt(int64(v))
}
func (p pointer) toUint64() *uint64 {
return p.v.Interface().(*uint64)
}
func (p pointer) toUint64Ptr() **uint64 {
return p.v.Interface().(**uint64)
}
func (p pointer) toUint64Slice() *[]uint64 {
return p.v.Interface().(*[]uint64)
}
func (p pointer) toUint32() *uint32 {
return p.v.Interface().(*uint32)
}
func (p pointer) toUint32Ptr() **uint32 {
return p.v.Interface().(**uint32)
}
func (p pointer) toUint32Slice() *[]uint32 {
return p.v.Interface().(*[]uint32)
}
func (p pointer) toBool() *bool {
return p.v.Interface().(*bool)
}
func (p pointer) toBoolPtr() **bool {
return p.v.Interface().(**bool)
}
func (p pointer) toBoolSlice() *[]bool {
return p.v.Interface().(*[]bool)
}
func (p pointer) toFloat64() *float64 {
return p.v.Interface().(*float64)
}
func (p pointer) toFloat64Ptr() **float64 {
return p.v.Interface().(**float64)
}
func (p pointer) toFloat64Slice() *[]float64 {
return p.v.Interface().(*[]float64)
}
func (p pointer) toFloat32() *float32 {
return p.v.Interface().(*float32)
}
func (p pointer) toFloat32Ptr() **float32 {
return p.v.Interface().(**float32)
}
func (p pointer) toFloat32Slice() *[]float32 {
return p.v.Interface().(*[]float32)
}
func (p pointer) toString() *string {
return p.v.Interface().(*string)
}
func (p pointer) toStringPtr() **string {
return p.v.Interface().(**string)
}
func (p pointer) toStringSlice() *[]string {
return p.v.Interface().(*[]string)
}
func (p pointer) toBytes() *[]byte {
return p.v.Interface().(*[]byte)
}
func (p pointer) toBytesSlice() *[][]byte {
return p.v.Interface().(*[][]byte)
}
func (p pointer) toExtensions() *XXX_InternalExtensions {
return p.v.Interface().(*XXX_InternalExtensions)
}
func (p pointer) toOldExtensions() *map[int32]Extension {
return p.v.Interface().(*map[int32]Extension)
}
func (p pointer) getPointer() pointer {
return pointer{v: p.v.Elem()}
}
func (p pointer) setPointer(q pointer) {
p.v.Elem().Set(q.v)
}
func (p pointer) appendPointer(q pointer) {
grow(p.v.Elem()).Set(q.v)
}
// getPointerSlice copies []*T from p as a new []pointer.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) getPointerSlice() []pointer {
if p.v.IsNil() {
return nil
}
n := p.v.Elem().Len()
s := make([]pointer, n)
for i := 0; i < n; i++ {
s[i] = pointer{v: p.v.Elem().Index(i)}
}
return s
}
// setPointerSlice copies []pointer into p as a new []*T.
// This behavior differs from the implementation in pointer_unsafe.go.
func (p pointer) setPointerSlice(v []pointer) {
if v == nil {
p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
return
}
s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
for _, p := range v {
s = reflect.Append(s, p.v)
}
p.v.Elem().Set(s)
}
// getInterfacePointer returns a pointer that points to the
// interface data of the interface pointed by p.
func (p pointer) getInterfacePointer() pointer {
if p.v.Elem().IsNil() {
return pointer{v: p.v.Elem()}
}
return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
}
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
// TODO: check that p.v.Type().Elem() == t?
return p.v
}
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
atomicLock.Lock()
defer atomicLock.Unlock()
return *p
}
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
atomicLock.Lock()
defer atomicLock.Unlock()
*p = v
}
var atomicLock sync.Mutex

View file

@ -0,0 +1,313 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2012 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// +build !purego,!appengine,!js
// This file contains the implementation of the proto field accesses using package unsafe.
package proto
import (
"reflect"
"sync/atomic"
"unsafe"
)
const unsafeAllowed = true
// A field identifies a field in a struct, accessible from a pointer.
// In this implementation, a field is identified by its byte offset from the start of the struct.
type field uintptr
// toField returns a field equivalent to the given reflect field.
func toField(f *reflect.StructField) field {
return field(f.Offset)
}
// invalidField is an invalid field identifier.
const invalidField = ^field(0)
// zeroField is a noop when calling pointer.offset.
const zeroField = field(0)
// IsValid reports whether the field identifier is valid.
func (f field) IsValid() bool {
return f != invalidField
}
// The pointer type below is for the new table-driven encoder/decoder.
// The implementation here uses unsafe.Pointer to create a generic pointer.
// In pointer_reflect.go we use reflect instead of unsafe to implement
// the same (but slower) interface.
type pointer struct {
p unsafe.Pointer
}
// size of pointer
var ptrSize = unsafe.Sizeof(uintptr(0))
// toPointer converts an interface of pointer type to a pointer
// that points to the same target.
func toPointer(i *Message) pointer {
// Super-tricky - read pointer out of data word of interface value.
// Saves ~25ns over the equivalent:
// return valToPointer(reflect.ValueOf(*i))
return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
}
// toAddrPointer converts an interface to a pointer that points to
// the interface data.
func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
// Super-tricky - read or get the address of data word of interface value.
if isptr {
// The interface is of pointer type, thus it is a direct interface.
// The data word is the pointer data itself. We take its address.
p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
} else {
// The interface is not of pointer type. The data word is the pointer
// to the data.
p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
}
if deref {
p.p = *(*unsafe.Pointer)(p.p)
}
return p
}
// valToPointer converts v to a pointer. v must be of pointer type.
func valToPointer(v reflect.Value) pointer {
return pointer{p: unsafe.Pointer(v.Pointer())}
}
// offset converts from a pointer to a structure to a pointer to
// one of its fields.
func (p pointer) offset(f field) pointer {
// For safety, we should panic if !f.IsValid, however calling panic causes
// this to no longer be inlineable, which is a serious performance cost.
/*
if !f.IsValid() {
panic("invalid field")
}
*/
return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
}
func (p pointer) isNil() bool {
return p.p == nil
}
func (p pointer) toInt64() *int64 {
return (*int64)(p.p)
}
func (p pointer) toInt64Ptr() **int64 {
return (**int64)(p.p)
}
func (p pointer) toInt64Slice() *[]int64 {
return (*[]int64)(p.p)
}
func (p pointer) toInt32() *int32 {
return (*int32)(p.p)
}
// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
/*
func (p pointer) toInt32Ptr() **int32 {
return (**int32)(p.p)
}
func (p pointer) toInt32Slice() *[]int32 {
return (*[]int32)(p.p)
}
*/
func (p pointer) getInt32Ptr() *int32 {
return *(**int32)(p.p)
}
func (p pointer) setInt32Ptr(v int32) {
*(**int32)(p.p) = &v
}
// getInt32Slice loads a []int32 from p.
// The value returned is aliased with the original slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) getInt32Slice() []int32 {
return *(*[]int32)(p.p)
}
// setInt32Slice stores a []int32 to p.
// The value set is aliased with the input slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) setInt32Slice(v []int32) {
*(*[]int32)(p.p) = v
}
// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
func (p pointer) appendInt32Slice(v int32) {
s := (*[]int32)(p.p)
*s = append(*s, v)
}
func (p pointer) toUint64() *uint64 {
return (*uint64)(p.p)
}
func (p pointer) toUint64Ptr() **uint64 {
return (**uint64)(p.p)
}
func (p pointer) toUint64Slice() *[]uint64 {
return (*[]uint64)(p.p)
}
func (p pointer) toUint32() *uint32 {
return (*uint32)(p.p)
}
func (p pointer) toUint32Ptr() **uint32 {
return (**uint32)(p.p)
}
func (p pointer) toUint32Slice() *[]uint32 {
return (*[]uint32)(p.p)
}
func (p pointer) toBool() *bool {
return (*bool)(p.p)
}
func (p pointer) toBoolPtr() **bool {
return (**bool)(p.p)
}
func (p pointer) toBoolSlice() *[]bool {
return (*[]bool)(p.p)
}
func (p pointer) toFloat64() *float64 {
return (*float64)(p.p)
}
func (p pointer) toFloat64Ptr() **float64 {
return (**float64)(p.p)
}
func (p pointer) toFloat64Slice() *[]float64 {
return (*[]float64)(p.p)
}
func (p pointer) toFloat32() *float32 {
return (*float32)(p.p)
}
func (p pointer) toFloat32Ptr() **float32 {
return (**float32)(p.p)
}
func (p pointer) toFloat32Slice() *[]float32 {
return (*[]float32)(p.p)
}
func (p pointer) toString() *string {
return (*string)(p.p)
}
func (p pointer) toStringPtr() **string {
return (**string)(p.p)
}
func (p pointer) toStringSlice() *[]string {
return (*[]string)(p.p)
}
func (p pointer) toBytes() *[]byte {
return (*[]byte)(p.p)
}
func (p pointer) toBytesSlice() *[][]byte {
return (*[][]byte)(p.p)
}
func (p pointer) toExtensions() *XXX_InternalExtensions {
return (*XXX_InternalExtensions)(p.p)
}
func (p pointer) toOldExtensions() *map[int32]Extension {
return (*map[int32]Extension)(p.p)
}
// getPointerSlice loads []*T from p as a []pointer.
// The value returned is aliased with the original slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) getPointerSlice() []pointer {
// Super-tricky - p should point to a []*T where T is a
// message type. We load it as []pointer.
return *(*[]pointer)(p.p)
}
// setPointerSlice stores []pointer into p as a []*T.
// The value set is aliased with the input slice.
// This behavior differs from the implementation in pointer_reflect.go.
func (p pointer) setPointerSlice(v []pointer) {
// Super-tricky - p should point to a []*T where T is a
// message type. We store it as []pointer.
*(*[]pointer)(p.p) = v
}
// getPointer loads the pointer at p and returns it.
func (p pointer) getPointer() pointer {
return pointer{p: *(*unsafe.Pointer)(p.p)}
}
// setPointer stores the pointer q at p.
func (p pointer) setPointer(q pointer) {
*(*unsafe.Pointer)(p.p) = q.p
}
// append q to the slice pointed to by p.
func (p pointer) appendPointer(q pointer) {
s := (*[]unsafe.Pointer)(p.p)
*s = append(*s, q.p)
}
// getInterfacePointer returns a pointer that points to the
// interface data of the interface pointed by p.
func (p pointer) getInterfacePointer() pointer {
// Super-tricky - read pointer out of data word of interface value.
return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
}
// asPointerTo returns a reflect.Value that is a pointer to an
// object of type t stored at p.
func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
return reflect.NewAt(t, p.p)
}
func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
}
func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}

544
vendor/github.com/golang/protobuf/proto/properties.go generated vendored Normal file
View file

@ -0,0 +1,544 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
/*
* Routines for encoding data into the wire format for protocol buffers.
*/
import (
"fmt"
"log"
"reflect"
"sort"
"strconv"
"strings"
"sync"
)
const debug bool = false
// Constants that identify the encoding of a value on the wire.
const (
WireVarint = 0
WireFixed64 = 1
WireBytes = 2
WireStartGroup = 3
WireEndGroup = 4
WireFixed32 = 5
)
// tagMap is an optimization over map[int]int for typical protocol buffer
// use-cases. Encoded protocol buffers are often in tag order with small tag
// numbers.
type tagMap struct {
fastTags []int
slowTags map[int]int
}
// tagMapFastLimit is the upper bound on the tag number that will be stored in
// the tagMap slice rather than its map.
const tagMapFastLimit = 1024
func (p *tagMap) get(t int) (int, bool) {
if t > 0 && t < tagMapFastLimit {
if t >= len(p.fastTags) {
return 0, false
}
fi := p.fastTags[t]
return fi, fi >= 0
}
fi, ok := p.slowTags[t]
return fi, ok
}
func (p *tagMap) put(t int, fi int) {
if t > 0 && t < tagMapFastLimit {
for len(p.fastTags) < t+1 {
p.fastTags = append(p.fastTags, -1)
}
p.fastTags[t] = fi
return
}
if p.slowTags == nil {
p.slowTags = make(map[int]int)
}
p.slowTags[t] = fi
}
// StructProperties represents properties for all the fields of a struct.
// decoderTags and decoderOrigNames should only be used by the decoder.
type StructProperties struct {
Prop []*Properties // properties for each field
reqCount int // required count
decoderTags tagMap // map from proto tag to struct field number
decoderOrigNames map[string]int // map from original name to struct field number
order []int // list of struct field numbers in tag order
// OneofTypes contains information about the oneof fields in this message.
// It is keyed by the original name of a field.
OneofTypes map[string]*OneofProperties
}
// OneofProperties represents information about a specific field in a oneof.
type OneofProperties struct {
Type reflect.Type // pointer to generated struct type for this oneof field
Field int // struct field number of the containing oneof in the message
Prop *Properties
}
// Implement the sorting interface so we can sort the fields in tag order, as recommended by the spec.
// See encode.go, (*Buffer).enc_struct.
func (sp *StructProperties) Len() int { return len(sp.order) }
func (sp *StructProperties) Less(i, j int) bool {
return sp.Prop[sp.order[i]].Tag < sp.Prop[sp.order[j]].Tag
}
func (sp *StructProperties) Swap(i, j int) { sp.order[i], sp.order[j] = sp.order[j], sp.order[i] }
// Properties represents the protocol-specific behavior of a single struct field.
type Properties struct {
Name string // name of the field, for error messages
OrigName string // original name before protocol compiler (always set)
JSONName string // name to use for JSON; determined by protoc
Wire string
WireType int
Tag int
Required bool
Optional bool
Repeated bool
Packed bool // relevant for repeated primitives only
Enum string // set for enum types only
proto3 bool // whether this is known to be a proto3 field
oneof bool // whether this is a oneof field
Default string // default value
HasDefault bool // whether an explicit default was provided
stype reflect.Type // set for struct types only
sprop *StructProperties // set for struct types only
mtype reflect.Type // set for map types only
MapKeyProp *Properties // set for map types only
MapValProp *Properties // set for map types only
}
// String formats the properties in the protobuf struct field tag style.
func (p *Properties) String() string {
s := p.Wire
s += ","
s += strconv.Itoa(p.Tag)
if p.Required {
s += ",req"
}
if p.Optional {
s += ",opt"
}
if p.Repeated {
s += ",rep"
}
if p.Packed {
s += ",packed"
}
s += ",name=" + p.OrigName
if p.JSONName != p.OrigName {
s += ",json=" + p.JSONName
}
if p.proto3 {
s += ",proto3"
}
if p.oneof {
s += ",oneof"
}
if len(p.Enum) > 0 {
s += ",enum=" + p.Enum
}
if p.HasDefault {
s += ",def=" + p.Default
}
return s
}
// Parse populates p by parsing a string in the protobuf struct field tag style.
func (p *Properties) Parse(s string) {
// "bytes,49,opt,name=foo,def=hello!"
fields := strings.Split(s, ",") // breaks def=, but handled below.
if len(fields) < 2 {
log.Printf("proto: tag has too few fields: %q", s)
return
}
p.Wire = fields[0]
switch p.Wire {
case "varint":
p.WireType = WireVarint
case "fixed32":
p.WireType = WireFixed32
case "fixed64":
p.WireType = WireFixed64
case "zigzag32":
p.WireType = WireVarint
case "zigzag64":
p.WireType = WireVarint
case "bytes", "group":
p.WireType = WireBytes
// no numeric converter for non-numeric types
default:
log.Printf("proto: tag has unknown wire type: %q", s)
return
}
var err error
p.Tag, err = strconv.Atoi(fields[1])
if err != nil {
return
}
outer:
for i := 2; i < len(fields); i++ {
f := fields[i]
switch {
case f == "req":
p.Required = true
case f == "opt":
p.Optional = true
case f == "rep":
p.Repeated = true
case f == "packed":
p.Packed = true
case strings.HasPrefix(f, "name="):
p.OrigName = f[5:]
case strings.HasPrefix(f, "json="):
p.JSONName = f[5:]
case strings.HasPrefix(f, "enum="):
p.Enum = f[5:]
case f == "proto3":
p.proto3 = true
case f == "oneof":
p.oneof = true
case strings.HasPrefix(f, "def="):
p.HasDefault = true
p.Default = f[4:] // rest of string
if i+1 < len(fields) {
// Commas aren't escaped, and def is always last.
p.Default += "," + strings.Join(fields[i+1:], ",")
break outer
}
}
}
}
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
// setFieldProps initializes the field properties for submessages and maps.
func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
switch t1 := typ; t1.Kind() {
case reflect.Ptr:
if t1.Elem().Kind() == reflect.Struct {
p.stype = t1.Elem()
}
case reflect.Slice:
if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct {
p.stype = t2.Elem()
}
case reflect.Map:
p.mtype = t1
p.MapKeyProp = &Properties{}
p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
p.MapValProp = &Properties{}
vtype := p.mtype.Elem()
if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
// The value type is not a message (*T) or bytes ([]byte),
// so we need encoders for the pointer to this type.
vtype = reflect.PtrTo(vtype)
}
p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
}
if p.stype != nil {
if lockGetProp {
p.sprop = GetProperties(p.stype)
} else {
p.sprop = getPropertiesLocked(p.stype)
}
}
}
var (
marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
)
// Init populates the properties from a protocol buffer struct tag.
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
p.init(typ, name, tag, f, true)
}
func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructField, lockGetProp bool) {
// "bytes,49,opt,def=hello!"
p.Name = name
p.OrigName = name
if tag == "" {
return
}
p.Parse(tag)
p.setFieldProps(typ, f, lockGetProp)
}
var (
propertiesMu sync.RWMutex
propertiesMap = make(map[reflect.Type]*StructProperties)
)
// GetProperties returns the list of properties for the type represented by t.
// t must represent a generated struct type of a protocol message.
func GetProperties(t reflect.Type) *StructProperties {
if t.Kind() != reflect.Struct {
panic("proto: type must have kind struct")
}
// Most calls to GetProperties in a long-running program will be
// retrieving details for types we have seen before.
propertiesMu.RLock()
sprop, ok := propertiesMap[t]
propertiesMu.RUnlock()
if ok {
return sprop
}
propertiesMu.Lock()
sprop = getPropertiesLocked(t)
propertiesMu.Unlock()
return sprop
}
type (
oneofFuncsIface interface {
XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
}
oneofWrappersIface interface {
XXX_OneofWrappers() []interface{}
}
)
// getPropertiesLocked requires that propertiesMu is held.
func getPropertiesLocked(t reflect.Type) *StructProperties {
if prop, ok := propertiesMap[t]; ok {
return prop
}
prop := new(StructProperties)
// in case of recursive protos, fill this in now.
propertiesMap[t] = prop
// build properties
prop.Prop = make([]*Properties, t.NumField())
prop.order = make([]int, t.NumField())
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
p := new(Properties)
name := f.Name
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
oneof := f.Tag.Get("protobuf_oneof") // special case
if oneof != "" {
// Oneof fields don't use the traditional protobuf tag.
p.OrigName = oneof
}
prop.Prop[i] = p
prop.order[i] = i
if debug {
print(i, " ", f.Name, " ", t.String(), " ")
if p.Tag > 0 {
print(p.String())
}
print("\n")
}
}
// Re-order prop.order.
sort.Sort(prop)
var oots []interface{}
switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
case oneofFuncsIface:
_, _, _, oots = m.XXX_OneofFuncs()
case oneofWrappersIface:
oots = m.XXX_OneofWrappers()
}
if len(oots) > 0 {
// Interpret oneof metadata.
prop.OneofTypes = make(map[string]*OneofProperties)
for _, oot := range oots {
oop := &OneofProperties{
Type: reflect.ValueOf(oot).Type(), // *T
Prop: new(Properties),
}
sft := oop.Type.Elem().Field(0)
oop.Prop.Name = sft.Name
oop.Prop.Parse(sft.Tag.Get("protobuf"))
// There will be exactly one interface field that
// this new value is assignable to.
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Type.Kind() != reflect.Interface {
continue
}
if !oop.Type.AssignableTo(f.Type) {
continue
}
oop.Field = i
break
}
prop.OneofTypes[oop.Prop.OrigName] = oop
}
}
// build required counts
// build tags
reqCount := 0
prop.decoderOrigNames = make(map[string]int)
for i, p := range prop.Prop {
if strings.HasPrefix(p.Name, "XXX_") {
// Internal fields should not appear in tags/origNames maps.
// They are handled specially when encoding and decoding.
continue
}
if p.Required {
reqCount++
}
prop.decoderTags.put(p.Tag, i)
prop.decoderOrigNames[p.OrigName] = i
}
prop.reqCount = reqCount
return prop
}
// A global registry of enum types.
// The generated code will register the generated maps by calling RegisterEnum.
var enumValueMaps = make(map[string]map[string]int32)
// RegisterEnum is called from the generated code to install the enum descriptor
// maps into the global table to aid parsing text format protocol buffers.
func RegisterEnum(typeName string, unusedNameMap map[int32]string, valueMap map[string]int32) {
if _, ok := enumValueMaps[typeName]; ok {
panic("proto: duplicate enum registered: " + typeName)
}
enumValueMaps[typeName] = valueMap
}
// EnumValueMap returns the mapping from names to integers of the
// enum type enumType, or a nil if not found.
func EnumValueMap(enumType string) map[string]int32 {
return enumValueMaps[enumType]
}
// A registry of all linked message types.
// The string is a fully-qualified proto name ("pkg.Message").
var (
protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers
protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types
revProtoTypes = make(map[reflect.Type]string)
)
// RegisterType is called from generated code and maps from the fully qualified
// proto name to the type (pointer to struct) of the protocol buffer.
func RegisterType(x Message, name string) {
if _, ok := protoTypedNils[name]; ok {
// TODO: Some day, make this a panic.
log.Printf("proto: duplicate proto type registered: %s", name)
return
}
t := reflect.TypeOf(x)
if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
// Generated code always calls RegisterType with nil x.
// This check is just for extra safety.
protoTypedNils[name] = x
} else {
protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
}
revProtoTypes[t] = name
}
// RegisterMapType is called from generated code and maps from the fully qualified
// proto name to the native map type of the proto map definition.
func RegisterMapType(x interface{}, name string) {
if reflect.TypeOf(x).Kind() != reflect.Map {
panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
}
if _, ok := protoMapTypes[name]; ok {
log.Printf("proto: duplicate proto type registered: %s", name)
return
}
t := reflect.TypeOf(x)
protoMapTypes[name] = t
revProtoTypes[t] = name
}
// MessageName returns the fully-qualified proto name for the given message type.
func MessageName(x Message) string {
type xname interface {
XXX_MessageName() string
}
if m, ok := x.(xname); ok {
return m.XXX_MessageName()
}
return revProtoTypes[reflect.TypeOf(x)]
}
// MessageType returns the message type (pointer to struct) for a named message.
// The type is not guaranteed to implement proto.Message if the name refers to a
// map entry.
func MessageType(name string) reflect.Type {
if t, ok := protoTypedNils[name]; ok {
return reflect.TypeOf(t)
}
return protoMapTypes[name]
}
// A registry of all linked proto files.
var (
protoFiles = make(map[string][]byte) // file name => fileDescriptor
)
// RegisterFile is called from generated code and maps from the
// full file name of a .proto file to its compressed FileDescriptorProto.
func RegisterFile(filename string, fileDescriptor []byte) {
protoFiles[filename] = fileDescriptor
}
// FileDescriptor returns the compressed FileDescriptorProto for a .proto file.
func FileDescriptor(filename string) []byte { return protoFiles[filename] }

2776
vendor/github.com/golang/protobuf/proto/table_marshal.go generated vendored Normal file

File diff suppressed because it is too large Load diff

654
vendor/github.com/golang/protobuf/proto/table_merge.go generated vendored Normal file
View file

@ -0,0 +1,654 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2016 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
import (
"fmt"
"reflect"
"strings"
"sync"
"sync/atomic"
)
// Merge merges the src message into dst.
// This assumes that dst and src of the same type and are non-nil.
func (a *InternalMessageInfo) Merge(dst, src Message) {
mi := atomicLoadMergeInfo(&a.merge)
if mi == nil {
mi = getMergeInfo(reflect.TypeOf(dst).Elem())
atomicStoreMergeInfo(&a.merge, mi)
}
mi.merge(toPointer(&dst), toPointer(&src))
}
type mergeInfo struct {
typ reflect.Type
initialized int32 // 0: only typ is valid, 1: everything is valid
lock sync.Mutex
fields []mergeFieldInfo
unrecognized field // Offset of XXX_unrecognized
}
type mergeFieldInfo struct {
field field // Offset of field, guaranteed to be valid
// isPointer reports whether the value in the field is a pointer.
// This is true for the following situations:
// * Pointer to struct
// * Pointer to basic type (proto2 only)
// * Slice (first value in slice header is a pointer)
// * String (first value in string header is a pointer)
isPointer bool
// basicWidth reports the width of the field assuming that it is directly
// embedded in the struct (as is the case for basic types in proto3).
// The possible values are:
// 0: invalid
// 1: bool
// 4: int32, uint32, float32
// 8: int64, uint64, float64
basicWidth int
// Where dst and src are pointers to the types being merged.
merge func(dst, src pointer)
}
var (
mergeInfoMap = map[reflect.Type]*mergeInfo{}
mergeInfoLock sync.Mutex
)
func getMergeInfo(t reflect.Type) *mergeInfo {
mergeInfoLock.Lock()
defer mergeInfoLock.Unlock()
mi := mergeInfoMap[t]
if mi == nil {
mi = &mergeInfo{typ: t}
mergeInfoMap[t] = mi
}
return mi
}
// merge merges src into dst assuming they are both of type *mi.typ.
func (mi *mergeInfo) merge(dst, src pointer) {
if dst.isNil() {
panic("proto: nil destination")
}
if src.isNil() {
return // Nothing to do.
}
if atomic.LoadInt32(&mi.initialized) == 0 {
mi.computeMergeInfo()
}
for _, fi := range mi.fields {
sfp := src.offset(fi.field)
// As an optimization, we can avoid the merge function call cost
// if we know for sure that the source will have no effect
// by checking if it is the zero value.
if unsafeAllowed {
if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
continue
}
if fi.basicWidth > 0 {
switch {
case fi.basicWidth == 1 && !*sfp.toBool():
continue
case fi.basicWidth == 4 && *sfp.toUint32() == 0:
continue
case fi.basicWidth == 8 && *sfp.toUint64() == 0:
continue
}
}
}
dfp := dst.offset(fi.field)
fi.merge(dfp, sfp)
}
// TODO: Make this faster?
out := dst.asPointerTo(mi.typ).Elem()
in := src.asPointerTo(mi.typ).Elem()
if emIn, err := extendable(in.Addr().Interface()); err == nil {
emOut, _ := extendable(out.Addr().Interface())
mIn, muIn := emIn.extensionsRead()
if mIn != nil {
mOut := emOut.extensionsWrite()
muIn.Lock()
mergeExtension(mOut, mIn)
muIn.Unlock()
}
}
if mi.unrecognized.IsValid() {
if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
*dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
}
}
}
func (mi *mergeInfo) computeMergeInfo() {
mi.lock.Lock()
defer mi.lock.Unlock()
if mi.initialized != 0 {
return
}
t := mi.typ
n := t.NumField()
props := GetProperties(t)
for i := 0; i < n; i++ {
f := t.Field(i)
if strings.HasPrefix(f.Name, "XXX_") {
continue
}
mfi := mergeFieldInfo{field: toField(&f)}
tf := f.Type
// As an optimization, we can avoid the merge function call cost
// if we know for sure that the source will have no effect
// by checking if it is the zero value.
if unsafeAllowed {
switch tf.Kind() {
case reflect.Ptr, reflect.Slice, reflect.String:
// As a special case, we assume slices and strings are pointers
// since we know that the first field in the SliceSlice or
// StringHeader is a data pointer.
mfi.isPointer = true
case reflect.Bool:
mfi.basicWidth = 1
case reflect.Int32, reflect.Uint32, reflect.Float32:
mfi.basicWidth = 4
case reflect.Int64, reflect.Uint64, reflect.Float64:
mfi.basicWidth = 8
}
}
// Unwrap tf to get at its most basic type.
var isPointer, isSlice bool
if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
isSlice = true
tf = tf.Elem()
}
if tf.Kind() == reflect.Ptr {
isPointer = true
tf = tf.Elem()
}
if isPointer && isSlice && tf.Kind() != reflect.Struct {
panic("both pointer and slice for basic type in " + tf.Name())
}
switch tf.Kind() {
case reflect.Int32:
switch {
case isSlice: // E.g., []int32
mfi.merge = func(dst, src pointer) {
// NOTE: toInt32Slice is not defined (see pointer_reflect.go).
/*
sfsp := src.toInt32Slice()
if *sfsp != nil {
dfsp := dst.toInt32Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []int64{}
}
}
*/
sfs := src.getInt32Slice()
if sfs != nil {
dfs := dst.getInt32Slice()
dfs = append(dfs, sfs...)
if dfs == nil {
dfs = []int32{}
}
dst.setInt32Slice(dfs)
}
}
case isPointer: // E.g., *int32
mfi.merge = func(dst, src pointer) {
// NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
/*
sfpp := src.toInt32Ptr()
if *sfpp != nil {
dfpp := dst.toInt32Ptr()
if *dfpp == nil {
*dfpp = Int32(**sfpp)
} else {
**dfpp = **sfpp
}
}
*/
sfp := src.getInt32Ptr()
if sfp != nil {
dfp := dst.getInt32Ptr()
if dfp == nil {
dst.setInt32Ptr(*sfp)
} else {
*dfp = *sfp
}
}
}
default: // E.g., int32
mfi.merge = func(dst, src pointer) {
if v := *src.toInt32(); v != 0 {
*dst.toInt32() = v
}
}
}
case reflect.Int64:
switch {
case isSlice: // E.g., []int64
mfi.merge = func(dst, src pointer) {
sfsp := src.toInt64Slice()
if *sfsp != nil {
dfsp := dst.toInt64Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []int64{}
}
}
}
case isPointer: // E.g., *int64
mfi.merge = func(dst, src pointer) {
sfpp := src.toInt64Ptr()
if *sfpp != nil {
dfpp := dst.toInt64Ptr()
if *dfpp == nil {
*dfpp = Int64(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., int64
mfi.merge = func(dst, src pointer) {
if v := *src.toInt64(); v != 0 {
*dst.toInt64() = v
}
}
}
case reflect.Uint32:
switch {
case isSlice: // E.g., []uint32
mfi.merge = func(dst, src pointer) {
sfsp := src.toUint32Slice()
if *sfsp != nil {
dfsp := dst.toUint32Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []uint32{}
}
}
}
case isPointer: // E.g., *uint32
mfi.merge = func(dst, src pointer) {
sfpp := src.toUint32Ptr()
if *sfpp != nil {
dfpp := dst.toUint32Ptr()
if *dfpp == nil {
*dfpp = Uint32(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., uint32
mfi.merge = func(dst, src pointer) {
if v := *src.toUint32(); v != 0 {
*dst.toUint32() = v
}
}
}
case reflect.Uint64:
switch {
case isSlice: // E.g., []uint64
mfi.merge = func(dst, src pointer) {
sfsp := src.toUint64Slice()
if *sfsp != nil {
dfsp := dst.toUint64Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []uint64{}
}
}
}
case isPointer: // E.g., *uint64
mfi.merge = func(dst, src pointer) {
sfpp := src.toUint64Ptr()
if *sfpp != nil {
dfpp := dst.toUint64Ptr()
if *dfpp == nil {
*dfpp = Uint64(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., uint64
mfi.merge = func(dst, src pointer) {
if v := *src.toUint64(); v != 0 {
*dst.toUint64() = v
}
}
}
case reflect.Float32:
switch {
case isSlice: // E.g., []float32
mfi.merge = func(dst, src pointer) {
sfsp := src.toFloat32Slice()
if *sfsp != nil {
dfsp := dst.toFloat32Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []float32{}
}
}
}
case isPointer: // E.g., *float32
mfi.merge = func(dst, src pointer) {
sfpp := src.toFloat32Ptr()
if *sfpp != nil {
dfpp := dst.toFloat32Ptr()
if *dfpp == nil {
*dfpp = Float32(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., float32
mfi.merge = func(dst, src pointer) {
if v := *src.toFloat32(); v != 0 {
*dst.toFloat32() = v
}
}
}
case reflect.Float64:
switch {
case isSlice: // E.g., []float64
mfi.merge = func(dst, src pointer) {
sfsp := src.toFloat64Slice()
if *sfsp != nil {
dfsp := dst.toFloat64Slice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []float64{}
}
}
}
case isPointer: // E.g., *float64
mfi.merge = func(dst, src pointer) {
sfpp := src.toFloat64Ptr()
if *sfpp != nil {
dfpp := dst.toFloat64Ptr()
if *dfpp == nil {
*dfpp = Float64(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., float64
mfi.merge = func(dst, src pointer) {
if v := *src.toFloat64(); v != 0 {
*dst.toFloat64() = v
}
}
}
case reflect.Bool:
switch {
case isSlice: // E.g., []bool
mfi.merge = func(dst, src pointer) {
sfsp := src.toBoolSlice()
if *sfsp != nil {
dfsp := dst.toBoolSlice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []bool{}
}
}
}
case isPointer: // E.g., *bool
mfi.merge = func(dst, src pointer) {
sfpp := src.toBoolPtr()
if *sfpp != nil {
dfpp := dst.toBoolPtr()
if *dfpp == nil {
*dfpp = Bool(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., bool
mfi.merge = func(dst, src pointer) {
if v := *src.toBool(); v {
*dst.toBool() = v
}
}
}
case reflect.String:
switch {
case isSlice: // E.g., []string
mfi.merge = func(dst, src pointer) {
sfsp := src.toStringSlice()
if *sfsp != nil {
dfsp := dst.toStringSlice()
*dfsp = append(*dfsp, *sfsp...)
if *dfsp == nil {
*dfsp = []string{}
}
}
}
case isPointer: // E.g., *string
mfi.merge = func(dst, src pointer) {
sfpp := src.toStringPtr()
if *sfpp != nil {
dfpp := dst.toStringPtr()
if *dfpp == nil {
*dfpp = String(**sfpp)
} else {
**dfpp = **sfpp
}
}
}
default: // E.g., string
mfi.merge = func(dst, src pointer) {
if v := *src.toString(); v != "" {
*dst.toString() = v
}
}
}
case reflect.Slice:
isProto3 := props.Prop[i].proto3
switch {
case isPointer:
panic("bad pointer in byte slice case in " + tf.Name())
case tf.Elem().Kind() != reflect.Uint8:
panic("bad element kind in byte slice case in " + tf.Name())
case isSlice: // E.g., [][]byte
mfi.merge = func(dst, src pointer) {
sbsp := src.toBytesSlice()
if *sbsp != nil {
dbsp := dst.toBytesSlice()
for _, sb := range *sbsp {
if sb == nil {
*dbsp = append(*dbsp, nil)
} else {
*dbsp = append(*dbsp, append([]byte{}, sb...))
}
}
if *dbsp == nil {
*dbsp = [][]byte{}
}
}
}
default: // E.g., []byte
mfi.merge = func(dst, src pointer) {
sbp := src.toBytes()
if *sbp != nil {
dbp := dst.toBytes()
if !isProto3 || len(*sbp) > 0 {
*dbp = append([]byte{}, *sbp...)
}
}
}
}
case reflect.Struct:
switch {
case !isPointer:
panic(fmt.Sprintf("message field %s without pointer", tf))
case isSlice: // E.g., []*pb.T
mi := getMergeInfo(tf)
mfi.merge = func(dst, src pointer) {
sps := src.getPointerSlice()
if sps != nil {
dps := dst.getPointerSlice()
for _, sp := range sps {
var dp pointer
if !sp.isNil() {
dp = valToPointer(reflect.New(tf))
mi.merge(dp, sp)
}
dps = append(dps, dp)
}
if dps == nil {
dps = []pointer{}
}
dst.setPointerSlice(dps)
}
}
default: // E.g., *pb.T
mi := getMergeInfo(tf)
mfi.merge = func(dst, src pointer) {
sp := src.getPointer()
if !sp.isNil() {
dp := dst.getPointer()
if dp.isNil() {
dp = valToPointer(reflect.New(tf))
dst.setPointer(dp)
}
mi.merge(dp, sp)
}
}
}
case reflect.Map:
switch {
case isPointer || isSlice:
panic("bad pointer or slice in map case in " + tf.Name())
default: // E.g., map[K]V
mfi.merge = func(dst, src pointer) {
sm := src.asPointerTo(tf).Elem()
if sm.Len() == 0 {
return
}
dm := dst.asPointerTo(tf).Elem()
if dm.IsNil() {
dm.Set(reflect.MakeMap(tf))
}
switch tf.Elem().Kind() {
case reflect.Ptr: // Proto struct (e.g., *T)
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
val = reflect.ValueOf(Clone(val.Interface().(Message)))
dm.SetMapIndex(key, val)
}
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
dm.SetMapIndex(key, val)
}
default: // Basic type (e.g., string)
for _, key := range sm.MapKeys() {
val := sm.MapIndex(key)
dm.SetMapIndex(key, val)
}
}
}
}
case reflect.Interface:
// Must be oneof field.
switch {
case isPointer || isSlice:
panic("bad pointer or slice in interface case in " + tf.Name())
default: // E.g., interface{}
// TODO: Make this faster?
mfi.merge = func(dst, src pointer) {
su := src.asPointerTo(tf).Elem()
if !su.IsNil() {
du := dst.asPointerTo(tf).Elem()
typ := su.Elem().Type()
if du.IsNil() || du.Elem().Type() != typ {
du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
}
sv := su.Elem().Elem().Field(0)
if sv.Kind() == reflect.Ptr && sv.IsNil() {
return
}
dv := du.Elem().Elem().Field(0)
if dv.Kind() == reflect.Ptr && dv.IsNil() {
dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
}
switch sv.Type().Kind() {
case reflect.Ptr: // Proto struct (e.g., *T)
Merge(dv.Interface().(Message), sv.Interface().(Message))
case reflect.Slice: // E.g. Bytes type (e.g., []byte)
dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
default: // Basic type (e.g., string)
dv.Set(sv)
}
}
}
}
default:
panic(fmt.Sprintf("merger not found for type:%s", tf))
}
mi.fields = append(mi.fields, mfi)
}
mi.unrecognized = invalidField
if f, ok := t.FieldByName("XXX_unrecognized"); ok {
if f.Type != reflect.TypeOf([]byte{}) {
panic("expected XXX_unrecognized to be of type []byte")
}
mi.unrecognized = toField(&f)
}
atomic.StoreInt32(&mi.initialized, 1)
}

File diff suppressed because it is too large Load diff

843
vendor/github.com/golang/protobuf/proto/text.go generated vendored Normal file
View file

@ -0,0 +1,843 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
// Functions for writing the text protocol buffer format.
import (
"bufio"
"bytes"
"encoding"
"errors"
"fmt"
"io"
"log"
"math"
"reflect"
"sort"
"strings"
)
var (
newline = []byte("\n")
spaces = []byte(" ")
endBraceNewline = []byte("}\n")
backslashN = []byte{'\\', 'n'}
backslashR = []byte{'\\', 'r'}
backslashT = []byte{'\\', 't'}
backslashDQ = []byte{'\\', '"'}
backslashBS = []byte{'\\', '\\'}
posInf = []byte("inf")
negInf = []byte("-inf")
nan = []byte("nan")
)
type writer interface {
io.Writer
WriteByte(byte) error
}
// textWriter is an io.Writer that tracks its indentation level.
type textWriter struct {
ind int
complete bool // if the current position is a complete line
compact bool // whether to write out as a one-liner
w writer
}
func (w *textWriter) WriteString(s string) (n int, err error) {
if !strings.Contains(s, "\n") {
if !w.compact && w.complete {
w.writeIndent()
}
w.complete = false
return io.WriteString(w.w, s)
}
// WriteString is typically called without newlines, so this
// codepath and its copy are rare. We copy to avoid
// duplicating all of Write's logic here.
return w.Write([]byte(s))
}
func (w *textWriter) Write(p []byte) (n int, err error) {
newlines := bytes.Count(p, newline)
if newlines == 0 {
if !w.compact && w.complete {
w.writeIndent()
}
n, err = w.w.Write(p)
w.complete = false
return n, err
}
frags := bytes.SplitN(p, newline, newlines+1)
if w.compact {
for i, frag := range frags {
if i > 0 {
if err := w.w.WriteByte(' '); err != nil {
return n, err
}
n++
}
nn, err := w.w.Write(frag)
n += nn
if err != nil {
return n, err
}
}
return n, nil
}
for i, frag := range frags {
if w.complete {
w.writeIndent()
}
nn, err := w.w.Write(frag)
n += nn
if err != nil {
return n, err
}
if i+1 < len(frags) {
if err := w.w.WriteByte('\n'); err != nil {
return n, err
}
n++
}
}
w.complete = len(frags[len(frags)-1]) == 0
return n, nil
}
func (w *textWriter) WriteByte(c byte) error {
if w.compact && c == '\n' {
c = ' '
}
if !w.compact && w.complete {
w.writeIndent()
}
err := w.w.WriteByte(c)
w.complete = c == '\n'
return err
}
func (w *textWriter) indent() { w.ind++ }
func (w *textWriter) unindent() {
if w.ind == 0 {
log.Print("proto: textWriter unindented too far")
return
}
w.ind--
}
func writeName(w *textWriter, props *Properties) error {
if _, err := w.WriteString(props.OrigName); err != nil {
return err
}
if props.Wire != "group" {
return w.WriteByte(':')
}
return nil
}
func requiresQuotes(u string) bool {
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
for _, ch := range u {
switch {
case ch == '.' || ch == '/' || ch == '_':
continue
case '0' <= ch && ch <= '9':
continue
case 'A' <= ch && ch <= 'Z':
continue
case 'a' <= ch && ch <= 'z':
continue
default:
return true
}
}
return false
}
// isAny reports whether sv is a google.protobuf.Any message
func isAny(sv reflect.Value) bool {
type wkt interface {
XXX_WellKnownType() string
}
t, ok := sv.Addr().Interface().(wkt)
return ok && t.XXX_WellKnownType() == "Any"
}
// writeProto3Any writes an expanded google.protobuf.Any message.
//
// It returns (false, nil) if sv value can't be unmarshaled (e.g. because
// required messages are not linked in).
//
// It returns (true, error) when sv was written in expanded format or an error
// was encountered.
func (tm *TextMarshaler) writeProto3Any(w *textWriter, sv reflect.Value) (bool, error) {
turl := sv.FieldByName("TypeUrl")
val := sv.FieldByName("Value")
if !turl.IsValid() || !val.IsValid() {
return true, errors.New("proto: invalid google.protobuf.Any message")
}
b, ok := val.Interface().([]byte)
if !ok {
return true, errors.New("proto: invalid google.protobuf.Any message")
}
parts := strings.Split(turl.String(), "/")
mt := MessageType(parts[len(parts)-1])
if mt == nil {
return false, nil
}
m := reflect.New(mt.Elem())
if err := Unmarshal(b, m.Interface().(Message)); err != nil {
return false, nil
}
w.Write([]byte("["))
u := turl.String()
if requiresQuotes(u) {
writeString(w, u)
} else {
w.Write([]byte(u))
}
if w.compact {
w.Write([]byte("]:<"))
} else {
w.Write([]byte("]: <\n"))
w.ind++
}
if err := tm.writeStruct(w, m.Elem()); err != nil {
return true, err
}
if w.compact {
w.Write([]byte("> "))
} else {
w.ind--
w.Write([]byte(">\n"))
}
return true, nil
}
func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
if tm.ExpandAny && isAny(sv) {
if canExpand, err := tm.writeProto3Any(w, sv); canExpand {
return err
}
}
st := sv.Type()
sprops := GetProperties(st)
for i := 0; i < sv.NumField(); i++ {
fv := sv.Field(i)
props := sprops.Prop[i]
name := st.Field(i).Name
if name == "XXX_NoUnkeyedLiteral" {
continue
}
if strings.HasPrefix(name, "XXX_") {
// There are two XXX_ fields:
// XXX_unrecognized []byte
// XXX_extensions map[int32]proto.Extension
// The first is handled here;
// the second is handled at the bottom of this function.
if name == "XXX_unrecognized" && !fv.IsNil() {
if err := writeUnknownStruct(w, fv.Interface().([]byte)); err != nil {
return err
}
}
continue
}
if fv.Kind() == reflect.Ptr && fv.IsNil() {
// Field not filled in. This could be an optional field or
// a required field that wasn't filled in. Either way, there
// isn't anything we can show for it.
continue
}
if fv.Kind() == reflect.Slice && fv.IsNil() {
// Repeated field that is empty, or a bytes field that is unused.
continue
}
if props.Repeated && fv.Kind() == reflect.Slice {
// Repeated field.
for j := 0; j < fv.Len(); j++ {
if err := writeName(w, props); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
v := fv.Index(j)
if v.Kind() == reflect.Ptr && v.IsNil() {
// A nil message in a repeated field is not valid,
// but we can handle that more gracefully than panicking.
if _, err := w.Write([]byte("<nil>\n")); err != nil {
return err
}
continue
}
if err := tm.writeAny(w, v, props); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
}
continue
}
if fv.Kind() == reflect.Map {
// Map fields are rendered as a repeated struct with key/value fields.
keys := fv.MapKeys()
sort.Sort(mapKeys(keys))
for _, key := range keys {
val := fv.MapIndex(key)
if err := writeName(w, props); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
// open struct
if err := w.WriteByte('<'); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte('\n'); err != nil {
return err
}
}
w.indent()
// key
if _, err := w.WriteString("key:"); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
// nil values aren't legal, but we can avoid panicking because of them.
if val.Kind() != reflect.Ptr || !val.IsNil() {
// value
if _, err := w.WriteString("value:"); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
if err := tm.writeAny(w, val, props.MapValProp); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
}
// close struct
w.unindent()
if err := w.WriteByte('>'); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
}
continue
}
if props.proto3 && fv.Kind() == reflect.Slice && fv.Len() == 0 {
// empty bytes field
continue
}
if fv.Kind() != reflect.Ptr && fv.Kind() != reflect.Slice {
// proto3 non-repeated scalar field; skip if zero value
if isProto3Zero(fv) {
continue
}
}
if fv.Kind() == reflect.Interface {
// Check if it is a oneof.
if st.Field(i).Tag.Get("protobuf_oneof") != "" {
// fv is nil, or holds a pointer to generated struct.
// That generated struct has exactly one field,
// which has a protobuf struct tag.
if fv.IsNil() {
continue
}
inner := fv.Elem().Elem() // interface -> *T -> T
tag := inner.Type().Field(0).Tag.Get("protobuf")
props = new(Properties) // Overwrite the outer props var, but not its pointee.
props.Parse(tag)
// Write the value in the oneof, not the oneof itself.
fv = inner.Field(0)
// Special case to cope with malformed messages gracefully:
// If the value in the oneof is a nil pointer, don't panic
// in writeAny.
if fv.Kind() == reflect.Ptr && fv.IsNil() {
// Use errors.New so writeAny won't render quotes.
msg := errors.New("/* nil */")
fv = reflect.ValueOf(&msg).Elem()
}
}
}
if err := writeName(w, props); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
// Enums have a String method, so writeAny will work fine.
if err := tm.writeAny(w, fv, props); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
}
// Extensions (the XXX_extensions field).
pv := sv.Addr()
if _, err := extendable(pv.Interface()); err == nil {
if err := tm.writeExtensions(w, pv); err != nil {
return err
}
}
return nil
}
// writeAny writes an arbitrary field.
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
v = reflect.Indirect(v)
// Floats have special cases.
if v.Kind() == reflect.Float32 || v.Kind() == reflect.Float64 {
x := v.Float()
var b []byte
switch {
case math.IsInf(x, 1):
b = posInf
case math.IsInf(x, -1):
b = negInf
case math.IsNaN(x):
b = nan
}
if b != nil {
_, err := w.Write(b)
return err
}
// Other values are handled below.
}
// We don't attempt to serialise every possible value type; only those
// that can occur in protocol buffers.
switch v.Kind() {
case reflect.Slice:
// Should only be a []byte; repeated fields are handled in writeStruct.
if err := writeString(w, string(v.Bytes())); err != nil {
return err
}
case reflect.String:
if err := writeString(w, v.String()); err != nil {
return err
}
case reflect.Struct:
// Required/optional group/message.
var bra, ket byte = '<', '>'
if props != nil && props.Wire == "group" {
bra, ket = '{', '}'
}
if err := w.WriteByte(bra); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte('\n'); err != nil {
return err
}
}
w.indent()
if v.CanAddr() {
// Calling v.Interface on a struct causes the reflect package to
// copy the entire struct. This is racy with the new Marshaler
// since we atomically update the XXX_sizecache.
//
// Thus, we retrieve a pointer to the struct if possible to avoid
// a race since v.Interface on the pointer doesn't copy the struct.
//
// If v is not addressable, then we are not worried about a race
// since it implies that the binary Marshaler cannot possibly be
// mutating this value.
v = v.Addr()
}
if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
text, err := etm.MarshalText()
if err != nil {
return err
}
if _, err = w.Write(text); err != nil {
return err
}
} else {
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if err := tm.writeStruct(w, v); err != nil {
return err
}
}
w.unindent()
if err := w.WriteByte(ket); err != nil {
return err
}
default:
_, err := fmt.Fprint(w, v.Interface())
return err
}
return nil
}
// equivalent to C's isprint.
func isprint(c byte) bool {
return c >= 0x20 && c < 0x7f
}
// writeString writes a string in the protocol buffer text format.
// It is similar to strconv.Quote except we don't use Go escape sequences,
// we treat the string as a byte sequence, and we use octal escapes.
// These differences are to maintain interoperability with the other
// languages' implementations of the text format.
func writeString(w *textWriter, s string) error {
// use WriteByte here to get any needed indent
if err := w.WriteByte('"'); err != nil {
return err
}
// Loop over the bytes, not the runes.
for i := 0; i < len(s); i++ {
var err error
// Divergence from C++: we don't escape apostrophes.
// There's no need to escape them, and the C++ parser
// copes with a naked apostrophe.
switch c := s[i]; c {
case '\n':
_, err = w.w.Write(backslashN)
case '\r':
_, err = w.w.Write(backslashR)
case '\t':
_, err = w.w.Write(backslashT)
case '"':
_, err = w.w.Write(backslashDQ)
case '\\':
_, err = w.w.Write(backslashBS)
default:
if isprint(c) {
err = w.w.WriteByte(c)
} else {
_, err = fmt.Fprintf(w.w, "\\%03o", c)
}
}
if err != nil {
return err
}
}
return w.WriteByte('"')
}
func writeUnknownStruct(w *textWriter, data []byte) (err error) {
if !w.compact {
if _, err := fmt.Fprintf(w, "/* %d unknown bytes */\n", len(data)); err != nil {
return err
}
}
b := NewBuffer(data)
for b.index < len(b.buf) {
x, err := b.DecodeVarint()
if err != nil {
_, err := fmt.Fprintf(w, "/* %v */\n", err)
return err
}
wire, tag := x&7, x>>3
if wire == WireEndGroup {
w.unindent()
if _, err := w.Write(endBraceNewline); err != nil {
return err
}
continue
}
if _, err := fmt.Fprint(w, tag); err != nil {
return err
}
if wire != WireStartGroup {
if err := w.WriteByte(':'); err != nil {
return err
}
}
if !w.compact || wire == WireStartGroup {
if err := w.WriteByte(' '); err != nil {
return err
}
}
switch wire {
case WireBytes:
buf, e := b.DecodeRawBytes(false)
if e == nil {
_, err = fmt.Fprintf(w, "%q", buf)
} else {
_, err = fmt.Fprintf(w, "/* %v */", e)
}
case WireFixed32:
x, err = b.DecodeFixed32()
err = writeUnknownInt(w, x, err)
case WireFixed64:
x, err = b.DecodeFixed64()
err = writeUnknownInt(w, x, err)
case WireStartGroup:
err = w.WriteByte('{')
w.indent()
case WireVarint:
x, err = b.DecodeVarint()
err = writeUnknownInt(w, x, err)
default:
_, err = fmt.Fprintf(w, "/* unknown wire type %d */", wire)
}
if err != nil {
return err
}
if err = w.WriteByte('\n'); err != nil {
return err
}
}
return nil
}
func writeUnknownInt(w *textWriter, x uint64, err error) error {
if err == nil {
_, err = fmt.Fprint(w, x)
} else {
_, err = fmt.Fprintf(w, "/* %v */", err)
}
return err
}
type int32Slice []int32
func (s int32Slice) Len() int { return len(s) }
func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] }
func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// writeExtensions writes all the extensions in pv.
// pv is assumed to be a pointer to a protocol message struct that is extendable.
func (tm *TextMarshaler) writeExtensions(w *textWriter, pv reflect.Value) error {
emap := extensionMaps[pv.Type().Elem()]
ep, _ := extendable(pv.Interface())
// Order the extensions by ID.
// This isn't strictly necessary, but it will give us
// canonical output, which will also make testing easier.
m, mu := ep.extensionsRead()
if m == nil {
return nil
}
mu.Lock()
ids := make([]int32, 0, len(m))
for id := range m {
ids = append(ids, id)
}
sort.Sort(int32Slice(ids))
mu.Unlock()
for _, extNum := range ids {
ext := m[extNum]
var desc *ExtensionDesc
if emap != nil {
desc = emap[extNum]
}
if desc == nil {
// Unknown extension.
if err := writeUnknownStruct(w, ext.enc); err != nil {
return err
}
continue
}
pb, err := GetExtension(ep, desc)
if err != nil {
return fmt.Errorf("failed getting extension: %v", err)
}
// Repeated extensions will appear as a slice.
if !desc.repeated() {
if err := tm.writeExtension(w, desc.Name, pb); err != nil {
return err
}
} else {
v := reflect.ValueOf(pb)
for i := 0; i < v.Len(); i++ {
if err := tm.writeExtension(w, desc.Name, v.Index(i).Interface()); err != nil {
return err
}
}
}
}
return nil
}
func (tm *TextMarshaler) writeExtension(w *textWriter, name string, pb interface{}) error {
if _, err := fmt.Fprintf(w, "[%s]:", name); err != nil {
return err
}
if !w.compact {
if err := w.WriteByte(' '); err != nil {
return err
}
}
if err := tm.writeAny(w, reflect.ValueOf(pb), nil); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
return err
}
return nil
}
func (w *textWriter) writeIndent() {
if !w.complete {
return
}
remain := w.ind * 2
for remain > 0 {
n := remain
if n > len(spaces) {
n = len(spaces)
}
w.w.Write(spaces[:n])
remain -= n
}
w.complete = false
}
// TextMarshaler is a configurable text format marshaler.
type TextMarshaler struct {
Compact bool // use compact text format (one line).
ExpandAny bool // expand google.protobuf.Any messages of known types
}
// Marshal writes a given protocol buffer in text format.
// The only errors returned are from w.
func (tm *TextMarshaler) Marshal(w io.Writer, pb Message) error {
val := reflect.ValueOf(pb)
if pb == nil || val.IsNil() {
w.Write([]byte("<nil>"))
return nil
}
var bw *bufio.Writer
ww, ok := w.(writer)
if !ok {
bw = bufio.NewWriter(w)
ww = bw
}
aw := &textWriter{
w: ww,
complete: true,
compact: tm.Compact,
}
if etm, ok := pb.(encoding.TextMarshaler); ok {
text, err := etm.MarshalText()
if err != nil {
return err
}
if _, err = aw.Write(text); err != nil {
return err
}
if bw != nil {
return bw.Flush()
}
return nil
}
// Dereference the received pointer so we don't have outer < and >.
v := reflect.Indirect(val)
if err := tm.writeStruct(aw, v); err != nil {
return err
}
if bw != nil {
return bw.Flush()
}
return nil
}
// Text is the same as Marshal, but returns the string directly.
func (tm *TextMarshaler) Text(pb Message) string {
var buf bytes.Buffer
tm.Marshal(&buf, pb)
return buf.String()
}
var (
defaultTextMarshaler = TextMarshaler{}
compactTextMarshaler = TextMarshaler{Compact: true}
)
// TODO: consider removing some of the Marshal functions below.
// MarshalText writes a given protocol buffer in text format.
// The only errors returned are from w.
func MarshalText(w io.Writer, pb Message) error { return defaultTextMarshaler.Marshal(w, pb) }
// MarshalTextString is the same as MarshalText, but returns the string directly.
func MarshalTextString(pb Message) string { return defaultTextMarshaler.Text(pb) }
// CompactText writes a given protocol buffer in compact text format (one line).
func CompactText(w io.Writer, pb Message) error { return compactTextMarshaler.Marshal(w, pb) }
// CompactTextString is the same as CompactText, but returns the string directly.
func CompactTextString(pb Message) string { return compactTextMarshaler.Text(pb) }

880
vendor/github.com/golang/protobuf/proto/text_parser.go generated vendored Normal file
View file

@ -0,0 +1,880 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2010 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package proto
// Functions for parsing the Text protocol buffer format.
// TODO: message sets.
import (
"encoding"
"errors"
"fmt"
"reflect"
"strconv"
"strings"
"unicode/utf8"
)
// Error string emitted when deserializing Any and fields are already set
const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set"
type ParseError struct {
Message string
Line int // 1-based line number
Offset int // 0-based byte offset from start of input
}
func (p *ParseError) Error() string {
if p.Line == 1 {
// show offset only for first line
return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message)
}
return fmt.Sprintf("line %d: %v", p.Line, p.Message)
}
type token struct {
value string
err *ParseError
line int // line number
offset int // byte number from start of input, not start of line
unquoted string // the unquoted version of value, if it was a quoted string
}
func (t *token) String() string {
if t.err == nil {
return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset)
}
return fmt.Sprintf("parse error: %v", t.err)
}
type textParser struct {
s string // remaining input
done bool // whether the parsing is finished (success or error)
backed bool // whether back() was called
offset, line int
cur token
}
func newTextParser(s string) *textParser {
p := new(textParser)
p.s = s
p.line = 1
p.cur.line = 1
return p
}
func (p *textParser) errorf(format string, a ...interface{}) *ParseError {
pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset}
p.cur.err = pe
p.done = true
return pe
}
// Numbers and identifiers are matched by [-+._A-Za-z0-9]
func isIdentOrNumberChar(c byte) bool {
switch {
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z':
return true
case '0' <= c && c <= '9':
return true
}
switch c {
case '-', '+', '.', '_':
return true
}
return false
}
func isWhitespace(c byte) bool {
switch c {
case ' ', '\t', '\n', '\r':
return true
}
return false
}
func isQuote(c byte) bool {
switch c {
case '"', '\'':
return true
}
return false
}
func (p *textParser) skipWhitespace() {
i := 0
for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') {
if p.s[i] == '#' {
// comment; skip to end of line or input
for i < len(p.s) && p.s[i] != '\n' {
i++
}
if i == len(p.s) {
break
}
}
if p.s[i] == '\n' {
p.line++
}
i++
}
p.offset += i
p.s = p.s[i:len(p.s)]
if len(p.s) == 0 {
p.done = true
}
}
func (p *textParser) advance() {
// Skip whitespace
p.skipWhitespace()
if p.done {
return
}
// Start of non-whitespace
p.cur.err = nil
p.cur.offset, p.cur.line = p.offset, p.line
p.cur.unquoted = ""
switch p.s[0] {
case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/':
// Single symbol
p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)]
case '"', '\'':
// Quoted string
i := 1
for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' {
if p.s[i] == '\\' && i+1 < len(p.s) {
// skip escaped char
i++
}
i++
}
if i >= len(p.s) || p.s[i] != p.s[0] {
p.errorf("unmatched quote")
return
}
unq, err := unquoteC(p.s[1:i], rune(p.s[0]))
if err != nil {
p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err)
return
}
p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)]
p.cur.unquoted = unq
default:
i := 0
for i < len(p.s) && isIdentOrNumberChar(p.s[i]) {
i++
}
if i == 0 {
p.errorf("unexpected byte %#x", p.s[0])
return
}
p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)]
}
p.offset += len(p.cur.value)
}
var (
errBadUTF8 = errors.New("proto: bad UTF-8")
)
func unquoteC(s string, quote rune) (string, error) {
// This is based on C++'s tokenizer.cc.
// Despite its name, this is *not* parsing C syntax.
// For instance, "\0" is an invalid quoted string.
// Avoid allocation in trivial cases.
simple := true
for _, r := range s {
if r == '\\' || r == quote {
simple = false
break
}
}
if simple {
return s, nil
}
buf := make([]byte, 0, 3*len(s)/2)
for len(s) > 0 {
r, n := utf8.DecodeRuneInString(s)
if r == utf8.RuneError && n == 1 {
return "", errBadUTF8
}
s = s[n:]
if r != '\\' {
if r < utf8.RuneSelf {
buf = append(buf, byte(r))
} else {
buf = append(buf, string(r)...)
}
continue
}
ch, tail, err := unescape(s)
if err != nil {
return "", err
}
buf = append(buf, ch...)
s = tail
}
return string(buf), nil
}
func unescape(s string) (ch string, tail string, err error) {
r, n := utf8.DecodeRuneInString(s)
if r == utf8.RuneError && n == 1 {
return "", "", errBadUTF8
}
s = s[n:]
switch r {
case 'a':
return "\a", s, nil
case 'b':
return "\b", s, nil
case 'f':
return "\f", s, nil
case 'n':
return "\n", s, nil
case 'r':
return "\r", s, nil
case 't':
return "\t", s, nil
case 'v':
return "\v", s, nil
case '?':
return "?", s, nil // trigraph workaround
case '\'', '"', '\\':
return string(r), s, nil
case '0', '1', '2', '3', '4', '5', '6', '7':
if len(s) < 2 {
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
}
ss := string(r) + s[:2]
s = s[2:]
i, err := strconv.ParseUint(ss, 8, 8)
if err != nil {
return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
}
return string([]byte{byte(i)}), s, nil
case 'x', 'X', 'u', 'U':
var n int
switch r {
case 'x', 'X':
n = 2
case 'u':
n = 4
case 'U':
n = 8
}
if len(s) < n {
return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
}
ss := s[:n]
s = s[n:]
i, err := strconv.ParseUint(ss, 16, 64)
if err != nil {
return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
}
if r == 'x' || r == 'X' {
return string([]byte{byte(i)}), s, nil
}
if i > utf8.MaxRune {
return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
}
return string(i), s, nil
}
return "", "", fmt.Errorf(`unknown escape \%c`, r)
}
// Back off the parser by one token. Can only be done between calls to next().
// It makes the next advance() a no-op.
func (p *textParser) back() { p.backed = true }
// Advances the parser and returns the new current token.
func (p *textParser) next() *token {
if p.backed || p.done {
p.backed = false
return &p.cur
}
p.advance()
if p.done {
p.cur.value = ""
} else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) {
// Look for multiple quoted strings separated by whitespace,
// and concatenate them.
cat := p.cur
for {
p.skipWhitespace()
if p.done || !isQuote(p.s[0]) {
break
}
p.advance()
if p.cur.err != nil {
return &p.cur
}
cat.value += " " + p.cur.value
cat.unquoted += p.cur.unquoted
}
p.done = false // parser may have seen EOF, but we want to return cat
p.cur = cat
}
return &p.cur
}
func (p *textParser) consumeToken(s string) error {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != s {
p.back()
return p.errorf("expected %q, found %q", s, tok.value)
}
return nil
}
// Return a RequiredNotSetError indicating which required field was not set.
func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError {
st := sv.Type()
sprops := GetProperties(st)
for i := 0; i < st.NumField(); i++ {
if !isNil(sv.Field(i)) {
continue
}
props := sprops.Prop[i]
if props.Required {
return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)}
}
}
return &RequiredNotSetError{fmt.Sprintf("%v.<unknown field name>", st)} // should not happen
}
// Returns the index in the struct for the named field, as well as the parsed tag properties.
func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) {
i, ok := sprops.decoderOrigNames[name]
if ok {
return i, sprops.Prop[i], true
}
return -1, nil, false
}
// Consume a ':' from the input stream (if the next token is a colon),
// returning an error if a colon is needed but not present.
func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != ":" {
// Colon is optional when the field is a group or message.
needColon := true
switch props.Wire {
case "group":
needColon = false
case "bytes":
// A "bytes" field is either a message, a string, or a repeated field;
// those three become *T, *string and []T respectively, so we can check for
// this field being a pointer to a non-string.
if typ.Kind() == reflect.Ptr {
// *T or *string
if typ.Elem().Kind() == reflect.String {
break
}
} else if typ.Kind() == reflect.Slice {
// []T or []*T
if typ.Elem().Kind() != reflect.Ptr {
break
}
} else if typ.Kind() == reflect.String {
// The proto3 exception is for a string field,
// which requires a colon.
break
}
needColon = false
}
if needColon {
return p.errorf("expected ':', found %q", tok.value)
}
p.back()
}
return nil
}
func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
st := sv.Type()
sprops := GetProperties(st)
reqCount := sprops.reqCount
var reqFieldErr error
fieldSet := make(map[string]bool)
// A struct is a sequence of "name: value", terminated by one of
// '>' or '}', or the end of the input. A name may also be
// "[extension]" or "[type/url]".
//
// The whole struct can also be an expanded Any message, like:
// [type/url] < ... struct contents ... >
for {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == terminator {
break
}
if tok.value == "[" {
// Looks like an extension or an Any.
//
// TODO: Check whether we need to handle
// namespace rooted names (e.g. ".something.Foo").
extName, err := p.consumeExtName()
if err != nil {
return err
}
if s := strings.LastIndex(extName, "/"); s >= 0 {
// If it contains a slash, it's an Any type URL.
messageName := extName[s+1:]
mt := MessageType(messageName)
if mt == nil {
return p.errorf("unrecognized message %q in google.protobuf.Any", messageName)
}
tok = p.next()
if tok.err != nil {
return tok.err
}
// consume an optional colon
if tok.value == ":" {
tok = p.next()
if tok.err != nil {
return tok.err
}
}
var terminator string
switch tok.value {
case "<":
terminator = ">"
case "{":
terminator = "}"
default:
return p.errorf("expected '{' or '<', found %q", tok.value)
}
v := reflect.New(mt.Elem())
if pe := p.readStruct(v.Elem(), terminator); pe != nil {
return pe
}
b, err := Marshal(v.Interface().(Message))
if err != nil {
return p.errorf("failed to marshal message of type %q: %v", messageName, err)
}
if fieldSet["type_url"] {
return p.errorf(anyRepeatedlyUnpacked, "type_url")
}
if fieldSet["value"] {
return p.errorf(anyRepeatedlyUnpacked, "value")
}
sv.FieldByName("TypeUrl").SetString(extName)
sv.FieldByName("Value").SetBytes(b)
fieldSet["type_url"] = true
fieldSet["value"] = true
continue
}
var desc *ExtensionDesc
// This could be faster, but it's functional.
// TODO: Do something smarter than a linear scan.
for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) {
if d.Name == extName {
desc = d
break
}
}
if desc == nil {
return p.errorf("unrecognized extension %q", extName)
}
props := &Properties{}
props.Parse(desc.Tag)
typ := reflect.TypeOf(desc.ExtensionType)
if err := p.checkForColon(props, typ); err != nil {
return err
}
rep := desc.repeated()
// Read the extension structure, and set it in
// the value we're constructing.
var ext reflect.Value
if !rep {
ext = reflect.New(typ).Elem()
} else {
ext = reflect.New(typ.Elem()).Elem()
}
if err := p.readAny(ext, props); err != nil {
if _, ok := err.(*RequiredNotSetError); !ok {
return err
}
reqFieldErr = err
}
ep := sv.Addr().Interface().(Message)
if !rep {
SetExtension(ep, desc, ext.Interface())
} else {
old, err := GetExtension(ep, desc)
var sl reflect.Value
if err == nil {
sl = reflect.ValueOf(old) // existing slice
} else {
sl = reflect.MakeSlice(typ, 0, 1)
}
sl = reflect.Append(sl, ext)
SetExtension(ep, desc, sl.Interface())
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
continue
}
// This is a normal, non-extension field.
name := tok.value
var dst reflect.Value
fi, props, ok := structFieldByName(sprops, name)
if ok {
dst = sv.Field(fi)
} else if oop, ok := sprops.OneofTypes[name]; ok {
// It is a oneof.
props = oop.Prop
nv := reflect.New(oop.Type.Elem())
dst = nv.Elem().Field(0)
field := sv.Field(oop.Field)
if !field.IsNil() {
return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name)
}
field.Set(nv)
}
if !dst.IsValid() {
return p.errorf("unknown field name %q in %v", name, st)
}
if dst.Kind() == reflect.Map {
// Consume any colon.
if err := p.checkForColon(props, dst.Type()); err != nil {
return err
}
// Construct the map if it doesn't already exist.
if dst.IsNil() {
dst.Set(reflect.MakeMap(dst.Type()))
}
key := reflect.New(dst.Type().Key()).Elem()
val := reflect.New(dst.Type().Elem()).Elem()
// The map entry should be this sequence of tokens:
// < key : KEY value : VALUE >
// However, implementations may omit key or value, and technically
// we should support them in any order. See b/28924776 for a time
// this went wrong.
tok := p.next()
var terminator string
switch tok.value {
case "<":
terminator = ">"
case "{":
terminator = "}"
default:
return p.errorf("expected '{' or '<', found %q", tok.value)
}
for {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == terminator {
break
}
switch tok.value {
case "key":
if err := p.consumeToken(":"); err != nil {
return err
}
if err := p.readAny(key, props.MapKeyProp); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
case "value":
if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
return err
}
if err := p.readAny(val, props.MapValProp); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
default:
p.back()
return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value)
}
}
dst.SetMapIndex(key, val)
continue
}
// Check that it's not already set if it's not a repeated field.
if !props.Repeated && fieldSet[name] {
return p.errorf("non-repeated field %q was repeated", name)
}
if err := p.checkForColon(props, dst.Type()); err != nil {
return err
}
// Parse into the field.
fieldSet[name] = true
if err := p.readAny(dst, props); err != nil {
if _, ok := err.(*RequiredNotSetError); !ok {
return err
}
reqFieldErr = err
}
if props.Required {
reqCount--
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
}
if reqCount > 0 {
return p.missingRequiredFieldError(sv)
}
return reqFieldErr
}
// consumeExtName consumes extension name or expanded Any type URL and the
// following ']'. It returns the name or URL consumed.
func (p *textParser) consumeExtName() (string, error) {
tok := p.next()
if tok.err != nil {
return "", tok.err
}
// If extension name or type url is quoted, it's a single token.
if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] {
name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0]))
if err != nil {
return "", err
}
return name, p.consumeToken("]")
}
// Consume everything up to "]"
var parts []string
for tok.value != "]" {
parts = append(parts, tok.value)
tok = p.next()
if tok.err != nil {
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
}
if p.done && tok.value != "]" {
return "", p.errorf("unclosed type_url or extension name")
}
}
return strings.Join(parts, ""), nil
}
// consumeOptionalSeparator consumes an optional semicolon or comma.
// It is used in readStruct to provide backward compatibility.
func (p *textParser) consumeOptionalSeparator() error {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value != ";" && tok.value != "," {
p.back()
}
return nil
}
func (p *textParser) readAny(v reflect.Value, props *Properties) error {
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == "" {
return p.errorf("unexpected EOF")
}
switch fv := v; fv.Kind() {
case reflect.Slice:
at := v.Type()
if at.Elem().Kind() == reflect.Uint8 {
// Special case for []byte
if tok.value[0] != '"' && tok.value[0] != '\'' {
// Deliberately written out here, as the error after
// this switch statement would write "invalid []byte: ...",
// which is not as user-friendly.
return p.errorf("invalid string: %v", tok.value)
}
bytes := []byte(tok.unquoted)
fv.Set(reflect.ValueOf(bytes))
return nil
}
// Repeated field.
if tok.value == "[" {
// Repeated field with list notation, like [1,2,3].
for {
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
err := p.readAny(fv.Index(fv.Len()-1), props)
if err != nil {
return err
}
tok := p.next()
if tok.err != nil {
return tok.err
}
if tok.value == "]" {
break
}
if tok.value != "," {
return p.errorf("Expected ']' or ',' found %q", tok.value)
}
}
return nil
}
// One value of the repeated field.
p.back()
fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem()))
return p.readAny(fv.Index(fv.Len()-1), props)
case reflect.Bool:
// true/1/t/True or false/f/0/False.
switch tok.value {
case "true", "1", "t", "True":
fv.SetBool(true)
return nil
case "false", "0", "f", "False":
fv.SetBool(false)
return nil
}
case reflect.Float32, reflect.Float64:
v := tok.value
// Ignore 'f' for compatibility with output generated by C++, but don't
// remove 'f' when the value is "-inf" or "inf".
if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" {
v = v[:len(v)-1]
}
if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil {
fv.SetFloat(f)
return nil
}
case reflect.Int32:
if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil {
fv.SetInt(x)
return nil
}
if len(props.Enum) == 0 {
break
}
m, ok := enumValueMaps[props.Enum]
if !ok {
break
}
x, ok := m[tok.value]
if !ok {
break
}
fv.SetInt(int64(x))
return nil
case reflect.Int64:
if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil {
fv.SetInt(x)
return nil
}
case reflect.Ptr:
// A basic field (indirected through pointer), or a repeated message/group
p.back()
fv.Set(reflect.New(fv.Type().Elem()))
return p.readAny(fv.Elem(), props)
case reflect.String:
if tok.value[0] == '"' || tok.value[0] == '\'' {
fv.SetString(tok.unquoted)
return nil
}
case reflect.Struct:
var terminator string
switch tok.value {
case "{":
terminator = "}"
case "<":
terminator = ">"
default:
return p.errorf("expected '{' or '<', found %q", tok.value)
}
// TODO: Handle nested messages which implement encoding.TextUnmarshaler.
return p.readStruct(fv, terminator)
case reflect.Uint32:
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
fv.SetUint(uint64(x))
return nil
}
case reflect.Uint64:
if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil {
fv.SetUint(x)
return nil
}
}
return p.errorf("invalid %v: %v", v.Type(), tok.value)
}
// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb
// before starting to unmarshal, so any existing data in pb is always removed.
// If a required field is not set and no other error occurs,
// UnmarshalText returns *RequiredNotSetError.
func UnmarshalText(s string, pb Message) error {
if um, ok := pb.(encoding.TextUnmarshaler); ok {
return um.UnmarshalText([]byte(s))
}
pb.Reset()
v := reflect.ValueOf(pb)
return newTextParser(s).readStruct(v.Elem(), "")
}

276
vendor/github.com/google/go-github/v29/AUTHORS generated vendored Normal file
View file

@ -0,0 +1,276 @@
# This is the official list of go-github authors for copyright purposes.
#
# This does not necessarily list everyone who has contributed code, since in
# some cases, their employer may be the copyright holder. To see the full list
# of contributors, see the revision history in source control or
# https://github.com/google/go-github/graphs/contributors.
#
# Authors who wish to be recognized in this file should add themselves (or
# their employer, as appropriate).
178inaba <masahiro.furudate@gmail.com>
413x <dedifferentiator@gmail.com>
Abhinav Gupta <mail@abhinavg.net>
adrienzieba <adrien.zieba@appdirect.com>
Ahmed Hagy <a.akram93@gmail.com>
Aidan Steele <aidan.steele@glassechidna.com.au>
Ainsley Chong <ainsley.chong@gmail.com>
Akeda Bagus <akeda@x-team.com>
Akhil Mohan <akhilerm@gmail.com>
Alec Thomas <alec@swapoff.org>
Aleks Clark <aleks.clark@gmail.com>
Alex Bramley <a.bramley@gmail.com>
Alexander Harkness <me@bearbin.net>
Allen Sun <shlallen1990@gmail.com>
Amey Sakhadeo <me@ameyms.com>
Andreas Garnæs <https://github.com/andreas>
Andrew Ryabchun <aryabchun@mail.ua>
Andy Grunwald <andygrunwald@gmail.com>
Andy Hume <andyhume@gmail.com>
Andy Lindeman <andy@lindeman.io>
anjanashenoy <anjanashenoy1@gmail.com>
Anshuman Bhartiya <anshuman.bhartiya@gmail.com>
Antoine <antoine.tu@mail.mcgill.ca>
Antoine Pelisse <apelisse@gmail.com>
Anubha Kushwaha <anubha_bt2k14@dtu.ac.in>
appilon <apilon@hashicorp.com>
Aravind <aravindkp@outlook.in>
Arda Kuyumcu <kuyumcuarda@gmail.com>
Arıl Bozoluk <arilbozoluk@hotmail.com>
Austin Dizzy <dizzy@wow.com>
Ben Batha <bhbatha@gmail.com>
Benjamen Keroack <benjamen@dollarshaveclub.com>
Beshr Kayali <beshrkayali@gmail.com>
Beyang Liu <beyang.liu@gmail.com>
Billy Lynch <wlynch92@gmail.com>
Björn Häuser <b.haeuser@rebuy.de>
Brad Harris <bmharris@gmail.com>
Brad Moylan <moylan.brad@gmail.com>
Bradley Falzon <brad@teambrad.net>
Brandon Cook <phylake@gmail.com>
Brian Egizi <brian@mojotech.com>
Bryan Boreham <bryan@weave.works>
Cami Diez <diezcami@gmail.com>
Carlos Alexandro Becker <caarlos0@gmail.com>
Carlos Tadeu Panato Junior <ctadeu@gmail.com>
chandresh-pancholi <chandreshpancholi007@gmail.com>
Charles Fenwick Elliott <Charles@FenwickElliott.io>
Charlie Yan <charlieyan08@gmail.com>
Chris King <chriskingnet@gmail.com>
Chris Raborg <craborg57@gmail.com>
Chris Roche <chris@vsco.co>
Chris Schaefer <chris@dtzq.com>
chrisforrette <chris@chrisforrette.com>
Christian Muehlhaeuser <muesli@gmail.com>
Christoph Sassenberg <defsprite@gmail.com>
Colin Misare <github.com/cmisare>
Craig Peterson <cpeterson@stackoverflow.com>
Cristian Maglie <c.maglie@bug.st>
Daehyeok Mun <daehyeok@gmail.com>
Daniel Leavitt <daniel.leavitt@gmail.com>
Daniel Nilsson <daniel.nilsson1989@gmail.com>
Daoq <masseto2002@gmail.com>
Dave Du Cros <davidducros@gmail.com>
Dave Henderson <dhenderson@gmail.com>
Dave Protasowski <dprotaso@gmail.com>
David Deng <daviddengcn@gmail.com>
David Jannotta <djannotta@gmail.com>
David Ji <github.com/davidji99>
David Lopez Reyes <davidlopezre@gmail.com>
Davide Zipeto <dawez1@gmail.com>
Dennis Webb <dennis@bluesentryit.com>
Dhi Aurrahman <diorahman@rockybars.com>
Diego Lapiduz <diego.lapiduz@cfpb.gov>
Dmitri Shuralyov <shurcooL@gmail.com>
dmnlk <seikima2demon@gmail.com>
Don Petersen <don@donpetersen.net>
Doug Turner <doug.turner@gmail.com>
Drew Fradette <drew.fradette@gmail.com>
Eivind <eivindkn@gmail.com>
Eli Uriegas <seemethere101@gmail.com>
Elliott Beach <elliott2.71828@gmail.com>
Emerson Wood <emersonwood94@gmail.com>
eperm <staffordworrell@gmail.com>
Erick Fejta <erick@fejta.com>
erwinvaneyk <erwinvaneyk@gmail.com>
Evan Elias <evanjelias@gmail.com>
Fabrice <fabrice.vaillant@student.ecp.fr>
Felix Geisendörfer <felix@debuggable.com>
Filippo Valsorda <hi@filippo.io>
Florian Forster <ff@octo.it>
Francesc Gil <xescugil@gmail.com>
Francis <hello@francismakes.com>
Francisco Guimarães <francisco.cpg@gmail.com>
Fredrik Jönsson <fredrik.jonsson@izettle.com>
Garrett Squire <garrettsquire@gmail.com>
George Kontridze <george.kontridze@gmail.com>
Georgy Buranov <gburanov@gmail.com>
Glen Mailer <glenjamin@gmail.com>
Gnahz <p@oath.pl>
Google Inc.
Grachev Mikhail <work@mgrachev.com>
griffin_stewie <panterathefamilyguy@gmail.com>
Guillaume Jacquet <guillaume.jacquet@gmail.com>
Guz Alexander <kalimatas@gmail.com>
Guðmundur Bjarni Ólafsson <gudmundur@github.com>
Hanno Hecker <hanno.hecker@zalando.de>
Hari haran <hariharan.uno@gmail.com>
haya14busa <haya14busa@gmail.com>
haya14busa <hayabusa1419@gmail.com>
Huy Tr <kingbazoka@gmail.com>
huydx <doxuanhuy@gmail.com>
i2bskn <i2bskn@gmail.com>
Ioannis Georgoulas <igeorgoulas21@gmail.com>
Isao Jonas <isao.jonas@gmail.com>
isqua <isqua@isqua.ru>
Jameel Haffejee <RC1140@republiccommandos.co.za>
James Cockbain <james.cockbain@ibm.com>
Jan Kosecki <jan.kosecki91@gmail.com>
Javier Campanini <jcampanini@palantir.com>
Jens Rantil <jens.rantil@gmail.com>
Jeremy Morris <jeremylevanmorris@gmail.com>
Jesse Newland <jesse@jnewland.com>
Jihoon Chung <j.c@navercorp.com>
Jimmi Dyson <jimmidyson@gmail.com>
Joan Saum <joan.saum@epitech.eu>
Joe Tsai <joetsai@digital-static.net>
John Barton <jrbarton@gmail.com>
John Engelman <john.r.engelman@gmail.com>
Jordan Brockopp <jdbro94@gmail.com>
Jordan Sussman <jordansail22@gmail.com>
Joshua Bezaleel Abednego <joshua.bezaleel@gmail.com>
JP Phillips <jonphill9@gmail.com>
jpbelanger-mtl <jp.belanger@gmail.com>
Juan Basso <jrbasso@gmail.com>
Julien Garcia Gonzalez <garciagonzalez.julien@gmail.com>
Julien Rostand <jrostand@users.noreply.github.com>
Junya Kono <junya03dance@gmail.com>
Justin Abrahms <justin@abrah.ms>
Jusung Lee <e.jusunglee@gmail.com>
jzhoucliqr <jzhou@cliqr.com>
Katrina Owen <kytrinyx@github.com>
Kautilya Tripathi < tripathi.kautilya@gmail.com>
Kautilya Tripathi <tripathi.kautilya@gmail.com>
Keita Urashima <ursm@ursm.jp>
Kevin Burke <kev@inburke.com>
Konrad Malawski <konrad.malawski@project13.pl>
Kookheon Kwon <kucuny@gmail.com>
Krzysztof Kowalczyk <kkowalczyk@gmail.com>
Kshitij Saraogi <KshitijSaraogi@gmail.com>
kyokomi <kyoko1220adword@gmail.com>
Laurent Verdoïa <verdoialaurent@gmail.com>
Liam Galvin <liam@liam-galvin.co.uk>
Lovro Mažgon <lovro.mazgon@gmail.com>
Lucas Alcantara <lucasalcantaraf@gmail.com>
Luke Evers <me@lukevers.com>
Luke Kysow <lkysow@gmail.com>
Luke Roberts <email@luke-roberts.co.uk>
Luke Young <luke@hydrantlabs.org>
Maksim Zhylinski <uzzable@gmail.com>
Mark Tareshawty <tarebyte@github.com>
Martin-Louis Bright <mlbright@gmail.com>
Marwan Sulaiman <marwan.sameer@gmail.com>
Masayuki Izumi <m@izum.in>
Mat Geist <matgeist@gmail.com>
Matt <alpmatthew@gmail.com>
Matt Brender <mjbrender@gmail.com>
Matt Gaunt <matt@gauntface.co.uk>
Matt Landis <landis.matt@gmail.com>
Maxime Bury <maxime.bury@gmail.com>
Michael Spiegel <michael.m.spiegel@gmail.com>
Michael Tiller <michael.tiller@gmail.com>
Michał Glapa <michal.glapa@gmail.com>
Nadav Kaner <nadavkaner1@gmail.com>
Nathan VanBenschoten <nvanbenschoten@gmail.com>
Navaneeth Suresh <navaneeths1998@gmail.com>
Neil O'Toole <neilotoole@apache.org>
Nick Miyake <nmiyake@palantir.com>
Nick Spragg <nick.spragg@bbc.co.uk>
Nikhita Raghunath <nikitaraghunath@gmail.com>
Noah Zoschke <noah+sso2@convox.com>
ns-cweber <cweber@narrativescience.com>
Oleg Kovalov <iamolegkovalov@gmail.com>
Ole Orhagen <ole.orhagen@northern.tech>
Ondřej Kupka <ondra.cap@gmail.com>
Palash Nigam <npalash25@gmail.com>
Panagiotis Moustafellos <pmoust@gmail.com>
Parham Alvani <parham.alvani@gmail.com>
Parker Moore <parkrmoore@gmail.com>
parkhyukjun89 <park.hyukjun89@gmail.com>
Pavel Shtanko <pavel.shtanko@gmail.com>
Pete Wagner <thepwagner@github.com>
Petr Shevtsov <petr.shevtsov@gmail.com>
Pierre Carrier <pierre@meteor.com>
Piotr Zurek <p.zurek@gmail.com>
Quang Le Hong <iamquang95@gmail.com>
Quentin Leffray <fiahil@gmail.com>
Quinn Slack <qslack@qslack.com>
Rackspace US, Inc.
Radek Simko <radek.simko@gmail.com>
Radliński Ignacy <radlinsk@student.agh.edu.pl>
Rajat Jindal <rajatjindal83@gmail.com>
Rajendra arora <rajendraarora16@yahoo.com>
Ranbir Singh <binkkatal.r@gmail.com>
RaviTeja Pothana <ravi-teja@live.com>
rc1140 <jameel@republiccommandos.co.za>
Red Hat, Inc.
Ricco Førgaard <ricco@fiskeben.dk>
Rob Figueiredo <robfig@yext.com>
Rohit Upadhyay <urohit011@gmail.com>
Ronak Jain <ronakjain@outlook.in>
Ruben Vereecken <rubenvereecken@gmail.com>
Ryan Leung <rleungx@gmail.com>
Ryan Lower <rpjlower@gmail.com>
Safwan Olaimat <safwan.olaimat@gmail.com>
Sahil Dua <sahildua2305@gmail.com>
saisi <saisi@users.noreply.github.com>
Sam Minnée <sam@silverstripe.com>
Sandeep Sukhani <sandeep.d.sukhani@gmail.com>
Sander Knape <s.knape88@gmail.com>
Sander van Harmelen <svanharmelen@schubergphilis.com>
Sanket Payghan <sanket.payghan8@gmail.com>
Sarasa Kisaragi <lingsamuelgrace@gmail.com>
Sean Wang <sean@decrypted.org>
Sebastian Mandrean <sebastian.mandrean@gmail.com>
Sebastian Mæland Pedersen <sem.pedersen@stud.uis.no>
Sergey Romanov <xxsmotur@gmail.com>
Sergio Garcia <sergio.garcia@gmail.com>
Sevki <s@sevki.org>
Shagun Khemka <shagun.khemka60@gmail.com>
shakeelrao <shakeelrao79@gmail.com>
Shawn Catanzarite <me@shawncatz.com>
Shawn Smith <shawnpsmith@gmail.com>
Shibasis Patel <patelshibasis@gmail.com>
Shrikrishna Singh <krishnasingh.ss30@gmail.com>
sona-tar <sona.zip@gmail.com>
SoundCloud, Ltd.
Sridhar Mocherla <srmocher@microsoft.com>
SriVignessh Pss <sriknowledge@gmail.com>
Stian Eikeland <stian@eikeland.se>
Suhaib Mujahid <suhaibmujahid@gmail.com>
Szymon Kodrebski <simonkey007@gmail.com>
Takayuki Watanabe <takanabe.w@gmail.com>
Taketoshi Fujiwara <taketoshi.fujiwara@gmail.com>
Tasya Aditya Rukmana <tadityar@gmail.com>
Thomas Bruyelle <thomas.bruyelle@gmail.com>
Timothée Peignier <timothee.peignier@tryphon.org>
tkhandel <tarunkhandelwal.iitr@gmail.com>
Trey Tacon <ttacon@gmail.com>
ttacon <ttacon@gmail.com>
Vaibhav Singh <vaibhav.singh.14cse@bml.edu.in>
Varadarajan Aravamudhan <varadaraajan@gmail.com>
Victor Castell <victor@victorcastell.com>
Victor Vrantchan <vrancean+github@gmail.com>
Vlad Ungureanu <vladu@palantir.com>
Wasim Thabraze <wasim@thabraze.me>
Will Maier <wcmaier@gmail.com>
Willem D'Haeseleer <dhwillem@gmail.com>
William Bailey <mail@williambailey.org.uk>
William Cooke <pipeston@gmail.com>
xibz <impactbchang@gmail.com>
Yann Malet <yann.malet@gmail.com>
Yannick Utard <yannickutard@gmail.com>
Yicheng Qin <qycqycqycqycqyc@gmail.com>
Yosuke Akatsuka <yosuke.akatsuka@access-company.com>
Yumikiyo Osanai <yumios.art@gmail.com>
Zach Latta <zach@zachlatta.com>

27
vendor/github.com/google/go-github/v29/LICENSE generated vendored Normal file
View file

@ -0,0 +1,27 @@
Copyright (c) 2013 The go-github AUTHORS. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,12 @@
// Copyright 2020 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
// ActionsService handles communication with the actions related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/actions/
type ActionsService service

View file

@ -0,0 +1,132 @@
// Copyright 2020 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// PublicKey represents the public key that should be used to encrypt secrets.
type PublicKey struct {
KeyID *string `json:"key_id"`
Key *string `json:"key"`
}
// GetPublicKey gets a public key that should be used for secret encryption.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#get-your-public-key
func (s *ActionsService) GetPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/secrets/public-key", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
pubKey := new(PublicKey)
resp, err := s.client.Do(ctx, req, pubKey)
if err != nil {
return nil, resp, err
}
return pubKey, resp, nil
}
// Secret represents a repository action secret.
type Secret struct {
Name string `json:"name"`
CreatedAt Timestamp `json:"created_at"`
UpdatedAt Timestamp `json:"updated_at"`
}
// Secrets represents one item from the ListSecrets response.
type Secrets struct {
TotalCount int `json:"total_count"`
Secrets []*Secret `json:"secrets"`
}
// ListSecrets lists all secrets available in a repository
// without revealing their encrypted values.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#list-secrets-for-a-repository
func (s *ActionsService) ListSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/actions/secrets", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
secrets := new(Secrets)
resp, err := s.client.Do(ctx, req, &secrets)
if err != nil {
return nil, resp, err
}
return secrets, resp, nil
}
// GetSecret gets a single secret without revealing its encrypted value.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#get-a-secret
func (s *ActionsService) GetSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
secret := new(Secret)
resp, err := s.client.Do(ctx, req, secret)
if err != nil {
return nil, resp, err
}
return secret, resp, nil
}
// EncryptedSecret represents a secret that is encrypted using a public key.
//
// The value of EncryptedValue must be your secret, encrypted with
// LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages)
// using the public key retrieved using the GetPublicKey method.
type EncryptedSecret struct {
Name string `json:"-"`
KeyID string `json:"key_id"`
EncryptedValue string `json:"encrypted_value"`
}
// CreateOrUpdateSecret creates or updates a secret with an encrypted value.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#create-or-update-a-secret-for-a-repository
func (s *ActionsService) CreateOrUpdateSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, eSecret.Name)
req, err := s.client.NewRequest("PUT", u, eSecret)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// DeleteSecret deletes a secret in a repository using the secret name.
//
// GitHub API docs: https://developer.github.com/v3/actions/secrets/#delete-a-secret-from-a-repository
func (s *ActionsService) DeleteSecret(ctx context.Context, owner, repo, name string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,88 @@
// Copyright 2020 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// Workflow represents a repository action workflow.
type Workflow struct {
ID int64 `json:"id"`
NodeID string `json:"node_id"`
Name string `json:"name"`
Path string `json:"path"`
State string `json:"state"`
CreatedAt Timestamp `json:"created_at"`
UpdatedAt Timestamp `json:"updated_at"`
URL string `json:"url"`
HTMLURL string `json:"html_url"`
BadgeURL string `json:"badge_url"`
}
// Workflows represents a slice of repository action workflows.
type Workflows struct {
TotalCount int `json:"total_count"`
Workflows []*Workflow `json:"workflows"`
}
// ListWorkflows lists all workflows in a repository.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflows/#list-repository-workflows
func (s *ActionsService) ListWorkflows(ctx context.Context, owner, repo string, opts *ListOptions) (*Workflows, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/actions/workflows", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
workflows := new(Workflows)
resp, err := s.client.Do(ctx, req, &workflows)
if err != nil {
return nil, resp, err
}
return workflows, resp, nil
}
// GetWorkflowByID gets a specific workflow by ID.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflows/#get-a-workflow
func (s *ActionsService) GetWorkflowByID(ctx context.Context, owner, repo string, workflowID int64) (*Workflow, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowID)
return s.getWorkflow(ctx, u)
}
// GetWorkflowByFileName gets a specific workflow by file name.
//
// GitHub API docs: https://developer.github.com/v3/actions/workflows/#get-a-workflow
func (s *ActionsService) GetWorkflowByFileName(ctx context.Context, owner, repo, workflowFileName string) (*Workflow, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/actions/workflows/%v", owner, repo, workflowFileName)
return s.getWorkflow(ctx, u)
}
func (s *ActionsService) getWorkflow(ctx context.Context, url string) (*Workflow, *Response, error) {
req, err := s.client.NewRequest("GET", url, nil)
if err != nil {
return nil, nil, err
}
workflow := new(Workflow)
resp, err := s.client.Do(ctx, req, workflow)
if err != nil {
return nil, resp, err
}
return workflow, resp, nil
}

View file

@ -0,0 +1,69 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import "context"
// ActivityService handles communication with the activity related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/activity/
type ActivityService service
// FeedLink represents a link to a related resource.
type FeedLink struct {
HRef *string `json:"href,omitempty"`
Type *string `json:"type,omitempty"`
}
// Feeds represents timeline resources in Atom format.
type Feeds struct {
TimelineURL *string `json:"timeline_url,omitempty"`
UserURL *string `json:"user_url,omitempty"`
CurrentUserPublicURL *string `json:"current_user_public_url,omitempty"`
CurrentUserURL *string `json:"current_user_url,omitempty"`
CurrentUserActorURL *string `json:"current_user_actor_url,omitempty"`
CurrentUserOrganizationURL *string `json:"current_user_organization_url,omitempty"`
CurrentUserOrganizationURLs []string `json:"current_user_organization_urls,omitempty"`
Links *struct {
Timeline *FeedLink `json:"timeline,omitempty"`
User *FeedLink `json:"user,omitempty"`
CurrentUserPublic *FeedLink `json:"current_user_public,omitempty"`
CurrentUser *FeedLink `json:"current_user,omitempty"`
CurrentUserActor *FeedLink `json:"current_user_actor,omitempty"`
CurrentUserOrganization *FeedLink `json:"current_user_organization,omitempty"`
CurrentUserOrganizations []FeedLink `json:"current_user_organizations,omitempty"`
} `json:"_links,omitempty"`
}
// ListFeeds lists all the feeds available to the authenticated user.
//
// GitHub provides several timeline resources in Atom format:
// Timeline: The GitHub global public timeline
// User: The public timeline for any user, using URI template
// Current user public: The public timeline for the authenticated user
// Current user: The private timeline for the authenticated user
// Current user actor: The private timeline for activity created by the
// authenticated user
// Current user organizations: The private timeline for the organizations
// the authenticated user is a member of.
//
// Note: Private feeds are only returned when authenticating via Basic Auth
// since current feed URIs use the older, non revocable auth tokens.
func (s *ActivityService) ListFeeds(ctx context.Context) (*Feeds, *Response, error) {
req, err := s.client.NewRequest("GET", "feeds", nil)
if err != nil {
return nil, nil, err
}
f := &Feeds{}
resp, err := s.client.Do(ctx, req, f)
if err != nil {
return nil, resp, err
}
return f, resp, nil
}

View file

@ -0,0 +1,215 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ListEvents drinks from the firehose of all public events across GitHub.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events
func (s *ActivityService) ListEvents(ctx context.Context, opts *ListOptions) ([]*Event, *Response, error) {
u, err := addOptions("events", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var events []*Event
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}
// ListRepositoryEvents lists events for a repository.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-repository-events
func (s *ActivityService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/events", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var events []*Event
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}
// ListIssueEventsForRepository lists issue events for a repository.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-issue-events-for-a-repository
func (s *ActivityService) ListIssueEventsForRepository(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var events []*IssueEvent
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}
// ListEventsForRepoNetwork lists public events for a network of repositories.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-a-network-of-repositories
func (s *ActivityService) ListEventsForRepoNetwork(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Event, *Response, error) {
u := fmt.Sprintf("networks/%v/%v/events", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var events []*Event
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}
// ListEventsForOrganization lists public events for an organization.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-public-events-for-an-organization
func (s *ActivityService) ListEventsForOrganization(ctx context.Context, org string, opts *ListOptions) ([]*Event, *Response, error) {
u := fmt.Sprintf("orgs/%v/events", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var events []*Event
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}
// ListEventsPerformedByUser lists the events performed by a user. If publicOnly is
// true, only public events will be returned.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-performed-by-a-user
func (s *ActivityService) ListEventsPerformedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) {
var u string
if publicOnly {
u = fmt.Sprintf("users/%v/events/public", user)
} else {
u = fmt.Sprintf("users/%v/events", user)
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var events []*Event
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}
// ListEventsReceivedByUser lists the events received by a user. If publicOnly is
// true, only public events will be returned.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-that-a-user-has-received
func (s *ActivityService) ListEventsReceivedByUser(ctx context.Context, user string, publicOnly bool, opts *ListOptions) ([]*Event, *Response, error) {
var u string
if publicOnly {
u = fmt.Sprintf("users/%v/received_events/public", user)
} else {
u = fmt.Sprintf("users/%v/received_events", user)
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var events []*Event
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}
// ListUserEventsForOrganization provides the users organization dashboard. You
// must be authenticated as the user to view this.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/#list-events-for-an-organization
func (s *ActivityService) ListUserEventsForOrganization(ctx context.Context, org, user string, opts *ListOptions) ([]*Event, *Response, error) {
u := fmt.Sprintf("users/%v/events/orgs/%v", user, org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var events []*Event
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}

View file

@ -0,0 +1,223 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// Notification identifies a GitHub notification for a user.
type Notification struct {
ID *string `json:"id,omitempty"`
Repository *Repository `json:"repository,omitempty"`
Subject *NotificationSubject `json:"subject,omitempty"`
// Reason identifies the event that triggered the notification.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#notification-reasons
Reason *string `json:"reason,omitempty"`
Unread *bool `json:"unread,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
LastReadAt *time.Time `json:"last_read_at,omitempty"`
URL *string `json:"url,omitempty"`
}
// NotificationSubject identifies the subject of a notification.
type NotificationSubject struct {
Title *string `json:"title,omitempty"`
URL *string `json:"url,omitempty"`
LatestCommentURL *string `json:"latest_comment_url,omitempty"`
Type *string `json:"type,omitempty"`
}
// NotificationListOptions specifies the optional parameters to the
// ActivityService.ListNotifications method.
type NotificationListOptions struct {
All bool `url:"all,omitempty"`
Participating bool `url:"participating,omitempty"`
Since time.Time `url:"since,omitempty"`
Before time.Time `url:"before,omitempty"`
ListOptions
}
// ListNotifications lists all notifications for the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications
func (s *ActivityService) ListNotifications(ctx context.Context, opts *NotificationListOptions) ([]*Notification, *Response, error) {
u := fmt.Sprintf("notifications")
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var notifications []*Notification
resp, err := s.client.Do(ctx, req, &notifications)
if err != nil {
return nil, resp, err
}
return notifications, resp, nil
}
// ListRepositoryNotifications lists all notifications in a given repository
// for the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#list-your-notifications-in-a-repository
func (s *ActivityService) ListRepositoryNotifications(ctx context.Context, owner, repo string, opts *NotificationListOptions) ([]*Notification, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var notifications []*Notification
resp, err := s.client.Do(ctx, req, &notifications)
if err != nil {
return nil, resp, err
}
return notifications, resp, nil
}
type markReadOptions struct {
LastReadAt time.Time `json:"last_read_at,omitempty"`
}
// MarkNotificationsRead marks all notifications up to lastRead as read.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-as-read
func (s *ActivityService) MarkNotificationsRead(ctx context.Context, lastRead time.Time) (*Response, error) {
opts := &markReadOptions{
LastReadAt: lastRead,
}
req, err := s.client.NewRequest("PUT", "notifications", opts)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// MarkRepositoryNotificationsRead marks all notifications up to lastRead in
// the specified repository as read.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-notifications-as-read-in-a-repository
func (s *ActivityService) MarkRepositoryNotificationsRead(ctx context.Context, owner, repo string, lastRead time.Time) (*Response, error) {
opts := &markReadOptions{
LastReadAt: lastRead,
}
u := fmt.Sprintf("repos/%v/%v/notifications", owner, repo)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// GetThread gets the specified notification thread.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#view-a-single-thread
func (s *ActivityService) GetThread(ctx context.Context, id string) (*Notification, *Response, error) {
u := fmt.Sprintf("notifications/threads/%v", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
notification := new(Notification)
resp, err := s.client.Do(ctx, req, notification)
if err != nil {
return nil, resp, err
}
return notification, resp, nil
}
// MarkThreadRead marks the specified thread as read.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#mark-a-thread-as-read
func (s *ActivityService) MarkThreadRead(ctx context.Context, id string) (*Response, error) {
u := fmt.Sprintf("notifications/threads/%v", id)
req, err := s.client.NewRequest("PATCH", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// GetThreadSubscription checks to see if the authenticated user is subscribed
// to a thread.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#get-a-thread-subscription
func (s *ActivityService) GetThreadSubscription(ctx context.Context, id string) (*Subscription, *Response, error) {
u := fmt.Sprintf("notifications/threads/%v/subscription", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
sub := new(Subscription)
resp, err := s.client.Do(ctx, req, sub)
if err != nil {
return nil, resp, err
}
return sub, resp, nil
}
// SetThreadSubscription sets the subscription for the specified thread for the
// authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#set-a-thread-subscription
func (s *ActivityService) SetThreadSubscription(ctx context.Context, id string, subscription *Subscription) (*Subscription, *Response, error) {
u := fmt.Sprintf("notifications/threads/%v/subscription", id)
req, err := s.client.NewRequest("PUT", u, subscription)
if err != nil {
return nil, nil, err
}
sub := new(Subscription)
resp, err := s.client.Do(ctx, req, sub)
if err != nil {
return nil, resp, err
}
return sub, resp, nil
}
// DeleteThreadSubscription deletes the subscription for the specified thread
// for the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/activity/notifications/#delete-a-thread-subscription
func (s *ActivityService) DeleteThreadSubscription(ctx context.Context, id string) (*Response, error) {
u := fmt.Sprintf("notifications/threads/%v/subscription", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,137 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"strings"
)
// StarredRepository is returned by ListStarred.
type StarredRepository struct {
StarredAt *Timestamp `json:"starred_at,omitempty"`
Repository *Repository `json:"repo,omitempty"`
}
// Stargazer represents a user that has starred a repository.
type Stargazer struct {
StarredAt *Timestamp `json:"starred_at,omitempty"`
User *User `json:"user,omitempty"`
}
// ListStargazers lists people who have starred the specified repo.
//
// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-stargazers
func (s *ActivityService) ListStargazers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Stargazer, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/stargazers", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches
req.Header.Set("Accept", mediaTypeStarringPreview)
var stargazers []*Stargazer
resp, err := s.client.Do(ctx, req, &stargazers)
if err != nil {
return nil, resp, err
}
return stargazers, resp, nil
}
// ActivityListStarredOptions specifies the optional parameters to the
// ActivityService.ListStarred method.
type ActivityListStarredOptions struct {
// How to sort the repository list. Possible values are: created, updated,
// pushed, full_name. Default is "full_name".
Sort string `url:"sort,omitempty"`
// Direction in which to sort repositories. Possible values are: asc, desc.
// Default is "asc" when sort is "full_name", otherwise default is "desc".
Direction string `url:"direction,omitempty"`
ListOptions
}
// ListStarred lists all the repos starred by a user. Passing the empty string
// will list the starred repositories for the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/activity/starring/#list-repositories-being-starred
func (s *ActivityService) ListStarred(ctx context.Context, user string, opts *ActivityListStarredOptions) ([]*StarredRepository, *Response, error) {
var u string
if user != "" {
u = fmt.Sprintf("users/%v/starred", user)
} else {
u = "user/starred"
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when APIs fully launch
acceptHeaders := []string{mediaTypeStarringPreview, mediaTypeTopicsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var repos []*StarredRepository
resp, err := s.client.Do(ctx, req, &repos)
if err != nil {
return nil, resp, err
}
return repos, resp, nil
}
// IsStarred checks if a repository is starred by authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/activity/starring/#check-if-you-are-starring-a-repository
func (s *ActivityService) IsStarred(ctx context.Context, owner, repo string) (bool, *Response, error) {
u := fmt.Sprintf("user/starred/%v/%v", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
resp, err := s.client.Do(ctx, req, nil)
starred, err := parseBoolResponse(err)
return starred, resp, err
}
// Star a repository as the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/activity/starring/#star-a-repository
func (s *ActivityService) Star(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("user/starred/%v/%v", owner, repo)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Unstar a repository as the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/activity/starring/#unstar-a-repository
func (s *ActivityService) Unstar(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("user/starred/%v/%v", owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,146 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// Subscription identifies a repository or thread subscription.
type Subscription struct {
Subscribed *bool `json:"subscribed,omitempty"`
Ignored *bool `json:"ignored,omitempty"`
Reason *string `json:"reason,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
URL *string `json:"url,omitempty"`
// only populated for repository subscriptions
RepositoryURL *string `json:"repository_url,omitempty"`
// only populated for thread subscriptions
ThreadURL *string `json:"thread_url,omitempty"`
}
// ListWatchers lists watchers of a particular repo.
//
// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-watchers
func (s *ActivityService) ListWatchers(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/subscribers", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var watchers []*User
resp, err := s.client.Do(ctx, req, &watchers)
if err != nil {
return nil, resp, err
}
return watchers, resp, nil
}
// ListWatched lists the repositories the specified user is watching. Passing
// the empty string will fetch watched repos for the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/activity/watching/#list-repositories-being-watched
func (s *ActivityService) ListWatched(ctx context.Context, user string, opts *ListOptions) ([]*Repository, *Response, error) {
var u string
if user != "" {
u = fmt.Sprintf("users/%v/subscriptions", user)
} else {
u = "user/subscriptions"
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var watched []*Repository
resp, err := s.client.Do(ctx, req, &watched)
if err != nil {
return nil, resp, err
}
return watched, resp, nil
}
// GetRepositorySubscription returns the subscription for the specified
// repository for the authenticated user. If the authenticated user is not
// watching the repository, a nil Subscription is returned.
//
// GitHub API docs: https://developer.github.com/v3/activity/watching/#get-a-repository-subscription
func (s *ActivityService) GetRepositorySubscription(ctx context.Context, owner, repo string) (*Subscription, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
sub := new(Subscription)
resp, err := s.client.Do(ctx, req, sub)
if err != nil {
// if it's just a 404, don't return that as an error
_, err = parseBoolResponse(err)
return nil, resp, err
}
return sub, resp, nil
}
// SetRepositorySubscription sets the subscription for the specified repository
// for the authenticated user.
//
// To watch a repository, set subscription.Subscribed to true.
// To ignore notifications made within a repository, set subscription.Ignored to true.
// To stop watching a repository, use DeleteRepositorySubscription.
//
// GitHub API docs: https://developer.github.com/v3/activity/watching/#set-a-repository-subscription
func (s *ActivityService) SetRepositorySubscription(ctx context.Context, owner, repo string, subscription *Subscription) (*Subscription, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
req, err := s.client.NewRequest("PUT", u, subscription)
if err != nil {
return nil, nil, err
}
sub := new(Subscription)
resp, err := s.client.Do(ctx, req, sub)
if err != nil {
return nil, resp, err
}
return sub, resp, nil
}
// DeleteRepositorySubscription deletes the subscription for the specified
// repository for the authenticated user.
//
// This is used to stop watching a repository. To control whether or not to
// receive notifications from a repository, use SetRepositorySubscription.
//
// GitHub API docs: https://developer.github.com/v3/activity/watching/#delete-a-repository-subscription
func (s *ActivityService) DeleteRepositorySubscription(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("repos/%s/%s/subscription", owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

119
vendor/github.com/google/go-github/v29/github/admin.go generated vendored Normal file
View file

@ -0,0 +1,119 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// AdminService handles communication with the admin related methods of the
// GitHub API. These API routes are normally only accessible for GitHub
// Enterprise installations.
//
// GitHub API docs: https://developer.github.com/v3/enterprise/
type AdminService service
// TeamLDAPMapping represents the mapping between a GitHub team and an LDAP group.
type TeamLDAPMapping struct {
ID *int64 `json:"id,omitempty"`
LDAPDN *string `json:"ldap_dn,omitempty"`
URL *string `json:"url,omitempty"`
Name *string `json:"name,omitempty"`
Slug *string `json:"slug,omitempty"`
Description *string `json:"description,omitempty"`
Privacy *string `json:"privacy,omitempty"`
Permission *string `json:"permission,omitempty"`
MembersURL *string `json:"members_url,omitempty"`
RepositoriesURL *string `json:"repositories_url,omitempty"`
}
func (m TeamLDAPMapping) String() string {
return Stringify(m)
}
// UserLDAPMapping represents the mapping between a GitHub user and an LDAP user.
type UserLDAPMapping struct {
ID *int64 `json:"id,omitempty"`
LDAPDN *string `json:"ldap_dn,omitempty"`
Login *string `json:"login,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
GravatarID *string `json:"gravatar_id,omitempty"`
Type *string `json:"type,omitempty"`
SiteAdmin *bool `json:"site_admin,omitempty"`
URL *string `json:"url,omitempty"`
EventsURL *string `json:"events_url,omitempty"`
FollowingURL *string `json:"following_url,omitempty"`
FollowersURL *string `json:"followers_url,omitempty"`
GistsURL *string `json:"gists_url,omitempty"`
OrganizationsURL *string `json:"organizations_url,omitempty"`
ReceivedEventsURL *string `json:"received_events_url,omitempty"`
ReposURL *string `json:"repos_url,omitempty"`
StarredURL *string `json:"starred_url,omitempty"`
SubscriptionsURL *string `json:"subscriptions_url,omitempty"`
}
func (m UserLDAPMapping) String() string {
return Stringify(m)
}
// Enterprise represents the GitHub enterprise profile.
type Enterprise struct {
ID *int `json:"id,omitempty"`
Slug *string `json:"slug,omitempty"`
Name *string `json:"name,omitempty"`
NodeID *string `json:"node_id,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
Description *string `json:"description,omitempty"`
WebsiteURL *string `json:"website_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
}
func (m Enterprise) String() string {
return Stringify(m)
}
// UpdateUserLDAPMapping updates the mapping between a GitHub user and an LDAP user.
//
// GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-user
func (s *AdminService) UpdateUserLDAPMapping(ctx context.Context, user string, mapping *UserLDAPMapping) (*UserLDAPMapping, *Response, error) {
u := fmt.Sprintf("admin/ldap/users/%v/mapping", user)
req, err := s.client.NewRequest("PATCH", u, mapping)
if err != nil {
return nil, nil, err
}
m := new(UserLDAPMapping)
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// UpdateTeamLDAPMapping updates the mapping between a GitHub team and an LDAP group.
//
// GitHub API docs: https://developer.github.com/v3/enterprise/ldap/#update-ldap-mapping-for-a-team
func (s *AdminService) UpdateTeamLDAPMapping(ctx context.Context, team int64, mapping *TeamLDAPMapping) (*TeamLDAPMapping, *Response, error) {
u := fmt.Sprintf("admin/ldap/teams/%v/mapping", team)
req, err := s.client.NewRequest("PATCH", u, mapping)
if err != nil {
return nil, nil, err
}
m := new(TeamLDAPMapping)
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}

View file

@ -0,0 +1,43 @@
// Copyright 2019 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import "context"
// createOrgRequest is a subset of Organization and is used internally
// by CreateOrg to pass only the known fields for the endpoint.
type createOrgRequest struct {
Login *string `json:"login,omitempty"`
Admin *string `json:"admin,omitempty"`
}
// CreateOrg creates a new organization in GitHub Enterprise.
//
// Note that only a subset of the org fields are used and org must
// not be nil.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/orgs/#create-an-organization
func (s *AdminService) CreateOrg(ctx context.Context, org *Organization, admin string) (*Organization, *Response, error) {
u := "admin/organizations"
orgReq := &createOrgRequest{
Login: org.Login,
Admin: &admin,
}
req, err := s.client.NewRequest("POST", u, orgReq)
if err != nil {
return nil, nil, err
}
o := new(Organization)
resp, err := s.client.Do(ctx, req, o)
if err != nil {
return nil, resp, err
}
return o, resp, nil
}

View file

@ -0,0 +1,171 @@
// Copyright 2017 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// AdminStats represents a variety of stats of a GitHub Enterprise
// installation.
type AdminStats struct {
Issues *IssueStats `json:"issues,omitempty"`
Hooks *HookStats `json:"hooks,omitempty"`
Milestones *MilestoneStats `json:"milestones,omitempty"`
Orgs *OrgStats `json:"orgs,omitempty"`
Comments *CommentStats `json:"comments,omitempty"`
Pages *PageStats `json:"pages,omitempty"`
Users *UserStats `json:"users,omitempty"`
Gists *GistStats `json:"gists,omitempty"`
Pulls *PullStats `json:"pulls,omitempty"`
Repos *RepoStats `json:"repos,omitempty"`
}
func (s AdminStats) String() string {
return Stringify(s)
}
// IssueStats represents the number of total, open and closed issues.
type IssueStats struct {
TotalIssues *int `json:"total_issues,omitempty"`
OpenIssues *int `json:"open_issues,omitempty"`
ClosedIssues *int `json:"closed_issues,omitempty"`
}
func (s IssueStats) String() string {
return Stringify(s)
}
// HookStats represents the number of total, active and inactive hooks.
type HookStats struct {
TotalHooks *int `json:"total_hooks,omitempty"`
ActiveHooks *int `json:"active_hooks,omitempty"`
InactiveHooks *int `json:"inactive_hooks,omitempty"`
}
func (s HookStats) String() string {
return Stringify(s)
}
// MilestoneStats represents the number of total, open and close milestones.
type MilestoneStats struct {
TotalMilestones *int `json:"total_milestones,omitempty"`
OpenMilestones *int `json:"open_milestones,omitempty"`
ClosedMilestones *int `json:"closed_milestones,omitempty"`
}
func (s MilestoneStats) String() string {
return Stringify(s)
}
// OrgStats represents the number of total, disabled organizations and the team
// and team member count.
type OrgStats struct {
TotalOrgs *int `json:"total_orgs,omitempty"`
DisabledOrgs *int `json:"disabled_orgs,omitempty"`
TotalTeams *int `json:"total_teams,omitempty"`
TotalTeamMembers *int `json:"total_team_members,omitempty"`
}
func (s OrgStats) String() string {
return Stringify(s)
}
// CommentStats represents the number of total comments on commits, gists, issues
// and pull requests.
type CommentStats struct {
TotalCommitComments *int `json:"total_commit_comments,omitempty"`
TotalGistComments *int `json:"total_gist_comments,omitempty"`
TotalIssueComments *int `json:"total_issue_comments,omitempty"`
TotalPullRequestComments *int `json:"total_pull_request_comments,omitempty"`
}
func (s CommentStats) String() string {
return Stringify(s)
}
// PageStats represents the total number of github pages.
type PageStats struct {
TotalPages *int `json:"total_pages,omitempty"`
}
func (s PageStats) String() string {
return Stringify(s)
}
// UserStats represents the number of total, admin and suspended users.
type UserStats struct {
TotalUsers *int `json:"total_users,omitempty"`
AdminUsers *int `json:"admin_users,omitempty"`
SuspendedUsers *int `json:"suspended_users,omitempty"`
}
func (s UserStats) String() string {
return Stringify(s)
}
// GistStats represents the number of total, private and public gists.
type GistStats struct {
TotalGists *int `json:"total_gists,omitempty"`
PrivateGists *int `json:"private_gists,omitempty"`
PublicGists *int `json:"public_gists,omitempty"`
}
func (s GistStats) String() string {
return Stringify(s)
}
// PullStats represents the number of total, merged, mergable and unmergeable
// pull-requests.
type PullStats struct {
TotalPulls *int `json:"total_pulls,omitempty"`
MergedPulls *int `json:"merged_pulls,omitempty"`
MergablePulls *int `json:"mergeable_pulls,omitempty"`
UnmergablePulls *int `json:"unmergeable_pulls,omitempty"`
}
func (s PullStats) String() string {
return Stringify(s)
}
// RepoStats represents the number of total, root, fork, organization repositories
// together with the total number of pushes and wikis.
type RepoStats struct {
TotalRepos *int `json:"total_repos,omitempty"`
RootRepos *int `json:"root_repos,omitempty"`
ForkRepos *int `json:"fork_repos,omitempty"`
OrgRepos *int `json:"org_repos,omitempty"`
TotalPushes *int `json:"total_pushes,omitempty"`
TotalWikis *int `json:"total_wikis,omitempty"`
}
func (s RepoStats) String() string {
return Stringify(s)
}
// GetAdminStats returns a variety of metrics about a GitHub Enterprise
// installation.
//
// Please note that this is only available to site administrators,
// otherwise it will error with a 404 not found (instead of 401 or 403).
//
// GitHub API docs: https://developer.github.com/v3/enterprise-admin/admin_stats/
func (s *AdminService) GetAdminStats(ctx context.Context) (*AdminStats, *Response, error) {
u := fmt.Sprintf("enterprise/stats/all")
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
m := new(AdminStats)
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}

View file

@ -0,0 +1,133 @@
// Copyright 2019 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// createUserRequest is a subset of User and is used internally
// by CreateUser to pass only the known fields for the endpoint.
type createUserRequest struct {
Login *string `json:"login,omitempty"`
Email *string `json:"email,omitempty"`
}
// CreateUser creates a new user in GitHub Enterprise.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-a-new-user
func (s *AdminService) CreateUser(ctx context.Context, login, email string) (*User, *Response, error) {
u := "admin/users"
userReq := &createUserRequest{
Login: &login,
Email: &email,
}
req, err := s.client.NewRequest("POST", u, userReq)
if err != nil {
return nil, nil, err
}
var user User
resp, err := s.client.Do(ctx, req, &user)
if err != nil {
return nil, resp, err
}
return &user, resp, nil
}
// DeleteUser deletes a user in GitHub Enterprise.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-a-user
func (s *AdminService) DeleteUser(ctx context.Context, username string) (*Response, error) {
u := "admin/users/" + username
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}
// ImpersonateUserOptions represents the scoping for the OAuth token.
type ImpersonateUserOptions struct {
Scopes []string `json:"scopes,omitempty"`
}
// OAuthAPP represents the GitHub Site Administrator OAuth app.
type OAuthAPP struct {
URL *string `json:"url,omitempty"`
Name *string `json:"name,omitempty"`
ClientID *string `json:"client_id,omitempty"`
}
func (s OAuthAPP) String() string {
return Stringify(s)
}
// UserAuthorization represents the impersonation response.
type UserAuthorization struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
Scopes []string `json:"scopes,omitempty"`
Token *string `json:"token,omitempty"`
TokenLastEight *string `json:"token_last_eight,omitempty"`
HashedToken *string `json:"hashed_token,omitempty"`
App *OAuthAPP `json:"app,omitempty"`
Note *string `json:"note,omitempty"`
NoteURL *string `json:"note_url,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
Fingerprint *string `json:"fingerprint,omitempty"`
}
// CreateUserImpersonation creates an impersonation OAuth token.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-an-impersonation-oauth-token
func (s *AdminService) CreateUserImpersonation(ctx context.Context, username string, opts *ImpersonateUserOptions) (*UserAuthorization, *Response, error) {
u := fmt.Sprintf("admin/users/%s/authorizations", username)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
a := new(UserAuthorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// DeleteUserImpersonation deletes an impersonation OAuth token.
//
// GitHub Enterprise API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-an-impersonation-oauth-token
func (s *AdminService) DeleteUserImpersonation(ctx context.Context, username string) (*Response, error) {
u := fmt.Sprintf("admin/users/%s/authorizations", username)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
resp, err := s.client.Do(ctx, req, nil)
if err != nil {
return resp, err
}
return resp, nil
}

303
vendor/github.com/google/go-github/v29/github/apps.go generated vendored Normal file
View file

@ -0,0 +1,303 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// AppsService provides access to the installation related functions
// in the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/apps/
type AppsService service
// App represents a GitHub App.
type App struct {
ID *int64 `json:"id,omitempty"`
Slug *string `json:"slug,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Owner *User `json:"owner,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
ExternalURL *string `json:"external_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
Events []string `json:"events,omitempty"`
}
// InstallationToken represents an installation token.
type InstallationToken struct {
Token *string `json:"token,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
Repositories []*Repository `json:"repositories,omitempty"`
}
// InstallationTokenOptions allow restricting a token's access to specific repositories.
type InstallationTokenOptions struct {
// The IDs of the repositories that the installation token can access.
// Providing repository IDs restricts the access of an installation token to specific repositories.
RepositoryIDs []int64 `json:"repository_ids,omitempty"`
// The permissions granted to the access token.
// The permissions object includes the permission names and their access type.
Permissions *InstallationPermissions `json:"permissions,omitempty"`
}
// InstallationPermissions lists the repository and organization permissions for an installation.
//
// Permission names taken from:
// https://developer.github.com/v3/apps/permissions/
// https://developer.github.com/enterprise/v3/apps/permissions/
type InstallationPermissions struct {
Administration *string `json:"administration,omitempty"`
Blocking *string `json:"blocking,omitempty"`
Checks *string `json:"checks,omitempty"`
Contents *string `json:"contents,omitempty"`
ContentReferences *string `json:"content_references,omitempty"`
Deployments *string `json:"deployments,omitempty"`
Emails *string `json:"emails,omitempty"`
Followers *string `json:"followers,omitempty"`
Issues *string `json:"issues,omitempty"`
Metadata *string `json:"metadata,omitempty"`
Members *string `json:"members,omitempty"`
OrganizationAdministration *string `json:"organization_administration,omitempty"`
OrganizationHooks *string `json:"organization_hooks,omitempty"`
OrganizationPlan *string `json:"organization_plan,omitempty"`
OrganizationPreReceiveHooks *string `json:"organization_pre_receive_hooks,omitempty"`
OrganizationProjects *string `json:"organization_projects,omitempty"`
OrganizationUserBlocking *string `json:"organization_user_blocking,omitempty"`
Packages *string `json:"packages,omitempty"`
Pages *string `json:"pages,omitempty"`
PullRequests *string `json:"pull_requests,omitempty"`
RepositoryHooks *string `json:"repository_hooks,omitempty"`
RepositoryProjects *string `json:"repository_projects,omitempty"`
RepositoryPreReceiveHooks *string `json:"repository_pre_receive_hooks,omitempty"`
SingleFile *string `json:"single_file,omitempty"`
Statuses *string `json:"statuses,omitempty"`
TeamDiscussions *string `json:"team_discussions,omitempty"`
VulnerabilityAlerts *string `json:"vulnerability_alerts,omitempty"`
}
// Installation represents a GitHub Apps installation.
type Installation struct {
ID *int64 `json:"id,omitempty"`
AppID *int64 `json:"app_id,omitempty"`
TargetID *int64 `json:"target_id,omitempty"`
Account *User `json:"account,omitempty"`
AccessTokensURL *string `json:"access_tokens_url,omitempty"`
RepositoriesURL *string `json:"repositories_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
TargetType *string `json:"target_type,omitempty"`
SingleFileName *string `json:"single_file_name,omitempty"`
RepositorySelection *string `json:"repository_selection,omitempty"`
Events []string `json:"events,omitempty"`
Permissions *InstallationPermissions `json:"permissions,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
}
// Attachment represents a GitHub Apps attachment.
type Attachment struct {
ID *int64 `json:"id,omitempty"`
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
}
func (i Installation) String() string {
return Stringify(i)
}
// Get a single GitHub App. Passing the empty string will get
// the authenticated GitHub App.
//
// Note: appSlug is just the URL-friendly name of your GitHub App.
// You can find this on the settings page for your GitHub App
// (e.g., https://github.com/settings/apps/:app_slug).
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-github-app
func (s *AppsService) Get(ctx context.Context, appSlug string) (*App, *Response, error) {
var u string
if appSlug != "" {
u = fmt.Sprintf("apps/%v", appSlug)
} else {
u = "app"
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
app := new(App)
resp, err := s.client.Do(ctx, req, app)
if err != nil {
return nil, resp, err
}
return app, resp, nil
}
// ListInstallations lists the installations that the current GitHub App has.
//
// GitHub API docs: https://developer.github.com/v3/apps/#list-installations
func (s *AppsService) ListInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) {
u, err := addOptions("app/installations", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
var i []*Installation
resp, err := s.client.Do(ctx, req, &i)
if err != nil {
return nil, resp, err
}
return i, resp, nil
}
// GetInstallation returns the specified installation.
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-a-single-installation
func (s *AppsService) GetInstallation(ctx context.Context, id int64) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("app/installations/%v", id))
}
// ListUserInstallations lists installations that are accessible to the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/apps/#list-installations-for-user
func (s *AppsService) ListUserInstallations(ctx context.Context, opts *ListOptions) ([]*Installation, *Response, error) {
u, err := addOptions("user/installations", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
var i struct {
Installations []*Installation `json:"installations"`
}
resp, err := s.client.Do(ctx, req, &i)
if err != nil {
return nil, resp, err
}
return i.Installations, resp, nil
}
// CreateInstallationToken creates a new installation token.
//
// GitHub API docs: https://developer.github.com/v3/apps/#create-a-new-installation-token
func (s *AppsService) CreateInstallationToken(ctx context.Context, id int64, opts *InstallationTokenOptions) (*InstallationToken, *Response, error) {
u := fmt.Sprintf("app/installations/%v/access_tokens", id)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
t := new(InstallationToken)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// CreateAttachment creates a new attachment on user comment containing a url.
//
// GitHub API docs: https://developer.github.com/v3/apps/#create-a-content-attachment
func (s *AppsService) CreateAttachment(ctx context.Context, contentReferenceID int64, title, body string) (*Attachment, *Response, error) {
u := fmt.Sprintf("content_references/%v/attachments", contentReferenceID)
payload := &Attachment{Title: String(title), Body: String(body)}
req, err := s.client.NewRequest("POST", u, payload)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
m := &Attachment{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// FindOrganizationInstallation finds the organization's installation information.
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-an-organization-installation
func (s *AppsService) FindOrganizationInstallation(ctx context.Context, org string) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("orgs/%v/installation", org))
}
// FindRepositoryInstallation finds the repository's installation information.
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-a-repository-installation
func (s *AppsService) FindRepositoryInstallation(ctx context.Context, owner, repo string) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("repos/%v/%v/installation", owner, repo))
}
// FindRepositoryInstallationByID finds the repository's installation information.
//
// Note: FindRepositoryInstallationByID uses the undocumented GitHub API endpoint /repositories/:id/installation.
func (s *AppsService) FindRepositoryInstallationByID(ctx context.Context, id int64) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("repositories/%d/installation", id))
}
// FindUserInstallation finds the user's installation information.
//
// GitHub API docs: https://developer.github.com/v3/apps/#get-a-user-installation
func (s *AppsService) FindUserInstallation(ctx context.Context, user string) (*Installation, *Response, error) {
return s.getInstallation(ctx, fmt.Sprintf("users/%v/installation", user))
}
func (s *AppsService) getInstallation(ctx context.Context, url string) (*Installation, *Response, error) {
req, err := s.client.NewRequest("GET", url, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
i := new(Installation)
resp, err := s.client.Do(ctx, req, i)
if err != nil {
return nil, resp, err
}
return i, resp, nil
}

View file

@ -0,0 +1,117 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ListRepos lists the repositories that are accessible to the authenticated installation.
//
// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories
func (s *AppsService) ListRepos(ctx context.Context, opts *ListOptions) ([]*Repository, *Response, error) {
u, err := addOptions("installation/repositories", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
var r struct {
Repositories []*Repository `json:"repositories"`
}
resp, err := s.client.Do(ctx, req, &r)
if err != nil {
return nil, resp, err
}
return r.Repositories, resp, nil
}
// ListUserRepos lists repositories that are accessible
// to the authenticated user for an installation.
//
// GitHub API docs: https://developer.github.com/v3/apps/installations/#list-repositories-accessible-to-the-user-for-an-installation
func (s *AppsService) ListUserRepos(ctx context.Context, id int64, opts *ListOptions) ([]*Repository, *Response, error) {
u := fmt.Sprintf("user/installations/%v/repositories", id)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
var r struct {
Repositories []*Repository `json:"repositories"`
}
resp, err := s.client.Do(ctx, req, &r)
if err != nil {
return nil, resp, err
}
return r.Repositories, resp, nil
}
// AddRepository adds a single repository to an installation.
//
// GitHub API docs: https://developer.github.com/v3/apps/installations/#add-repository-to-installation
func (s *AppsService) AddRepository(ctx context.Context, instID, repoID int64) (*Repository, *Response, error) {
u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeIntegrationPreview)
r := new(Repository)
resp, err := s.client.Do(ctx, req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// RemoveRepository removes a single repository from an installation.
//
// GitHub docs: https://developer.github.com/v3/apps/installations/#remove-repository-from-installation
func (s *AppsService) RemoveRepository(ctx context.Context, instID, repoID int64) (*Response, error) {
u := fmt.Sprintf("user/installations/%v/repositories/%v", instID, repoID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", mediaTypeIntegrationPreview)
return s.client.Do(ctx, req, nil)
}
// RevokeInstallationToken revokes an installation token.
//
// GitHub docs: https://developer.github.com/v3/apps/installations/#revoke-an-installation-token
func (s *AppsService) RevokeInstallationToken(ctx context.Context) (*Response, error) {
u := "installation/token"
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", mediaTypeRevokeTokenPreview)
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,53 @@
// Copyright 2019 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
const (
mediaTypeAppManifestPreview = "application/vnd.github.fury-preview+json"
)
// AppConfig describes the configuration of a GitHub App.
type AppConfig struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Owner *User `json:"owner,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
ExternalURL *string `json:"external_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
ClientID *string `json:"client_id,omitempty"`
ClientSecret *string `json:"client_secret,omitempty"`
WebhookSecret *string `json:"webhook_secret,omitempty"`
PEM *string `json:"pem,omitempty"`
}
// CompleteAppManifest completes the App manifest handshake flow for the given
// code.
//
// GitHub API docs: https://developer.github.com/apps/building-github-apps/creating-github-apps-from-a-manifest/#3-you-exchange-the-temporary-code-to-retrieve-the-app-configuration
func (s *AppsService) CompleteAppManifest(ctx context.Context, code string) (*AppConfig, *Response, error) {
u := fmt.Sprintf("app-manifests/%s/conversions", code)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeAppManifestPreview)
cfg := new(AppConfig)
resp, err := s.client.Do(ctx, req, cfg)
if err != nil {
return nil, resp, err
}
return cfg, resp, nil
}

View file

@ -0,0 +1,184 @@
// Copyright 2017 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// MarketplaceService handles communication with the marketplace related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/
type MarketplaceService struct {
client *Client
// Stubbed controls whether endpoints that return stubbed data are used
// instead of production endpoints. Stubbed data is fake data that's useful
// for testing your GitHub Apps. Stubbed data is hard-coded and will not
// change based on actual subscriptions.
//
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/
Stubbed bool
}
// MarketplacePlan represents a GitHub Apps Marketplace Listing Plan.
type MarketplacePlan struct {
URL *string `json:"url,omitempty"`
AccountsURL *string `json:"accounts_url,omitempty"`
ID *int64 `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
MonthlyPriceInCents *int `json:"monthly_price_in_cents,omitempty"`
YearlyPriceInCents *int `json:"yearly_price_in_cents,omitempty"`
// The pricing model for this listing. Can be one of "flat-rate", "per-unit", or "free".
PriceModel *string `json:"price_model,omitempty"`
UnitName *string `json:"unit_name,omitempty"`
Bullets *[]string `json:"bullets,omitempty"`
// State can be one of the values "draft" or "published".
State *string `json:"state,omitempty"`
HasFreeTrial *bool `json:"has_free_trial,omitempty"`
}
// MarketplacePurchase represents a GitHub Apps Marketplace Purchase.
type MarketplacePurchase struct {
// BillingCycle can be one of the values "yearly", "monthly" or nil.
BillingCycle *string `json:"billing_cycle,omitempty"`
NextBillingDate *Timestamp `json:"next_billing_date,omitempty"`
UnitCount *int `json:"unit_count,omitempty"`
Plan *MarketplacePlan `json:"plan,omitempty"`
Account *MarketplacePlanAccount `json:"account,omitempty"`
OnFreeTrial *bool `json:"on_free_trial,omitempty"`
FreeTrialEndsOn *Timestamp `json:"free_trial_ends_on,omitempty"`
}
// MarketplacePendingChange represents a pending change to a GitHub Apps Marketplace Plan.
type MarketplacePendingChange struct {
EffectiveDate *Timestamp `json:"effective_date,omitempty"`
UnitCount *int `json:"unit_count,omitempty"`
ID *int64 `json:"id,omitempty"`
Plan *MarketplacePlan `json:"plan,omitempty"`
}
// MarketplacePlanAccount represents a GitHub Account (user or organization) on a specific plan.
type MarketplacePlanAccount struct {
URL *string `json:"url,omitempty"`
Type *string `json:"type,omitempty"`
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Login *string `json:"login,omitempty"`
Email *string `json:"email,omitempty"`
OrganizationBillingEmail *string `json:"organization_billing_email,omitempty"`
MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"`
MarketplacePendingChange *MarketplacePendingChange `json:"marketplace_pending_change,omitempty"`
}
// ListPlans lists all plans for your Marketplace listing.
//
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-plans-for-your-marketplace-listing
func (s *MarketplaceService) ListPlans(ctx context.Context, opts *ListOptions) ([]*MarketplacePlan, *Response, error) {
uri := s.marketplaceURI("plans")
u, err := addOptions(uri, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var plans []*MarketplacePlan
resp, err := s.client.Do(ctx, req, &plans)
if err != nil {
return nil, resp, err
}
return plans, resp, nil
}
// ListPlanAccountsForPlan lists all GitHub accounts (user or organization) on a specific plan.
//
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#list-all-github-accounts-user-or-organization-on-a-specific-plan
func (s *MarketplaceService) ListPlanAccountsForPlan(ctx context.Context, planID int64, opts *ListOptions) ([]*MarketplacePlanAccount, *Response, error) {
uri := s.marketplaceURI(fmt.Sprintf("plans/%v/accounts", planID))
u, err := addOptions(uri, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var accounts []*MarketplacePlanAccount
resp, err := s.client.Do(ctx, req, &accounts)
if err != nil {
return nil, resp, err
}
return accounts, resp, nil
}
// ListPlanAccountsForAccount lists all GitHub accounts (user or organization) associated with an account.
//
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#check-if-a-github-account-is-associated-with-any-marketplace-listing
func (s *MarketplaceService) ListPlanAccountsForAccount(ctx context.Context, accountID int64, opts *ListOptions) ([]*MarketplacePlanAccount, *Response, error) {
uri := s.marketplaceURI(fmt.Sprintf("accounts/%v", accountID))
u, err := addOptions(uri, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var accounts []*MarketplacePlanAccount
resp, err := s.client.Do(ctx, req, &accounts)
if err != nil {
return nil, resp, err
}
return accounts, resp, nil
}
// ListMarketplacePurchasesForUser lists all GitHub marketplace purchases made by a user.
//
// GitHub API docs: https://developer.github.com/v3/apps/marketplace/#get-a-users-marketplace-purchases
func (s *MarketplaceService) ListMarketplacePurchasesForUser(ctx context.Context, opts *ListOptions) ([]*MarketplacePurchase, *Response, error) {
uri := "user/marketplace_purchases"
if s.Stubbed {
uri = "user/marketplace_purchases/stubbed"
}
u, err := addOptions(uri, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var purchases []*MarketplacePurchase
resp, err := s.client.Do(ctx, req, &purchases)
if err != nil {
return nil, resp, err
}
return purchases, resp, nil
}
func (s *MarketplaceService) marketplaceURI(endpoint string) string {
url := "marketplace_listing"
if s.Stubbed {
url = "marketplace_listing/stubbed"
}
return url + "/" + endpoint
}

View file

@ -0,0 +1,435 @@
// Copyright 2015 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// Scope models a GitHub authorization scope.
//
// GitHub API docs: https://developer.github.com/v3/oauth/#scopes
type Scope string
// This is the set of scopes for GitHub API V3
const (
ScopeNone Scope = "(no scope)" // REVISIT: is this actually returned, or just a documentation artifact?
ScopeUser Scope = "user"
ScopeUserEmail Scope = "user:email"
ScopeUserFollow Scope = "user:follow"
ScopePublicRepo Scope = "public_repo"
ScopeRepo Scope = "repo"
ScopeRepoDeployment Scope = "repo_deployment"
ScopeRepoStatus Scope = "repo:status"
ScopeDeleteRepo Scope = "delete_repo"
ScopeNotifications Scope = "notifications"
ScopeGist Scope = "gist"
ScopeReadRepoHook Scope = "read:repo_hook"
ScopeWriteRepoHook Scope = "write:repo_hook"
ScopeAdminRepoHook Scope = "admin:repo_hook"
ScopeAdminOrgHook Scope = "admin:org_hook"
ScopeReadOrg Scope = "read:org"
ScopeWriteOrg Scope = "write:org"
ScopeAdminOrg Scope = "admin:org"
ScopeReadPublicKey Scope = "read:public_key"
ScopeWritePublicKey Scope = "write:public_key"
ScopeAdminPublicKey Scope = "admin:public_key"
ScopeReadGPGKey Scope = "read:gpg_key"
ScopeWriteGPGKey Scope = "write:gpg_key"
ScopeAdminGPGKey Scope = "admin:gpg_key"
)
// AuthorizationsService handles communication with the authorization related
// methods of the GitHub API.
//
// This service requires HTTP Basic Authentication; it cannot be accessed using
// an OAuth token.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/
type AuthorizationsService service
// Authorization represents an individual GitHub authorization.
type Authorization struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
Scopes []Scope `json:"scopes,omitempty"`
Token *string `json:"token,omitempty"`
TokenLastEight *string `json:"token_last_eight,omitempty"`
HashedToken *string `json:"hashed_token,omitempty"`
App *AuthorizationApp `json:"app,omitempty"`
Note *string `json:"note,omitempty"`
NoteURL *string `json:"note_url,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
Fingerprint *string `json:"fingerprint,omitempty"`
// User is only populated by the Check and Reset methods.
User *User `json:"user,omitempty"`
}
func (a Authorization) String() string {
return Stringify(a)
}
// AuthorizationApp represents an individual GitHub app (in the context of authorization).
type AuthorizationApp struct {
URL *string `json:"url,omitempty"`
Name *string `json:"name,omitempty"`
ClientID *string `json:"client_id,omitempty"`
}
func (a AuthorizationApp) String() string {
return Stringify(a)
}
// Grant represents an OAuth application that has been granted access to an account.
type Grant struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
App *AuthorizationApp `json:"app,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
Scopes []string `json:"scopes,omitempty"`
}
func (g Grant) String() string {
return Stringify(g)
}
// AuthorizationRequest represents a request to create an authorization.
type AuthorizationRequest struct {
Scopes []Scope `json:"scopes,omitempty"`
Note *string `json:"note,omitempty"`
NoteURL *string `json:"note_url,omitempty"`
ClientID *string `json:"client_id,omitempty"`
ClientSecret *string `json:"client_secret,omitempty"`
Fingerprint *string `json:"fingerprint,omitempty"`
}
func (a AuthorizationRequest) String() string {
return Stringify(a)
}
// AuthorizationUpdateRequest represents a request to update an authorization.
//
// Note that for any one update, you must only provide one of the "scopes"
// fields. That is, you may provide only one of "Scopes", or "AddScopes", or
// "RemoveScopes".
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization
type AuthorizationUpdateRequest struct {
Scopes []string `json:"scopes,omitempty"`
AddScopes []string `json:"add_scopes,omitempty"`
RemoveScopes []string `json:"remove_scopes,omitempty"`
Note *string `json:"note,omitempty"`
NoteURL *string `json:"note_url,omitempty"`
Fingerprint *string `json:"fingerprint,omitempty"`
}
func (a AuthorizationUpdateRequest) String() string {
return Stringify(a)
}
// List the authorizations for the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-authorizations
func (s *AuthorizationsService) List(ctx context.Context, opts *ListOptions) ([]*Authorization, *Response, error) {
u := "authorizations"
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var auths []*Authorization
resp, err := s.client.Do(ctx, req, &auths)
if err != nil {
return nil, resp, err
}
return auths, resp, nil
}
// Get a single authorization.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-authorization
func (s *AuthorizationsService) Get(ctx context.Context, id int64) (*Authorization, *Response, error) {
u := fmt.Sprintf("authorizations/%d", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// Create a new authorization for the specified OAuth application.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#create-a-new-authorization
func (s *AuthorizationsService) Create(ctx context.Context, auth *AuthorizationRequest) (*Authorization, *Response, error) {
u := "authorizations"
req, err := s.client.NewRequest("POST", u, auth)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// GetOrCreateForApp creates a new authorization for the specified OAuth
// application, only if an authorization for that application doesnt already
// exist for the user.
//
// If a new token is created, the HTTP status code will be "201 Created", and
// the returned Authorization.Token field will be populated. If an existing
// token is returned, the status code will be "200 OK" and the
// Authorization.Token field will be empty.
//
// clientID is the OAuth Client ID with which to create the token.
//
// GitHub API docs:
// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app
// https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app-and-fingerprint
func (s *AuthorizationsService) GetOrCreateForApp(ctx context.Context, clientID string, auth *AuthorizationRequest) (*Authorization, *Response, error) {
var u string
if auth.Fingerprint == nil || *auth.Fingerprint == "" {
u = fmt.Sprintf("authorizations/clients/%v", clientID)
} else {
u = fmt.Sprintf("authorizations/clients/%v/%v", clientID, *auth.Fingerprint)
}
req, err := s.client.NewRequest("PUT", u, auth)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// Edit a single authorization.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#update-an-existing-authorization
func (s *AuthorizationsService) Edit(ctx context.Context, id int64, auth *AuthorizationUpdateRequest) (*Authorization, *Response, error) {
u := fmt.Sprintf("authorizations/%d", id)
req, err := s.client.NewRequest("PATCH", u, auth)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// Delete a single authorization.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-an-authorization
func (s *AuthorizationsService) Delete(ctx context.Context, id int64) (*Response, error) {
u := fmt.Sprintf("authorizations/%d", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Check if an OAuth token is valid for a specific app.
//
// Note that this operation requires the use of BasicAuth, but where the
// username is the OAuth application clientID, and the password is its
// clientSecret. Invalid tokens will return a 404 Not Found.
//
// The returned Authorization.User field will be populated.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#check-an-authorization
func (s *AuthorizationsService) Check(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) {
u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// Reset is used to reset a valid OAuth token without end user involvement.
// Applications must save the "token" property in the response, because changes
// take effect immediately.
//
// Note that this operation requires the use of BasicAuth, but where the
// username is the OAuth application clientID, and the password is its
// clientSecret. Invalid tokens will return a 404 Not Found.
//
// The returned Authorization.User field will be populated.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization
func (s *AuthorizationsService) Reset(ctx context.Context, clientID string, token string) (*Authorization, *Response, error) {
u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// Revoke an authorization for an application.
//
// Note that this operation requires the use of BasicAuth, but where the
// username is the OAuth application clientID, and the password is its
// clientSecret. Invalid tokens will return a 404 Not Found.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#revoke-an-authorization-for-an-application
func (s *AuthorizationsService) Revoke(ctx context.Context, clientID string, token string) (*Response, error) {
u := fmt.Sprintf("applications/%v/tokens/%v", clientID, token)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListGrants lists the set of OAuth applications that have been granted
// access to a user's account. This will return one entry for each application
// that has been granted access to the account, regardless of the number of
// tokens an application has generated for the user.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#list-your-grants
func (s *AuthorizationsService) ListGrants(ctx context.Context, opts *ListOptions) ([]*Grant, *Response, error) {
u, err := addOptions("applications/grants", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
grants := []*Grant{}
resp, err := s.client.Do(ctx, req, &grants)
if err != nil {
return nil, resp, err
}
return grants, resp, nil
}
// GetGrant gets a single OAuth application grant.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#get-a-single-grant
func (s *AuthorizationsService) GetGrant(ctx context.Context, id int64) (*Grant, *Response, error) {
u := fmt.Sprintf("applications/grants/%d", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
grant := new(Grant)
resp, err := s.client.Do(ctx, req, grant)
if err != nil {
return nil, resp, err
}
return grant, resp, nil
}
// DeleteGrant deletes an OAuth application grant. Deleting an application's
// grant will also delete all OAuth tokens associated with the application for
// the user.
//
// GitHub API docs: https://developer.github.com/v3/oauth_authorizations/#delete-a-grant
func (s *AuthorizationsService) DeleteGrant(ctx context.Context, id int64) (*Response, error) {
u := fmt.Sprintf("applications/grants/%d", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// CreateImpersonation creates an impersonation OAuth token.
//
// This requires admin permissions. With the returned Authorization.Token
// you can e.g. create or delete a user's public SSH key. NOTE: creating a
// new token automatically revokes an existing one.
//
// GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#create-an-impersonation-oauth-token
func (s *AuthorizationsService) CreateImpersonation(ctx context.Context, username string, authReq *AuthorizationRequest) (*Authorization, *Response, error) {
u := fmt.Sprintf("admin/users/%v/authorizations", username)
req, err := s.client.NewRequest("POST", u, authReq)
if err != nil {
return nil, nil, err
}
a := new(Authorization)
resp, err := s.client.Do(ctx, req, a)
if err != nil {
return nil, resp, err
}
return a, resp, nil
}
// DeleteImpersonation deletes an impersonation OAuth token.
//
// NOTE: there can be only one at a time.
//
// GitHub API docs: https://developer.github.com/enterprise/v3/enterprise-admin/users/#delete-an-impersonation-oauth-token
func (s *AuthorizationsService) DeleteImpersonation(ctx context.Context, username string) (*Response, error) {
u := fmt.Sprintf("admin/users/%v/authorizations", username)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

434
vendor/github.com/google/go-github/v29/github/checks.go generated vendored Normal file
View file

@ -0,0 +1,434 @@
// Copyright 2018 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"net/url"
)
// ChecksService provides access to the Checks API in the
// GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/checks/
type ChecksService service
// CheckRun represents a GitHub check run on a repository associated with a GitHub app.
type CheckRun struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
HeadSHA *string `json:"head_sha,omitempty"`
ExternalID *string `json:"external_id,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
DetailsURL *string `json:"details_url,omitempty"`
Status *string `json:"status,omitempty"`
Conclusion *string `json:"conclusion,omitempty"`
StartedAt *Timestamp `json:"started_at,omitempty"`
CompletedAt *Timestamp `json:"completed_at,omitempty"`
Output *CheckRunOutput `json:"output,omitempty"`
Name *string `json:"name,omitempty"`
CheckSuite *CheckSuite `json:"check_suite,omitempty"`
App *App `json:"app,omitempty"`
PullRequests []*PullRequest `json:"pull_requests,omitempty"`
}
// CheckRunOutput represents the output of a CheckRun.
type CheckRunOutput struct {
Title *string `json:"title,omitempty"`
Summary *string `json:"summary,omitempty"`
Text *string `json:"text,omitempty"`
AnnotationsCount *int `json:"annotations_count,omitempty"`
AnnotationsURL *string `json:"annotations_url,omitempty"`
Annotations []*CheckRunAnnotation `json:"annotations,omitempty"`
Images []*CheckRunImage `json:"images,omitempty"`
}
// CheckRunAnnotation represents an annotation object for a CheckRun output.
type CheckRunAnnotation struct {
Path *string `json:"path,omitempty"`
StartLine *int `json:"start_line,omitempty"`
EndLine *int `json:"end_line,omitempty"`
StartColumn *int `json:"start_column,omitempty"`
EndColumn *int `json:"end_column,omitempty"`
AnnotationLevel *string `json:"annotation_level,omitempty"`
Message *string `json:"message,omitempty"`
Title *string `json:"title,omitempty"`
RawDetails *string `json:"raw_details,omitempty"`
}
// CheckRunImage represents an image object for a CheckRun output.
type CheckRunImage struct {
Alt *string `json:"alt,omitempty"`
ImageURL *string `json:"image_url,omitempty"`
Caption *string `json:"caption,omitempty"`
}
// CheckSuite represents a suite of check runs.
type CheckSuite struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
HeadBranch *string `json:"head_branch,omitempty"`
HeadSHA *string `json:"head_sha,omitempty"`
URL *string `json:"url,omitempty"`
BeforeSHA *string `json:"before,omitempty"`
AfterSHA *string `json:"after,omitempty"`
Status *string `json:"status,omitempty"`
Conclusion *string `json:"conclusion,omitempty"`
App *App `json:"app,omitempty"`
Repository *Repository `json:"repository,omitempty"`
PullRequests []*PullRequest `json:"pull_requests,omitempty"`
// The following fields are only populated by Webhook events.
HeadCommit *Commit `json:"head_commit,omitempty"`
}
func (c CheckRun) String() string {
return Stringify(c)
}
func (c CheckSuite) String() string {
return Stringify(c)
}
// GetCheckRun gets a check-run for a repository.
//
// GitHub API docs: https://developer.github.com/v3/checks/runs/#get-a-single-check-run
func (s *ChecksService) GetCheckRun(ctx context.Context, owner, repo string, checkRunID int64) (*CheckRun, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
checkRun := new(CheckRun)
resp, err := s.client.Do(ctx, req, checkRun)
if err != nil {
return nil, resp, err
}
return checkRun, resp, nil
}
// GetCheckSuite gets a single check suite.
//
// GitHub API docs: https://developer.github.com/v3/checks/suites/#get-a-single-check-suite
func (s *ChecksService) GetCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*CheckSuite, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites/%v", owner, repo, checkSuiteID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
checkSuite := new(CheckSuite)
resp, err := s.client.Do(ctx, req, checkSuite)
if err != nil {
return nil, resp, err
}
return checkSuite, resp, nil
}
// CreateCheckRunOptions sets up parameters needed to create a CheckRun.
type CreateCheckRunOptions struct {
Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.)
HeadSHA string `json:"head_sha"` // The SHA of the commit. (Required.)
DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.)
ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.)
Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.)
Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".)
StartedAt *Timestamp `json:"started_at,omitempty"` // The time that the check run began. (Optional.)
CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.)
Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional)
Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.)
}
// CheckRunAction exposes further actions the integrator can perform, which a user may trigger.
type CheckRunAction struct {
Label string `json:"label"` // The text to be displayed on a button in the web UI. The maximum size is 20 characters. (Required.)
Description string `json:"description"` // A short explanation of what this action would do. The maximum size is 40 characters. (Required.)
Identifier string `json:"identifier"` // A reference for the action on the integrator's system. The maximum size is 20 characters. (Required.)
}
// CreateCheckRun creates a check run for repository.
//
// GitHub API docs: https://developer.github.com/v3/checks/runs/#create-a-check-run
func (s *ChecksService) CreateCheckRun(ctx context.Context, owner, repo string, opts CreateCheckRunOptions) (*CheckRun, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-runs", owner, repo)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
checkRun := new(CheckRun)
resp, err := s.client.Do(ctx, req, checkRun)
if err != nil {
return nil, resp, err
}
return checkRun, resp, nil
}
// UpdateCheckRunOptions sets up parameters needed to update a CheckRun.
type UpdateCheckRunOptions struct {
Name string `json:"name"` // The name of the check (e.g., "code-coverage"). (Required.)
HeadSHA *string `json:"head_sha,omitempty"` // The SHA of the commit. (Optional.)
DetailsURL *string `json:"details_url,omitempty"` // The URL of the integrator's site that has the full details of the check. (Optional.)
ExternalID *string `json:"external_id,omitempty"` // A reference for the run on the integrator's system. (Optional.)
Status *string `json:"status,omitempty"` // The current status. Can be one of "queued", "in_progress", or "completed". Default: "queued". (Optional.)
Conclusion *string `json:"conclusion,omitempty"` // Can be one of "success", "failure", "neutral", "cancelled", "timed_out", or "action_required". (Optional. Required if you provide a status of "completed".)
CompletedAt *Timestamp `json:"completed_at,omitempty"` // The time the check completed. (Optional. Required if you provide conclusion.)
Output *CheckRunOutput `json:"output,omitempty"` // Provide descriptive details about the run. (Optional)
Actions []*CheckRunAction `json:"actions,omitempty"` // Possible further actions the integrator can perform, which a user may trigger. (Optional.)
}
// UpdateCheckRun updates a check run for a specific commit in a repository.
//
// GitHub API docs: https://developer.github.com/v3/checks/runs/#update-a-check-run
func (s *ChecksService) UpdateCheckRun(ctx context.Context, owner, repo string, checkRunID int64, opts UpdateCheckRunOptions) (*CheckRun, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-runs/%v", owner, repo, checkRunID)
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
checkRun := new(CheckRun)
resp, err := s.client.Do(ctx, req, checkRun)
if err != nil {
return nil, resp, err
}
return checkRun, resp, nil
}
// ListCheckRunAnnotations lists the annotations for a check run.
//
// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-annotations-for-a-check-run
func (s *ChecksService) ListCheckRunAnnotations(ctx context.Context, owner, repo string, checkRunID int64, opts *ListOptions) ([]*CheckRunAnnotation, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-runs/%v/annotations", owner, repo, checkRunID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
var checkRunAnnotations []*CheckRunAnnotation
resp, err := s.client.Do(ctx, req, &checkRunAnnotations)
if err != nil {
return nil, resp, err
}
return checkRunAnnotations, resp, nil
}
// ListCheckRunsOptions represents parameters to list check runs.
type ListCheckRunsOptions struct {
CheckName *string `url:"check_name,omitempty"` // Returns check runs with the specified name.
Status *string `url:"status,omitempty"` // Returns check runs with the specified status. Can be one of "queued", "in_progress", or "completed".
Filter *string `url:"filter,omitempty"` // Filters check runs by their completed_at timestamp. Can be one of "latest" (returning the most recent check runs) or "all". Default: "latest"
ListOptions
}
// ListCheckRunsResults represents the result of a check run list.
type ListCheckRunsResults struct {
Total *int `json:"total_count,omitempty"`
CheckRuns []*CheckRun `json:"check_runs,omitempty"`
}
// ListCheckRunsForRef lists check runs for a specific ref.
//
// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-for-a-specific-ref
func (s *ChecksService) ListCheckRunsForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/check-runs", owner, repo, url.QueryEscape(ref))
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
var checkRunResults *ListCheckRunsResults
resp, err := s.client.Do(ctx, req, &checkRunResults)
if err != nil {
return nil, resp, err
}
return checkRunResults, resp, nil
}
// ListCheckRunsCheckSuite lists check runs for a check suite.
//
// GitHub API docs: https://developer.github.com/v3/checks/runs/#list-check-runs-in-a-check-suite
func (s *ChecksService) ListCheckRunsCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64, opts *ListCheckRunsOptions) (*ListCheckRunsResults, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites/%v/check-runs", owner, repo, checkSuiteID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
var checkRunResults *ListCheckRunsResults
resp, err := s.client.Do(ctx, req, &checkRunResults)
if err != nil {
return nil, resp, err
}
return checkRunResults, resp, nil
}
// ListCheckSuiteOptions represents parameters to list check suites.
type ListCheckSuiteOptions struct {
CheckName *string `url:"check_name,omitempty"` // Filters checks suites by the name of the check run.
AppID *int `url:"app_id,omitempty"` // Filters check suites by GitHub App id.
ListOptions
}
// ListCheckSuiteResults represents the result of a check run list.
type ListCheckSuiteResults struct {
Total *int `json:"total_count,omitempty"`
CheckSuites []*CheckSuite `json:"check_suites,omitempty"`
}
// ListCheckSuitesForRef lists check suite for a specific ref.
//
// GitHub API docs: https://developer.github.com/v3/checks/suites/#list-check-suites-for-a-specific-ref
func (s *ChecksService) ListCheckSuitesForRef(ctx context.Context, owner, repo, ref string, opts *ListCheckSuiteOptions) (*ListCheckSuiteResults, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/check-suites", owner, repo, url.QueryEscape(ref))
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
var checkSuiteResults *ListCheckSuiteResults
resp, err := s.client.Do(ctx, req, &checkSuiteResults)
if err != nil {
return nil, resp, err
}
return checkSuiteResults, resp, nil
}
// AutoTriggerCheck enables or disables automatic creation of CheckSuite events upon pushes to the repository.
type AutoTriggerCheck struct {
AppID *int64 `json:"app_id,omitempty"` // The id of the GitHub App. (Required.)
Setting *bool `json:"setting,omitempty"` // Set to "true" to enable automatic creation of CheckSuite events upon pushes to the repository, or "false" to disable them. Default: "true" (Required.)
}
// CheckSuitePreferenceOptions set options for check suite preferences for a repository.
type CheckSuitePreferenceOptions struct {
AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository.
}
// CheckSuitePreferenceResults represents the results of the preference set operation.
type CheckSuitePreferenceResults struct {
Preferences *PreferenceList `json:"preferences,omitempty"`
Repository *Repository `json:"repository,omitempty"`
}
// PreferenceList represents a list of auto trigger checks for repository
type PreferenceList struct {
AutoTriggerChecks []*AutoTriggerCheck `json:"auto_trigger_checks,omitempty"` // A slice of auto trigger checks that can be set for a check suite in a repository.
}
// SetCheckSuitePreferences changes the default automatic flow when creating check suites.
//
// GitHub API docs: https://developer.github.com/v3/checks/suites/#set-preferences-for-check-suites-on-a-repository
func (s *ChecksService) SetCheckSuitePreferences(ctx context.Context, owner, repo string, opts CheckSuitePreferenceOptions) (*CheckSuitePreferenceResults, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites/preferences", owner, repo)
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
var checkSuitePrefResults *CheckSuitePreferenceResults
resp, err := s.client.Do(ctx, req, &checkSuitePrefResults)
if err != nil {
return nil, resp, err
}
return checkSuitePrefResults, resp, nil
}
// CreateCheckSuiteOptions sets up parameters to manually create a check suites
type CreateCheckSuiteOptions struct {
HeadSHA string `json:"head_sha"` // The sha of the head commit. (Required.)
HeadBranch *string `json:"head_branch,omitempty"` // The name of the head branch where the code changes are implemented.
}
// CreateCheckSuite manually creates a check suite for a repository.
//
// GitHub API docs: https://developer.github.com/v3/checks/suites/#create-a-check-suite
func (s *ChecksService) CreateCheckSuite(ctx context.Context, owner, repo string, opts CreateCheckSuiteOptions) (*CheckSuite, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites", owner, repo)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
checkSuite := new(CheckSuite)
resp, err := s.client.Do(ctx, req, checkSuite)
if err != nil {
return nil, resp, err
}
return checkSuite, resp, nil
}
// ReRequestCheckSuite triggers GitHub to rerequest an existing check suite, without pushing new code to a repository.
//
// GitHub API docs: https://developer.github.com/v3/checks/suites/#rerequest-check-suite
func (s *ChecksService) ReRequestCheckSuite(ctx context.Context, owner, repo string, checkSuiteID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/check-suites/%v/rerequest", owner, repo, checkSuiteID)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", mediaTypeCheckRunsPreview)
resp, err := s.client.Do(ctx, req, nil)
return resp, err
}

188
vendor/github.com/google/go-github/v29/github/doc.go generated vendored Normal file
View file

@ -0,0 +1,188 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package github provides a client for using the GitHub API.
Usage:
import "github.com/google/go-github/v29/github" // with go modules enabled (GO111MODULE=on or outside GOPATH)
import "github.com/google/go-github/github" // with go modules disabled
Construct a new GitHub client, then use the various services on the client to
access different parts of the GitHub API. For example:
client := github.NewClient(nil)
// list all organizations for user "willnorris"
orgs, _, err := client.Organizations.List(ctx, "willnorris", nil)
Some API methods have optional parameters that can be passed. For example:
client := github.NewClient(nil)
// list public repositories for org "github"
opt := &github.RepositoryListByOrgOptions{Type: "public"}
repos, _, err := client.Repositories.ListByOrg(ctx, "github", opt)
The services of a client divide the API into logical chunks and correspond to
the structure of the GitHub API documentation at
https://developer.github.com/v3/.
NOTE: Using the https://godoc.org/context package, one can easily
pass cancelation signals and deadlines to various services of the client for
handling a request. In case there is no context available, then context.Background()
can be used as a starting point.
For more sample code snippets, head over to the https://github.com/google/go-github/tree/master/example directory.
Authentication
The go-github library does not directly handle authentication. Instead, when
creating a new client, pass an http.Client that can handle authentication for
you. The easiest and recommended way to do this is using the golang.org/x/oauth2
library, but you can always use any other library that provides an http.Client.
If you have an OAuth2 access token (for example, a personal API token), you can
use it with the oauth2 library using:
import "golang.org/x/oauth2"
func main() {
ctx := context.Background()
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: "... your access token ..."},
)
tc := oauth2.NewClient(ctx, ts)
client := github.NewClient(tc)
// list all repositories for the authenticated user
repos, _, err := client.Repositories.List(ctx, "", nil)
}
Note that when using an authenticated Client, all calls made by the client will
include the specified OAuth token. Therefore, authenticated clients should
almost never be shared between different users.
See the oauth2 docs for complete instructions on using that library.
For API methods that require HTTP Basic Authentication, use the
BasicAuthTransport.
GitHub Apps authentication can be provided by the
https://github.com/bradleyfalzon/ghinstallation package.
import "github.com/bradleyfalzon/ghinstallation"
func main() {
// Wrap the shared transport for use with the integration ID 1 authenticating with installation ID 99.
itr, err := ghinstallation.NewKeyFromFile(http.DefaultTransport, 1, 99, "2016-10-19.private-key.pem")
if err != nil {
// Handle error.
}
// Use installation transport with client
client := github.NewClient(&http.Client{Transport: itr})
// Use client...
}
Rate Limiting
GitHub imposes a rate limit on all API clients. Unauthenticated clients are
limited to 60 requests per hour, while authenticated clients can make up to
5,000 requests per hour. The Search API has a custom rate limit. Unauthenticated
clients are limited to 10 requests per minute, while authenticated clients
can make up to 30 requests per minute. To receive the higher rate limit when
making calls that are not issued on behalf of a user,
use UnauthenticatedRateLimitedTransport.
The returned Response.Rate value contains the rate limit information
from the most recent API call. If a recent enough response isn't
available, you can use RateLimits to fetch the most up-to-date rate
limit data for the client.
To detect an API rate limit error, you can check if its type is *github.RateLimitError:
repos, _, err := client.Repositories.List(ctx, "", nil)
if _, ok := err.(*github.RateLimitError); ok {
log.Println("hit rate limit")
}
Learn more about GitHub rate limiting at
https://developer.github.com/v3/#rate-limiting.
Accepted Status
Some endpoints may return a 202 Accepted status code, meaning that the
information required is not yet ready and was scheduled to be gathered on
the GitHub side. Methods known to behave like this are documented specifying
this behavior.
To detect this condition of error, you can check if its type is
*github.AcceptedError:
stats, _, err := client.Repositories.ListContributorsStats(ctx, org, repo)
if _, ok := err.(*github.AcceptedError); ok {
log.Println("scheduled on GitHub side")
}
Conditional Requests
The GitHub API has good support for conditional requests which will help
prevent you from burning through your rate limit, as well as help speed up your
application. go-github does not handle conditional requests directly, but is
instead designed to work with a caching http.Transport. We recommend using
https://github.com/gregjones/httpcache for that.
Learn more about GitHub conditional requests at
https://developer.github.com/v3/#conditional-requests.
Creating and Updating Resources
All structs for GitHub resources use pointer values for all non-repeated fields.
This allows distinguishing between unset fields and those set to a zero-value.
Helper functions have been provided to easily create these pointers for string,
bool, and int values. For example:
// create a new private repository named "foo"
repo := &github.Repository{
Name: github.String("foo"),
Private: github.Bool(true),
}
client.Repositories.Create(ctx, "", repo)
Users who have worked with protocol buffers should find this pattern familiar.
Pagination
All requests for resource collections (repos, pull requests, issues, etc.)
support pagination. Pagination options are described in the
github.ListOptions struct and passed to the list methods directly or as an
embedded type of a more specific list options struct (for example
github.PullRequestListOptions). Pages information is available via the
github.Response struct.
client := github.NewClient(nil)
opt := &github.RepositoryListByOrgOptions{
ListOptions: github.ListOptions{PerPage: 10},
}
// get all pages of results
var allRepos []*github.Repository
for {
repos, resp, err := client.Repositories.ListByOrg(ctx, "github", opt)
if err != nil {
return err
}
allRepos = append(allRepos, repos...)
if resp.NextPage == 0 {
break
}
opt.Page = resp.NextPage
}
*/
package github

136
vendor/github.com/google/go-github/v29/github/event.go generated vendored Normal file
View file

@ -0,0 +1,136 @@
// Copyright 2018 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"encoding/json"
"time"
)
// Event represents a GitHub event.
type Event struct {
Type *string `json:"type,omitempty"`
Public *bool `json:"public,omitempty"`
RawPayload *json.RawMessage `json:"payload,omitempty"`
Repo *Repository `json:"repo,omitempty"`
Actor *User `json:"actor,omitempty"`
Org *Organization `json:"org,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
ID *string `json:"id,omitempty"`
}
func (e Event) String() string {
return Stringify(e)
}
// ParsePayload parses the event payload. For recognized event types,
// a value of the corresponding struct type will be returned.
func (e *Event) ParsePayload() (payload interface{}, err error) {
switch *e.Type {
case "CheckRunEvent":
payload = &CheckRunEvent{}
case "CheckSuiteEvent":
payload = &CheckSuiteEvent{}
case "CommitCommentEvent":
payload = &CommitCommentEvent{}
case "CreateEvent":
payload = &CreateEvent{}
case "DeleteEvent":
payload = &DeleteEvent{}
case "DeployKeyEvent":
payload = &DeployKeyEvent{}
case "DeploymentEvent":
payload = &DeploymentEvent{}
case "DeploymentStatusEvent":
payload = &DeploymentStatusEvent{}
case "ForkEvent":
payload = &ForkEvent{}
case "GitHubAppAuthorizationEvent":
payload = &GitHubAppAuthorizationEvent{}
case "GollumEvent":
payload = &GollumEvent{}
case "InstallationEvent":
payload = &InstallationEvent{}
case "InstallationRepositoriesEvent":
payload = &InstallationRepositoriesEvent{}
case "IssueCommentEvent":
payload = &IssueCommentEvent{}
case "IssuesEvent":
payload = &IssuesEvent{}
case "LabelEvent":
payload = &LabelEvent{}
case "MarketplacePurchaseEvent":
payload = &MarketplacePurchaseEvent{}
case "MemberEvent":
payload = &MemberEvent{}
case "MembershipEvent":
payload = &MembershipEvent{}
case "MetaEvent":
payload = &MetaEvent{}
case "MilestoneEvent":
payload = &MilestoneEvent{}
case "OrganizationEvent":
payload = &OrganizationEvent{}
case "OrgBlockEvent":
payload = &OrgBlockEvent{}
case "PageBuildEvent":
payload = &PageBuildEvent{}
case "PingEvent":
payload = &PingEvent{}
case "ProjectEvent":
payload = &ProjectEvent{}
case "ProjectCardEvent":
payload = &ProjectCardEvent{}
case "ProjectColumnEvent":
payload = &ProjectColumnEvent{}
case "PublicEvent":
payload = &PublicEvent{}
case "PullRequestEvent":
payload = &PullRequestEvent{}
case "PullRequestReviewEvent":
payload = &PullRequestReviewEvent{}
case "PullRequestReviewCommentEvent":
payload = &PullRequestReviewCommentEvent{}
case "PushEvent":
payload = &PushEvent{}
case "ReleaseEvent":
payload = &ReleaseEvent{}
case "RepositoryEvent":
payload = &RepositoryEvent{}
case "RepositoryDispatchEvent":
payload = &RepositoryDispatchEvent{}
case "RepositoryVulnerabilityAlertEvent":
payload = &RepositoryVulnerabilityAlertEvent{}
case "StarEvent":
payload = &StarEvent{}
case "StatusEvent":
payload = &StatusEvent{}
case "TeamEvent":
payload = &TeamEvent{}
case "TeamAddEvent":
payload = &TeamAddEvent{}
case "UserEvent":
payload = &UserEvent{}
case "WatchEvent":
payload = &WatchEvent{}
}
err = json.Unmarshal(*e.RawPayload, &payload)
return payload, err
}
// Payload returns the parsed event payload. For recognized event types,
// a value of the corresponding struct type will be returned.
//
// Deprecated: Use ParsePayload instead, which returns an error
// rather than panics if JSON unmarshaling raw payload fails.
func (e *Event) Payload() (payload interface{}) {
var err error
payload, err = e.ParsePayload()
if err != nil {
panic(err)
}
return payload
}

View file

@ -0,0 +1,928 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// These event types are shared between the Events API and used as Webhook payloads.
package github
import "encoding/json"
// RequestedAction is included in a CheckRunEvent when a user has invoked an action,
// i.e. when the CheckRunEvent's Action field is "requested_action".
type RequestedAction struct {
Identifier string `json:"identifier"` // The integrator reference of the action requested by the user.
}
// CheckRunEvent is triggered when a check run is "created", "updated", or "rerequested".
// The Webhook event name is "check_run".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#checkrunevent
type CheckRunEvent struct {
CheckRun *CheckRun `json:"check_run,omitempty"`
// The action performed. Possible values are: "created", "updated", "rerequested" or "requested_action".
Action *string `json:"action,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
// The action requested by the user. Populated when the Action is "requested_action".
RequestedAction *RequestedAction `json:"requested_action,omitempty"` //
}
// CheckSuiteEvent is triggered when a check suite is "completed", "requested", or "rerequested".
// The Webhook event name is "check_suite".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#checksuiteevent
type CheckSuiteEvent struct {
CheckSuite *CheckSuite `json:"check_suite,omitempty"`
// The action performed. Possible values are: "completed", "requested" or "rerequested".
Action *string `json:"action,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// CommitCommentEvent is triggered when a commit comment is created.
// The Webhook event name is "commit_comment".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#commitcommentevent
type CommitCommentEvent struct {
Comment *RepositoryComment `json:"comment,omitempty"`
// The following fields are only populated by Webhook events.
Action *string `json:"action,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// CreateEvent represents a created repository, branch, or tag.
// The Webhook event name is "create".
//
// Note: webhooks will not receive this event for created repositories.
// Additionally, webhooks will not receive this event for tags if more
// than three tags are pushed at once.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#createevent
type CreateEvent struct {
Ref *string `json:"ref,omitempty"`
// RefType is the object that was created. Possible values are: "repository", "branch", "tag".
RefType *string `json:"ref_type,omitempty"`
MasterBranch *string `json:"master_branch,omitempty"`
Description *string `json:"description,omitempty"`
// The following fields are only populated by Webhook events.
PusherType *string `json:"pusher_type,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// DeleteEvent represents a deleted branch or tag.
// The Webhook event name is "delete".
//
// Note: webhooks will not receive this event for tags if more than three tags
// are deleted at once.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deleteevent
type DeleteEvent struct {
Ref *string `json:"ref,omitempty"`
// RefType is the object that was deleted. Possible values are: "branch", "tag".
RefType *string `json:"ref_type,omitempty"`
// The following fields are only populated by Webhook events.
PusherType *string `json:"pusher_type,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// DeployKeyEvent is triggered when a deploy key is added or removed from a repository.
// The Webhook event name is "deploy_key".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploykeyevent
type DeployKeyEvent struct {
// Action is the action that was performed. Possible values are:
// "created" or "deleted".
Action *string `json:"action,omitempty"`
// The deploy key resource.
Key *Key `json:"key,omitempty"`
}
// DeploymentEvent represents a deployment.
// The Webhook event name is "deployment".
//
// Events of this type are not visible in timelines, they are only used to trigger hooks.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentevent
type DeploymentEvent struct {
Deployment *Deployment `json:"deployment,omitempty"`
Repo *Repository `json:"repository,omitempty"`
// The following fields are only populated by Webhook events.
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// DeploymentStatusEvent represents a deployment status.
// The Webhook event name is "deployment_status".
//
// Events of this type are not visible in timelines, they are only used to trigger hooks.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#deploymentstatusevent
type DeploymentStatusEvent struct {
Deployment *Deployment `json:"deployment,omitempty"`
DeploymentStatus *DeploymentStatus `json:"deployment_status,omitempty"`
Repo *Repository `json:"repository,omitempty"`
// The following fields are only populated by Webhook events.
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// ForkEvent is triggered when a user forks a repository.
// The Webhook event name is "fork".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#forkevent
type ForkEvent struct {
// Forkee is the created repository.
Forkee *Repository `json:"forkee,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// GitHubAppAuthorizationEvent is triggered when a user's authorization for a
// GitHub Application is revoked.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#githubappauthorizationevent
type GitHubAppAuthorizationEvent struct {
// The action performed. Possible value is: "revoked".
Action *string `json:"action,omitempty"`
// The following fields are only populated by Webhook events.
Sender *User `json:"sender,omitempty"`
}
// Page represents a single Wiki page.
type Page struct {
PageName *string `json:"page_name,omitempty"`
Title *string `json:"title,omitempty"`
Summary *string `json:"summary,omitempty"`
Action *string `json:"action,omitempty"`
SHA *string `json:"sha,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
}
// GollumEvent is triggered when a Wiki page is created or updated.
// The Webhook event name is "gollum".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#gollumevent
type GollumEvent struct {
Pages []*Page `json:"pages,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// EditChange represents the changes when an issue, pull request, or comment has
// been edited.
type EditChange struct {
Title *struct {
From *string `json:"from,omitempty"`
} `json:"title,omitempty"`
Body *struct {
From *string `json:"from,omitempty"`
} `json:"body,omitempty"`
}
// ProjectChange represents the changes when a project has been edited.
type ProjectChange struct {
Name *struct {
From *string `json:"from,omitempty"`
} `json:"name,omitempty"`
Body *struct {
From *string `json:"from,omitempty"`
} `json:"body,omitempty"`
}
// ProjectCardChange represents the changes when a project card has been edited.
type ProjectCardChange struct {
Note *struct {
From *string `json:"from,omitempty"`
} `json:"note,omitempty"`
}
// ProjectColumnChange represents the changes when a project column has been edited.
type ProjectColumnChange struct {
Name *struct {
From *string `json:"from,omitempty"`
} `json:"name,omitempty"`
}
// TeamChange represents the changes when a team has been edited.
type TeamChange struct {
Description *struct {
From *string `json:"from,omitempty"`
} `json:"description,omitempty"`
Name *struct {
From *string `json:"from,omitempty"`
} `json:"name,omitempty"`
Privacy *struct {
From *string `json:"from,omitempty"`
} `json:"privacy,omitempty"`
Repository *struct {
Permissions *struct {
From *struct {
Admin *bool `json:"admin,omitempty"`
Pull *bool `json:"pull,omitempty"`
Push *bool `json:"push,omitempty"`
} `json:"from,omitempty"`
} `json:"permissions,omitempty"`
} `json:"repository,omitempty"`
}
// InstallationEvent is triggered when a GitHub App has been installed or uninstalled.
// The Webhook event name is "installation".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationevent
type InstallationEvent struct {
// The action that was performed. Can be either "created" or "deleted".
Action *string `json:"action,omitempty"`
Repositories []*Repository `json:"repositories,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// InstallationRepositoriesEvent is triggered when a repository is added or
// removed from an installation. The Webhook event name is "installation_repositories".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#installationrepositoriesevent
type InstallationRepositoriesEvent struct {
// The action that was performed. Can be either "added" or "removed".
Action *string `json:"action,omitempty"`
RepositoriesAdded []*Repository `json:"repositories_added,omitempty"`
RepositoriesRemoved []*Repository `json:"repositories_removed,omitempty"`
RepositorySelection *string `json:"repository_selection,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// IssueCommentEvent is triggered when an issue comment is created on an issue
// or pull request.
// The Webhook event name is "issue_comment".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuecommentevent
type IssueCommentEvent struct {
// Action is the action that was performed on the comment.
// Possible values are: "created", "edited", "deleted".
Action *string `json:"action,omitempty"`
Issue *Issue `json:"issue,omitempty"`
Comment *IssueComment `json:"comment,omitempty"`
// The following fields are only populated by Webhook events.
Changes *EditChange `json:"changes,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// IssuesEvent is triggered when an issue is opened, edited, deleted, transferred,
// pinned, unpinned, closed, reopened, assigned, unassigned, labeled, unlabeled,
// locked, unlocked, milestoned, or demilestoned.
// The Webhook event name is "issues".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#issuesevent
type IssuesEvent struct {
// Action is the action that was performed. Possible values are: "opened",
// "edited", "deleted", "transferred", "pinned", "unpinned", "closed", "reopened",
// "assigned", "unassigned", "labeled", "unlabeled", "locked", "unlocked",
// "milestoned", or "demilestoned".
Action *string `json:"action,omitempty"`
Issue *Issue `json:"issue,omitempty"`
Assignee *User `json:"assignee,omitempty"`
Label *Label `json:"label,omitempty"`
// The following fields are only populated by Webhook events.
Changes *EditChange `json:"changes,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// LabelEvent is triggered when a repository's label is created, edited, or deleted.
// The Webhook event name is "label"
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#labelevent
type LabelEvent struct {
// Action is the action that was performed. Possible values are:
// "created", "edited", "deleted"
Action *string `json:"action,omitempty"`
Label *Label `json:"label,omitempty"`
// The following fields are only populated by Webhook events.
Changes *EditChange `json:"changes,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Org *Organization `json:"organization,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// MarketplacePurchaseEvent is triggered when a user purchases, cancels, or changes
// their GitHub Marketplace plan.
// Webhook event name "marketplace_purchase".
//
// Github API docs: https://developer.github.com/v3/activity/events/types/#marketplacepurchaseevent
type MarketplacePurchaseEvent struct {
// Action is the action that was performed. Possible values are:
// "purchased", "cancelled", "pending_change", "pending_change_cancelled", "changed".
Action *string `json:"action,omitempty"`
// The following fields are only populated by Webhook events.
EffectiveDate *Timestamp `json:"effective_date,omitempty"`
MarketplacePurchase *MarketplacePurchase `json:"marketplace_purchase,omitempty"`
PreviousMarketplacePurchase *MarketplacePurchase `json:"previous_marketplace_purchase,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// MemberEvent is triggered when a user is added as a collaborator to a repository.
// The Webhook event name is "member".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#memberevent
type MemberEvent struct {
// Action is the action that was performed. Possible value is: "added".
Action *string `json:"action,omitempty"`
Member *User `json:"member,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// MembershipEvent is triggered when a user is added or removed from a team.
// The Webhook event name is "membership".
//
// Events of this type are not visible in timelines, they are only used to
// trigger organization webhooks.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#membershipevent
type MembershipEvent struct {
// Action is the action that was performed. Possible values are: "added", "removed".
Action *string `json:"action,omitempty"`
// Scope is the scope of the membership. Possible value is: "team".
Scope *string `json:"scope,omitempty"`
Member *User `json:"member,omitempty"`
Team *Team `json:"team,omitempty"`
// The following fields are only populated by Webhook events.
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// MetaEvent is triggered when the webhook that this event is configured on is deleted.
// This event will only listen for changes to the particular hook the event is installed on.
// Therefore, it must be selected for each hook that you'd like to receive meta events for.
// The Webhook event name is "meta".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#metaevent
type MetaEvent struct {
// Action is the action that was performed. Possible value is: "deleted".
Action *string `json:"action,omitempty"`
// The ID of the modified webhook.
HookID *int64 `json:"hook_id,omitempty"`
// The modified webhook.
// This will contain different keys based on the type of webhook it is: repository,
// organization, business, app, or GitHub Marketplace.
Hook *Hook `json:"hook,omitempty"`
}
// MilestoneEvent is triggered when a milestone is created, closed, opened, edited, or deleted.
// The Webhook event name is "milestone".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#milestoneevent
type MilestoneEvent struct {
// Action is the action that was performed. Possible values are:
// "created", "closed", "opened", "edited", "deleted"
Action *string `json:"action,omitempty"`
Milestone *Milestone `json:"milestone,omitempty"`
// The following fields are only populated by Webhook events.
Changes *EditChange `json:"changes,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Org *Organization `json:"organization,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// OrganizationEvent is triggered when an organization is deleted and renamed, and when a user is added,
// removed, or invited to an organization.
// Events of this type are not visible in timelines. These events are only used to trigger organization hooks.
// Webhook event name is "organization".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#organizationevent
type OrganizationEvent struct {
// Action is the action that was performed.
// Possible values are: "deleted", "renamed", "member_added", "member_removed", or "member_invited".
Action *string `json:"action,omitempty"`
// Invitation is the invitation for the user or email if the action is "member_invited".
Invitation *Invitation `json:"invitation,omitempty"`
// Membership is the membership between the user and the organization.
// Not present when the action is "member_invited".
Membership *Membership `json:"membership,omitempty"`
Organization *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// OrgBlockEvent is triggered when an organization blocks or unblocks a user.
// The Webhook event name is "org_block".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#orgblockevent
type OrgBlockEvent struct {
// Action is the action that was performed.
// Can be "blocked" or "unblocked".
Action *string `json:"action,omitempty"`
BlockedUser *User `json:"blocked_user,omitempty"`
Organization *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
// The following fields are only populated by Webhook events.
Installation *Installation `json:"installation,omitempty"`
}
// PageBuildEvent represents an attempted build of a GitHub Pages site, whether
// successful or not.
// The Webhook event name is "page_build".
//
// This event is triggered on push to a GitHub Pages enabled branch (gh-pages
// for project pages, master for user and organization pages).
//
// Events of this type are not visible in timelines, they are only used to trigger hooks.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pagebuildevent
type PageBuildEvent struct {
Build *PagesBuild `json:"build,omitempty"`
// The following fields are only populated by Webhook events.
ID *int64 `json:"id,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// PingEvent is triggered when a Webhook is added to GitHub.
//
// GitHub API docs: https://developer.github.com/webhooks/#ping-event
type PingEvent struct {
// Random string of GitHub zen.
Zen *string `json:"zen,omitempty"`
// The ID of the webhook that triggered the ping.
HookID *int64 `json:"hook_id,omitempty"`
// The webhook configuration.
Hook *Hook `json:"hook,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// ProjectEvent is triggered when project is created, modified or deleted.
// The webhook event name is "project".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectevent
type ProjectEvent struct {
Action *string `json:"action,omitempty"`
Changes *ProjectChange `json:"changes,omitempty"`
Project *Project `json:"project,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// ProjectCardEvent is triggered when a project card is created, updated, moved, converted to an issue, or deleted.
// The webhook event name is "project_card".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcardevent
type ProjectCardEvent struct {
Action *string `json:"action,omitempty"`
Changes *ProjectCardChange `json:"changes,omitempty"`
AfterID *int64 `json:"after_id,omitempty"`
ProjectCard *ProjectCard `json:"project_card,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// ProjectColumnEvent is triggered when a project column is created, updated, moved, or deleted.
// The webhook event name is "project_column".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#projectcolumnevent
type ProjectColumnEvent struct {
Action *string `json:"action,omitempty"`
Changes *ProjectColumnChange `json:"changes,omitempty"`
AfterID *int64 `json:"after_id,omitempty"`
ProjectColumn *ProjectColumn `json:"project_column,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// PublicEvent is triggered when a private repository is open sourced.
// According to GitHub: "Without a doubt: the best GitHub event."
// The Webhook event name is "public".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#publicevent
type PublicEvent struct {
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// PullRequestEvent is triggered when a pull request is assigned, unassigned, labeled,
// unlabeled, opened, edited, closed, reopened, synchronize, ready_for_review,
// locked, unlocked, a pull request review is requested, or a review request is removed.
// The Webhook event name is "pull_request".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestevent
type PullRequestEvent struct {
// Action is the action that was performed. Possible values are:
// "assigned", "unassigned", "review_requested", "review_request_removed", "labeled", "unlabeled",
// "opened", "edited", "closed", "ready_for_review", "locked", "unlocked", or "reopened".
// If the action is "closed" and the "merged" key is "false", the pull request was closed with unmerged commits.
// If the action is "closed" and the "merged" key is "true", the pull request was merged.
// While webhooks are also triggered when a pull request is synchronized, Events API timelines
// don't include pull request events with the "synchronize" action.
Action *string `json:"action,omitempty"`
Assignee *User `json:"assignee,omitempty"`
Number *int `json:"number,omitempty"`
PullRequest *PullRequest `json:"pull_request,omitempty"`
// The following fields are only populated by Webhook events.
Changes *EditChange `json:"changes,omitempty"`
// RequestedReviewer is populated in "review_requested", "review_request_removed" event deliveries.
// A request affecting multiple reviewers at once is split into multiple
// such event deliveries, each with a single, different RequestedReviewer.
RequestedReviewer *User `json:"requested_reviewer,omitempty"`
// In the event that a team is requested instead of a user, "requested_team" gets sent in place of
// "requested_user" with the same delivery behavior.
RequestedTeam *Team `json:"requested_team,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
Label *Label `json:"label,omitempty"` // Populated in "labeled" event deliveries.
// The following field is only present when the webhook is triggered on
// a repository belonging to an organization.
Organization *Organization `json:"organization,omitempty"`
// The following fields are only populated when the Action is "synchronize".
Before *string `json:"before,omitempty"`
After *string `json:"after,omitempty"`
}
// PullRequestReviewEvent is triggered when a review is submitted on a pull
// request.
// The Webhook event name is "pull_request_review".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewevent
type PullRequestReviewEvent struct {
// Action is always "submitted".
Action *string `json:"action,omitempty"`
Review *PullRequestReview `json:"review,omitempty"`
PullRequest *PullRequest `json:"pull_request,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
// The following field is only present when the webhook is triggered on
// a repository belonging to an organization.
Organization *Organization `json:"organization,omitempty"`
}
// PullRequestReviewCommentEvent is triggered when a comment is created on a
// portion of the unified diff of a pull request.
// The Webhook event name is "pull_request_review_comment".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pullrequestreviewcommentevent
type PullRequestReviewCommentEvent struct {
// Action is the action that was performed on the comment.
// Possible values are: "created", "edited", "deleted".
Action *string `json:"action,omitempty"`
PullRequest *PullRequest `json:"pull_request,omitempty"`
Comment *PullRequestComment `json:"comment,omitempty"`
// The following fields are only populated by Webhook events.
Changes *EditChange `json:"changes,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// PushEvent represents a git push to a GitHub repository.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#pushevent
type PushEvent struct {
PushID *int64 `json:"push_id,omitempty"`
Head *string `json:"head,omitempty"`
Ref *string `json:"ref,omitempty"`
Size *int `json:"size,omitempty"`
Commits []PushEventCommit `json:"commits,omitempty"`
Before *string `json:"before,omitempty"`
DistinctSize *int `json:"distinct_size,omitempty"`
// The following fields are only populated by Webhook events.
After *string `json:"after,omitempty"`
Created *bool `json:"created,omitempty"`
Deleted *bool `json:"deleted,omitempty"`
Forced *bool `json:"forced,omitempty"`
BaseRef *string `json:"base_ref,omitempty"`
Compare *string `json:"compare,omitempty"`
Repo *PushEventRepository `json:"repository,omitempty"`
HeadCommit *PushEventCommit `json:"head_commit,omitempty"`
Pusher *User `json:"pusher,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
func (p PushEvent) String() string {
return Stringify(p)
}
// PushEventCommit represents a git commit in a GitHub PushEvent.
type PushEventCommit struct {
Message *string `json:"message,omitempty"`
Author *CommitAuthor `json:"author,omitempty"`
URL *string `json:"url,omitempty"`
Distinct *bool `json:"distinct,omitempty"`
// The following fields are only populated by Events API.
SHA *string `json:"sha,omitempty"`
// The following fields are only populated by Webhook events.
ID *string `json:"id,omitempty"`
TreeID *string `json:"tree_id,omitempty"`
Timestamp *Timestamp `json:"timestamp,omitempty"`
Committer *CommitAuthor `json:"committer,omitempty"`
Added []string `json:"added,omitempty"`
Removed []string `json:"removed,omitempty"`
Modified []string `json:"modified,omitempty"`
}
func (p PushEventCommit) String() string {
return Stringify(p)
}
// PushEventRepository represents the repo object in a PushEvent payload.
type PushEventRepository struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Name *string `json:"name,omitempty"`
FullName *string `json:"full_name,omitempty"`
Owner *User `json:"owner,omitempty"`
Private *bool `json:"private,omitempty"`
Description *string `json:"description,omitempty"`
Fork *bool `json:"fork,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
PushedAt *Timestamp `json:"pushed_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
Homepage *string `json:"homepage,omitempty"`
PullsURL *string `json:"pulls_url,omitempty"`
Size *int `json:"size,omitempty"`
StargazersCount *int `json:"stargazers_count,omitempty"`
WatchersCount *int `json:"watchers_count,omitempty"`
Language *string `json:"language,omitempty"`
HasIssues *bool `json:"has_issues,omitempty"`
HasDownloads *bool `json:"has_downloads,omitempty"`
HasWiki *bool `json:"has_wiki,omitempty"`
HasPages *bool `json:"has_pages,omitempty"`
ForksCount *int `json:"forks_count,omitempty"`
Archived *bool `json:"archived,omitempty"`
Disabled *bool `json:"disabled,omitempty"`
OpenIssuesCount *int `json:"open_issues_count,omitempty"`
DefaultBranch *string `json:"default_branch,omitempty"`
MasterBranch *string `json:"master_branch,omitempty"`
Organization *string `json:"organization,omitempty"`
URL *string `json:"url,omitempty"`
ArchiveURL *string `json:"archive_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
StatusesURL *string `json:"statuses_url,omitempty"`
GitURL *string `json:"git_url,omitempty"`
SSHURL *string `json:"ssh_url,omitempty"`
CloneURL *string `json:"clone_url,omitempty"`
SVNURL *string `json:"svn_url,omitempty"`
}
// PushEventRepoOwner is a basic representation of user/org in a PushEvent payload.
type PushEventRepoOwner struct {
Name *string `json:"name,omitempty"`
Email *string `json:"email,omitempty"`
}
// ReleaseEvent is triggered when a release is published, unpublished, created,
// edited, deleted, or prereleased.
// The Webhook event name is "release".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#releaseevent
type ReleaseEvent struct {
// Action is the action that was performed. Possible values are: "published", "unpublished",
// "created", "edited", "deleted", or "prereleased".
Action *string `json:"action,omitempty"`
Release *RepositoryRelease `json:"release,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// RepositoryEvent is triggered when a repository is created, archived, unarchived,
// renamed, edited, transferred, made public, or made private. Organization hooks are
// also trigerred when a repository is deleted.
// The Webhook event name is "repository".
//
// Events of this type are not visible in timelines, they are only used to
// trigger organization webhooks.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryevent
type RepositoryEvent struct {
// Action is the action that was performed. Possible values are: "created",
// "deleted" (organization hooks only), "archived", "unarchived", "edited", "renamed",
// "transferred", "publicized", or "privatized".
Action *string `json:"action,omitempty"`
Repo *Repository `json:"repository,omitempty"`
// The following fields are only populated by Webhook events.
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// RepositoryDispatchEvent is triggered when a client sends a POST request to the repository dispatch event endpoint.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositorydispatchevent
type RepositoryDispatchEvent struct {
// Action is the event_type that submitted with the repository dispatch payload. Value can be any string.
Action *string `json:"action,omitempty"`
Branch *string `json:"branch,omitempty"`
ClientPayload json.RawMessage `json:"client_payload,omitempty"`
Repo *Repository `json:"repository,omitempty"`
// The following fields are only populated by Webhook events.
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// RepositoryVulnerabilityAlertEvent is triggered when a security alert is created, dismissed, or resolved.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#repositoryvulnerabilityalertevent
type RepositoryVulnerabilityAlertEvent struct {
// Action is the action that was performed. Possible values are: "create", "dismiss", "resolve".
Action *string `json:"action,omitempty"`
//The security alert of the vulnerable dependency.
Alert *struct {
ID *int64 `json:"id,omitempty"`
AffectedRange *string `json:"affected_range,omitempty"`
AffectedPackageName *string `json:"affected_package_name,omitempty"`
ExternalReference *string `json:"external_reference,omitempty"`
ExternalIdentifier *string `json:"external_identifier,omitempty"`
FixedIn *string `json:"fixed_in,omitempty"`
Dismisser *User `json:"dismisser,omitempty"`
DismissReason *string `json:"dismiss_reason,omitempty"`
DismissedAt *Timestamp `json:"dismissed_at,omitempty"`
} `json:"alert,omitempty"`
}
// StarEvent is triggered when a star is added or removed from a repository.
// The Webhook event name is "star".
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#starevent
type StarEvent struct {
// Action is the action that was performed. Possible values are: "created" or "deleted".
Action *string `json:"action,omitempty"`
// StarredAt is the time the star was created. It will be null for the "deleted" action.
StarredAt *Timestamp `json:"starred_at,omitempty"`
}
// StatusEvent is triggered when the status of a Git commit changes.
// The Webhook event name is "status".
//
// Events of this type are not visible in timelines, they are only used to
// trigger hooks.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#statusevent
type StatusEvent struct {
SHA *string `json:"sha,omitempty"`
// State is the new state. Possible values are: "pending", "success", "failure", "error".
State *string `json:"state,omitempty"`
Description *string `json:"description,omitempty"`
TargetURL *string `json:"target_url,omitempty"`
Branches []*Branch `json:"branches,omitempty"`
// The following fields are only populated by Webhook events.
ID *int64 `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
Context *string `json:"context,omitempty"`
Commit *RepositoryCommit `json:"commit,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// TeamEvent is triggered when an organization's team is created, modified or deleted.
// The Webhook event name is "team".
//
// Events of this type are not visible in timelines. These events are only used
// to trigger hooks.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamevent
type TeamEvent struct {
Action *string `json:"action,omitempty"`
Team *Team `json:"team,omitempty"`
Changes *TeamChange `json:"changes,omitempty"`
Repo *Repository `json:"repository,omitempty"`
// The following fields are only populated by Webhook events.
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// TeamAddEvent is triggered when a repository is added to a team.
// The Webhook event name is "team_add".
//
// Events of this type are not visible in timelines. These events are only used
// to trigger hooks.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#teamaddevent
type TeamAddEvent struct {
Team *Team `json:"team,omitempty"`
Repo *Repository `json:"repository,omitempty"`
// The following fields are only populated by Webhook events.
Org *Organization `json:"organization,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}
// UserEvent is triggered when a user is created or deleted.
// The Webhook event name is "user".
//
// Only global webhooks can subscribe to this event type.
//
// GitHub API docs: https://developer.github.com/enterprise/v3/activity/events/types/#userevent-enterprise
type UserEvent struct {
User *User `json:"user,omitempty"`
// The action performed. Possible values are: "created" or "deleted".
Action *string `json:"action,omitempty"`
Enterprise *Enterprise `json:"enterprise,omitempty"`
Sender *User `json:"sender,omitempty"`
}
// WatchEvent is related to starring a repository, not watching. See this API
// blog post for an explanation: https://developer.github.com/changes/2012-09-05-watcher-api/
//
// The events actor is the user who starred a repository, and the events
// repository is the repository that was starred.
//
// GitHub API docs: https://developer.github.com/v3/activity/events/types/#watchevent
type WatchEvent struct {
// Action is the action that was performed. Possible value is: "started".
Action *string `json:"action,omitempty"`
// The following fields are only populated by Webhook events.
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
Installation *Installation `json:"installation,omitempty"`
}

363
vendor/github.com/google/go-github/v29/github/gists.go generated vendored Normal file
View file

@ -0,0 +1,363 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// GistsService handles communication with the Gist related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/gists/
type GistsService service
// Gist represents a GitHub's gist.
type Gist struct {
ID *string `json:"id,omitempty"`
Description *string `json:"description,omitempty"`
Public *bool `json:"public,omitempty"`
Owner *User `json:"owner,omitempty"`
Files map[GistFilename]GistFile `json:"files,omitempty"`
Comments *int `json:"comments,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
GitPullURL *string `json:"git_pull_url,omitempty"`
GitPushURL *string `json:"git_push_url,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
func (g Gist) String() string {
return Stringify(g)
}
// GistFilename represents filename on a gist.
type GistFilename string
// GistFile represents a file on a gist.
type GistFile struct {
Size *int `json:"size,omitempty"`
Filename *string `json:"filename,omitempty"`
Language *string `json:"language,omitempty"`
Type *string `json:"type,omitempty"`
RawURL *string `json:"raw_url,omitempty"`
Content *string `json:"content,omitempty"`
}
func (g GistFile) String() string {
return Stringify(g)
}
// GistCommit represents a commit on a gist.
type GistCommit struct {
URL *string `json:"url,omitempty"`
Version *string `json:"version,omitempty"`
User *User `json:"user,omitempty"`
ChangeStatus *CommitStats `json:"change_status,omitempty"`
CommittedAt *Timestamp `json:"committed_at,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
func (gc GistCommit) String() string {
return Stringify(gc)
}
// GistFork represents a fork of a gist.
type GistFork struct {
URL *string `json:"url,omitempty"`
User *User `json:"user,omitempty"`
ID *string `json:"id,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
func (gf GistFork) String() string {
return Stringify(gf)
}
// GistListOptions specifies the optional parameters to the
// GistsService.List, GistsService.ListAll, and GistsService.ListStarred methods.
type GistListOptions struct {
// Since filters Gists by time.
Since time.Time `url:"since,omitempty"`
ListOptions
}
// List gists for a user. Passing the empty string will list
// all public gists if called anonymously. However, if the call
// is authenticated, it will returns all gists for the authenticated
// user.
//
// GitHub API docs: https://developer.github.com/v3/gists/#list-gists
func (s *GistsService) List(ctx context.Context, user string, opts *GistListOptions) ([]*Gist, *Response, error) {
var u string
if user != "" {
u = fmt.Sprintf("users/%v/gists", user)
} else {
u = "gists"
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var gists []*Gist
resp, err := s.client.Do(ctx, req, &gists)
if err != nil {
return nil, resp, err
}
return gists, resp, nil
}
// ListAll lists all public gists.
//
// GitHub API docs: https://developer.github.com/v3/gists/#list-gists
func (s *GistsService) ListAll(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) {
u, err := addOptions("gists/public", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var gists []*Gist
resp, err := s.client.Do(ctx, req, &gists)
if err != nil {
return nil, resp, err
}
return gists, resp, nil
}
// ListStarred lists starred gists of authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/gists/#list-gists
func (s *GistsService) ListStarred(ctx context.Context, opts *GistListOptions) ([]*Gist, *Response, error) {
u, err := addOptions("gists/starred", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var gists []*Gist
resp, err := s.client.Do(ctx, req, &gists)
if err != nil {
return nil, resp, err
}
return gists, resp, nil
}
// Get a single gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/#get-a-single-gist
func (s *GistsService) Get(ctx context.Context, id string) (*Gist, *Response, error) {
u := fmt.Sprintf("gists/%v", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
gist := new(Gist)
resp, err := s.client.Do(ctx, req, gist)
if err != nil {
return nil, resp, err
}
return gist, resp, nil
}
// GetRevision gets a specific revision of a gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/#get-a-specific-revision-of-a-gist
func (s *GistsService) GetRevision(ctx context.Context, id, sha string) (*Gist, *Response, error) {
u := fmt.Sprintf("gists/%v/%v", id, sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
gist := new(Gist)
resp, err := s.client.Do(ctx, req, gist)
if err != nil {
return nil, resp, err
}
return gist, resp, nil
}
// Create a gist for authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/gists/#create-a-gist
func (s *GistsService) Create(ctx context.Context, gist *Gist) (*Gist, *Response, error) {
u := "gists"
req, err := s.client.NewRequest("POST", u, gist)
if err != nil {
return nil, nil, err
}
g := new(Gist)
resp, err := s.client.Do(ctx, req, g)
if err != nil {
return nil, resp, err
}
return g, resp, nil
}
// Edit a gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/#edit-a-gist
func (s *GistsService) Edit(ctx context.Context, id string, gist *Gist) (*Gist, *Response, error) {
u := fmt.Sprintf("gists/%v", id)
req, err := s.client.NewRequest("PATCH", u, gist)
if err != nil {
return nil, nil, err
}
g := new(Gist)
resp, err := s.client.Do(ctx, req, g)
if err != nil {
return nil, resp, err
}
return g, resp, nil
}
// ListCommits lists commits of a gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-commits
func (s *GistsService) ListCommits(ctx context.Context, id string, opts *ListOptions) ([]*GistCommit, *Response, error) {
u := fmt.Sprintf("gists/%v/commits", id)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var gistCommits []*GistCommit
resp, err := s.client.Do(ctx, req, &gistCommits)
if err != nil {
return nil, resp, err
}
return gistCommits, resp, nil
}
// Delete a gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/#delete-a-gist
func (s *GistsService) Delete(ctx context.Context, id string) (*Response, error) {
u := fmt.Sprintf("gists/%v", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Star a gist on behalf of authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/gists/#star-a-gist
func (s *GistsService) Star(ctx context.Context, id string) (*Response, error) {
u := fmt.Sprintf("gists/%v/star", id)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// Unstar a gist on a behalf of authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/gists/#unstar-a-gist
func (s *GistsService) Unstar(ctx context.Context, id string) (*Response, error) {
u := fmt.Sprintf("gists/%v/star", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// IsStarred checks if a gist is starred by authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/gists/#check-if-a-gist-is-starred
func (s *GistsService) IsStarred(ctx context.Context, id string) (bool, *Response, error) {
u := fmt.Sprintf("gists/%v/star", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
resp, err := s.client.Do(ctx, req, nil)
starred, err := parseBoolResponse(err)
return starred, resp, err
}
// Fork a gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/#fork-a-gist
func (s *GistsService) Fork(ctx context.Context, id string) (*Gist, *Response, error) {
u := fmt.Sprintf("gists/%v/forks", id)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
g := new(Gist)
resp, err := s.client.Do(ctx, req, g)
if err != nil {
return nil, resp, err
}
return g, resp, nil
}
// ListForks lists forks of a gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/#list-gist-forks
func (s *GistsService) ListForks(ctx context.Context, id string, opts *ListOptions) ([]*GistFork, *Response, error) {
u := fmt.Sprintf("gists/%v/forks", id)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var gistForks []*GistFork
resp, err := s.client.Do(ctx, req, &gistForks)
if err != nil {
return nil, resp, err
}
return gistForks, resp, nil
}

View file

@ -0,0 +1,119 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// GistComment represents a Gist comment.
type GistComment struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
Body *string `json:"body,omitempty"`
User *User `json:"user,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
}
func (g GistComment) String() string {
return Stringify(g)
}
// ListComments lists all comments for a gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/comments/#list-comments-on-a-gist
func (s *GistsService) ListComments(ctx context.Context, gistID string, opts *ListOptions) ([]*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments", gistID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var comments []*GistComment
resp, err := s.client.Do(ctx, req, &comments)
if err != nil {
return nil, resp, err
}
return comments, resp, nil
}
// GetComment retrieves a single comment from a gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/comments/#get-a-single-comment
func (s *GistsService) GetComment(ctx context.Context, gistID string, commentID int64) (*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
c := new(GistComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// CreateComment creates a comment for a gist.
//
// GitHub API docs: https://developer.github.com/v3/gists/comments/#create-a-comment
func (s *GistsService) CreateComment(ctx context.Context, gistID string, comment *GistComment) (*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments", gistID)
req, err := s.client.NewRequest("POST", u, comment)
if err != nil {
return nil, nil, err
}
c := new(GistComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// EditComment edits an existing gist comment.
//
// GitHub API docs: https://developer.github.com/v3/gists/comments/#edit-a-comment
func (s *GistsService) EditComment(ctx context.Context, gistID string, commentID int64, comment *GistComment) (*GistComment, *Response, error) {
u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
req, err := s.client.NewRequest("PATCH", u, comment)
if err != nil {
return nil, nil, err
}
c := new(GistComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// DeleteComment deletes a gist comment.
//
// GitHub API docs: https://developer.github.com/v3/gists/comments/#delete-a-comment
func (s *GistsService) DeleteComment(ctx context.Context, gistID string, commentID int64) (*Response, error) {
u := fmt.Sprintf("gists/%v/comments/%v", gistID, commentID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

12
vendor/github.com/google/go-github/v29/github/git.go generated vendored Normal file
View file

@ -0,0 +1,12 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
// GitService handles communication with the git data related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/git/
type GitService service

View file

@ -0,0 +1,69 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"bytes"
"context"
"fmt"
)
// Blob represents a blob object.
type Blob struct {
Content *string `json:"content,omitempty"`
Encoding *string `json:"encoding,omitempty"`
SHA *string `json:"sha,omitempty"`
Size *int `json:"size,omitempty"`
URL *string `json:"url,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
// GetBlob fetches a blob from a repo given a SHA.
//
// GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob
func (s *GitService) GetBlob(ctx context.Context, owner string, repo string, sha string) (*Blob, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
blob := new(Blob)
resp, err := s.client.Do(ctx, req, blob)
return blob, resp, err
}
// GetBlobRaw fetches a blob's contents from a repo.
// Unlike GetBlob, it returns the raw bytes rather than the base64-encoded data.
//
// GitHub API docs: https://developer.github.com/v3/git/blobs/#get-a-blob
func (s *GitService) GetBlobRaw(ctx context.Context, owner, repo, sha string) ([]byte, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/blobs/%v", owner, repo, sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", "application/vnd.github.v3.raw")
var buf bytes.Buffer
resp, err := s.client.Do(ctx, req, &buf)
return buf.Bytes(), resp, err
}
// CreateBlob creates a blob object.
//
// GitHub API docs: https://developer.github.com/v3/git/blobs/#create-a-blob
func (s *GitService) CreateBlob(ctx context.Context, owner string, repo string, blob *Blob) (*Blob, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/blobs", owner, repo)
req, err := s.client.NewRequest("POST", u, blob)
if err != nil {
return nil, nil, err
}
t := new(Blob)
resp, err := s.client.Do(ctx, req, t)
return t, resp, err
}

View file

@ -0,0 +1,200 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"bytes"
"context"
"errors"
"fmt"
"strings"
"time"
"golang.org/x/crypto/openpgp"
)
// SignatureVerification represents GPG signature verification.
type SignatureVerification struct {
Verified *bool `json:"verified,omitempty"`
Reason *string `json:"reason,omitempty"`
Signature *string `json:"signature,omitempty"`
Payload *string `json:"payload,omitempty"`
}
// Commit represents a GitHub commit.
type Commit struct {
SHA *string `json:"sha,omitempty"`
Author *CommitAuthor `json:"author,omitempty"`
Committer *CommitAuthor `json:"committer,omitempty"`
Message *string `json:"message,omitempty"`
Tree *Tree `json:"tree,omitempty"`
Parents []Commit `json:"parents,omitempty"`
Stats *CommitStats `json:"stats,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
URL *string `json:"url,omitempty"`
Verification *SignatureVerification `json:"verification,omitempty"`
NodeID *string `json:"node_id,omitempty"`
// CommentCount is the number of GitHub comments on the commit. This
// is only populated for requests that fetch GitHub data like
// Pulls.ListCommits, Repositories.ListCommits, etc.
CommentCount *int `json:"comment_count,omitempty"`
// SigningKey denotes a key to sign the commit with. If not nil this key will
// be used to sign the commit. The private key must be present and already
// decrypted. Ignored if Verification.Signature is defined.
SigningKey *openpgp.Entity `json:"-"`
}
func (c Commit) String() string {
return Stringify(c)
}
// CommitAuthor represents the author or committer of a commit. The commit
// author may not correspond to a GitHub User.
type CommitAuthor struct {
Date *time.Time `json:"date,omitempty"`
Name *string `json:"name,omitempty"`
Email *string `json:"email,omitempty"`
// The following fields are only populated by Webhook events.
Login *string `json:"username,omitempty"` // Renamed for go-github consistency.
}
func (c CommitAuthor) String() string {
return Stringify(c)
}
// GetCommit fetches the Commit object for a given SHA.
//
// GitHub API docs: https://developer.github.com/v3/git/commits/#get-a-commit
func (s *GitService) GetCommit(ctx context.Context, owner string, repo string, sha string) (*Commit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/commits/%v", owner, repo, sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
c := new(Commit)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// createCommit represents the body of a CreateCommit request.
type createCommit struct {
Author *CommitAuthor `json:"author,omitempty"`
Committer *CommitAuthor `json:"committer,omitempty"`
Message *string `json:"message,omitempty"`
Tree *string `json:"tree,omitempty"`
Parents []string `json:"parents,omitempty"`
Signature *string `json:"signature,omitempty"`
}
// CreateCommit creates a new commit in a repository.
// commit must not be nil.
//
// The commit.Committer is optional and will be filled with the commit.Author
// data if omitted. If the commit.Author is omitted, it will be filled in with
// the authenticated users information and the current date.
//
// GitHub API docs: https://developer.github.com/v3/git/commits/#create-a-commit
func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string, commit *Commit) (*Commit, *Response, error) {
if commit == nil {
return nil, nil, fmt.Errorf("commit must be provided")
}
u := fmt.Sprintf("repos/%v/%v/git/commits", owner, repo)
parents := make([]string, len(commit.Parents))
for i, parent := range commit.Parents {
parents[i] = *parent.SHA
}
body := &createCommit{
Author: commit.Author,
Committer: commit.Committer,
Message: commit.Message,
Parents: parents,
}
if commit.Tree != nil {
body.Tree = commit.Tree.SHA
}
if commit.SigningKey != nil {
signature, err := createSignature(commit.SigningKey, body)
if err != nil {
return nil, nil, err
}
body.Signature = &signature
}
if commit.Verification != nil {
body.Signature = commit.Verification.Signature
}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
c := new(Commit)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
func createSignature(signingKey *openpgp.Entity, commit *createCommit) (string, error) {
if signingKey == nil || commit == nil {
return "", errors.New("createSignature: invalid parameters")
}
message, err := createSignatureMessage(commit)
if err != nil {
return "", err
}
writer := new(bytes.Buffer)
reader := bytes.NewReader([]byte(message))
if err := openpgp.ArmoredDetachSign(writer, signingKey, reader, nil); err != nil {
return "", err
}
return writer.String(), nil
}
func createSignatureMessage(commit *createCommit) (string, error) {
if commit == nil || commit.Message == nil || *commit.Message == "" || commit.Author == nil {
return "", errors.New("createSignatureMessage: invalid parameters")
}
var message []string
if commit.Tree != nil {
message = append(message, fmt.Sprintf("tree %s", *commit.Tree))
}
for _, parent := range commit.Parents {
message = append(message, fmt.Sprintf("parent %s", parent))
}
message = append(message, fmt.Sprintf("author %s <%s> %d %s", commit.Author.GetName(), commit.Author.GetEmail(), commit.Author.GetDate().Unix(), commit.Author.GetDate().Format("-0700")))
committer := commit.Committer
if committer == nil {
committer = commit.Author
}
// There needs to be a double newline after committer
message = append(message, fmt.Sprintf("committer %s <%s> %d %s\n", committer.GetName(), committer.GetEmail(), committer.GetDate().Unix(), committer.GetDate().Format("-0700")))
message = append(message, *commit.Message)
return strings.Join(message, "\n"), nil
}

View file

@ -0,0 +1,222 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/url"
"strings"
)
// Reference represents a GitHub reference.
type Reference struct {
Ref *string `json:"ref"`
URL *string `json:"url"`
Object *GitObject `json:"object"`
NodeID *string `json:"node_id,omitempty"`
}
func (r Reference) String() string {
return Stringify(r)
}
// GitObject represents a Git object.
type GitObject struct {
Type *string `json:"type"`
SHA *string `json:"sha"`
URL *string `json:"url"`
}
func (o GitObject) String() string {
return Stringify(o)
}
// createRefRequest represents the payload for creating a reference.
type createRefRequest struct {
Ref *string `json:"ref"`
SHA *string `json:"sha"`
}
// updateRefRequest represents the payload for updating a reference.
type updateRefRequest struct {
SHA *string `json:"sha"`
Force *bool `json:"force"`
}
// GetRef fetches a single Reference object for a given Git ref.
// If there is no exact match, GetRef will return an error.
//
// Note: The GitHub API can return multiple matches.
// If you wish to use this functionality please use the GetRefs() method.
//
// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference
func (s *GitService) GetRef(ctx context.Context, owner string, repo string, ref string) (*Reference, *Response, error) {
ref = strings.TrimPrefix(ref, "refs/")
u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, url.QueryEscape(ref))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
r := new(Reference)
resp, err := s.client.Do(ctx, req, r)
if _, ok := err.(*json.UnmarshalTypeError); ok {
// Multiple refs, means there wasn't an exact match.
return nil, resp, errors.New("multiple matches found for this ref")
} else if _, ok := err.(*ErrorResponse); ok && resp.StatusCode == 404 {
// No ref, there was no match for the ref
return nil, resp, errors.New("no match found for this ref")
} else if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// GetRefs fetches a slice of Reference objects for a given Git ref.
// If there is an exact match, only that ref is returned.
// If there is no exact match, GitHub returns all refs that start with ref.
// If returned error is nil, there will be at least 1 ref returned.
// For example:
//
// "heads/featureA" -> ["refs/heads/featureA"] // Exact match, single ref is returned.
// "heads/feature" -> ["refs/heads/featureA", "refs/heads/featureB"] // All refs that start with ref.
// "heads/notexist" -> [] // Returns an error.
//
// GitHub API docs: https://developer.github.com/v3/git/refs/#get-a-reference
func (s *GitService) GetRefs(ctx context.Context, owner string, repo string, ref string) ([]*Reference, *Response, error) {
ref = strings.TrimPrefix(ref, "refs/")
u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, url.QueryEscape(ref))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var rawJSON json.RawMessage
resp, err := s.client.Do(ctx, req, &rawJSON)
if err != nil {
return nil, resp, err
}
// Prioritize the most common case: a single returned ref.
r := new(Reference)
singleUnmarshalError := json.Unmarshal(rawJSON, r)
if singleUnmarshalError == nil {
return []*Reference{r}, resp, nil
}
// Attempt to unmarshal multiple refs.
var rs []*Reference
multipleUnmarshalError := json.Unmarshal(rawJSON, &rs)
if multipleUnmarshalError == nil {
if len(rs) == 0 {
return nil, resp, fmt.Errorf("unexpected response from GitHub API: an array of refs with length 0")
}
return rs, resp, nil
}
return nil, resp, fmt.Errorf("unmarshalling failed for both single and multiple refs: %s and %s", singleUnmarshalError, multipleUnmarshalError)
}
// ReferenceListOptions specifies optional parameters to the
// GitService.ListRefs method.
type ReferenceListOptions struct {
Type string `url:"-"`
ListOptions
}
// ListRefs lists all refs in a repository.
//
// GitHub API docs: https://developer.github.com/v3/git/refs/#get-all-references
func (s *GitService) ListRefs(ctx context.Context, owner, repo string, opts *ReferenceListOptions) ([]*Reference, *Response, error) {
var u string
if opts != nil && opts.Type != "" {
u = fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, opts.Type)
} else {
u = fmt.Sprintf("repos/%v/%v/git/refs", owner, repo)
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var rs []*Reference
resp, err := s.client.Do(ctx, req, &rs)
if err != nil {
return nil, resp, err
}
return rs, resp, nil
}
// CreateRef creates a new ref in a repository.
//
// GitHub API docs: https://developer.github.com/v3/git/refs/#create-a-reference
func (s *GitService) CreateRef(ctx context.Context, owner string, repo string, ref *Reference) (*Reference, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/refs", owner, repo)
req, err := s.client.NewRequest("POST", u, &createRefRequest{
// back-compat with previous behavior that didn't require 'refs/' prefix
Ref: String("refs/" + strings.TrimPrefix(*ref.Ref, "refs/")),
SHA: ref.Object.SHA,
})
if err != nil {
return nil, nil, err
}
r := new(Reference)
resp, err := s.client.Do(ctx, req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// UpdateRef updates an existing ref in a repository.
//
// GitHub API docs: https://developer.github.com/v3/git/refs/#update-a-reference
func (s *GitService) UpdateRef(ctx context.Context, owner string, repo string, ref *Reference, force bool) (*Reference, *Response, error) {
refPath := strings.TrimPrefix(*ref.Ref, "refs/")
u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, refPath)
req, err := s.client.NewRequest("PATCH", u, &updateRefRequest{
SHA: ref.Object.SHA,
Force: &force,
})
if err != nil {
return nil, nil, err
}
r := new(Reference)
resp, err := s.client.Do(ctx, req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// DeleteRef deletes a ref from a repository.
//
// GitHub API docs: https://developer.github.com/v3/git/refs/#delete-a-reference
func (s *GitService) DeleteRef(ctx context.Context, owner string, repo string, ref string) (*Response, error) {
ref = strings.TrimPrefix(ref, "refs/")
u := fmt.Sprintf("repos/%v/%v/git/refs/%v", owner, repo, url.QueryEscape(ref))
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,76 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// Tag represents a tag object.
type Tag struct {
Tag *string `json:"tag,omitempty"`
SHA *string `json:"sha,omitempty"`
URL *string `json:"url,omitempty"`
Message *string `json:"message,omitempty"`
Tagger *CommitAuthor `json:"tagger,omitempty"`
Object *GitObject `json:"object,omitempty"`
Verification *SignatureVerification `json:"verification,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
// createTagRequest represents the body of a CreateTag request. This is mostly
// identical to Tag with the exception that the object SHA and Type are
// top-level fields, rather than being nested inside a JSON object.
type createTagRequest struct {
Tag *string `json:"tag,omitempty"`
Message *string `json:"message,omitempty"`
Object *string `json:"object,omitempty"`
Type *string `json:"type,omitempty"`
Tagger *CommitAuthor `json:"tagger,omitempty"`
}
// GetTag fetches a tag from a repo given a SHA.
//
// GitHub API docs: https://developer.github.com/v3/git/tags/#get-a-tag
func (s *GitService) GetTag(ctx context.Context, owner string, repo string, sha string) (*Tag, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/tags/%v", owner, repo, sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
tag := new(Tag)
resp, err := s.client.Do(ctx, req, tag)
return tag, resp, err
}
// CreateTag creates a tag object.
//
// GitHub API docs: https://developer.github.com/v3/git/tags/#create-a-tag-object
func (s *GitService) CreateTag(ctx context.Context, owner string, repo string, tag *Tag) (*Tag, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/tags", owner, repo)
// convert Tag into a createTagRequest
tagRequest := &createTagRequest{
Tag: tag.Tag,
Message: tag.Message,
Tagger: tag.Tagger,
}
if tag.Object != nil {
tagRequest.Object = tag.Object.SHA
tagRequest.Type = tag.Object.Type
}
req, err := s.client.NewRequest("POST", u, tagRequest)
if err != nil {
return nil, nil, err
}
t := new(Tag)
resp, err := s.client.Do(ctx, req, t)
return t, resp, err
}

View file

@ -0,0 +1,162 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"encoding/json"
"fmt"
)
// Tree represents a GitHub tree.
type Tree struct {
SHA *string `json:"sha,omitempty"`
Entries []TreeEntry `json:"tree,omitempty"`
// Truncated is true if the number of items in the tree
// exceeded GitHub's maximum limit and the Entries were truncated
// in the response. Only populated for requests that fetch
// trees like Git.GetTree.
Truncated *bool `json:"truncated,omitempty"`
}
func (t Tree) String() string {
return Stringify(t)
}
// TreeEntry represents the contents of a tree structure. TreeEntry can
// represent either a blob, a commit (in the case of a submodule), or another
// tree.
type TreeEntry struct {
SHA *string `json:"sha,omitempty"`
Path *string `json:"path,omitempty"`
Mode *string `json:"mode,omitempty"`
Type *string `json:"type,omitempty"`
Size *int `json:"size,omitempty"`
Content *string `json:"content,omitempty"`
URL *string `json:"url,omitempty"`
}
func (t TreeEntry) String() string {
return Stringify(t)
}
// treeEntryWithFileDelete is used internally to delete a file whose
// Content and SHA fields are empty. It does this by removing the "omitempty"
// tag modifier on the SHA field which causes the GitHub API to receive
// {"sha":null} and thereby delete the file.
type treeEntryWithFileDelete struct {
SHA *string `json:"sha"`
Path *string `json:"path,omitempty"`
Mode *string `json:"mode,omitempty"`
Type *string `json:"type,omitempty"`
Size *int `json:"size,omitempty"`
Content *string `json:"content,omitempty"`
URL *string `json:"url,omitempty"`
}
func (t *TreeEntry) MarshalJSON() ([]byte, error) {
if t.SHA == nil && t.Content == nil {
return json.Marshal(struct {
SHA *string `json:"sha"`
Path *string `json:"path,omitempty"`
Mode *string `json:"mode,omitempty"`
Type *string `json:"type,omitempty"`
}{
nil,
t.Path,
t.Mode,
t.Type,
})
}
return json.Marshal(struct {
SHA *string `json:"sha,omitempty"`
Path *string `json:"path,omitempty"`
Mode *string `json:"mode,omitempty"`
Type *string `json:"type,omitempty"`
Size *int `json:"size,omitempty"`
Content *string `json:"content,omitempty"`
URL *string `json:"url,omitempty"`
}{
SHA: t.SHA,
Path: t.Path,
Mode: t.Mode,
Type: t.Type,
Size: t.Size,
Content: t.Content,
URL: t.URL,
})
}
// GetTree fetches the Tree object for a given sha hash from a repository.
//
// GitHub API docs: https://developer.github.com/v3/git/trees/#get-a-tree
func (s *GitService) GetTree(ctx context.Context, owner string, repo string, sha string, recursive bool) (*Tree, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/trees/%v", owner, repo, sha)
if recursive {
u += "?recursive=1"
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
t := new(Tree)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}
// createTree represents the body of a CreateTree request.
type createTree struct {
BaseTree string `json:"base_tree,omitempty"`
Entries []interface{} `json:"tree"`
}
// CreateTree creates a new tree in a repository. If both a tree and a nested
// path modifying that tree are specified, it will overwrite the contents of
// that tree with the new path contents and write a new tree out.
//
// GitHub API docs: https://developer.github.com/v3/git/trees/#create-a-tree
func (s *GitService) CreateTree(ctx context.Context, owner string, repo string, baseTree string, entries []TreeEntry) (*Tree, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/git/trees", owner, repo)
newEntries := make([]interface{}, 0, len(entries))
for _, entry := range entries {
if entry.Content == nil && entry.SHA == nil {
newEntries = append(newEntries, treeEntryWithFileDelete{
Path: entry.Path,
Mode: entry.Mode,
Type: entry.Type,
Size: entry.Size,
URL: entry.URL,
})
continue
}
newEntries = append(newEntries, entry)
}
body := &createTree{
BaseTree: baseTree,
Entries: newEntries,
}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
t := new(Tree)
resp, err := s.client.Do(ctx, req, t)
if err != nil {
return nil, resp, err
}
return t, resp, nil
}

File diff suppressed because it is too large Load diff

1082
vendor/github.com/google/go-github/v29/github/github.go generated vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,64 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// GitignoresService provides access to the gitignore related functions in the
// GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/gitignore/
type GitignoresService service
// Gitignore represents a .gitignore file as returned by the GitHub API.
type Gitignore struct {
Name *string `json:"name,omitempty"`
Source *string `json:"source,omitempty"`
}
func (g Gitignore) String() string {
return Stringify(g)
}
// List all available Gitignore templates.
//
// GitHub API docs: https://developer.github.com/v3/gitignore/#listing-available-templates
func (s GitignoresService) List(ctx context.Context) ([]string, *Response, error) {
req, err := s.client.NewRequest("GET", "gitignore/templates", nil)
if err != nil {
return nil, nil, err
}
var availableTemplates []string
resp, err := s.client.Do(ctx, req, &availableTemplates)
if err != nil {
return nil, resp, err
}
return availableTemplates, resp, nil
}
// Get a Gitignore by name.
//
// GitHub API docs: https://developer.github.com/v3/gitignore/#get-a-single-template
func (s GitignoresService) Get(ctx context.Context, name string) (*Gitignore, *Response, error) {
u := fmt.Sprintf("gitignore/templates/%v", name)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
gitignore := new(Gitignore)
resp, err := s.client.Do(ctx, req, gitignore)
if err != nil {
return nil, resp, err
}
return gitignore, resp, nil
}

View file

@ -0,0 +1,28 @@
// Copyright 2018 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
// InteractionsService handles communication with the repository and organization related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/interactions/
type InteractionsService service
// InteractionRestriction represents the interaction restrictions for repository and organization.
type InteractionRestriction struct {
// Specifies the group of GitHub users who can
// comment, open issues, or create pull requests for the given repository.
// Possible values are: "existing_users", "contributors_only" and "collaborators_only".
Limit *string `json:"limit,omitempty"`
// Origin specifies the type of the resource to interact with.
// Possible values are: "repository" and "organization".
Origin *string `json:"origin,omitempty"`
// ExpiresAt specifies the time after which the interaction restrictions expire.
// The default expiry time is 24 hours from the time restriction is created.
ExpiresAt *Timestamp `json:"expires_at,omitempty"`
}

View file

@ -0,0 +1,80 @@
// Copyright 2019 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// GetRestrictionsForOrg fetches the interaction restrictions for an organization.
//
// GitHub API docs: https://developer.github.com/v3/interactions/orgs/#get-interaction-restrictions-for-an-organization
func (s *InteractionsService) GetRestrictionsForOrg(ctx context.Context, organization string) (*InteractionRestriction, *Response, error) {
u := fmt.Sprintf("orgs/%v/interaction-limits", organization)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview)
organizationInteractions := new(InteractionRestriction)
resp, err := s.client.Do(ctx, req, organizationInteractions)
if err != nil {
return nil, resp, err
}
return organizationInteractions, resp, nil
}
// UpdateRestrictionsForOrg adds or updates the interaction restrictions for an organization.
//
// limit specifies the group of GitHub users who can comment, open issues, or create pull requests
// in public repositories for the given organization.
// Possible values are: "existing_users", "contributors_only", "collaborators_only".
//
// GitHub API docs: https://developer.github.com/v3/interactions/orgs/#add-or-update-interaction-restrictions-for-an-organization
func (s *InteractionsService) UpdateRestrictionsForOrg(ctx context.Context, organization, limit string) (*InteractionRestriction, *Response, error) {
u := fmt.Sprintf("orgs/%v/interaction-limits", organization)
interaction := &InteractionRestriction{Limit: String(limit)}
req, err := s.client.NewRequest("PUT", u, interaction)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview)
organizationInteractions := new(InteractionRestriction)
resp, err := s.client.Do(ctx, req, organizationInteractions)
if err != nil {
return nil, resp, err
}
return organizationInteractions, resp, nil
}
// RemoveRestrictionsFromOrg removes the interaction restrictions for an organization.
//
// GitHub API docs: https://developer.github.com/v3/interactions/orgs/#remove-interaction-restrictions-for-an-organization
func (s *InteractionsService) RemoveRestrictionsFromOrg(ctx context.Context, organization string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/interaction-limits", organization)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview)
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,80 @@
// Copyright 2018 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// GetRestrictionsForRepo fetches the interaction restrictions for a repository.
//
// GitHub API docs: https://developer.github.com/v3/interactions/repos/#get-interaction-restrictions-for-a-repository
func (s *InteractionsService) GetRestrictionsForRepo(ctx context.Context, owner, repo string) (*InteractionRestriction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview)
repositoryInteractions := new(InteractionRestriction)
resp, err := s.client.Do(ctx, req, repositoryInteractions)
if err != nil {
return nil, resp, err
}
return repositoryInteractions, resp, nil
}
// UpdateRestrictionsForRepo adds or updates the interaction restrictions for a repository.
//
// limit specifies the group of GitHub users who can comment, open issues, or create pull requests
// for the given repository.
// Possible values are: "existing_users", "contributors_only", "collaborators_only".
//
// GitHub API docs: https://developer.github.com/v3/interactions/repos/#add-or-update-interaction-restrictions-for-a-repository
func (s *InteractionsService) UpdateRestrictionsForRepo(ctx context.Context, owner, repo, limit string) (*InteractionRestriction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo)
interaction := &InteractionRestriction{Limit: String(limit)}
req, err := s.client.NewRequest("PUT", u, interaction)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview)
repositoryInteractions := new(InteractionRestriction)
resp, err := s.client.Do(ctx, req, repositoryInteractions)
if err != nil {
return nil, resp, err
}
return repositoryInteractions, resp, nil
}
// RemoveRestrictionsFromRepo removes the interaction restrictions for a repository.
//
// GitHub API docs: https://developer.github.com/v3/interactions/repos/#remove-interaction-restrictions-for-a-repository
func (s *InteractionsService) RemoveRestrictionsFromRepo(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/interaction-limits", owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeInteractionRestrictionsPreview)
return s.client.Do(ctx, req, nil)
}

341
vendor/github.com/google/go-github/v29/github/issues.go generated vendored Normal file
View file

@ -0,0 +1,341 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"strings"
"time"
)
// IssuesService handles communication with the issue related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/issues/
type IssuesService service
// Issue represents a GitHub issue on a repository.
//
// Note: As far as the GitHub API is concerned, every pull request is an issue,
// but not every issue is a pull request. Some endpoints, events, and webhooks
// may also return pull requests via this struct. If PullRequestLinks is nil,
// this is an issue, and if PullRequestLinks is not nil, this is a pull request.
// The IsPullRequest helper method can be used to check that.
type Issue struct {
ID *int64 `json:"id,omitempty"`
Number *int `json:"number,omitempty"`
State *string `json:"state,omitempty"`
Locked *bool `json:"locked,omitempty"`
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
User *User `json:"user,omitempty"`
Labels []Label `json:"labels,omitempty"`
Assignee *User `json:"assignee,omitempty"`
Comments *int `json:"comments,omitempty"`
ClosedAt *time.Time `json:"closed_at,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
ClosedBy *User `json:"closed_by,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
CommentsURL *string `json:"comments_url,omitempty"`
EventsURL *string `json:"events_url,omitempty"`
LabelsURL *string `json:"labels_url,omitempty"`
RepositoryURL *string `json:"repository_url,omitempty"`
Milestone *Milestone `json:"milestone,omitempty"`
PullRequestLinks *PullRequestLinks `json:"pull_request,omitempty"`
Repository *Repository `json:"repository,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"`
Assignees []*User `json:"assignees,omitempty"`
NodeID *string `json:"node_id,omitempty"`
// TextMatches is only populated from search results that request text matches
// See: search.go and https://developer.github.com/v3/search/#text-match-metadata
TextMatches []TextMatch `json:"text_matches,omitempty"`
// ActiveLockReason is populated only when LockReason is provided while locking the issue.
// Possible values are: "off-topic", "too heated", "resolved", and "spam".
ActiveLockReason *string `json:"active_lock_reason,omitempty"`
}
func (i Issue) String() string {
return Stringify(i)
}
// IsPullRequest reports whether the issue is also a pull request. It uses the
// method recommended by GitHub's API documentation, which is to check whether
// PullRequestLinks is non-nil.
func (i Issue) IsPullRequest() bool {
return i.PullRequestLinks != nil
}
// IssueRequest represents a request to create/edit an issue.
// It is separate from Issue above because otherwise Labels
// and Assignee fail to serialize to the correct JSON.
type IssueRequest struct {
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
Labels *[]string `json:"labels,omitempty"`
Assignee *string `json:"assignee,omitempty"`
State *string `json:"state,omitempty"`
Milestone *int `json:"milestone,omitempty"`
Assignees *[]string `json:"assignees,omitempty"`
}
// IssueListOptions specifies the optional parameters to the IssuesService.List
// and IssuesService.ListByOrg methods.
type IssueListOptions struct {
// Filter specifies which issues to list. Possible values are: assigned,
// created, mentioned, subscribed, all. Default is "assigned".
Filter string `url:"filter,omitempty"`
// State filters issues based on their state. Possible values are: open,
// closed, all. Default is "open".
State string `url:"state,omitempty"`
// Labels filters issues based on their label.
Labels []string `url:"labels,comma,omitempty"`
// Sort specifies how to sort issues. Possible values are: created, updated,
// and comments. Default value is "created".
Sort string `url:"sort,omitempty"`
// Direction in which to sort issues. Possible values are: asc, desc.
// Default is "desc".
Direction string `url:"direction,omitempty"`
// Since filters issues by time.
Since time.Time `url:"since,omitempty"`
ListOptions
}
// PullRequestLinks object is added to the Issue object when it's an issue included
// in the IssueCommentEvent webhook payload, if the webhook is fired by a comment on a PR.
type PullRequestLinks struct {
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
DiffURL *string `json:"diff_url,omitempty"`
PatchURL *string `json:"patch_url,omitempty"`
}
// List the issues for the authenticated user. If all is true, list issues
// across all the user's visible repositories including owned, member, and
// organization repositories; if false, list only owned and member
// repositories.
//
// GitHub API docs: https://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) List(ctx context.Context, all bool, opts *IssueListOptions) ([]*Issue, *Response, error) {
var u string
if all {
u = "issues"
} else {
u = "user/issues"
}
return s.listIssues(ctx, u, opts)
}
// ListByOrg fetches the issues in the specified organization for the
// authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/issues/#list-issues
func (s *IssuesService) ListByOrg(ctx context.Context, org string, opts *IssueListOptions) ([]*Issue, *Response, error) {
u := fmt.Sprintf("orgs/%v/issues", org)
return s.listIssues(ctx, u, opts)
}
func (s *IssuesService) listIssues(ctx context.Context, u string, opts *IssueListOptions) ([]*Issue, *Response, error) {
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var issues []*Issue
resp, err := s.client.Do(ctx, req, &issues)
if err != nil {
return nil, resp, err
}
return issues, resp, nil
}
// IssueListByRepoOptions specifies the optional parameters to the
// IssuesService.ListByRepo method.
type IssueListByRepoOptions struct {
// Milestone limits issues for the specified milestone. Possible values are
// a milestone number, "none" for issues with no milestone, "*" for issues
// with any milestone.
Milestone string `url:"milestone,omitempty"`
// State filters issues based on their state. Possible values are: open,
// closed, all. Default is "open".
State string `url:"state,omitempty"`
// Assignee filters issues based on their assignee. Possible values are a
// user name, "none" for issues that are not assigned, "*" for issues with
// any assigned user.
Assignee string `url:"assignee,omitempty"`
// Creator filters issues based on their creator.
Creator string `url:"creator,omitempty"`
// Mentioned filters issues to those mentioned a specific user.
Mentioned string `url:"mentioned,omitempty"`
// Labels filters issues based on their label.
Labels []string `url:"labels,omitempty,comma"`
// Sort specifies how to sort issues. Possible values are: created, updated,
// and comments. Default value is "created".
Sort string `url:"sort,omitempty"`
// Direction in which to sort issues. Possible values are: asc, desc.
// Default is "desc".
Direction string `url:"direction,omitempty"`
// Since filters issues by time.
Since time.Time `url:"since,omitempty"`
ListOptions
}
// ListByRepo lists the issues for the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/#list-issues-for-a-repository
func (s *IssuesService) ListByRepo(ctx context.Context, owner string, repo string, opts *IssueListByRepoOptions) ([]*Issue, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeIntegrationPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var issues []*Issue
resp, err := s.client.Do(ctx, req, &issues)
if err != nil {
return nil, resp, err
}
return issues, resp, nil
}
// Get a single issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/#get-a-single-issue
func (s *IssuesService) Get(ctx context.Context, owner string, repo string, number int) (*Issue, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
issue := new(Issue)
resp, err := s.client.Do(ctx, req, issue)
if err != nil {
return nil, resp, err
}
return issue, resp, nil
}
// Create a new issue on the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/#create-an-issue
func (s *IssuesService) Create(ctx context.Context, owner string, repo string, issue *IssueRequest) (*Issue, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues", owner, repo)
req, err := s.client.NewRequest("POST", u, issue)
if err != nil {
return nil, nil, err
}
i := new(Issue)
resp, err := s.client.Do(ctx, req, i)
if err != nil {
return nil, resp, err
}
return i, resp, nil
}
// Edit an issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/#edit-an-issue
func (s *IssuesService) Edit(ctx context.Context, owner string, repo string, number int, issue *IssueRequest) (*Issue, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d", owner, repo, number)
req, err := s.client.NewRequest("PATCH", u, issue)
if err != nil {
return nil, nil, err
}
i := new(Issue)
resp, err := s.client.Do(ctx, req, i)
if err != nil {
return nil, resp, err
}
return i, resp, nil
}
// LockIssueOptions specifies the optional parameters to the
// IssuesService.Lock method.
type LockIssueOptions struct {
// LockReason specifies the reason to lock this issue.
// Providing a lock reason can help make it clearer to contributors why an issue
// was locked. Possible values are: "off-topic", "too heated", "resolved", and "spam".
LockReason string `json:"lock_reason,omitempty"`
}
// Lock an issue's conversation.
//
// GitHub API docs: https://developer.github.com/v3/issues/#lock-an-issue
func (s *IssuesService) Lock(ctx context.Context, owner string, repo string, number int, opts *LockIssueOptions) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, err
}
if opts != nil {
req.Header.Set("Accept", mediaTypeLockReasonPreview)
}
return s.client.Do(ctx, req, nil)
}
// Unlock an issue's conversation.
//
// GitHub API docs: https://developer.github.com/v3/issues/#unlock-an-issue
func (s *IssuesService) Unlock(ctx context.Context, owner string, repo string, number int) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/lock", owner, repo, number)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,85 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ListAssignees fetches all available assignees (owners and collaborators) to
// which issues may be assigned.
//
// GitHub API docs: https://developer.github.com/v3/issues/assignees/#list-assignees
func (s *IssuesService) ListAssignees(ctx context.Context, owner, repo string, opts *ListOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/assignees", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var assignees []*User
resp, err := s.client.Do(ctx, req, &assignees)
if err != nil {
return nil, resp, err
}
return assignees, resp, nil
}
// IsAssignee checks if a user is an assignee for the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/assignees/#check-assignee
func (s *IssuesService) IsAssignee(ctx context.Context, owner, repo, user string) (bool, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/assignees/%v", owner, repo, user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
resp, err := s.client.Do(ctx, req, nil)
assignee, err := parseBoolResponse(err)
return assignee, resp, err
}
// AddAssignees adds the provided GitHub users as assignees to the issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/assignees/#add-assignees-to-an-issue
func (s *IssuesService) AddAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) {
users := &struct {
Assignees []string `json:"assignees,omitempty"`
}{Assignees: assignees}
u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number)
req, err := s.client.NewRequest("POST", u, users)
if err != nil {
return nil, nil, err
}
issue := &Issue{}
resp, err := s.client.Do(ctx, req, issue)
return issue, resp, err
}
// RemoveAssignees removes the provided GitHub users as assignees from the issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/assignees/#remove-assignees-from-an-issue
func (s *IssuesService) RemoveAssignees(ctx context.Context, owner, repo string, number int, assignees []string) (*Issue, *Response, error) {
users := &struct {
Assignees []string `json:"assignees,omitempty"`
}{Assignees: assignees}
u := fmt.Sprintf("repos/%v/%v/issues/%v/assignees", owner, repo, number)
req, err := s.client.NewRequest("DELETE", u, users)
if err != nil {
return nil, nil, err
}
issue := &Issue{}
resp, err := s.client.Do(ctx, req, issue)
return issue, resp, err
}

View file

@ -0,0 +1,153 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// IssueComment represents a comment left on an issue.
type IssueComment struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Body *string `json:"body,omitempty"`
User *User `json:"user,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
// AuthorAssociation is the comment author's relationship to the issue's repository.
// Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE".
AuthorAssociation *string `json:"author_association,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
IssueURL *string `json:"issue_url,omitempty"`
}
func (i IssueComment) String() string {
return Stringify(i)
}
// IssueListCommentsOptions specifies the optional parameters to the
// IssuesService.ListComments method.
type IssueListCommentsOptions struct {
// Sort specifies how to sort comments. Possible values are: created, updated.
Sort *string `url:"sort,omitempty"`
// Direction in which to sort comments. Possible values are: asc, desc.
Direction *string `url:"direction,omitempty"`
// Since filters comments by time.
Since *time.Time `url:"since,omitempty"`
ListOptions
}
// ListComments lists all comments on the specified issue. Specifying an issue
// number of 0 will return all comments on all issues for the repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/comments/#list-comments-on-an-issue
func (s *IssuesService) ListComments(ctx context.Context, owner string, repo string, number int, opts *IssueListCommentsOptions) ([]*IssueComment, *Response, error) {
var u string
if number == 0 {
u = fmt.Sprintf("repos/%v/%v/issues/comments", owner, repo)
} else {
u = fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number)
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeReactionsPreview)
var comments []*IssueComment
resp, err := s.client.Do(ctx, req, &comments)
if err != nil {
return nil, resp, err
}
return comments, resp, nil
}
// GetComment fetches the specified issue comment.
//
// GitHub API docs: https://developer.github.com/v3/issues/comments/#get-a-single-comment
func (s *IssuesService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*IssueComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeReactionsPreview)
comment := new(IssueComment)
resp, err := s.client.Do(ctx, req, comment)
if err != nil {
return nil, resp, err
}
return comment, resp, nil
}
// CreateComment creates a new comment on the specified issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/comments/#create-a-comment
func (s *IssuesService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *IssueComment) (*IssueComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/comments", owner, repo, number)
req, err := s.client.NewRequest("POST", u, comment)
if err != nil {
return nil, nil, err
}
c := new(IssueComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// EditComment updates an issue comment.
// A non-nil comment.Body must be provided. Other comment fields should be left nil.
//
// GitHub API docs: https://developer.github.com/v3/issues/comments/#edit-a-comment
func (s *IssuesService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *IssueComment) (*IssueComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("PATCH", u, comment)
if err != nil {
return nil, nil, err
}
c := new(IssueComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// DeleteComment deletes an issue comment.
//
// GitHub API docs: https://developer.github.com/v3/issues/comments/#delete-a-comment
func (s *IssuesService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,175 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"strings"
"time"
)
// IssueEvent represents an event that occurred around an Issue or Pull Request.
type IssueEvent struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
// The User that generated this event.
Actor *User `json:"actor,omitempty"`
// Event identifies the actual type of Event that occurred. Possible
// values are:
//
// closed
// The Actor closed the issue.
// If the issue was closed by commit message, CommitID holds the SHA1 hash of the commit.
//
// merged
// The Actor merged into master a branch containing a commit mentioning the issue.
// CommitID holds the SHA1 of the merge commit.
//
// referenced
// The Actor committed to master a commit mentioning the issue in its commit message.
// CommitID holds the SHA1 of the commit.
//
// reopened, unlocked
// The Actor did that to the issue.
//
// locked
// The Actor locked the issue.
// LockReason holds the reason of locking the issue (if provided while locking).
//
// renamed
// The Actor changed the issue title from Rename.From to Rename.To.
//
// mentioned
// Someone unspecified @mentioned the Actor [sic] in an issue comment body.
//
// assigned, unassigned
// The Assigner assigned the issue to or removed the assignment from the Assignee.
//
// labeled, unlabeled
// The Actor added or removed the Label from the issue.
//
// milestoned, demilestoned
// The Actor added or removed the issue from the Milestone.
//
// subscribed, unsubscribed
// The Actor subscribed to or unsubscribed from notifications for an issue.
//
// head_ref_deleted, head_ref_restored
// The pull requests branch was deleted or restored.
//
// review_dismissed
// The review was dismissed and `DismissedReview` will be populated below.
//
Event *string `json:"event,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
Issue *Issue `json:"issue,omitempty"`
// Only present on certain events; see above.
Assignee *User `json:"assignee,omitempty"`
Assigner *User `json:"assigner,omitempty"`
CommitID *string `json:"commit_id,omitempty"`
Milestone *Milestone `json:"milestone,omitempty"`
Label *Label `json:"label,omitempty"`
Rename *Rename `json:"rename,omitempty"`
LockReason *string `json:"lock_reason,omitempty"`
ProjectCard *ProjectCard `json:"project_card,omitempty"`
DismissedReview *DismissedReview `json:"dismissed_review,omitempty"`
}
// DismissedReview represents details for 'dismissed_review' events.
type DismissedReview struct {
// State represents the state of the dismissed review.
// Possible values are: "commented", "approved", and "changes_requested".
State *string `json:"state,omitempty"`
ReviewID *int64 `json:"review_id,omitempty"`
DismissalMessage *string `json:"dismissal_message,omitempty"`
DismissalCommitID *string `json:"dismissal_commit_id,omitempty"`
}
// ListIssueEvents lists events for the specified issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-an-issue
func (s *IssuesService) ListIssueEvents(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*IssueEvent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%v/events", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
acceptHeaders := []string{mediaTypeLockReasonPreview, mediaTypeProjectCardDetailsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var events []*IssueEvent
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}
// ListRepositoryEvents lists events for the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/events/#list-events-for-a-repository
func (s *IssuesService) ListRepositoryEvents(ctx context.Context, owner, repo string, opts *ListOptions) ([]*IssueEvent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/events", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var events []*IssueEvent
resp, err := s.client.Do(ctx, req, &events)
if err != nil {
return nil, resp, err
}
return events, resp, nil
}
// GetEvent returns the specified issue event.
//
// GitHub API docs: https://developer.github.com/v3/issues/events/#get-a-single-event
func (s *IssuesService) GetEvent(ctx context.Context, owner, repo string, id int64) (*IssueEvent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/events/%v", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
event := new(IssueEvent)
resp, err := s.client.Do(ctx, req, event)
if err != nil {
return nil, resp, err
}
return event, resp, nil
}
// Rename contains details for 'renamed' events.
type Rename struct {
From *string `json:"from,omitempty"`
To *string `json:"to,omitempty"`
}
func (r Rename) String() string {
return Stringify(r)
}

View file

@ -0,0 +1,231 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// Label represents a GitHub label on an Issue
type Label struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
Name *string `json:"name,omitempty"`
Color *string `json:"color,omitempty"`
Description *string `json:"description,omitempty"`
Default *bool `json:"default,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
func (l Label) String() string {
return Stringify(l)
}
// ListLabels lists all labels for a repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-all-labels-for-this-repository
func (s *IssuesService) ListLabels(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/labels", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var labels []*Label
resp, err := s.client.Do(ctx, req, &labels)
if err != nil {
return nil, resp, err
}
return labels, resp, nil
}
// GetLabel gets a single label.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-a-single-label
func (s *IssuesService) GetLabel(ctx context.Context, owner string, repo string, name string) (*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
label := new(Label)
resp, err := s.client.Do(ctx, req, label)
if err != nil {
return nil, resp, err
}
return label, resp, nil
}
// CreateLabel creates a new label on the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#create-a-label
func (s *IssuesService) CreateLabel(ctx context.Context, owner string, repo string, label *Label) (*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/labels", owner, repo)
req, err := s.client.NewRequest("POST", u, label)
if err != nil {
return nil, nil, err
}
l := new(Label)
resp, err := s.client.Do(ctx, req, l)
if err != nil {
return nil, resp, err
}
return l, resp, nil
}
// EditLabel edits a label.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#update-a-label
func (s *IssuesService) EditLabel(ctx context.Context, owner string, repo string, name string, label *Label) (*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name)
req, err := s.client.NewRequest("PATCH", u, label)
if err != nil {
return nil, nil, err
}
l := new(Label)
resp, err := s.client.Do(ctx, req, l)
if err != nil {
return nil, resp, err
}
return l, resp, nil
}
// DeleteLabel deletes a label.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#delete-a-label
func (s *IssuesService) DeleteLabel(ctx context.Context, owner string, repo string, name string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/labels/%v", owner, repo, name)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListLabelsByIssue lists all labels for an issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#list-labels-on-an-issue
func (s *IssuesService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var labels []*Label
resp, err := s.client.Do(ctx, req, &labels)
if err != nil {
return nil, resp, err
}
return labels, resp, nil
}
// AddLabelsToIssue adds labels to an issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#add-labels-to-an-issue
func (s *IssuesService) AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
req, err := s.client.NewRequest("POST", u, labels)
if err != nil {
return nil, nil, err
}
var l []*Label
resp, err := s.client.Do(ctx, req, &l)
if err != nil {
return nil, resp, err
}
return l, resp, nil
}
// RemoveLabelForIssue removes a label for an issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-a-label-from-an-issue
func (s *IssuesService) RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/labels/%v", owner, repo, number, label)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ReplaceLabelsForIssue replaces all labels for an issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#replace-all-labels-for-an-issue
func (s *IssuesService) ReplaceLabelsForIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
req, err := s.client.NewRequest("PUT", u, labels)
if err != nil {
return nil, nil, err
}
var l []*Label
resp, err := s.client.Do(ctx, req, &l)
if err != nil {
return nil, resp, err
}
return l, resp, nil
}
// RemoveLabelsForIssue removes all labels for an issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#remove-all-labels-from-an-issue
func (s *IssuesService) RemoveLabelsForIssue(ctx context.Context, owner string, repo string, number int) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%d/labels", owner, repo, number)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListLabelsForMilestone lists labels for every issue in a milestone.
//
// GitHub API docs: https://developer.github.com/v3/issues/labels/#get-labels-for-every-issue-in-a-milestone
func (s *IssuesService) ListLabelsForMilestone(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*Label, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones/%d/labels", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var labels []*Label
resp, err := s.client.Do(ctx, req, &labels)
if err != nil {
return nil, resp, err
}
return labels, resp, nil
}

View file

@ -0,0 +1,148 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// Milestone represents a GitHub repository milestone.
type Milestone struct {
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
LabelsURL *string `json:"labels_url,omitempty"`
ID *int64 `json:"id,omitempty"`
Number *int `json:"number,omitempty"`
State *string `json:"state,omitempty"`
Title *string `json:"title,omitempty"`
Description *string `json:"description,omitempty"`
Creator *User `json:"creator,omitempty"`
OpenIssues *int `json:"open_issues,omitempty"`
ClosedIssues *int `json:"closed_issues,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
ClosedAt *time.Time `json:"closed_at,omitempty"`
DueOn *time.Time `json:"due_on,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
func (m Milestone) String() string {
return Stringify(m)
}
// MilestoneListOptions specifies the optional parameters to the
// IssuesService.ListMilestones method.
type MilestoneListOptions struct {
// State filters milestones based on their state. Possible values are:
// open, closed, all. Default is "open".
State string `url:"state,omitempty"`
// Sort specifies how to sort milestones. Possible values are: due_on, completeness.
// Default value is "due_on".
Sort string `url:"sort,omitempty"`
// Direction in which to sort milestones. Possible values are: asc, desc.
// Default is "asc".
Direction string `url:"direction,omitempty"`
ListOptions
}
// ListMilestones lists all milestones for a repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository
func (s *IssuesService) ListMilestones(ctx context.Context, owner string, repo string, opts *MilestoneListOptions) ([]*Milestone, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var milestones []*Milestone
resp, err := s.client.Do(ctx, req, &milestones)
if err != nil {
return nil, resp, err
}
return milestones, resp, nil
}
// GetMilestone gets a single milestone.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#get-a-single-milestone
func (s *IssuesService) GetMilestone(ctx context.Context, owner string, repo string, number int) (*Milestone, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
milestone := new(Milestone)
resp, err := s.client.Do(ctx, req, milestone)
if err != nil {
return nil, resp, err
}
return milestone, resp, nil
}
// CreateMilestone creates a new milestone on the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#create-a-milestone
func (s *IssuesService) CreateMilestone(ctx context.Context, owner string, repo string, milestone *Milestone) (*Milestone, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones", owner, repo)
req, err := s.client.NewRequest("POST", u, milestone)
if err != nil {
return nil, nil, err
}
m := new(Milestone)
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// EditMilestone edits a milestone.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#update-a-milestone
func (s *IssuesService) EditMilestone(ctx context.Context, owner string, repo string, number int, milestone *Milestone) (*Milestone, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number)
req, err := s.client.NewRequest("PATCH", u, milestone)
if err != nil {
return nil, nil, err
}
m := new(Milestone)
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// DeleteMilestone deletes a milestone.
//
// GitHub API docs: https://developer.github.com/v3/issues/milestones/#delete-a-milestone
func (s *IssuesService) DeleteMilestone(ctx context.Context, owner string, repo string, number int) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/milestones/%d", owner, repo, number)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,154 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"strings"
"time"
)
// Timeline represents an event that occurred around an Issue or Pull Request.
//
// It is similar to an IssueEvent but may contain more information.
// GitHub API docs: https://developer.github.com/v3/issues/timeline/
type Timeline struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
CommitURL *string `json:"commit_url,omitempty"`
// The User object that generated the event.
Actor *User `json:"actor,omitempty"`
// Event identifies the actual type of Event that occurred. Possible values
// are:
//
// assigned
// The issue was assigned to the assignee.
//
// closed
// The issue was closed by the actor. When the commit_id is present, it
// identifies the commit that closed the issue using "closes / fixes #NN"
// syntax.
//
// commented
// A comment was added to the issue.
//
// committed
// A commit was added to the pull request's 'HEAD' branch. Only provided
// for pull requests.
//
// cross-referenced
// The issue was referenced from another issue. The 'source' attribute
// contains the 'id', 'actor', and 'url' of the reference's source.
//
// demilestoned
// The issue was removed from a milestone.
//
// head_ref_deleted
// The pull request's branch was deleted.
//
// head_ref_restored
// The pull request's branch was restored.
//
// labeled
// A label was added to the issue.
//
// locked
// The issue was locked by the actor.
//
// mentioned
// The actor was @mentioned in an issue body.
//
// merged
// The issue was merged by the actor. The 'commit_id' attribute is the
// SHA1 of the HEAD commit that was merged.
//
// milestoned
// The issue was added to a milestone.
//
// referenced
// The issue was referenced from a commit message. The 'commit_id'
// attribute is the commit SHA1 of where that happened.
//
// renamed
// The issue title was changed.
//
// reopened
// The issue was reopened by the actor.
//
// subscribed
// The actor subscribed to receive notifications for an issue.
//
// unassigned
// The assignee was unassigned from the issue.
//
// unlabeled
// A label was removed from the issue.
//
// unlocked
// The issue was unlocked by the actor.
//
// unsubscribed
// The actor unsubscribed to stop receiving notifications for an issue.
//
Event *string `json:"event,omitempty"`
// The string SHA of a commit that referenced this Issue or Pull Request.
CommitID *string `json:"commit_id,omitempty"`
// The timestamp indicating when the event occurred.
CreatedAt *time.Time `json:"created_at,omitempty"`
// The Label object including `name` and `color` attributes. Only provided for
// 'labeled' and 'unlabeled' events.
Label *Label `json:"label,omitempty"`
// The User object which was assigned to (or unassigned from) this Issue or
// Pull Request. Only provided for 'assigned' and 'unassigned' events.
Assignee *User `json:"assignee,omitempty"`
// The Milestone object including a 'title' attribute.
// Only provided for 'milestoned' and 'demilestoned' events.
Milestone *Milestone `json:"milestone,omitempty"`
// The 'id', 'actor', and 'url' for the source of a reference from another issue.
// Only provided for 'cross-referenced' events.
Source *Source `json:"source,omitempty"`
// An object containing rename details including 'from' and 'to' attributes.
// Only provided for 'renamed' events.
Rename *Rename `json:"rename,omitempty"`
ProjectCard *ProjectCard `json:"project_card,omitempty"`
}
// Source represents a reference's source.
type Source struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
Actor *User `json:"actor,omitempty"`
Type *string `json:"type,omitempty"`
Issue *Issue `json:"issue,omitempty"`
}
// ListIssueTimeline lists events for the specified issue.
//
// GitHub API docs: https://developer.github.com/v3/issues/timeline/#list-events-for-an-issue
func (s *IssuesService) ListIssueTimeline(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Timeline, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%v/timeline", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeTimelinePreview, mediaTypeProjectCardDetailsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var events []*Timeline
resp, err := s.client.Do(ctx, req, &events)
return events, resp, err
}

View file

@ -0,0 +1,97 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// LicensesService handles communication with the license related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/licenses/
type LicensesService service
// RepositoryLicense represents the license for a repository.
type RepositoryLicense struct {
Name *string `json:"name,omitempty"`
Path *string `json:"path,omitempty"`
SHA *string `json:"sha,omitempty"`
Size *int `json:"size,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
GitURL *string `json:"git_url,omitempty"`
DownloadURL *string `json:"download_url,omitempty"`
Type *string `json:"type,omitempty"`
Content *string `json:"content,omitempty"`
Encoding *string `json:"encoding,omitempty"`
License *License `json:"license,omitempty"`
}
func (l RepositoryLicense) String() string {
return Stringify(l)
}
// License represents an open source license.
type License struct {
Key *string `json:"key,omitempty"`
Name *string `json:"name,omitempty"`
URL *string `json:"url,omitempty"`
SPDXID *string `json:"spdx_id,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
Featured *bool `json:"featured,omitempty"`
Description *string `json:"description,omitempty"`
Implementation *string `json:"implementation,omitempty"`
Permissions *[]string `json:"permissions,omitempty"`
Conditions *[]string `json:"conditions,omitempty"`
Limitations *[]string `json:"limitations,omitempty"`
Body *string `json:"body,omitempty"`
}
func (l License) String() string {
return Stringify(l)
}
// List popular open source licenses.
//
// GitHub API docs: https://developer.github.com/v3/licenses/#list-all-licenses
func (s *LicensesService) List(ctx context.Context) ([]*License, *Response, error) {
req, err := s.client.NewRequest("GET", "licenses", nil)
if err != nil {
return nil, nil, err
}
var licenses []*License
resp, err := s.client.Do(ctx, req, &licenses)
if err != nil {
return nil, resp, err
}
return licenses, resp, nil
}
// Get extended metadata for one license.
//
// GitHub API docs: https://developer.github.com/v3/licenses/#get-an-individual-license
func (s *LicensesService) Get(ctx context.Context, licenseName string) (*License, *Response, error) {
u := fmt.Sprintf("licenses/%s", licenseName)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
license := new(License)
resp, err := s.client.Do(ctx, req, license)
if err != nil {
return nil, resp, err
}
return license, resp, nil
}

View file

@ -0,0 +1,260 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file provides functions for validating payloads from GitHub Webhooks.
// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github
package github
import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"hash"
"io/ioutil"
"net/http"
"net/url"
"strings"
)
const (
// sha1Prefix is the prefix used by GitHub before the HMAC hexdigest.
sha1Prefix = "sha1"
// sha256Prefix and sha512Prefix are provided for future compatibility.
sha256Prefix = "sha256"
sha512Prefix = "sha512"
// signatureHeader is the GitHub header key used to pass the HMAC hexdigest.
signatureHeader = "X-Hub-Signature"
// eventTypeHeader is the GitHub header key used to pass the event type.
eventTypeHeader = "X-Github-Event"
// deliveryIDHeader is the GitHub header key used to pass the unique ID for the webhook event.
deliveryIDHeader = "X-Github-Delivery"
)
var (
// eventTypeMapping maps webhooks types to their corresponding go-github struct types.
eventTypeMapping = map[string]string{
"check_run": "CheckRunEvent",
"check_suite": "CheckSuiteEvent",
"commit_comment": "CommitCommentEvent",
"create": "CreateEvent",
"delete": "DeleteEvent",
"deploy_key": "DeployKeyEvent",
"deployment": "DeploymentEvent",
"deployment_status": "DeploymentStatusEvent",
"fork": "ForkEvent",
"gollum": "GollumEvent",
"installation": "InstallationEvent",
"installation_repositories": "InstallationRepositoriesEvent",
"issue_comment": "IssueCommentEvent",
"issues": "IssuesEvent",
"label": "LabelEvent",
"marketplace_purchase": "MarketplacePurchaseEvent",
"member": "MemberEvent",
"membership": "MembershipEvent",
"meta": "MetaEvent",
"milestone": "MilestoneEvent",
"organization": "OrganizationEvent",
"org_block": "OrgBlockEvent",
"page_build": "PageBuildEvent",
"ping": "PingEvent",
"project": "ProjectEvent",
"project_card": "ProjectCardEvent",
"project_column": "ProjectColumnEvent",
"public": "PublicEvent",
"pull_request_review": "PullRequestReviewEvent",
"pull_request_review_comment": "PullRequestReviewCommentEvent",
"pull_request": "PullRequestEvent",
"push": "PushEvent",
"repository": "RepositoryEvent",
"repository_dispatch": "RepositoryDispatchEvent",
"repository_vulnerability_alert": "RepositoryVulnerabilityAlertEvent",
"release": "ReleaseEvent",
"star": "StarEvent",
"status": "StatusEvent",
"team": "TeamEvent",
"team_add": "TeamAddEvent",
"user": "UserEvent",
"watch": "WatchEvent",
}
)
// genMAC generates the HMAC signature for a message provided the secret key
// and hashFunc.
func genMAC(message, key []byte, hashFunc func() hash.Hash) []byte {
mac := hmac.New(hashFunc, key)
mac.Write(message)
return mac.Sum(nil)
}
// checkMAC reports whether messageMAC is a valid HMAC tag for message.
func checkMAC(message, messageMAC, key []byte, hashFunc func() hash.Hash) bool {
expectedMAC := genMAC(message, key, hashFunc)
return hmac.Equal(messageMAC, expectedMAC)
}
// messageMAC returns the hex-decoded HMAC tag from the signature and its
// corresponding hash function.
func messageMAC(signature string) ([]byte, func() hash.Hash, error) {
if signature == "" {
return nil, nil, errors.New("missing signature")
}
sigParts := strings.SplitN(signature, "=", 2)
if len(sigParts) != 2 {
return nil, nil, fmt.Errorf("error parsing signature %q", signature)
}
var hashFunc func() hash.Hash
switch sigParts[0] {
case sha1Prefix:
hashFunc = sha1.New
case sha256Prefix:
hashFunc = sha256.New
case sha512Prefix:
hashFunc = sha512.New
default:
return nil, nil, fmt.Errorf("unknown hash type prefix: %q", sigParts[0])
}
buf, err := hex.DecodeString(sigParts[1])
if err != nil {
return nil, nil, fmt.Errorf("error decoding signature %q: %v", signature, err)
}
return buf, hashFunc, nil
}
// ValidatePayload validates an incoming GitHub Webhook event request
// and returns the (JSON) payload.
// The Content-Type header of the payload can be "application/json" or "application/x-www-form-urlencoded".
// If the Content-Type is neither then an error is returned.
// secretToken is the GitHub Webhook secret token.
// If your webhook does not contain a secret token, you can pass nil or an empty slice.
// This is intended for local development purposes only and all webhooks should ideally set up a secret token.
//
// Example usage:
//
// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// payload, err := github.ValidatePayload(r, s.webhookSecretKey)
// if err != nil { ... }
// // Process payload...
// }
//
func ValidatePayload(r *http.Request, secretToken []byte) (payload []byte, err error) {
var body []byte // Raw body that GitHub uses to calculate the signature.
switch ct := r.Header.Get("Content-Type"); ct {
case "application/json":
var err error
if body, err = ioutil.ReadAll(r.Body); err != nil {
return nil, err
}
// If the content type is application/json,
// the JSON payload is just the original body.
payload = body
case "application/x-www-form-urlencoded":
// payloadFormParam is the name of the form parameter that the JSON payload
// will be in if a webhook has its content type set to application/x-www-form-urlencoded.
const payloadFormParam = "payload"
var err error
if body, err = ioutil.ReadAll(r.Body); err != nil {
return nil, err
}
// If the content type is application/x-www-form-urlencoded,
// the JSON payload will be under the "payload" form param.
form, err := url.ParseQuery(string(body))
if err != nil {
return nil, err
}
payload = []byte(form.Get(payloadFormParam))
default:
return nil, fmt.Errorf("Webhook request has unsupported Content-Type %q", ct)
}
// Only validate the signature if a secret token exists. This is intended for
// local development only and all webhooks should ideally set up a secret token.
if len(secretToken) > 0 {
sig := r.Header.Get(signatureHeader)
if err := ValidateSignature(sig, body, secretToken); err != nil {
return nil, err
}
}
return payload, nil
}
// ValidateSignature validates the signature for the given payload.
// signature is the GitHub hash signature delivered in the X-Hub-Signature header.
// payload is the JSON payload sent by GitHub Webhooks.
// secretToken is the GitHub Webhook secret token.
//
// GitHub API docs: https://developer.github.com/webhooks/securing/#validating-payloads-from-github
func ValidateSignature(signature string, payload, secretToken []byte) error {
messageMAC, hashFunc, err := messageMAC(signature)
if err != nil {
return err
}
if !checkMAC(payload, messageMAC, secretToken, hashFunc) {
return errors.New("payload signature check failed")
}
return nil
}
// WebHookType returns the event type of webhook request r.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers
func WebHookType(r *http.Request) string {
return r.Header.Get(eventTypeHeader)
}
// DeliveryID returns the unique delivery ID of webhook request r.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#webhook-headers
func DeliveryID(r *http.Request) string {
return r.Header.Get(deliveryIDHeader)
}
// ParseWebHook parses the event payload. For recognized event types, a
// value of the corresponding struct type will be returned (as returned
// by Event.ParsePayload()). An error will be returned for unrecognized event
// types.
//
// Example usage:
//
// func (s *GitHubEventMonitor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// payload, err := github.ValidatePayload(r, s.webhookSecretKey)
// if err != nil { ... }
// event, err := github.ParseWebHook(github.WebHookType(r), payload)
// if err != nil { ... }
// switch event := event.(type) {
// case *github.CommitCommentEvent:
// processCommitCommentEvent(event)
// case *github.CreateEvent:
// processCreateEvent(event)
// ...
// }
// }
//
func ParseWebHook(messageType string, payload []byte) (interface{}, error) {
eventType, ok := eventTypeMapping[messageType]
if !ok {
return nil, fmt.Errorf("unknown X-Github-Event in message: %v", messageType)
}
event := Event{
Type: &eventType,
RawPayload: (*json.RawMessage)(&payload),
}
return event.ParsePayload()
}

View file

@ -0,0 +1,228 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"errors"
"fmt"
"net/http"
"strings"
)
// MigrationService provides access to the migration related functions
// in the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/migration/
type MigrationService service
// Migration represents a GitHub migration (archival).
type Migration struct {
ID *int64 `json:"id,omitempty"`
GUID *string `json:"guid,omitempty"`
// State is the current state of a migration.
// Possible values are:
// "pending" which means the migration hasn't started yet,
// "exporting" which means the migration is in progress,
// "exported" which means the migration finished successfully, or
// "failed" which means the migration failed.
State *string `json:"state,omitempty"`
// LockRepositories indicates whether repositories are locked (to prevent
// manipulation) while migrating data.
LockRepositories *bool `json:"lock_repositories,omitempty"`
// ExcludeAttachments indicates whether attachments should be excluded from
// the migration (to reduce migration archive file size).
ExcludeAttachments *bool `json:"exclude_attachments,omitempty"`
URL *string `json:"url,omitempty"`
CreatedAt *string `json:"created_at,omitempty"`
UpdatedAt *string `json:"updated_at,omitempty"`
Repositories []*Repository `json:"repositories,omitempty"`
}
func (m Migration) String() string {
return Stringify(m)
}
// MigrationOptions specifies the optional parameters to Migration methods.
type MigrationOptions struct {
// LockRepositories indicates whether repositories should be locked (to prevent
// manipulation) while migrating data.
LockRepositories bool
// ExcludeAttachments indicates whether attachments should be excluded from
// the migration (to reduce migration archive file size).
ExcludeAttachments bool
}
// startMigration represents the body of a StartMigration request.
type startMigration struct {
// Repositories is a slice of repository names to migrate.
Repositories []string `json:"repositories,omitempty"`
// LockRepositories indicates whether repositories should be locked (to prevent
// manipulation) while migrating data.
LockRepositories *bool `json:"lock_repositories,omitempty"`
// ExcludeAttachments indicates whether attachments should be excluded from
// the migration (to reduce migration archive file size).
ExcludeAttachments *bool `json:"exclude_attachments,omitempty"`
}
// StartMigration starts the generation of a migration archive.
// repos is a slice of repository names to migrate.
//
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#start-a-migration
func (s *MigrationService) StartMigration(ctx context.Context, org string, repos []string, opts *MigrationOptions) (*Migration, *Response, error) {
u := fmt.Sprintf("orgs/%v/migrations", org)
body := &startMigration{Repositories: repos}
if opts != nil {
body.LockRepositories = Bool(opts.LockRepositories)
body.ExcludeAttachments = Bool(opts.ExcludeAttachments)
}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
m := &Migration{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListMigrations lists the most recent migrations.
//
// GitHub API docs: https://developer.github.com/v3/migrations/orgs/#get-a-list-of-organization-migrations
func (s *MigrationService) ListMigrations(ctx context.Context, org string, opts *ListOptions) ([]*Migration, *Response, error) {
u := fmt.Sprintf("orgs/%v/migrations", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
var m []*Migration
resp, err := s.client.Do(ctx, req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// MigrationStatus gets the status of a specific migration archive.
// id is the migration ID.
//
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#get-the-status-of-a-migration
func (s *MigrationService) MigrationStatus(ctx context.Context, org string, id int64) (*Migration, *Response, error) {
u := fmt.Sprintf("orgs/%v/migrations/%v", org, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
m := &Migration{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// MigrationArchiveURL fetches a migration archive URL.
// id is the migration ID.
//
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#download-a-migration-archive
func (s *MigrationService) MigrationArchiveURL(ctx context.Context, org string, id int64) (url string, err error) {
u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return "", err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
s.client.clientMu.Lock()
defer s.client.clientMu.Unlock()
// Disable the redirect mechanism because AWS fails if the GitHub auth token is provided.
var loc string
saveRedirect := s.client.client.CheckRedirect
s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
loc = req.URL.String()
return errors.New("disable redirect")
}
defer func() { s.client.client.CheckRedirect = saveRedirect }()
_, err = s.client.Do(ctx, req, nil) // expect error from disable redirect
if err == nil {
return "", errors.New("expected redirect, none provided")
}
if !strings.Contains(err.Error(), "disable redirect") {
return "", err
}
return loc, nil
}
// DeleteMigration deletes a previous migration archive.
// id is the migration ID.
//
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#delete-a-migration-archive
func (s *MigrationService) DeleteMigration(ctx context.Context, org string, id int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/migrations/%v/archive", org, id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
return s.client.Do(ctx, req, nil)
}
// UnlockRepo unlocks a repository that was locked for migration.
// id is the migration ID.
// You should unlock each migrated repository and delete them when the migration
// is complete and you no longer need the source data.
//
// GitHub API docs: https://developer.github.com/v3/migration/migrations/#unlock-a-repository
func (s *MigrationService) UnlockRepo(ctx context.Context, org string, id int64, repo string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/migrations/%v/repos/%v/lock", org, id, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,305 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// Import represents a repository import request.
type Import struct {
// The URL of the originating repository.
VCSURL *string `json:"vcs_url,omitempty"`
// The originating VCS type. Can be one of 'subversion', 'git',
// 'mercurial', or 'tfvc'. Without this parameter, the import job will
// take additional time to detect the VCS type before beginning the
// import. This detection step will be reflected in the response.
VCS *string `json:"vcs,omitempty"`
// VCSUsername and VCSPassword are only used for StartImport calls that
// are importing a password-protected repository.
VCSUsername *string `json:"vcs_username,omitempty"`
VCSPassword *string `json:"vcs_password,omitempty"`
// For a tfvc import, the name of the project that is being imported.
TFVCProject *string `json:"tfvc_project,omitempty"`
// LFS related fields that may be preset in the Import Progress response
// Describes whether the import has been opted in or out of using Git
// LFS. The value can be 'opt_in', 'opt_out', or 'undecided' if no
// action has been taken.
UseLFS *string `json:"use_lfs,omitempty"`
// Describes whether files larger than 100MB were found during the
// importing step.
HasLargeFiles *bool `json:"has_large_files,omitempty"`
// The total size in gigabytes of files larger than 100MB found in the
// originating repository.
LargeFilesSize *int `json:"large_files_size,omitempty"`
// The total number of files larger than 100MB found in the originating
// repository. To see a list of these files, call LargeFiles.
LargeFilesCount *int `json:"large_files_count,omitempty"`
// Identifies the current status of an import. An import that does not
// have errors will progress through these steps:
//
// detecting - the "detection" step of the import is in progress
// because the request did not include a VCS parameter. The
// import is identifying the type of source control present at
// the URL.
// importing - the "raw" step of the import is in progress. This is
// where commit data is fetched from the original repository.
// The import progress response will include CommitCount (the
// total number of raw commits that will be imported) and
// Percent (0 - 100, the current progress through the import).
// mapping - the "rewrite" step of the import is in progress. This
// is where SVN branches are converted to Git branches, and
// where author updates are applied. The import progress
// response does not include progress information.
// pushing - the "push" step of the import is in progress. This is
// where the importer updates the repository on GitHub. The
// import progress response will include PushPercent, which is
// the percent value reported by git push when it is "Writing
// objects".
// complete - the import is complete, and the repository is ready
// on GitHub.
//
// If there are problems, you will see one of these in the status field:
//
// auth_failed - the import requires authentication in order to
// connect to the original repository. Make an UpdateImport
// request, and include VCSUsername and VCSPassword.
// error - the import encountered an error. The import progress
// response will include the FailedStep and an error message.
// Contact GitHub support for more information.
// detection_needs_auth - the importer requires authentication for
// the originating repository to continue detection. Make an
// UpdatImport request, and include VCSUsername and
// VCSPassword.
// detection_found_nothing - the importer didn't recognize any
// source control at the URL.
// detection_found_multiple - the importer found several projects
// or repositories at the provided URL. When this is the case,
// the Import Progress response will also include a
// ProjectChoices field with the possible project choices as
// values. Make an UpdateImport request, and include VCS and
// (if applicable) TFVCProject.
Status *string `json:"status,omitempty"`
CommitCount *int `json:"commit_count,omitempty"`
StatusText *string `json:"status_text,omitempty"`
AuthorsCount *int `json:"authors_count,omitempty"`
Percent *int `json:"percent,omitempty"`
PushPercent *int `json:"push_percent,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
AuthorsURL *string `json:"authors_url,omitempty"`
RepositoryURL *string `json:"repository_url,omitempty"`
Message *string `json:"message,omitempty"`
FailedStep *string `json:"failed_step,omitempty"`
// Human readable display name, provided when the Import appears as
// part of ProjectChoices.
HumanName *string `json:"human_name,omitempty"`
// When the importer finds several projects or repositories at the
// provided URLs, this will identify the available choices. Call
// UpdateImport with the selected Import value.
ProjectChoices []Import `json:"project_choices,omitempty"`
}
func (i Import) String() string {
return Stringify(i)
}
// SourceImportAuthor identifies an author imported from a source repository.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors
type SourceImportAuthor struct {
ID *int64 `json:"id,omitempty"`
RemoteID *string `json:"remote_id,omitempty"`
RemoteName *string `json:"remote_name,omitempty"`
Email *string `json:"email,omitempty"`
Name *string `json:"name,omitempty"`
URL *string `json:"url,omitempty"`
ImportURL *string `json:"import_url,omitempty"`
}
func (a SourceImportAuthor) String() string {
return Stringify(a)
}
// LargeFile identifies a file larger than 100MB found during a repository import.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files
type LargeFile struct {
RefName *string `json:"ref_name,omitempty"`
Path *string `json:"path,omitempty"`
OID *string `json:"oid,omitempty"`
Size *int `json:"size,omitempty"`
}
func (f LargeFile) String() string {
return Stringify(f)
}
// StartImport initiates a repository import.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#start-an-import
func (s *MigrationService) StartImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
req, err := s.client.NewRequest("PUT", u, in)
if err != nil {
return nil, nil, err
}
out := new(Import)
resp, err := s.client.Do(ctx, req, out)
if err != nil {
return nil, resp, err
}
return out, resp, nil
}
// ImportProgress queries for the status and progress of an ongoing repository import.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-import-progress
func (s *MigrationService) ImportProgress(ctx context.Context, owner, repo string) (*Import, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
out := new(Import)
resp, err := s.client.Do(ctx, req, out)
if err != nil {
return nil, resp, err
}
return out, resp, nil
}
// UpdateImport initiates a repository import.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#update-existing-import
func (s *MigrationService) UpdateImport(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
req, err := s.client.NewRequest("PATCH", u, in)
if err != nil {
return nil, nil, err
}
out := new(Import)
resp, err := s.client.Do(ctx, req, out)
if err != nil {
return nil, resp, err
}
return out, resp, nil
}
// CommitAuthors gets the authors mapped from the original repository.
//
// Each type of source control system represents authors in a different way.
// For example, a Git commit author has a display name and an email address,
// but a Subversion commit author just has a username. The GitHub Importer will
// make the author information valid, but the author might not be correct. For
// example, it will change the bare Subversion username "hubot" into something
// like "hubot <hubot@12341234-abab-fefe-8787-fedcba987654>".
//
// This method and MapCommitAuthor allow you to provide correct Git author
// information.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-commit-authors
func (s *MigrationService) CommitAuthors(ctx context.Context, owner, repo string) ([]*SourceImportAuthor, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import/authors", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var authors []*SourceImportAuthor
resp, err := s.client.Do(ctx, req, &authors)
if err != nil {
return nil, resp, err
}
return authors, resp, nil
}
// MapCommitAuthor updates an author's identity for the import. Your
// application can continue updating authors any time before you push new
// commits to the repository.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#map-a-commit-author
func (s *MigrationService) MapCommitAuthor(ctx context.Context, owner, repo string, id int64, author *SourceImportAuthor) (*SourceImportAuthor, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import/authors/%v", owner, repo, id)
req, err := s.client.NewRequest("PATCH", u, author)
if err != nil {
return nil, nil, err
}
out := new(SourceImportAuthor)
resp, err := s.client.Do(ctx, req, out)
if err != nil {
return nil, resp, err
}
return out, resp, nil
}
// SetLFSPreference sets whether imported repositories should use Git LFS for
// files larger than 100MB. Only the UseLFS field on the provided Import is
// used.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#set-git-lfs-preference
func (s *MigrationService) SetLFSPreference(ctx context.Context, owner, repo string, in *Import) (*Import, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import/lfs", owner, repo)
req, err := s.client.NewRequest("PATCH", u, in)
if err != nil {
return nil, nil, err
}
out := new(Import)
resp, err := s.client.Do(ctx, req, out)
if err != nil {
return nil, resp, err
}
return out, resp, nil
}
// LargeFiles lists files larger than 100MB found during the import.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#get-large-files
func (s *MigrationService) LargeFiles(ctx context.Context, owner, repo string) ([]*LargeFile, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/import/large_files", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var files []*LargeFile
resp, err := s.client.Do(ctx, req, &files)
if err != nil {
return nil, resp, err
}
return files, resp, nil
}
// CancelImport stops an import for a repository.
//
// GitHub API docs: https://developer.github.com/v3/migration/source_imports/#cancel-an-import
func (s *MigrationService) CancelImport(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/import", owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,214 @@
// Copyright 2018 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"errors"
"fmt"
"net/http"
)
// UserMigration represents a GitHub migration (archival).
type UserMigration struct {
ID *int64 `json:"id,omitempty"`
GUID *string `json:"guid,omitempty"`
// State is the current state of a migration.
// Possible values are:
// "pending" which means the migration hasn't started yet,
// "exporting" which means the migration is in progress,
// "exported" which means the migration finished successfully, or
// "failed" which means the migration failed.
State *string `json:"state,omitempty"`
// LockRepositories indicates whether repositories are locked (to prevent
// manipulation) while migrating data.
LockRepositories *bool `json:"lock_repositories,omitempty"`
// ExcludeAttachments indicates whether attachments should be excluded from
// the migration (to reduce migration archive file size).
ExcludeAttachments *bool `json:"exclude_attachments,omitempty"`
URL *string `json:"url,omitempty"`
CreatedAt *string `json:"created_at,omitempty"`
UpdatedAt *string `json:"updated_at,omitempty"`
Repositories []*Repository `json:"repositories,omitempty"`
}
func (m UserMigration) String() string {
return Stringify(m)
}
// UserMigrationOptions specifies the optional parameters to Migration methods.
type UserMigrationOptions struct {
// LockRepositories indicates whether repositories should be locked (to prevent
// manipulation) while migrating data.
LockRepositories bool
// ExcludeAttachments indicates whether attachments should be excluded from
// the migration (to reduce migration archive file size).
ExcludeAttachments bool
}
// startUserMigration represents the body of a StartMigration request.
type startUserMigration struct {
// Repositories is a slice of repository names to migrate.
Repositories []string `json:"repositories,omitempty"`
// LockRepositories indicates whether repositories should be locked (to prevent
// manipulation) while migrating data.
LockRepositories *bool `json:"lock_repositories,omitempty"`
// ExcludeAttachments indicates whether attachments should be excluded from
// the migration (to reduce migration archive file size).
ExcludeAttachments *bool `json:"exclude_attachments,omitempty"`
}
// StartUserMigration starts the generation of a migration archive.
// repos is a slice of repository names to migrate.
//
// GitHub API docs: https://developer.github.com/v3/migrations/users/#start-a-user-migration
func (s *MigrationService) StartUserMigration(ctx context.Context, repos []string, opts *UserMigrationOptions) (*UserMigration, *Response, error) {
u := "user/migrations"
body := &startUserMigration{Repositories: repos}
if opts != nil {
body.LockRepositories = Bool(opts.LockRepositories)
body.ExcludeAttachments = Bool(opts.ExcludeAttachments)
}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
m := &UserMigration{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListUserMigrations lists the most recent migrations.
//
// GitHub API docs: https://developer.github.com/v3/migrations/users/#get-a-list-of-user-migrations
func (s *MigrationService) ListUserMigrations(ctx context.Context) ([]*UserMigration, *Response, error) {
u := "user/migrations"
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
var m []*UserMigration
resp, err := s.client.Do(ctx, req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// UserMigrationStatus gets the status of a specific migration archive.
// id is the migration ID.
//
// GitHub API docs: https://developer.github.com/v3/migrations/users/#get-the-status-of-a-user-migration
func (s *MigrationService) UserMigrationStatus(ctx context.Context, id int64) (*UserMigration, *Response, error) {
u := fmt.Sprintf("user/migrations/%v", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
m := &UserMigration{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// UserMigrationArchiveURL gets the URL for a specific migration archive.
// id is the migration ID.
//
// GitHub API docs: https://developer.github.com/v3/migrations/users/#download-a-user-migration-archive
func (s *MigrationService) UserMigrationArchiveURL(ctx context.Context, id int64) (string, error) {
url := fmt.Sprintf("user/migrations/%v/archive", id)
req, err := s.client.NewRequest("GET", url, nil)
if err != nil {
return "", err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
m := &UserMigration{}
var loc string
originalRedirect := s.client.client.CheckRedirect
s.client.client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
loc = req.URL.String()
return http.ErrUseLastResponse
}
defer func() {
s.client.client.CheckRedirect = originalRedirect
}()
resp, err := s.client.Do(ctx, req, m)
if err == nil {
return "", errors.New("expected redirect, none provided")
}
loc = resp.Header.Get("Location")
return loc, nil
}
// DeleteUserMigration will delete a previous migration archive.
// id is the migration ID.
//
// GitHub API docs: https://developer.github.com/v3/migrations/users/#delete-a-user-migration-archive
func (s *MigrationService) DeleteUserMigration(ctx context.Context, id int64) (*Response, error) {
url := fmt.Sprintf("user/migrations/%v/archive", id)
req, err := s.client.NewRequest("DELETE", url, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
return s.client.Do(ctx, req, nil)
}
// UnlockUserRepo will unlock a repo that was locked for migration.
// id is migration ID.
// You should unlock each migrated repository and delete them when the migration
// is complete and you no longer need the source data.
//
// GitHub API docs: https://developer.github.com/v3/migrations/users/#unlock-a-user-repository
func (s *MigrationService) UnlockUserRepo(ctx context.Context, id int64, repo string) (*Response, error) {
url := fmt.Sprintf("user/migrations/%v/repos/%v/lock", id, repo)
req, err := s.client.NewRequest("DELETE", url, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMigrationsPreview)
return s.client.Do(ctx, req, nil)
}

257
vendor/github.com/google/go-github/v29/github/misc.go generated vendored Normal file
View file

@ -0,0 +1,257 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"bytes"
"context"
"fmt"
"net/url"
)
// MarkdownOptions specifies optional parameters to the Markdown method.
type MarkdownOptions struct {
// Mode identifies the rendering mode. Possible values are:
// markdown - render a document as plain Markdown, just like
// README files are rendered.
//
// gfm - to render a document as user-content, e.g. like user
// comments or issues are rendered. In GFM mode, hard line breaks are
// always taken into account, and issue and user mentions are linked
// accordingly.
//
// Default is "markdown".
Mode string
// Context identifies the repository context. Only taken into account
// when rendering as "gfm".
Context string
}
type markdownRequest struct {
Text *string `json:"text,omitempty"`
Mode *string `json:"mode,omitempty"`
Context *string `json:"context,omitempty"`
}
// Markdown renders an arbitrary Markdown document.
//
// GitHub API docs: https://developer.github.com/v3/markdown/
func (c *Client) Markdown(ctx context.Context, text string, opts *MarkdownOptions) (string, *Response, error) {
request := &markdownRequest{Text: String(text)}
if opts != nil {
if opts.Mode != "" {
request.Mode = String(opts.Mode)
}
if opts.Context != "" {
request.Context = String(opts.Context)
}
}
req, err := c.NewRequest("POST", "markdown", request)
if err != nil {
return "", nil, err
}
buf := new(bytes.Buffer)
resp, err := c.Do(ctx, req, buf)
if err != nil {
return "", resp, err
}
return buf.String(), resp, nil
}
// ListEmojis returns the emojis available to use on GitHub.
//
// GitHub API docs: https://developer.github.com/v3/emojis/
func (c *Client) ListEmojis(ctx context.Context) (map[string]string, *Response, error) {
req, err := c.NewRequest("GET", "emojis", nil)
if err != nil {
return nil, nil, err
}
var emoji map[string]string
resp, err := c.Do(ctx, req, &emoji)
if err != nil {
return nil, resp, err
}
return emoji, resp, nil
}
// CodeOfConduct represents a code of conduct.
type CodeOfConduct struct {
Name *string `json:"name,omitempty"`
Key *string `json:"key,omitempty"`
URL *string `json:"url,omitempty"`
Body *string `json:"body,omitempty"`
}
func (c *CodeOfConduct) String() string {
return Stringify(c)
}
// ListCodesOfConduct returns all codes of conduct.
//
// GitHub API docs: https://developer.github.com/v3/codes_of_conduct/#list-all-codes-of-conduct
func (c *Client) ListCodesOfConduct(ctx context.Context) ([]*CodeOfConduct, *Response, error) {
req, err := c.NewRequest("GET", "codes_of_conduct", nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeCodesOfConductPreview)
var cs []*CodeOfConduct
resp, err := c.Do(ctx, req, &cs)
if err != nil {
return nil, resp, err
}
return cs, resp, nil
}
// GetCodeOfConduct returns an individual code of conduct.
//
// https://developer.github.com/v3/codes_of_conduct/#get-an-individual-code-of-conduct
func (c *Client) GetCodeOfConduct(ctx context.Context, key string) (*CodeOfConduct, *Response, error) {
u := fmt.Sprintf("codes_of_conduct/%s", key)
req, err := c.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeCodesOfConductPreview)
coc := new(CodeOfConduct)
resp, err := c.Do(ctx, req, coc)
if err != nil {
return nil, resp, err
}
return coc, resp, nil
}
// APIMeta represents metadata about the GitHub API.
type APIMeta struct {
// An Array of IP addresses in CIDR format specifying the addresses
// that incoming service hooks will originate from on GitHub.com.
Hooks []string `json:"hooks,omitempty"`
// An Array of IP addresses in CIDR format specifying the Git servers
// for GitHub.com.
Git []string `json:"git,omitempty"`
// Whether authentication with username and password is supported.
// (GitHub Enterprise instances using CAS or OAuth for authentication
// will return false. Features like Basic Authentication with a
// username and password, sudo mode, and two-factor authentication are
// not supported on these servers.)
VerifiablePasswordAuthentication *bool `json:"verifiable_password_authentication,omitempty"`
// An array of IP addresses in CIDR format specifying the addresses
// which serve GitHub Pages websites.
Pages []string `json:"pages,omitempty"`
// An Array of IP addresses specifying the addresses that source imports
// will originate from on GitHub.com.
Importer []string `json:"importer,omitempty"`
}
// APIMeta returns information about GitHub.com, the service. Or, if you access
// this endpoint on your organizations GitHub Enterprise installation, this
// endpoint provides information about that installation.
//
// GitHub API docs: https://developer.github.com/v3/meta/
func (c *Client) APIMeta(ctx context.Context) (*APIMeta, *Response, error) {
req, err := c.NewRequest("GET", "meta", nil)
if err != nil {
return nil, nil, err
}
meta := new(APIMeta)
resp, err := c.Do(ctx, req, meta)
if err != nil {
return nil, resp, err
}
return meta, resp, nil
}
// Octocat returns an ASCII art octocat with the specified message in a speech
// bubble. If message is empty, a random zen phrase is used.
func (c *Client) Octocat(ctx context.Context, message string) (string, *Response, error) {
u := "octocat"
if message != "" {
u = fmt.Sprintf("%s?s=%s", u, url.QueryEscape(message))
}
req, err := c.NewRequest("GET", u, nil)
if err != nil {
return "", nil, err
}
buf := new(bytes.Buffer)
resp, err := c.Do(ctx, req, buf)
if err != nil {
return "", resp, err
}
return buf.String(), resp, nil
}
// Zen returns a random line from The Zen of GitHub.
//
// see also: http://warpspire.com/posts/taste/
func (c *Client) Zen(ctx context.Context) (string, *Response, error) {
req, err := c.NewRequest("GET", "zen", nil)
if err != nil {
return "", nil, err
}
buf := new(bytes.Buffer)
resp, err := c.Do(ctx, req, buf)
if err != nil {
return "", resp, err
}
return buf.String(), resp, nil
}
// ServiceHook represents a hook that has configuration settings, a list of
// available events, and default events.
type ServiceHook struct {
Name *string `json:"name,omitempty"`
Events []string `json:"events,omitempty"`
SupportedEvents []string `json:"supported_events,omitempty"`
Schema [][]string `json:"schema,omitempty"`
}
func (s *ServiceHook) String() string {
return Stringify(s)
}
// ListServiceHooks lists all of the available service hooks.
//
// GitHub API docs: https://developer.github.com/webhooks/#services
func (c *Client) ListServiceHooks(ctx context.Context) ([]*ServiceHook, *Response, error) {
u := "hooks"
req, err := c.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var hooks []*ServiceHook
resp, err := c.Do(ctx, req, &hooks)
if err != nil {
return nil, resp, err
}
return hooks, resp, nil
}

263
vendor/github.com/google/go-github/v29/github/orgs.go generated vendored Normal file
View file

@ -0,0 +1,263 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// OrganizationsService provides access to the organization related functions
// in the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/orgs/
type OrganizationsService service
// Organization represents a GitHub organization account.
type Organization struct {
Login *string `json:"login,omitempty"`
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
AvatarURL *string `json:"avatar_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
Name *string `json:"name,omitempty"`
Company *string `json:"company,omitempty"`
Blog *string `json:"blog,omitempty"`
Location *string `json:"location,omitempty"`
Email *string `json:"email,omitempty"`
Description *string `json:"description,omitempty"`
PublicRepos *int `json:"public_repos,omitempty"`
PublicGists *int `json:"public_gists,omitempty"`
Followers *int `json:"followers,omitempty"`
Following *int `json:"following,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
TotalPrivateRepos *int `json:"total_private_repos,omitempty"`
OwnedPrivateRepos *int `json:"owned_private_repos,omitempty"`
PrivateGists *int `json:"private_gists,omitempty"`
DiskUsage *int `json:"disk_usage,omitempty"`
Collaborators *int `json:"collaborators,omitempty"`
BillingEmail *string `json:"billing_email,omitempty"`
Type *string `json:"type,omitempty"`
Plan *Plan `json:"plan,omitempty"`
TwoFactorRequirementEnabled *bool `json:"two_factor_requirement_enabled,omitempty"`
// DefaultRepoPermission can be one of: "read", "write", "admin", or "none". (Default: "read").
// It is only used in OrganizationsService.Edit.
DefaultRepoPermission *string `json:"default_repository_permission,omitempty"`
// DefaultRepoSettings can be one of: "read", "write", "admin", or "none". (Default: "read").
// It is only used in OrganizationsService.Get.
DefaultRepoSettings *string `json:"default_repository_settings,omitempty"`
// MembersCanCreateRepos default value is true and is only used in Organizations.Edit.
MembersCanCreateRepos *bool `json:"members_can_create_repositories,omitempty"`
// https://developer.github.com/changes/2019-12-03-internal-visibility-changes/#rest-v3-api
MembersCanCreatePublicRepos *bool `json:"members_can_create_public_repositories,omitempty"`
MembersCanCreatePrivateRepos *bool `json:"members_can_create_private_repositories,omitempty"`
MembersCanCreateInternalRepos *bool `json:"members_can_create_internal_repositories,omitempty"`
// MembersAllowedRepositoryCreationType denotes if organization members can create repositories
// and the type of repositories they can create. Possible values are: "all", "private", or "none".
//
// Deprecated: Use MembersCanCreatePublicRepos, MembersCanCreatePrivateRepos, MembersCanCreateInternalRepos
// instead. The new fields overrides the existing MembersAllowedRepositoryCreationType during 'edit'
// operation and does not consider 'internal' repositories during 'get' operation
MembersAllowedRepositoryCreationType *string `json:"members_allowed_repository_creation_type,omitempty"`
// API URLs
URL *string `json:"url,omitempty"`
EventsURL *string `json:"events_url,omitempty"`
HooksURL *string `json:"hooks_url,omitempty"`
IssuesURL *string `json:"issues_url,omitempty"`
MembersURL *string `json:"members_url,omitempty"`
PublicMembersURL *string `json:"public_members_url,omitempty"`
ReposURL *string `json:"repos_url,omitempty"`
}
// OrganizationInstallations represents GitHub app installations for an organization.
type OrganizationInstallations struct {
TotalCount *int `json:"total_count,omitempty"`
Installations []*Installation `json:"installations,omitempty"`
}
func (o Organization) String() string {
return Stringify(o)
}
// Plan represents the payment plan for an account. See plans at https://github.com/plans.
type Plan struct {
Name *string `json:"name,omitempty"`
Space *int `json:"space,omitempty"`
Collaborators *int `json:"collaborators,omitempty"`
PrivateRepos *int `json:"private_repos,omitempty"`
FilledSeats *int `json:"filled_seats,omitempty"`
Seats *int `json:"seats,omitempty"`
}
func (p Plan) String() string {
return Stringify(p)
}
// OrganizationsListOptions specifies the optional parameters to the
// OrganizationsService.ListAll method.
type OrganizationsListOptions struct {
// Since filters Organizations by ID.
Since int64 `url:"since,omitempty"`
// Note: Pagination is powered exclusively by the Since parameter,
// ListOptions.Page has no effect.
// ListOptions.PerPage controls an undocumented GitHub API parameter.
ListOptions
}
// ListAll lists all organizations, in the order that they were created on GitHub.
//
// Note: Pagination is powered exclusively by the since parameter. To continue
// listing the next set of organizations, use the ID of the last-returned organization
// as the opts.Since parameter for the next call.
//
// GitHub API docs: https://developer.github.com/v3/orgs/#list-all-organizations
func (s *OrganizationsService) ListAll(ctx context.Context, opts *OrganizationsListOptions) ([]*Organization, *Response, error) {
u, err := addOptions("organizations", opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
orgs := []*Organization{}
resp, err := s.client.Do(ctx, req, &orgs)
if err != nil {
return nil, resp, err
}
return orgs, resp, nil
}
// List the organizations for a user. Passing the empty string will list
// organizations for the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/orgs/#list-user-organizations
func (s *OrganizationsService) List(ctx context.Context, user string, opts *ListOptions) ([]*Organization, *Response, error) {
var u string
if user != "" {
u = fmt.Sprintf("users/%v/orgs", user)
} else {
u = "user/orgs"
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var orgs []*Organization
resp, err := s.client.Do(ctx, req, &orgs)
if err != nil {
return nil, resp, err
}
return orgs, resp, nil
}
// Get fetches an organization by name.
//
// GitHub API docs: https://developer.github.com/v3/orgs/#get-an-organization
func (s *OrganizationsService) Get(ctx context.Context, org string) (*Organization, *Response, error) {
u := fmt.Sprintf("orgs/%v", org)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview)
organization := new(Organization)
resp, err := s.client.Do(ctx, req, organization)
if err != nil {
return nil, resp, err
}
return organization, resp, nil
}
// GetByID fetches an organization.
//
// Note: GetByID uses the undocumented GitHub API endpoint /organizations/:id.
func (s *OrganizationsService) GetByID(ctx context.Context, id int64) (*Organization, *Response, error) {
u := fmt.Sprintf("organizations/%d", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
organization := new(Organization)
resp, err := s.client.Do(ctx, req, organization)
if err != nil {
return nil, resp, err
}
return organization, resp, nil
}
// Edit an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/#edit-an-organization
func (s *OrganizationsService) Edit(ctx context.Context, name string, org *Organization) (*Organization, *Response, error) {
u := fmt.Sprintf("orgs/%v", name)
req, err := s.client.NewRequest("PATCH", u, org)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeMemberAllowedRepoCreationTypePreview)
o := new(Organization)
resp, err := s.client.Do(ctx, req, o)
if err != nil {
return nil, resp, err
}
return o, resp, nil
}
// ListInstallations lists installations for an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/#list-installations-for-an-organization
func (s *OrganizationsService) ListInstallations(ctx context.Context, org string, opts *ListOptions) (*OrganizationInstallations, *Response, error) {
u := fmt.Sprintf("orgs/%v/installations", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeIntegrationPreview)
result := new(OrganizationInstallations)
resp, err := s.client.Do(ctx, req, result)
if err != nil {
return nil, resp, err
}
return result, resp, nil
}

View file

@ -0,0 +1,118 @@
// Copyright 2015 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ListHooks lists all Hooks for the specified organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#list-hooks
func (s *OrganizationsService) ListHooks(ctx context.Context, org string, opts *ListOptions) ([]*Hook, *Response, error) {
u := fmt.Sprintf("orgs/%v/hooks", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var hooks []*Hook
resp, err := s.client.Do(ctx, req, &hooks)
if err != nil {
return nil, resp, err
}
return hooks, resp, nil
}
// GetHook returns a single specified Hook.
//
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#get-single-hook
func (s *OrganizationsService) GetHook(ctx context.Context, org string, id int64) (*Hook, *Response, error) {
u := fmt.Sprintf("orgs/%v/hooks/%d", org, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
hook := new(Hook)
resp, err := s.client.Do(ctx, req, hook)
return hook, resp, err
}
// CreateHook creates a Hook for the specified org.
// Config is a required field.
//
// Note that only a subset of the hook fields are used and hook must
// not be nil.
//
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#create-a-hook
func (s *OrganizationsService) CreateHook(ctx context.Context, org string, hook *Hook) (*Hook, *Response, error) {
u := fmt.Sprintf("orgs/%v/hooks", org)
hookReq := &createHookRequest{
Name: "web",
Events: hook.Events,
Active: hook.Active,
Config: hook.Config,
}
req, err := s.client.NewRequest("POST", u, hookReq)
if err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := s.client.Do(ctx, req, h)
if err != nil {
return nil, resp, err
}
return h, resp, nil
}
// EditHook updates a specified Hook.
//
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#edit-a-hook
func (s *OrganizationsService) EditHook(ctx context.Context, org string, id int64, hook *Hook) (*Hook, *Response, error) {
u := fmt.Sprintf("orgs/%v/hooks/%d", org, id)
req, err := s.client.NewRequest("PATCH", u, hook)
if err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := s.client.Do(ctx, req, h)
return h, resp, err
}
// PingHook triggers a 'ping' event to be sent to the Hook.
//
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#ping-a-hook
func (s *OrganizationsService) PingHook(ctx context.Context, org string, id int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/hooks/%d/pings", org, id)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// DeleteHook deletes a specified Hook.
//
// GitHub API docs: https://developer.github.com/v3/orgs/hooks/#delete-a-hook
func (s *OrganizationsService) DeleteHook(ctx context.Context, org string, id int64) (*Response, error) {
u := fmt.Sprintf("orgs/%v/hooks/%d", org, id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,364 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// Membership represents the status of a user's membership in an organization or team.
type Membership struct {
URL *string `json:"url,omitempty"`
// State is the user's status within the organization or team.
// Possible values are: "active", "pending"
State *string `json:"state,omitempty"`
// Role identifies the user's role within the organization or team.
// Possible values for organization membership:
// member - non-owner organization member
// admin - organization owner
//
// Possible values for team membership are:
// member - a normal member of the team
// maintainer - a team maintainer. Able to add/remove other team
// members, promote other team members to team
// maintainer, and edit the teams name and description
Role *string `json:"role,omitempty"`
// For organization membership, the API URL of the organization.
OrganizationURL *string `json:"organization_url,omitempty"`
// For organization membership, the organization the membership is for.
Organization *Organization `json:"organization,omitempty"`
// For organization membership, the user the membership is for.
User *User `json:"user,omitempty"`
}
func (m Membership) String() string {
return Stringify(m)
}
// ListMembersOptions specifies optional parameters to the
// OrganizationsService.ListMembers method.
type ListMembersOptions struct {
// If true (or if the authenticated user is not an owner of the
// organization), list only publicly visible members.
PublicOnly bool `url:"-"`
// Filter members returned in the list. Possible values are:
// 2fa_disabled, all. Default is "all".
Filter string `url:"filter,omitempty"`
// Role filters members returned by their role in the organization.
// Possible values are:
// all - all members of the organization, regardless of role
// admin - organization owners
// member - non-owner organization members
//
// Default is "all".
Role string `url:"role,omitempty"`
ListOptions
}
// ListMembers lists the members for an organization. If the authenticated
// user is an owner of the organization, this will return both concealed and
// public members, otherwise it will only return public members.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#members-list
func (s *OrganizationsService) ListMembers(ctx context.Context, org string, opts *ListMembersOptions) ([]*User, *Response, error) {
var u string
if opts != nil && opts.PublicOnly {
u = fmt.Sprintf("orgs/%v/public_members", org)
} else {
u = fmt.Sprintf("orgs/%v/members", org)
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var members []*User
resp, err := s.client.Do(ctx, req, &members)
if err != nil {
return nil, resp, err
}
return members, resp, nil
}
// IsMember checks if a user is a member of an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-membership
func (s *OrganizationsService) IsMember(ctx context.Context, org, user string) (bool, *Response, error) {
u := fmt.Sprintf("orgs/%v/members/%v", org, user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
resp, err := s.client.Do(ctx, req, nil)
member, err := parseBoolResponse(err)
return member, resp, err
}
// IsPublicMember checks if a user is a public member of an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#check-public-membership
func (s *OrganizationsService) IsPublicMember(ctx context.Context, org, user string) (bool, *Response, error) {
u := fmt.Sprintf("orgs/%v/public_members/%v", org, user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
resp, err := s.client.Do(ctx, req, nil)
member, err := parseBoolResponse(err)
return member, resp, err
}
// RemoveMember removes a user from all teams of an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-a-member
func (s *OrganizationsService) RemoveMember(ctx context.Context, org, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/members/%v", org, user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// PublicizeMembership publicizes a user's membership in an organization. (A
// user cannot publicize the membership for another user.)
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#publicize-a-users-membership
func (s *OrganizationsService) PublicizeMembership(ctx context.Context, org, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/public_members/%v", org, user)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ConcealMembership conceals a user's membership in an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#conceal-a-users-membership
func (s *OrganizationsService) ConcealMembership(ctx context.Context, org, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/public_members/%v", org, user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListOrgMembershipsOptions specifies optional parameters to the
// OrganizationsService.ListOrgMemberships method.
type ListOrgMembershipsOptions struct {
// Filter memberships to include only those with the specified state.
// Possible values are: "active", "pending".
State string `url:"state,omitempty"`
ListOptions
}
// ListOrgMemberships lists the organization memberships for the authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-your-organization-memberships
func (s *OrganizationsService) ListOrgMemberships(ctx context.Context, opts *ListOrgMembershipsOptions) ([]*Membership, *Response, error) {
u := "user/memberships/orgs"
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var memberships []*Membership
resp, err := s.client.Do(ctx, req, &memberships)
if err != nil {
return nil, resp, err
}
return memberships, resp, nil
}
// GetOrgMembership gets the membership for a user in a specified organization.
// Passing an empty string for user will get the membership for the
// authenticated user.
//
// GitHub API docs:
// https://developer.github.com/v3/orgs/members/#get-organization-membership
// https://developer.github.com/v3/orgs/members/#get-your-organization-membership
func (s *OrganizationsService) GetOrgMembership(ctx context.Context, user, org string) (*Membership, *Response, error) {
var u string
if user != "" {
u = fmt.Sprintf("orgs/%v/memberships/%v", org, user)
} else {
u = fmt.Sprintf("user/memberships/orgs/%v", org)
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
membership := new(Membership)
resp, err := s.client.Do(ctx, req, membership)
if err != nil {
return nil, resp, err
}
return membership, resp, nil
}
// EditOrgMembership edits the membership for user in specified organization.
// Passing an empty string for user will edit the membership for the
// authenticated user.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership
// GitHub API docs: https://developer.github.com/v3/orgs/members/#edit-your-organization-membership
func (s *OrganizationsService) EditOrgMembership(ctx context.Context, user, org string, membership *Membership) (*Membership, *Response, error) {
var u, method string
if user != "" {
u = fmt.Sprintf("orgs/%v/memberships/%v", org, user)
method = "PUT"
} else {
u = fmt.Sprintf("user/memberships/orgs/%v", org)
method = "PATCH"
}
req, err := s.client.NewRequest(method, u, membership)
if err != nil {
return nil, nil, err
}
m := new(Membership)
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// RemoveOrgMembership removes user from the specified organization. If the
// user has been invited to the organization, this will cancel their invitation.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#remove-organization-membership
func (s *OrganizationsService) RemoveOrgMembership(ctx context.Context, user, org string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/memberships/%v", org, user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ListPendingOrgInvitations returns a list of pending invitations.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-pending-organization-invitations
func (s *OrganizationsService) ListPendingOrgInvitations(ctx context.Context, org string, opts *ListOptions) ([]*Invitation, *Response, error) {
u := fmt.Sprintf("orgs/%v/invitations", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var pendingInvitations []*Invitation
resp, err := s.client.Do(ctx, req, &pendingInvitations)
if err != nil {
return nil, resp, err
}
return pendingInvitations, resp, nil
}
// CreateOrgInvitationOptions specifies the parameters to the OrganizationService.Invite
// method.
type CreateOrgInvitationOptions struct {
// GitHub user ID for the person you are inviting. Not required if you provide Email.
InviteeID *int64 `json:"invitee_id,omitempty"`
// Email address of the person you are inviting, which can be an existing GitHub user.
// Not required if you provide InviteeID
Email *string `json:"email,omitempty"`
// Specify role for new member. Can be one of:
// * admin - Organization owners with full administrative rights to the
// organization and complete access to all repositories and teams.
// * direct_member - Non-owner organization members with ability to see
// other members and join teams by invitation.
// * billing_manager - Non-owner organization members with ability to
// manage the billing settings of your organization.
// Default is "direct_member".
Role *string `json:"role"`
TeamID []int64 `json:"team_ids"`
}
// CreateOrgInvitation invites people to an organization by using their GitHub user ID or their email address.
// In order to create invitations in an organization,
// the authenticated user must be an organization owner.
//
// https://developer.github.com/v3/orgs/members/#create-organization-invitation
func (s *OrganizationsService) CreateOrgInvitation(ctx context.Context, org string, opts *CreateOrgInvitationOptions) (*Invitation, *Response, error) {
u := fmt.Sprintf("orgs/%v/invitations", org)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
var invitation *Invitation
resp, err := s.client.Do(ctx, req, &invitation)
if err != nil {
return nil, resp, err
}
return invitation, resp, nil
}
// ListOrgInvitationTeams lists all teams associated with an invitation. In order to see invitations in an organization,
// the authenticated user must be an organization owner.
//
// GitHub API docs: https://developer.github.com/v3/orgs/members/#list-organization-invitation-teams
func (s *OrganizationsService) ListOrgInvitationTeams(ctx context.Context, org, invitationID string, opts *ListOptions) ([]*Team, *Response, error) {
u := fmt.Sprintf("orgs/%v/invitations/%v/teams", org, invitationID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var orgInvitationTeams []*Team
resp, err := s.client.Do(ctx, req, &orgInvitationTeams)
if err != nil {
return nil, resp, err
}
return orgInvitationTeams, resp, nil
}

View file

@ -0,0 +1,81 @@
// Copyright 2017 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ListOutsideCollaboratorsOptions specifies optional parameters to the
// OrganizationsService.ListOutsideCollaborators method.
type ListOutsideCollaboratorsOptions struct {
// Filter outside collaborators returned in the list. Possible values are:
// 2fa_disabled, all. Default is "all".
Filter string `url:"filter,omitempty"`
ListOptions
}
// ListOutsideCollaborators lists outside collaborators of organization's repositories.
// This will only work if the authenticated
// user is an owner of the organization.
//
// Warning: The API may change without advance notice during the preview period.
// Preview features are not supported for production use.
//
// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#list-outside-collaborators
func (s *OrganizationsService) ListOutsideCollaborators(ctx context.Context, org string, opts *ListOutsideCollaboratorsOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("orgs/%v/outside_collaborators", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var members []*User
resp, err := s.client.Do(ctx, req, &members)
if err != nil {
return nil, resp, err
}
return members, resp, nil
}
// RemoveOutsideCollaborator removes a user from the list of outside collaborators;
// consequently, removing them from all the organization's repositories.
//
// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#remove-outside-collaborator
func (s *OrganizationsService) RemoveOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// ConvertMemberToOutsideCollaborator reduces the permission level of a member of the
// organization to that of an outside collaborator. Therefore, they will only
// have access to the repositories that their current team membership allows.
// Responses for converting a non-member or the last owner to an outside collaborator
// are listed in GitHub API docs.
//
// GitHub API docs: https://developer.github.com/v3/orgs/outside_collaborators/#convert-member-to-outside-collaborator
func (s *OrganizationsService) ConvertMemberToOutsideCollaborator(ctx context.Context, org string, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/outside_collaborators/%v", org, user)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,60 @@
// Copyright 2017 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ListProjects lists the projects for an organization.
//
// GitHub API docs: https://developer.github.com/v3/projects/#list-organization-projects
func (s *OrganizationsService) ListProjects(ctx context.Context, org string, opts *ProjectListOptions) ([]*Project, *Response, error) {
u := fmt.Sprintf("orgs/%v/projects", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
var projects []*Project
resp, err := s.client.Do(ctx, req, &projects)
if err != nil {
return nil, resp, err
}
return projects, resp, nil
}
// CreateProject creates a GitHub Project for the specified organization.
//
// GitHub API docs: https://developer.github.com/v3/projects/#create-an-organization-project
func (s *OrganizationsService) CreateProject(ctx context.Context, org string, opts *ProjectOptions) (*Project, *Response, error) {
u := fmt.Sprintf("orgs/%v/projects", org)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
project := &Project{}
resp, err := s.client.Do(ctx, req, project)
if err != nil {
return nil, resp, err
}
return project, resp, nil
}

View file

@ -0,0 +1,91 @@
// Copyright 2017 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ListBlockedUsers lists all the users blocked by an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#list-blocked-users
func (s *OrganizationsService) ListBlockedUsers(ctx context.Context, org string, opts *ListOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("orgs/%v/blocks", org)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeBlockUsersPreview)
var blockedUsers []*User
resp, err := s.client.Do(ctx, req, &blockedUsers)
if err != nil {
return nil, resp, err
}
return blockedUsers, resp, nil
}
// IsBlocked reports whether specified user is blocked from an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#check-whether-a-user-is-blocked-from-an-organization
func (s *OrganizationsService) IsBlocked(ctx context.Context, org string, user string) (bool, *Response, error) {
u := fmt.Sprintf("orgs/%v/blocks/%v", org, user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeBlockUsersPreview)
resp, err := s.client.Do(ctx, req, nil)
isBlocked, err := parseBoolResponse(err)
return isBlocked, resp, err
}
// BlockUser blocks specified user from an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#block-a-user
func (s *OrganizationsService) BlockUser(ctx context.Context, org string, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/blocks/%v", org, user)
req, err := s.client.NewRequest("PUT", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeBlockUsersPreview)
return s.client.Do(ctx, req, nil)
}
// UnblockUser unblocks specified user from an organization.
//
// GitHub API docs: https://developer.github.com/v3/orgs/blocking/#unblock-a-user
func (s *OrganizationsService) UnblockUser(ctx context.Context, org string, user string) (*Response, error) {
u := fmt.Sprintf("orgs/%v/blocks/%v", org, user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeBlockUsersPreview)
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,594 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ProjectsService provides access to the projects functions in the
// GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/projects/
type ProjectsService service
// Project represents a GitHub Project.
type Project struct {
ID *int64 `json:"id,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
ColumnsURL *string `json:"columns_url,omitempty"`
OwnerURL *string `json:"owner_url,omitempty"`
Name *string `json:"name,omitempty"`
Body *string `json:"body,omitempty"`
Number *int `json:"number,omitempty"`
State *string `json:"state,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
NodeID *string `json:"node_id,omitempty"`
// The User object that generated the project.
Creator *User `json:"creator,omitempty"`
}
func (p Project) String() string {
return Stringify(p)
}
// GetProject gets a GitHub Project for a repo.
//
// GitHub API docs: https://developer.github.com/v3/projects/#get-a-project
func (s *ProjectsService) GetProject(ctx context.Context, id int64) (*Project, *Response, error) {
u := fmt.Sprintf("projects/%v", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
project := &Project{}
resp, err := s.client.Do(ctx, req, project)
if err != nil {
return nil, resp, err
}
return project, resp, nil
}
// ProjectOptions specifies the parameters to the
// RepositoriesService.CreateProject and
// ProjectsService.UpdateProject methods.
type ProjectOptions struct {
// The name of the project. (Required for creation; optional for update.)
Name *string `json:"name,omitempty"`
// The body of the project. (Optional.)
Body *string `json:"body,omitempty"`
// The following field(s) are only applicable for update.
// They should be left with zero values for creation.
// State of the project. Either "open" or "closed". (Optional.)
State *string `json:"state,omitempty"`
// The permission level that all members of the project's organization
// will have on this project.
// Setting the organization permission is only available
// for organization projects. (Optional.)
OrganizationPermission *string `json:"organization_permission,omitempty"`
// Sets visibility of the project within the organization.
// Setting visibility is only available
// for organization projects.(Optional.)
Public *bool `json:"public,omitempty"`
}
// UpdateProject updates a repository project.
//
// GitHub API docs: https://developer.github.com/v3/projects/#update-a-project
func (s *ProjectsService) UpdateProject(ctx context.Context, id int64, opts *ProjectOptions) (*Project, *Response, error) {
u := fmt.Sprintf("projects/%v", id)
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
project := &Project{}
resp, err := s.client.Do(ctx, req, project)
if err != nil {
return nil, resp, err
}
return project, resp, nil
}
// DeleteProject deletes a GitHub Project from a repository.
//
// GitHub API docs: https://developer.github.com/v3/projects/#delete-a-project
func (s *ProjectsService) DeleteProject(ctx context.Context, id int64) (*Response, error) {
u := fmt.Sprintf("projects/%v", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
return s.client.Do(ctx, req, nil)
}
// ProjectColumn represents a column of a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/repos/projects/
type ProjectColumn struct {
ID *int64 `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
URL *string `json:"url,omitempty"`
ProjectURL *string `json:"project_url,omitempty"`
CardsURL *string `json:"cards_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
// ListProjectColumns lists the columns of a GitHub Project for a repo.
//
// GitHub API docs: https://developer.github.com/v3/projects/columns/#list-project-columns
func (s *ProjectsService) ListProjectColumns(ctx context.Context, projectID int64, opts *ListOptions) ([]*ProjectColumn, *Response, error) {
u := fmt.Sprintf("projects/%v/columns", projectID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
columns := []*ProjectColumn{}
resp, err := s.client.Do(ctx, req, &columns)
if err != nil {
return nil, resp, err
}
return columns, resp, nil
}
// GetProjectColumn gets a column of a GitHub Project for a repo.
//
// GitHub API docs: https://developer.github.com/v3/projects/columns/#get-a-project-column
func (s *ProjectsService) GetProjectColumn(ctx context.Context, id int64) (*ProjectColumn, *Response, error) {
u := fmt.Sprintf("projects/columns/%v", id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
column := &ProjectColumn{}
resp, err := s.client.Do(ctx, req, column)
if err != nil {
return nil, resp, err
}
return column, resp, nil
}
// ProjectColumnOptions specifies the parameters to the
// ProjectsService.CreateProjectColumn and
// ProjectsService.UpdateProjectColumn methods.
type ProjectColumnOptions struct {
// The name of the project column. (Required for creation and update.)
Name string `json:"name"`
}
// CreateProjectColumn creates a column for the specified (by number) project.
//
// GitHub API docs: https://developer.github.com/v3/projects/columns/#create-a-project-column
func (s *ProjectsService) CreateProjectColumn(ctx context.Context, projectID int64, opts *ProjectColumnOptions) (*ProjectColumn, *Response, error) {
u := fmt.Sprintf("projects/%v/columns", projectID)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
column := &ProjectColumn{}
resp, err := s.client.Do(ctx, req, column)
if err != nil {
return nil, resp, err
}
return column, resp, nil
}
// UpdateProjectColumn updates a column of a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/columns/#update-a-project-column
func (s *ProjectsService) UpdateProjectColumn(ctx context.Context, columnID int64, opts *ProjectColumnOptions) (*ProjectColumn, *Response, error) {
u := fmt.Sprintf("projects/columns/%v", columnID)
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
column := &ProjectColumn{}
resp, err := s.client.Do(ctx, req, column)
if err != nil {
return nil, resp, err
}
return column, resp, nil
}
// DeleteProjectColumn deletes a column from a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/columns/#delete-a-project-column
func (s *ProjectsService) DeleteProjectColumn(ctx context.Context, columnID int64) (*Response, error) {
u := fmt.Sprintf("projects/columns/%v", columnID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
return s.client.Do(ctx, req, nil)
}
// ProjectColumnMoveOptions specifies the parameters to the
// ProjectsService.MoveProjectColumn method.
type ProjectColumnMoveOptions struct {
// Position can be one of "first", "last", or "after:<column-id>", where
// <column-id> is the ID of a column in the same project. (Required.)
Position string `json:"position"`
}
// MoveProjectColumn moves a column within a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/columns/#move-a-project-column
func (s *ProjectsService) MoveProjectColumn(ctx context.Context, columnID int64, opts *ProjectColumnMoveOptions) (*Response, error) {
u := fmt.Sprintf("projects/columns/%v/moves", columnID)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
return s.client.Do(ctx, req, nil)
}
// ProjectCard represents a card in a column of a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card
type ProjectCard struct {
URL *string `json:"url,omitempty"`
ColumnURL *string `json:"column_url,omitempty"`
ContentURL *string `json:"content_url,omitempty"`
ID *int64 `json:"id,omitempty"`
Note *string `json:"note,omitempty"`
Creator *User `json:"creator,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
NodeID *string `json:"node_id,omitempty"`
Archived *bool `json:"archived,omitempty"`
// The following fields are only populated by Webhook events.
ColumnID *int64 `json:"column_id,omitempty"`
// The following fields are only populated by Events API.
ProjectID *int64 `json:"project_id,omitempty"`
ProjectURL *string `json:"project_url,omitempty"`
ColumnName *string `json:"column_name,omitempty"`
PreviousColumnName *string `json:"previous_column_name,omitempty"` // Populated in "moved_columns_in_project" event deliveries.
}
// ProjectCardListOptions specifies the optional parameters to the
// ProjectsService.ListProjectCards method.
type ProjectCardListOptions struct {
// ArchivedState is used to list all, archived, or not_archived project cards.
// Defaults to not_archived when you omit this parameter.
ArchivedState *string `url:"archived_state,omitempty"`
ListOptions
}
// ListProjectCards lists the cards in a column of a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/cards/#list-project-cards
func (s *ProjectsService) ListProjectCards(ctx context.Context, columnID int64, opts *ProjectCardListOptions) ([]*ProjectCard, *Response, error) {
u := fmt.Sprintf("projects/columns/%v/cards", columnID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
cards := []*ProjectCard{}
resp, err := s.client.Do(ctx, req, &cards)
if err != nil {
return nil, resp, err
}
return cards, resp, nil
}
// GetProjectCard gets a card in a column of a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/cards/#get-a-project-card
func (s *ProjectsService) GetProjectCard(ctx context.Context, cardID int64) (*ProjectCard, *Response, error) {
u := fmt.Sprintf("projects/columns/cards/%v", cardID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
card := &ProjectCard{}
resp, err := s.client.Do(ctx, req, card)
if err != nil {
return nil, resp, err
}
return card, resp, nil
}
// ProjectCardOptions specifies the parameters to the
// ProjectsService.CreateProjectCard and
// ProjectsService.UpdateProjectCard methods.
type ProjectCardOptions struct {
// The note of the card. Note and ContentID are mutually exclusive.
Note string `json:"note,omitempty"`
// The ID (not Number) of the Issue to associate with this card.
// Note and ContentID are mutually exclusive.
ContentID int64 `json:"content_id,omitempty"`
// The type of content to associate with this card. Possible values are: "Issue" and "PullRequest".
ContentType string `json:"content_type,omitempty"`
// Use true to archive a project card.
// Specify false if you need to restore a previously archived project card.
Archived *bool `json:"archived,omitempty"`
}
// CreateProjectCard creates a card in the specified column of a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/cards/#create-a-project-card
func (s *ProjectsService) CreateProjectCard(ctx context.Context, columnID int64, opts *ProjectCardOptions) (*ProjectCard, *Response, error) {
u := fmt.Sprintf("projects/columns/%v/cards", columnID)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
card := &ProjectCard{}
resp, err := s.client.Do(ctx, req, card)
if err != nil {
return nil, resp, err
}
return card, resp, nil
}
// UpdateProjectCard updates a card of a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/cards/#update-a-project-card
func (s *ProjectsService) UpdateProjectCard(ctx context.Context, cardID int64, opts *ProjectCardOptions) (*ProjectCard, *Response, error) {
u := fmt.Sprintf("projects/columns/cards/%v", cardID)
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeProjectsPreview)
card := &ProjectCard{}
resp, err := s.client.Do(ctx, req, card)
if err != nil {
return nil, resp, err
}
return card, resp, nil
}
// DeleteProjectCard deletes a card from a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/cards/#delete-a-project-card
func (s *ProjectsService) DeleteProjectCard(ctx context.Context, cardID int64) (*Response, error) {
u := fmt.Sprintf("projects/columns/cards/%v", cardID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
return s.client.Do(ctx, req, nil)
}
// ProjectCardMoveOptions specifies the parameters to the
// ProjectsService.MoveProjectCard method.
type ProjectCardMoveOptions struct {
// Position can be one of "top", "bottom", or "after:<card-id>", where
// <card-id> is the ID of a card in the same project.
Position string `json:"position"`
// ColumnID is the ID of a column in the same project. Note that ColumnID
// is required when using Position "after:<card-id>" when that card is in
// another column; otherwise it is optional.
ColumnID int64 `json:"column_id,omitempty"`
}
// MoveProjectCard moves a card within a GitHub Project.
//
// GitHub API docs: https://developer.github.com/v3/projects/cards/#move-a-project-card
func (s *ProjectsService) MoveProjectCard(ctx context.Context, cardID int64, opts *ProjectCardMoveOptions) (*Response, error) {
u := fmt.Sprintf("projects/columns/cards/%v/moves", cardID)
req, err := s.client.NewRequest("POST", u, opts)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
return s.client.Do(ctx, req, nil)
}
// ProjectCollaboratorOptions specifies the optional parameters to the
// ProjectsService.AddProjectCollaborator method.
type ProjectCollaboratorOptions struct {
// Permission specifies the permission to grant to the collaborator.
// Possible values are:
// "read" - can read, but not write to or administer this project.
// "write" - can read and write, but not administer this project.
// "admin" - can read, write and administer this project.
//
// Default value is "write"
Permission *string `json:"permission,omitempty"`
}
// AddProjectCollaborator adds a collaborator to an organization project and sets
// their permission level. You must be an organization owner or a project admin to add a collaborator.
//
// GitHub API docs: https://developer.github.com/v3/projects/collaborators/#add-user-as-a-collaborator
func (s *ProjectsService) AddProjectCollaborator(ctx context.Context, id int64, username string, opts *ProjectCollaboratorOptions) (*Response, error) {
u := fmt.Sprintf("projects/%v/collaborators/%v", id, username)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
return s.client.Do(ctx, req, nil)
}
// RemoveProjectCollaborator removes a collaborator from an organization project.
// You must be an organization owner or a project admin to remove a collaborator.
//
// GitHub API docs: https://developer.github.com/v3/projects/collaborators/#remove-user-as-a-collaborator
func (s *ProjectsService) RemoveProjectCollaborator(ctx context.Context, id int64, username string) (*Response, error) {
u := fmt.Sprintf("projects/%v/collaborators/%v", id, username)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
return s.client.Do(ctx, req, nil)
}
// ListCollaboratorOptions specifies the optional parameters to the
// ProjectsService.ListProjectCollaborators method.
type ListCollaboratorOptions struct {
// Affiliation specifies how collaborators should be filtered by their affiliation.
// Possible values are:
// "outside" - All outside collaborators of an organization-owned repository
// "direct" - All collaborators with permissions to an organization-owned repository,
// regardless of organization membership status
// "all" - All collaborators the authenticated user can see
//
// Default value is "all".
Affiliation *string `url:"affiliation,omitempty"`
ListOptions
}
// ListProjectCollaborators lists the collaborators for an organization project. For a project,
// the list of collaborators includes outside collaborators, organization members that are direct
// collaborators, organization members with access through team memberships, organization members
// with access through default organization permissions, and organization owners. You must be an
// organization owner or a project admin to list collaborators.
//
// GitHub API docs: https://developer.github.com/v3/projects/collaborators/#list-collaborators
func (s *ProjectsService) ListProjectCollaborators(ctx context.Context, id int64, opts *ListCollaboratorOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("projects/%v/collaborators", id)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
var users []*User
resp, err := s.client.Do(ctx, req, &users)
if err != nil {
return nil, resp, err
}
return users, resp, nil
}
// ProjectPermissionLevel represents the permission level an organization
// member has for a given project.
type ProjectPermissionLevel struct {
// Possible values: "admin", "write", "read", "none"
Permission *string `json:"permission,omitempty"`
User *User `json:"user,omitempty"`
}
// ReviewProjectCollaboratorPermission returns the collaborator's permission level for an organization
// project. Possible values for the permission key: "admin", "write", "read", "none".
// You must be an organization owner or a project admin to review a user's permission level.
//
// GitHub API docs: https://developer.github.com/v3/projects/collaborators/#review-a-users-permission-level
func (s *ProjectsService) ReviewProjectCollaboratorPermission(ctx context.Context, id int64, username string) (*ProjectPermissionLevel, *Response, error) {
u := fmt.Sprintf("projects/%v/collaborators/%v/permission", id, username)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeProjectsPreview)
ppl := new(ProjectPermissionLevel)
resp, err := s.client.Do(ctx, req, ppl)
if err != nil {
return nil, resp, err
}
return ppl, resp, nil
}

483
vendor/github.com/google/go-github/v29/github/pulls.go generated vendored Normal file
View file

@ -0,0 +1,483 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"bytes"
"context"
"fmt"
"strings"
"time"
)
// PullRequestsService handles communication with the pull request related
// methods of the GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/pulls/
type PullRequestsService service
// PullRequest represents a GitHub pull request on a repository.
type PullRequest struct {
ID *int64 `json:"id,omitempty"`
Number *int `json:"number,omitempty"`
State *string `json:"state,omitempty"`
Locked *bool `json:"locked,omitempty"`
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
ClosedAt *time.Time `json:"closed_at,omitempty"`
MergedAt *time.Time `json:"merged_at,omitempty"`
Labels []*Label `json:"labels,omitempty"`
User *User `json:"user,omitempty"`
Draft *bool `json:"draft,omitempty"`
Merged *bool `json:"merged,omitempty"`
Mergeable *bool `json:"mergeable,omitempty"`
MergeableState *string `json:"mergeable_state,omitempty"`
MergedBy *User `json:"merged_by,omitempty"`
MergeCommitSHA *string `json:"merge_commit_sha,omitempty"`
Rebaseable *bool `json:"rebaseable,omitempty"`
Comments *int `json:"comments,omitempty"`
Commits *int `json:"commits,omitempty"`
Additions *int `json:"additions,omitempty"`
Deletions *int `json:"deletions,omitempty"`
ChangedFiles *int `json:"changed_files,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
IssueURL *string `json:"issue_url,omitempty"`
StatusesURL *string `json:"statuses_url,omitempty"`
DiffURL *string `json:"diff_url,omitempty"`
PatchURL *string `json:"patch_url,omitempty"`
CommitsURL *string `json:"commits_url,omitempty"`
CommentsURL *string `json:"comments_url,omitempty"`
ReviewCommentsURL *string `json:"review_comments_url,omitempty"`
ReviewCommentURL *string `json:"review_comment_url,omitempty"`
ReviewComments *int `json:"review_comments,omitempty"`
Assignee *User `json:"assignee,omitempty"`
Assignees []*User `json:"assignees,omitempty"`
Milestone *Milestone `json:"milestone,omitempty"`
MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"`
AuthorAssociation *string `json:"author_association,omitempty"`
NodeID *string `json:"node_id,omitempty"`
RequestedReviewers []*User `json:"requested_reviewers,omitempty"`
// RequestedTeams is populated as part of the PullRequestEvent.
// See, https://developer.github.com/v3/activity/events/types/#pullrequestevent for an example.
RequestedTeams []*Team `json:"requested_teams,omitempty"`
Links *PRLinks `json:"_links,omitempty"`
Head *PullRequestBranch `json:"head,omitempty"`
Base *PullRequestBranch `json:"base,omitempty"`
// ActiveLockReason is populated only when LockReason is provided while locking the pull request.
// Possible values are: "off-topic", "too heated", "resolved", and "spam".
ActiveLockReason *string `json:"active_lock_reason,omitempty"`
}
func (p PullRequest) String() string {
return Stringify(p)
}
// PRLink represents a single link object from Github pull request _links.
type PRLink struct {
HRef *string `json:"href,omitempty"`
}
// PRLinks represents the "_links" object in a Github pull request.
type PRLinks struct {
Self *PRLink `json:"self,omitempty"`
HTML *PRLink `json:"html,omitempty"`
Issue *PRLink `json:"issue,omitempty"`
Comments *PRLink `json:"comments,omitempty"`
ReviewComments *PRLink `json:"review_comments,omitempty"`
ReviewComment *PRLink `json:"review_comment,omitempty"`
Commits *PRLink `json:"commits,omitempty"`
Statuses *PRLink `json:"statuses,omitempty"`
}
// PullRequestBranch represents a base or head branch in a GitHub pull request.
type PullRequestBranch struct {
Label *string `json:"label,omitempty"`
Ref *string `json:"ref,omitempty"`
SHA *string `json:"sha,omitempty"`
Repo *Repository `json:"repo,omitempty"`
User *User `json:"user,omitempty"`
}
// PullRequestListOptions specifies the optional parameters to the
// PullRequestsService.List method.
type PullRequestListOptions struct {
// State filters pull requests based on their state. Possible values are:
// open, closed, all. Default is "open".
State string `url:"state,omitempty"`
// Head filters pull requests by head user and branch name in the format of:
// "user:ref-name".
Head string `url:"head,omitempty"`
// Base filters pull requests by base branch name.
Base string `url:"base,omitempty"`
// Sort specifies how to sort pull requests. Possible values are: created,
// updated, popularity, long-running. Default is "created".
Sort string `url:"sort,omitempty"`
// Direction in which to sort pull requests. Possible values are: asc, desc.
// If Sort is "created" or not specified, Default is "desc", otherwise Default
// is "asc"
Direction string `url:"direction,omitempty"`
ListOptions
}
// List the pull requests for the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests
func (s *PullRequestsService) List(ctx context.Context, owner string, repo string, opts *PullRequestListOptions) ([]*PullRequest, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeLockReasonPreview, mediaTypeDraftPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var pulls []*PullRequest
resp, err := s.client.Do(ctx, req, &pulls)
if err != nil {
return nil, resp, err
}
return pulls, resp, nil
}
// ListPullRequestsWithCommit returns pull requests associated with a commit SHA.
//
// The results will include open and closed pull requests.
//
// GitHub API docs: https://developer.github.com/v3/repos/commits/#list-pull-requests-associated-with-commit
func (s *PullRequestsService) ListPullRequestsWithCommit(ctx context.Context, owner, repo, sha string, opts *PullRequestListOptions) ([]*PullRequest, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/pulls", owner, repo, sha)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeListPullsOrBranchesForCommitPreview, mediaTypeDraftPreview, mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var pulls []*PullRequest
resp, err := s.client.Do(ctx, req, &pulls)
if err != nil {
return nil, resp, err
}
return pulls, resp, nil
}
// Get a single pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#get-a-single-pull-request
func (s *PullRequestsService) Get(ctx context.Context, owner string, repo string, number int) (*PullRequest, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeLockReasonPreview, mediaTypeDraftPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
pull := new(PullRequest)
resp, err := s.client.Do(ctx, req, pull)
if err != nil {
return nil, resp, err
}
return pull, resp, nil
}
// GetRaw gets a single pull request in raw (diff or patch) format.
func (s *PullRequestsService) GetRaw(ctx context.Context, owner string, repo string, number int, opts RawOptions) (string, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return "", nil, err
}
switch opts.Type {
case Diff:
req.Header.Set("Accept", mediaTypeV3Diff)
case Patch:
req.Header.Set("Accept", mediaTypeV3Patch)
default:
return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type)
}
var buf bytes.Buffer
resp, err := s.client.Do(ctx, req, &buf)
if err != nil {
return "", resp, err
}
return buf.String(), resp, nil
}
// NewPullRequest represents a new pull request to be created.
type NewPullRequest struct {
Title *string `json:"title,omitempty"`
Head *string `json:"head,omitempty"`
Base *string `json:"base,omitempty"`
Body *string `json:"body,omitempty"`
Issue *int `json:"issue,omitempty"`
MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"`
Draft *bool `json:"draft,omitempty"`
}
// Create a new pull request on the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#create-a-pull-request
func (s *PullRequestsService) Create(ctx context.Context, owner string, repo string, pull *NewPullRequest) (*PullRequest, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls", owner, repo)
req, err := s.client.NewRequest("POST", u, pull)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeDraftPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
p := new(PullRequest)
resp, err := s.client.Do(ctx, req, p)
if err != nil {
return nil, resp, err
}
return p, resp, nil
}
// PullRequestBranchUpdateOptions specifies the optional parameters to the
// PullRequestsService.UpdateBranch method.
type PullRequestBranchUpdateOptions struct {
// ExpectedHeadSHA specifies the most recent commit on the pull request's branch.
// Default value is the SHA of the pull request's current HEAD ref.
ExpectedHeadSHA *string `json:"expected_head_sha,omitempty"`
}
// PullRequestBranchUpdateResponse specifies the response of pull request branch update.
type PullRequestBranchUpdateResponse struct {
Message *string `json:"message,omitempty"`
URL *string `json:"url,omitempty"`
}
// UpdateBranch updates the pull request branch with latest upstream changes.
//
// This method might return an AcceptedError and a status code of
// 202. This is because this is the status that GitHub returns to signify that
// it has now scheduled the update of the pull request branch in a background task.
// A follow up request, after a delay of a second or so, should result
// in a successful request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#update-a-pull-request-branch
func (s *PullRequestsService) UpdateBranch(ctx context.Context, owner, repo string, number int, opts *PullRequestBranchUpdateOptions) (*PullRequestBranchUpdateResponse, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/update-branch", owner, repo, number)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeUpdatePullRequestBranchPreview)
p := new(PullRequestBranchUpdateResponse)
resp, err := s.client.Do(ctx, req, p)
if err != nil {
return nil, resp, err
}
return p, resp, nil
}
type pullRequestUpdate struct {
Title *string `json:"title,omitempty"`
Body *string `json:"body,omitempty"`
State *string `json:"state,omitempty"`
Base *string `json:"base,omitempty"`
MaintainerCanModify *bool `json:"maintainer_can_modify,omitempty"`
}
// Edit a pull request.
// pull must not be nil.
//
// The following fields are editable: Title, Body, State, Base.Ref and MaintainerCanModify.
// Base.Ref updates the base branch of the pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#update-a-pull-request
func (s *PullRequestsService) Edit(ctx context.Context, owner string, repo string, number int, pull *PullRequest) (*PullRequest, *Response, error) {
if pull == nil {
return nil, nil, fmt.Errorf("pull must be provided")
}
u := fmt.Sprintf("repos/%v/%v/pulls/%d", owner, repo, number)
update := &pullRequestUpdate{
Title: pull.Title,
Body: pull.Body,
State: pull.State,
MaintainerCanModify: pull.MaintainerCanModify,
}
// avoid updating the base branch when closing the Pull Request
// - otherwise the GitHub API server returns a "Validation Failed" error:
// "Cannot change base branch of closed pull request".
if pull.Base != nil && pull.GetState() != "closed" {
update.Base = pull.Base.Ref
}
req, err := s.client.NewRequest("PATCH", u, update)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeLockReasonPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
p := new(PullRequest)
resp, err := s.client.Do(ctx, req, p)
if err != nil {
return nil, resp, err
}
return p, resp, nil
}
// ListCommits lists the commits in a pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request
func (s *PullRequestsService) ListCommits(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/commits", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var commits []*RepositoryCommit
resp, err := s.client.Do(ctx, req, &commits)
if err != nil {
return nil, resp, err
}
return commits, resp, nil
}
// ListFiles lists the files in a pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#list-pull-requests-files
func (s *PullRequestsService) ListFiles(ctx context.Context, owner string, repo string, number int, opts *ListOptions) ([]*CommitFile, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/files", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var commitFiles []*CommitFile
resp, err := s.client.Do(ctx, req, &commitFiles)
if err != nil {
return nil, resp, err
}
return commitFiles, resp, nil
}
// IsMerged checks if a pull request has been merged.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#get-if-a-pull-request-has-been-merged
func (s *PullRequestsService) IsMerged(ctx context.Context, owner string, repo string, number int) (bool, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
resp, err := s.client.Do(ctx, req, nil)
merged, err := parseBoolResponse(err)
return merged, resp, err
}
// PullRequestMergeResult represents the result of merging a pull request.
type PullRequestMergeResult struct {
SHA *string `json:"sha,omitempty"`
Merged *bool `json:"merged,omitempty"`
Message *string `json:"message,omitempty"`
}
// PullRequestOptions lets you define how a pull request will be merged.
type PullRequestOptions struct {
CommitTitle string // Extra detail to append to automatic commit message. (Optional.)
SHA string // SHA that pull request head must match to allow merge. (Optional.)
// The merge method to use. Possible values include: "merge", "squash", and "rebase" with the default being merge. (Optional.)
MergeMethod string
}
type pullRequestMergeRequest struct {
CommitMessage string `json:"commit_message"`
CommitTitle string `json:"commit_title,omitempty"`
MergeMethod string `json:"merge_method,omitempty"`
SHA string `json:"sha,omitempty"`
}
// Merge a pull request (Merge Button™).
// commitMessage is the title for the automatic commit message.
//
// GitHub API docs: https://developer.github.com/v3/pulls/#merge-a-pull-request-merge-buttontrade
func (s *PullRequestsService) Merge(ctx context.Context, owner string, repo string, number int, commitMessage string, options *PullRequestOptions) (*PullRequestMergeResult, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/merge", owner, repo, number)
pullRequestBody := &pullRequestMergeRequest{CommitMessage: commitMessage}
if options != nil {
pullRequestBody.CommitTitle = options.CommitTitle
pullRequestBody.MergeMethod = options.MergeMethod
pullRequestBody.SHA = options.SHA
}
req, err := s.client.NewRequest("PUT", u, pullRequestBody)
if err != nil {
return nil, nil, err
}
mergeResult := new(PullRequestMergeResult)
resp, err := s.client.Do(ctx, req, mergeResult)
if err != nil {
return nil, resp, err
}
return mergeResult, resp, nil
}

View file

@ -0,0 +1,201 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"strings"
"time"
)
// PullRequestComment represents a comment left on a pull request.
type PullRequestComment struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
InReplyTo *int64 `json:"in_reply_to_id,omitempty"`
Body *string `json:"body,omitempty"`
Path *string `json:"path,omitempty"`
DiffHunk *string `json:"diff_hunk,omitempty"`
PullRequestReviewID *int64 `json:"pull_request_review_id,omitempty"`
Position *int `json:"position,omitempty"`
OriginalPosition *int `json:"original_position,omitempty"`
StartLine *int `json:"start_line,omitempty"`
Line *int `json:"line,omitempty"`
OriginalLine *int `json:"original_line,omitempty"`
OriginalStartLine *int `json:"original_start_line,omitempty"`
Side *string `json:"side,omitempty"`
StartSide *string `json:"start_side,omitempty"`
CommitID *string `json:"commit_id,omitempty"`
OriginalCommitID *string `json:"original_commit_id,omitempty"`
User *User `json:"user,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
// AuthorAssociation is the comment author's relationship to the pull request's repository.
// Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE".
AuthorAssociation *string `json:"author_association,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
PullRequestURL *string `json:"pull_request_url,omitempty"`
}
func (p PullRequestComment) String() string {
return Stringify(p)
}
// PullRequestListCommentsOptions specifies the optional parameters to the
// PullRequestsService.ListComments method.
type PullRequestListCommentsOptions struct {
// Sort specifies how to sort comments. Possible values are: created, updated.
Sort string `url:"sort,omitempty"`
// Direction in which to sort comments. Possible values are: asc, desc.
Direction string `url:"direction,omitempty"`
// Since filters comments by time.
Since time.Time `url:"since,omitempty"`
ListOptions
}
// ListComments lists all comments on the specified pull request. Specifying a
// pull request number of 0 will return all comments on all pull requests for
// the repository.
//
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request
func (s *PullRequestsService) ListComments(ctx context.Context, owner string, repo string, number int, opts *PullRequestListCommentsOptions) ([]*PullRequestComment, *Response, error) {
var u string
if number == 0 {
u = fmt.Sprintf("repos/%v/%v/pulls/comments", owner, repo)
} else {
u = fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number)
}
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
var comments []*PullRequestComment
resp, err := s.client.Do(ctx, req, &comments)
if err != nil {
return nil, resp, err
}
return comments, resp, nil
}
// GetComment fetches the specified pull request comment.
//
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#get-a-single-comment
func (s *PullRequestsService) GetComment(ctx context.Context, owner string, repo string, commentID int64) (*PullRequestComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
comment := new(PullRequestComment)
resp, err := s.client.Do(ctx, req, comment)
if err != nil {
return nil, resp, err
}
return comment, resp, nil
}
// CreateComment creates a new comment on the specified pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#create-a-comment
func (s *PullRequestsService) CreateComment(ctx context.Context, owner string, repo string, number int, comment *PullRequestComment) (*PullRequestComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number)
req, err := s.client.NewRequest("POST", u, comment)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when their respective API fully launches.
acceptHeaders := []string{mediaTypeReactionsPreview, mediaTypeMultiLineCommentsPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
c := new(PullRequestComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// CreateCommentInReplyTo creates a new comment as a reply to an existing pull request comment.
//
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#alternative-input
func (s *PullRequestsService) CreateCommentInReplyTo(ctx context.Context, owner string, repo string, number int, body string, commentID int64) (*PullRequestComment, *Response, error) {
comment := &struct {
Body string `json:"body,omitempty"`
InReplyTo int64 `json:"in_reply_to,omitempty"`
}{
Body: body,
InReplyTo: commentID,
}
u := fmt.Sprintf("repos/%v/%v/pulls/%d/comments", owner, repo, number)
req, err := s.client.NewRequest("POST", u, comment)
if err != nil {
return nil, nil, err
}
c := new(PullRequestComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// EditComment updates a pull request comment.
// A non-nil comment.Body must be provided. Other comment fields should be left nil.
//
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#edit-a-comment
func (s *PullRequestsService) EditComment(ctx context.Context, owner string, repo string, commentID int64, comment *PullRequestComment) (*PullRequestComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("PATCH", u, comment)
if err != nil {
return nil, nil, err
}
c := new(PullRequestComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// DeleteComment deletes a pull request comment.
//
// GitHub API docs: https://developer.github.com/v3/pulls/comments/#delete-a-comment
func (s *PullRequestsService) DeleteComment(ctx context.Context, owner string, repo string, commentID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%d", owner, repo, commentID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,80 @@
// Copyright 2017 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ReviewersRequest specifies users and teams for a pull request review request.
type ReviewersRequest struct {
NodeID *string `json:"node_id,omitempty"`
Reviewers []string `json:"reviewers,omitempty"`
TeamReviewers []string `json:"team_reviewers,omitempty"`
}
// Reviewers represents reviewers of a pull request.
type Reviewers struct {
Users []*User `json:"users,omitempty"`
Teams []*Team `json:"teams,omitempty"`
}
// RequestReviewers creates a review request for the provided reviewers for the specified pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#create-a-review-request
func (s *PullRequestsService) RequestReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*PullRequest, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number)
req, err := s.client.NewRequest("POST", u, &reviewers)
if err != nil {
return nil, nil, err
}
r := new(PullRequest)
resp, err := s.client.Do(ctx, req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// ListReviewers lists reviewers whose reviews have been requested on the specified pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#list-review-requests
func (s *PullRequestsService) ListReviewers(ctx context.Context, owner, repo string, number int, opts *ListOptions) (*Reviewers, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/requested_reviewers", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
reviewers := new(Reviewers)
resp, err := s.client.Do(ctx, req, reviewers)
if err != nil {
return nil, resp, err
}
return reviewers, resp, nil
}
// RemoveReviewers removes the review request for the provided reviewers for the specified pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/review_requests/#delete-a-review-request
func (s *PullRequestsService) RemoveReviewers(ctx context.Context, owner, repo string, number int, reviewers ReviewersRequest) (*Response, error) {
u := fmt.Sprintf("repos/%s/%s/pulls/%d/requested_reviewers", owner, repo, number)
req, err := s.client.NewRequest("DELETE", u, &reviewers)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,264 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// PullRequestReview represents a review of a pull request.
type PullRequestReview struct {
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
User *User `json:"user,omitempty"`
Body *string `json:"body,omitempty"`
SubmittedAt *time.Time `json:"submitted_at,omitempty"`
CommitID *string `json:"commit_id,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
PullRequestURL *string `json:"pull_request_url,omitempty"`
State *string `json:"state,omitempty"`
// AuthorAssociation is the comment author's relationship to the issue's repository.
// Possible values are "COLLABORATOR", "CONTRIBUTOR", "FIRST_TIMER", "FIRST_TIME_CONTRIBUTOR", "MEMBER", "OWNER", or "NONE".
AuthorAssociation *string `json:"author_association,omitempty"`
}
func (p PullRequestReview) String() string {
return Stringify(p)
}
// DraftReviewComment represents a comment part of the review.
type DraftReviewComment struct {
Path *string `json:"path,omitempty"`
Position *int `json:"position,omitempty"`
Body *string `json:"body,omitempty"`
}
func (c DraftReviewComment) String() string {
return Stringify(c)
}
// PullRequestReviewRequest represents a request to create a review.
type PullRequestReviewRequest struct {
NodeID *string `json:"node_id,omitempty"`
CommitID *string `json:"commit_id,omitempty"`
Body *string `json:"body,omitempty"`
Event *string `json:"event,omitempty"`
Comments []*DraftReviewComment `json:"comments,omitempty"`
}
func (r PullRequestReviewRequest) String() string {
return Stringify(r)
}
// PullRequestReviewDismissalRequest represents a request to dismiss a review.
type PullRequestReviewDismissalRequest struct {
Message *string `json:"message,omitempty"`
}
func (r PullRequestReviewDismissalRequest) String() string {
return Stringify(r)
}
// ListReviews lists all reviews on the specified pull request.
//
// TODO: Follow up with GitHub support about an issue with this method's
// returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request
func (s *PullRequestsService) ListReviews(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var reviews []*PullRequestReview
resp, err := s.client.Do(ctx, req, &reviews)
if err != nil {
return nil, resp, err
}
return reviews, resp, nil
}
// GetReview fetches the specified pull request review.
//
// TODO: Follow up with GitHub support about an issue with this method's
// returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-a-single-review
func (s *PullRequestsService) GetReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
review := new(PullRequestReview)
resp, err := s.client.Do(ctx, req, review)
if err != nil {
return nil, resp, err
}
return review, resp, nil
}
// DeletePendingReview deletes the specified pull request pending review.
//
// TODO: Follow up with GitHub support about an issue with this method's
// returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review
func (s *PullRequestsService) DeletePendingReview(ctx context.Context, owner, repo string, number int, reviewID int64) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, nil, err
}
review := new(PullRequestReview)
resp, err := s.client.Do(ctx, req, review)
if err != nil {
return nil, resp, err
}
return review, resp, nil
}
// ListReviewComments lists all the comments for the specified review.
//
// TODO: Follow up with GitHub support about an issue with this method's
// returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review
func (s *PullRequestsService) ListReviewComments(ctx context.Context, owner, repo string, number int, reviewID int64, opts *ListOptions) ([]*PullRequestComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/comments", owner, repo, number, reviewID)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var comments []*PullRequestComment
resp, err := s.client.Do(ctx, req, &comments)
if err != nil {
return nil, resp, err
}
return comments, resp, nil
}
// CreateReview creates a new review on the specified pull request.
//
// TODO: Follow up with GitHub support about an issue with this method's
// returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review
func (s *PullRequestsService) CreateReview(ctx context.Context, owner, repo string, number int, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)
req, err := s.client.NewRequest("POST", u, review)
if err != nil {
return nil, nil, err
}
r := new(PullRequestReview)
resp, err := s.client.Do(ctx, req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// UpdateReview updates the review summary on the specified pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#update-a-pull-request-review
func (s *PullRequestsService) UpdateReview(ctx context.Context, owner, repo string, number int, reviewID int64, body string) (*PullRequestReview, *Response, error) {
opts := &struct {
Body string `json:"body"`
}{Body: body}
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d", owner, repo, number, reviewID)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, nil, err
}
review := &PullRequestReview{}
resp, err := s.client.Do(ctx, req, review)
if err != nil {
return nil, resp, err
}
return review, resp, nil
}
// SubmitReview submits a specified review on the specified pull request.
//
// TODO: Follow up with GitHub support about an issue with this method's
// returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review
func (s *PullRequestsService) SubmitReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewRequest) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/events", owner, repo, number, reviewID)
req, err := s.client.NewRequest("POST", u, review)
if err != nil {
return nil, nil, err
}
r := new(PullRequestReview)
resp, err := s.client.Do(ctx, req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}
// DismissReview dismisses a specified review on the specified pull request.
//
// TODO: Follow up with GitHub support about an issue with this method's
// returned error format and remove this comment once it's fixed.
// Read more about it here - https://github.com/google/go-github/issues/540
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review
func (s *PullRequestsService) DismissReview(ctx context.Context, owner, repo string, number int, reviewID int64, review *PullRequestReviewDismissalRequest) (*PullRequestReview, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews/%d/dismissals", owner, repo, number, reviewID)
req, err := s.client.NewRequest("PUT", u, review)
if err != nil {
return nil, nil, err
}
r := new(PullRequestReview)
resp, err := s.client.Do(ctx, req, r)
if err != nil {
return nil, resp, err
}
return r, resp, nil
}

View file

@ -0,0 +1,388 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ReactionsService provides access to the reactions-related functions in the
// GitHub API.
//
// GitHub API docs: https://developer.github.com/v3/reactions/
type ReactionsService service
// Reaction represents a GitHub reaction.
type Reaction struct {
// ID is the Reaction ID.
ID *int64 `json:"id,omitempty"`
User *User `json:"user,omitempty"`
NodeID *string `json:"node_id,omitempty"`
// Content is the type of reaction.
// Possible values are:
// "+1", "-1", "laugh", "confused", "heart", "hooray".
Content *string `json:"content,omitempty"`
}
// Reactions represents a summary of GitHub reactions.
type Reactions struct {
TotalCount *int `json:"total_count,omitempty"`
PlusOne *int `json:"+1,omitempty"`
MinusOne *int `json:"-1,omitempty"`
Laugh *int `json:"laugh,omitempty"`
Confused *int `json:"confused,omitempty"`
Heart *int `json:"heart,omitempty"`
Hooray *int `json:"hooray,omitempty"`
URL *string `json:"url,omitempty"`
}
func (r Reaction) String() string {
return Stringify(r)
}
// ListCommentReactionOptions specifies the optional parameters to the
// ReactionsService.ListCommentReactions method.
type ListCommentReactionOptions struct {
// Content restricts the returned comment reactions to only those with the given type.
// Omit this parameter to list all reactions to a commit comment.
// Possible values are: "+1", "-1", "laugh", "confused", "heart", "hooray", "rocket", or "eyes".
Content string `url:"content,omitempty"`
ListOptions
}
// ListCommentReactions lists the reactions for a commit comment.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-commit-comment
func (s *ReactionsService) ListCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListCommentReactionOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
var m []*Reaction
resp, err := s.client.Do(ctx, req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// CreateCommentReaction creates a reaction for a commit comment.
// Note that if you have already created a reaction of type content, the
// previously created reaction will be returned with Status: 200 OK.
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
//
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-commit-comment
func (s ReactionsService) CreateCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments/%v/reactions", owner, repo, id)
body := &Reaction{Content: String(content)}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
m := &Reaction{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListIssueReactions lists the reactions for an issue.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue
func (s *ReactionsService) ListIssueReactions(ctx context.Context, owner, repo string, number int, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
var m []*Reaction
resp, err := s.client.Do(ctx, req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// CreateIssueReaction creates a reaction for an issue.
// Note that if you have already created a reaction of type content, the
// previously created reaction will be returned with Status: 200 OK.
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
//
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue
func (s ReactionsService) CreateIssueReaction(ctx context.Context, owner, repo string, number int, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/%v/reactions", owner, repo, number)
body := &Reaction{Content: String(content)}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
m := &Reaction{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListIssueCommentReactions lists the reactions for an issue comment.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment
func (s *ReactionsService) ListIssueCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
var m []*Reaction
resp, err := s.client.Do(ctx, req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// CreateIssueCommentReaction creates a reaction for an issue comment.
// Note that if you have already created a reaction of type content, the
// previously created reaction will be returned with Status: 200 OK.
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
//
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment
func (s ReactionsService) CreateIssueCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/issues/comments/%v/reactions", owner, repo, id)
body := &Reaction{Content: String(content)}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
m := &Reaction{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListPullRequestCommentReactions lists the reactions for a pull request review comment.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-an-issue-comment
func (s *ReactionsService) ListPullRequestCommentReactions(ctx context.Context, owner, repo string, id int64, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
var m []*Reaction
resp, err := s.client.Do(ctx, req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// CreatePullRequestCommentReaction creates a reaction for a pull request review comment.
// Note that if you have already created a reaction of type content, the
// previously created reaction will be returned with Status: 200 OK.
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
//
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-an-issue-comment
func (s ReactionsService) CreatePullRequestCommentReaction(ctx context.Context, owner, repo string, id int64, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pulls/comments/%v/reactions", owner, repo, id)
body := &Reaction{Content: String(content)}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
req.Header.Set("Accept", mediaTypeReactionsPreview)
m := &Reaction{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListTeamDiscussionReactions lists the reactions for a team discussion.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion
func (s *ReactionsService) ListTeamDiscussionReactions(ctx context.Context, teamID int64, discussionNumber int, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeReactionsPreview)
var m []*Reaction
resp, err := s.client.Do(ctx, req, &m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// CreateTeamDiscussionReaction creates a reaction for a team discussion.
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
//
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-team-discussion
func (s *ReactionsService) CreateTeamDiscussionReaction(ctx context.Context, teamID int64, discussionNumber int, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/reactions", teamID, discussionNumber)
body := &Reaction{Content: String(content)}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeReactionsPreview)
m := &Reaction{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// ListTeamDiscussionCommentReactions lists the reactions for a team discussion comment.
//
// GitHub API docs: https://developer.github.com/v3/reactions/#list-reactions-for-a-team-discussion-comment
func (s *ReactionsService) ListTeamDiscussionCommentReactions(ctx context.Context, teamID int64, discussionNumber, commentNumber int, opts *ListOptions) ([]*Reaction, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeReactionsPreview)
var m []*Reaction
resp, err := s.client.Do(ctx, req, &m)
if err != nil {
return nil, nil, err
}
return m, resp, nil
}
// CreateTeamDiscussionCommentReaction creates a reaction for a team discussion comment.
// The content should have one of the following values: "+1", "-1", "laugh", "confused", "heart", "hooray".
//
// GitHub API docs: https://developer.github.com/v3/reactions/#create-reaction-for-a-team-discussion-comment
func (s *ReactionsService) CreateTeamDiscussionCommentReaction(ctx context.Context, teamID int64, discussionNumber, commentNumber int, content string) (*Reaction, *Response, error) {
u := fmt.Sprintf("teams/%v/discussions/%v/comments/%v/reactions", teamID, discussionNumber, commentNumber)
body := &Reaction{Content: String(content)}
req, err := s.client.NewRequest("POST", u, body)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeReactionsPreview)
m := &Reaction{}
resp, err := s.client.Do(ctx, req, m)
if err != nil {
return nil, resp, err
}
return m, resp, nil
}
// DeleteReaction deletes a reaction.
//
// GitHub API docs: https://developer.github.com/v3/reaction/reactions/#delete-a-reaction-archive
func (s *ReactionsService) DeleteReaction(ctx context.Context, id int64) (*Response, error) {
u := fmt.Sprintf("reactions/%v", id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeReactionsPreview)
return s.client.Do(ctx, req, nil)
}

1487
vendor/github.com/google/go-github/v29/github/repos.go generated vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,152 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// ListCollaboratorsOptions specifies the optional parameters to the
// RepositoriesService.ListCollaborators method.
type ListCollaboratorsOptions struct {
// Affiliation specifies how collaborators should be filtered by their affiliation.
// Possible values are:
// outside - All outside collaborators of an organization-owned repository
// direct - All collaborators with permissions to an organization-owned repository,
// regardless of organization membership status
// all - All collaborators the authenticated user can see
//
// Default value is "all".
Affiliation string `url:"affiliation,omitempty"`
ListOptions
}
// CollaboratorInvitation represents an invitation created when adding a collaborator.
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#response-when-a-new-invitation-is-created
type CollaboratorInvitation struct {
ID *int64 `json:"id,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Invitee *User `json:"invitee,omitempty"`
Inviter *User `json:"inviter,omitempty"`
Permissions *string `json:"permissions,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
}
// ListCollaborators lists the GitHub users that have access to the repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#list-collaborators
func (s *RepositoriesService) ListCollaborators(ctx context.Context, owner, repo string, opts *ListCollaboratorsOptions) ([]*User, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var users []*User
resp, err := s.client.Do(ctx, req, &users)
if err != nil {
return nil, resp, err
}
return users, resp, nil
}
// IsCollaborator checks whether the specified GitHub user has collaborator
// access to the given repo.
// Note: This will return false if the user is not a collaborator OR the user
// is not a GitHub user.
//
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#get
func (s *RepositoriesService) IsCollaborator(ctx context.Context, owner, repo, user string) (bool, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return false, nil, err
}
resp, err := s.client.Do(ctx, req, nil)
isCollab, err := parseBoolResponse(err)
return isCollab, resp, err
}
// RepositoryPermissionLevel represents the permission level an organization
// member has for a given repository.
type RepositoryPermissionLevel struct {
// Possible values: "admin", "write", "read", "none"
Permission *string `json:"permission,omitempty"`
User *User `json:"user,omitempty"`
}
// GetPermissionLevel retrieves the specific permission level a collaborator has for a given repository.
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level
func (s *RepositoriesService) GetPermissionLevel(ctx context.Context, owner, repo, user string) (*RepositoryPermissionLevel, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators/%v/permission", owner, repo, user)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
rpl := new(RepositoryPermissionLevel)
resp, err := s.client.Do(ctx, req, rpl)
if err != nil {
return nil, resp, err
}
return rpl, resp, nil
}
// RepositoryAddCollaboratorOptions specifies the optional parameters to the
// RepositoriesService.AddCollaborator method.
type RepositoryAddCollaboratorOptions struct {
// Permission specifies the permission to grant the user on this repository.
// Possible values are:
// pull - team members can pull, but not push to or administer this repository
// push - team members can pull and push, but not administer this repository
// admin - team members can pull, push and administer this repository
//
// Default value is "push". This option is only valid for organization-owned repositories.
Permission string `json:"permission,omitempty"`
}
// AddCollaborator sends an invitation to the specified GitHub user
// to become a collaborator to the given repo.
//
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#add-user-as-a-collaborator
func (s *RepositoriesService) AddCollaborator(ctx context.Context, owner, repo, user string, opts *RepositoryAddCollaboratorOptions) (*CollaboratorInvitation, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, nil, err
}
acr := new(CollaboratorInvitation)
resp, err := s.client.Do(ctx, req, acr)
if err != nil {
return nil, resp, err
}
return acr, resp, nil
}
// RemoveCollaborator removes the specified GitHub user as collaborator from the given repo.
// Note: Does not return error if a valid user that is not a collaborator is removed.
//
// GitHub API docs: https://developer.github.com/v3/repos/collaborators/#remove-collaborator
func (s *RepositoriesService) RemoveCollaborator(ctx context.Context, owner, repo, user string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/collaborators/%v", owner, repo, user)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,162 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// RepositoryComment represents a comment for a commit, file, or line in a repository.
type RepositoryComment struct {
HTMLURL *string `json:"html_url,omitempty"`
URL *string `json:"url,omitempty"`
ID *int64 `json:"id,omitempty"`
NodeID *string `json:"node_id,omitempty"`
CommitID *string `json:"commit_id,omitempty"`
User *User `json:"user,omitempty"`
Reactions *Reactions `json:"reactions,omitempty"`
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
// User-mutable fields
Body *string `json:"body"`
// User-initialized fields
Path *string `json:"path,omitempty"`
Position *int `json:"position,omitempty"`
}
func (r RepositoryComment) String() string {
return Stringify(r)
}
// ListComments lists all the comments for the repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-commit-comments-for-a-repository
func (s *RepositoriesService) ListComments(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeReactionsPreview)
var comments []*RepositoryComment
resp, err := s.client.Do(ctx, req, &comments)
if err != nil {
return nil, resp, err
}
return comments, resp, nil
}
// ListCommitComments lists all the comments for a given commit SHA.
//
// GitHub API docs: https://developer.github.com/v3/repos/comments/#list-comments-for-a-single-commit
func (s *RepositoriesService) ListCommitComments(ctx context.Context, owner, repo, sha string, opts *ListOptions) ([]*RepositoryComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeReactionsPreview)
var comments []*RepositoryComment
resp, err := s.client.Do(ctx, req, &comments)
if err != nil {
return nil, resp, err
}
return comments, resp, nil
}
// CreateComment creates a comment for the given commit.
// Note: GitHub allows for comments to be created for non-existing files and positions.
//
// GitHub API docs: https://developer.github.com/v3/repos/comments/#create-a-commit-comment
func (s *RepositoriesService) CreateComment(ctx context.Context, owner, repo, sha string, comment *RepositoryComment) (*RepositoryComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/comments", owner, repo, sha)
req, err := s.client.NewRequest("POST", u, comment)
if err != nil {
return nil, nil, err
}
c := new(RepositoryComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// GetComment gets a single comment from a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/comments/#get-a-single-commit-comment
func (s *RepositoriesService) GetComment(ctx context.Context, owner, repo string, id int64) (*RepositoryComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeReactionsPreview)
c := new(RepositoryComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// UpdateComment updates the body of a single comment.
//
// GitHub API docs: https://developer.github.com/v3/repos/comments/#update-a-commit-comment
func (s *RepositoriesService) UpdateComment(ctx context.Context, owner, repo string, id int64, comment *RepositoryComment) (*RepositoryComment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id)
req, err := s.client.NewRequest("PATCH", u, comment)
if err != nil {
return nil, nil, err
}
c := new(RepositoryComment)
resp, err := s.client.Do(ctx, req, c)
if err != nil {
return nil, resp, err
}
return c, resp, nil
}
// DeleteComment deletes a single comment from a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/comments/#delete-a-commit-comment
func (s *RepositoriesService) DeleteComment(ctx context.Context, owner, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/comments/%v", owner, repo, id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,264 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"bytes"
"context"
"fmt"
"net/url"
"time"
)
// RepositoryCommit represents a commit in a repo.
// Note that it's wrapping a Commit, so author/committer information is in two places,
// but contain different details about them: in RepositoryCommit "github details", in Commit - "git details".
type RepositoryCommit struct {
NodeID *string `json:"node_id,omitempty"`
SHA *string `json:"sha,omitempty"`
Commit *Commit `json:"commit,omitempty"`
Author *User `json:"author,omitempty"`
Committer *User `json:"committer,omitempty"`
Parents []Commit `json:"parents,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
URL *string `json:"url,omitempty"`
CommentsURL *string `json:"comments_url,omitempty"`
// Details about how many changes were made in this commit. Only filled in during GetCommit!
Stats *CommitStats `json:"stats,omitempty"`
// Details about which files, and how this commit touched. Only filled in during GetCommit!
Files []CommitFile `json:"files,omitempty"`
}
func (r RepositoryCommit) String() string {
return Stringify(r)
}
// CommitStats represents the number of additions / deletions from a file in a given RepositoryCommit or GistCommit.
type CommitStats struct {
Additions *int `json:"additions,omitempty"`
Deletions *int `json:"deletions,omitempty"`
Total *int `json:"total,omitempty"`
}
func (c CommitStats) String() string {
return Stringify(c)
}
// CommitFile represents a file modified in a commit.
type CommitFile struct {
SHA *string `json:"sha,omitempty"`
Filename *string `json:"filename,omitempty"`
Additions *int `json:"additions,omitempty"`
Deletions *int `json:"deletions,omitempty"`
Changes *int `json:"changes,omitempty"`
Status *string `json:"status,omitempty"`
Patch *string `json:"patch,omitempty"`
BlobURL *string `json:"blob_url,omitempty"`
RawURL *string `json:"raw_url,omitempty"`
ContentsURL *string `json:"contents_url,omitempty"`
PreviousFilename *string `json:"previous_filename,omitempty"`
}
func (c CommitFile) String() string {
return Stringify(c)
}
// CommitsComparison is the result of comparing two commits.
// See CompareCommits() for details.
type CommitsComparison struct {
BaseCommit *RepositoryCommit `json:"base_commit,omitempty"`
MergeBaseCommit *RepositoryCommit `json:"merge_base_commit,omitempty"`
// Head can be 'behind' or 'ahead'
Status *string `json:"status,omitempty"`
AheadBy *int `json:"ahead_by,omitempty"`
BehindBy *int `json:"behind_by,omitempty"`
TotalCommits *int `json:"total_commits,omitempty"`
Commits []RepositoryCommit `json:"commits,omitempty"`
Files []CommitFile `json:"files,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
PermalinkURL *string `json:"permalink_url,omitempty"`
DiffURL *string `json:"diff_url,omitempty"`
PatchURL *string `json:"patch_url,omitempty"`
URL *string `json:"url,omitempty"` // API URL.
}
func (c CommitsComparison) String() string {
return Stringify(c)
}
// CommitsListOptions specifies the optional parameters to the
// RepositoriesService.ListCommits method.
type CommitsListOptions struct {
// SHA or branch to start listing Commits from.
SHA string `url:"sha,omitempty"`
// Path that should be touched by the returned Commits.
Path string `url:"path,omitempty"`
// Author of by which to filter Commits.
Author string `url:"author,omitempty"`
// Since when should Commits be included in the response.
Since time.Time `url:"since,omitempty"`
// Until when should Commits be included in the response.
Until time.Time `url:"until,omitempty"`
ListOptions
}
// BranchCommit is the result of listing branches with commit SHA.
type BranchCommit struct {
Name *string `json:"name,omitempty"`
Commit *Commit `json:"commit,omitempty"`
Protected *bool `json:"protected,omitempty"`
}
// ListCommits lists the commits of a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/commits/#list
func (s *RepositoriesService) ListCommits(ctx context.Context, owner, repo string, opts *CommitsListOptions) ([]*RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var commits []*RepositoryCommit
resp, err := s.client.Do(ctx, req, &commits)
if err != nil {
return nil, resp, err
}
return commits, resp, nil
}
// GetCommit fetches the specified commit, including all details about it.
//
// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-a-single-commit
// See also: https://developer.github.com/v3/git/commits/#get-a-single-commit provides the same functionality
func (s *RepositoriesService) GetCommit(ctx context.Context, owner, repo, sha string) (*RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
commit := new(RepositoryCommit)
resp, err := s.client.Do(ctx, req, commit)
if err != nil {
return nil, resp, err
}
return commit, resp, nil
}
// GetCommitRaw fetches the specified commit in raw (diff or patch) format.
func (s *RepositoriesService) GetCommitRaw(ctx context.Context, owner string, repo string, sha string, opts RawOptions) (string, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return "", nil, err
}
switch opts.Type {
case Diff:
req.Header.Set("Accept", mediaTypeV3Diff)
case Patch:
req.Header.Set("Accept", mediaTypeV3Patch)
default:
return "", nil, fmt.Errorf("unsupported raw type %d", opts.Type)
}
var buf bytes.Buffer
resp, err := s.client.Do(ctx, req, &buf)
if err != nil {
return "", resp, err
}
return buf.String(), resp, nil
}
// GetCommitSHA1 gets the SHA-1 of a commit reference. If a last-known SHA1 is
// supplied and no new commits have occurred, a 304 Unmodified response is returned.
//
// GitHub API docs: https://developer.github.com/v3/repos/commits/#get-the-sha-1-of-a-commit-reference
func (s *RepositoriesService) GetCommitSHA1(ctx context.Context, owner, repo, ref, lastSHA string) (string, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v", owner, repo, url.QueryEscape(ref))
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return "", nil, err
}
if lastSHA != "" {
req.Header.Set("If-None-Match", `"`+lastSHA+`"`)
}
req.Header.Set("Accept", mediaTypeV3SHA)
var buf bytes.Buffer
resp, err := s.client.Do(ctx, req, &buf)
if err != nil {
return "", resp, err
}
return buf.String(), resp, nil
}
// CompareCommits compares a range of commits with each other.
// todo: support media formats - https://github.com/google/go-github/issues/6
//
// GitHub API docs: https://developer.github.com/v3/repos/commits/#compare-two-commits
func (s *RepositoriesService) CompareCommits(ctx context.Context, owner, repo string, base, head string) (*CommitsComparison, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/compare/%v...%v", owner, repo, base, head)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
comp := new(CommitsComparison)
resp, err := s.client.Do(ctx, req, comp)
if err != nil {
return nil, resp, err
}
return comp, resp, nil
}
// ListBranchesHeadCommit gets all branches where the given commit SHA is the HEAD,
// or latest commit for the branch.
//
// GitHub API docs: https://developer.github.com/v3/repos/commits/#list-branches-for-head-commit
func (s *RepositoriesService) ListBranchesHeadCommit(ctx context.Context, owner, repo, sha string) ([]*BranchCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/commits/%v/branches-where-head", owner, repo, sha)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeListPullsOrBranchesForCommitPreview)
var branchCommits []*BranchCommit
resp, err := s.client.Do(ctx, req, &branchCommits)
if err != nil {
return nil, resp, err
}
return branchCommits, resp, nil
}

View file

@ -0,0 +1,59 @@
// Copyright 2017 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// Metric represents the different fields for one file in community health files.
type Metric struct {
Name *string `json:"name"`
Key *string `json:"key"`
URL *string `json:"url"`
HTMLURL *string `json:"html_url"`
}
// CommunityHealthFiles represents the different files in the community health metrics response.
type CommunityHealthFiles struct {
CodeOfConduct *Metric `json:"code_of_conduct"`
Contributing *Metric `json:"contributing"`
IssueTemplate *Metric `json:"issue_template"`
PullRequestTemplate *Metric `json:"pull_request_template"`
License *Metric `json:"license"`
Readme *Metric `json:"readme"`
}
// CommunityHealthMetrics represents a response containing the community metrics of a repository.
type CommunityHealthMetrics struct {
HealthPercentage *int `json:"health_percentage"`
Files *CommunityHealthFiles `json:"files"`
UpdatedAt *time.Time `json:"updated_at"`
}
// GetCommunityHealthMetrics retrieves all the community health metrics for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/community/#retrieve-community-health-metrics
func (s *RepositoriesService) GetCommunityHealthMetrics(ctx context.Context, owner, repo string) (*CommunityHealthMetrics, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/community/profile", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeRepositoryCommunityHealthMetricsPreview)
metrics := &CommunityHealthMetrics{}
resp, err := s.client.Do(ctx, req, metrics)
if err != nil {
return nil, resp, err
}
return metrics, resp, nil
}

View file

@ -0,0 +1,288 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Repository contents API methods.
// GitHub API docs: https://developer.github.com/v3/repos/contents/
package github
import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"path"
)
// RepositoryContent represents a file or directory in a github repository.
type RepositoryContent struct {
Type *string `json:"type,omitempty"`
// Target is only set if the type is "symlink" and the target is not a normal file.
// If Target is set, Path will be the symlink path.
Target *string `json:"target,omitempty"`
Encoding *string `json:"encoding,omitempty"`
Size *int `json:"size,omitempty"`
Name *string `json:"name,omitempty"`
Path *string `json:"path,omitempty"`
// Content contains the actual file content, which may be encoded.
// Callers should call GetContent which will decode the content if
// necessary.
Content *string `json:"content,omitempty"`
SHA *string `json:"sha,omitempty"`
URL *string `json:"url,omitempty"`
GitURL *string `json:"git_url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
DownloadURL *string `json:"download_url,omitempty"`
}
// RepositoryContentResponse holds the parsed response from CreateFile, UpdateFile, and DeleteFile.
type RepositoryContentResponse struct {
Content *RepositoryContent `json:"content,omitempty"`
Commit `json:"commit,omitempty"`
}
// RepositoryContentFileOptions specifies optional parameters for CreateFile, UpdateFile, and DeleteFile.
type RepositoryContentFileOptions struct {
Message *string `json:"message,omitempty"`
Content []byte `json:"content,omitempty"` // unencoded
SHA *string `json:"sha,omitempty"`
Branch *string `json:"branch,omitempty"`
Author *CommitAuthor `json:"author,omitempty"`
Committer *CommitAuthor `json:"committer,omitempty"`
}
// RepositoryContentGetOptions represents an optional ref parameter, which can be a SHA,
// branch, or tag
type RepositoryContentGetOptions struct {
Ref string `url:"ref,omitempty"`
}
// String converts RepositoryContent to a string. It's primarily for testing.
func (r RepositoryContent) String() string {
return Stringify(r)
}
// GetContent returns the content of r, decoding it if necessary.
func (r *RepositoryContent) GetContent() (string, error) {
var encoding string
if r.Encoding != nil {
encoding = *r.Encoding
}
switch encoding {
case "base64":
if r.Content == nil {
return "", errors.New("malformed response: base64 encoding of null content")
}
c, err := base64.StdEncoding.DecodeString(*r.Content)
return string(c), err
case "":
if r.Content == nil {
return "", nil
}
return *r.Content, nil
default:
return "", fmt.Errorf("unsupported content encoding: %v", encoding)
}
}
// GetReadme gets the Readme file for the repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-the-readme
func (s *RepositoriesService) GetReadme(ctx context.Context, owner, repo string, opts *RepositoryContentGetOptions) (*RepositoryContent, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/readme", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
readme := new(RepositoryContent)
resp, err := s.client.Do(ctx, req, readme)
if err != nil {
return nil, resp, err
}
return readme, resp, nil
}
// DownloadContents returns an io.ReadCloser that reads the contents of the
// specified file. This function will work with files of any size, as opposed
// to GetContents which is limited to 1 Mb files. It is the caller's
// responsibility to close the ReadCloser.
func (s *RepositoriesService) DownloadContents(ctx context.Context, owner, repo, filepath string, opts *RepositoryContentGetOptions) (io.ReadCloser, error) {
dir := path.Dir(filepath)
filename := path.Base(filepath)
_, dirContents, _, err := s.GetContents(ctx, owner, repo, dir, opts)
if err != nil {
return nil, err
}
for _, contents := range dirContents {
if *contents.Name == filename {
if contents.DownloadURL == nil || *contents.DownloadURL == "" {
return nil, fmt.Errorf("No download link found for %s", filepath)
}
resp, err := s.client.client.Get(*contents.DownloadURL)
if err != nil {
return nil, err
}
return resp.Body, nil
}
}
return nil, fmt.Errorf("No file named %s found in %s", filename, dir)
}
// GetContents can return either the metadata and content of a single file
// (when path references a file) or the metadata of all the files and/or
// subdirectories of a directory (when path references a directory). To make it
// easy to distinguish between both result types and to mimic the API as much
// as possible, both result types will be returned but only one will contain a
// value and the other will be nil.
//
// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-contents
func (s *RepositoriesService) GetContents(ctx context.Context, owner, repo, path string, opts *RepositoryContentGetOptions) (fileContent *RepositoryContent, directoryContent []*RepositoryContent, resp *Response, err error) {
escapedPath := (&url.URL{Path: path}).String()
u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, escapedPath)
u, err = addOptions(u, opts)
if err != nil {
return nil, nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, nil, err
}
var rawJSON json.RawMessage
resp, err = s.client.Do(ctx, req, &rawJSON)
if err != nil {
return nil, nil, resp, err
}
fileUnmarshalError := json.Unmarshal(rawJSON, &fileContent)
if fileUnmarshalError == nil {
return fileContent, nil, resp, nil
}
directoryUnmarshalError := json.Unmarshal(rawJSON, &directoryContent)
if directoryUnmarshalError == nil {
return nil, directoryContent, resp, nil
}
return nil, nil, resp, fmt.Errorf("unmarshalling failed for both file and directory content: %s and %s", fileUnmarshalError, directoryUnmarshalError)
}
// CreateFile creates a new file in a repository at the given path and returns
// the commit and file metadata.
//
// GitHub API docs: https://developer.github.com/v3/repos/contents/#create-a-file
func (s *RepositoriesService) CreateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, nil, err
}
createResponse := new(RepositoryContentResponse)
resp, err := s.client.Do(ctx, req, createResponse)
if err != nil {
return nil, resp, err
}
return createResponse, resp, nil
}
// UpdateFile updates a file in a repository at the given path and returns the
// commit and file metadata. Requires the blob SHA of the file being updated.
//
// GitHub API docs: https://developer.github.com/v3/repos/contents/#update-a-file
func (s *RepositoriesService) UpdateFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
req, err := s.client.NewRequest("PUT", u, opts)
if err != nil {
return nil, nil, err
}
updateResponse := new(RepositoryContentResponse)
resp, err := s.client.Do(ctx, req, updateResponse)
if err != nil {
return nil, resp, err
}
return updateResponse, resp, nil
}
// DeleteFile deletes a file from a repository and returns the commit.
// Requires the blob SHA of the file to be deleted.
//
// GitHub API docs: https://developer.github.com/v3/repos/contents/#delete-a-file
func (s *RepositoriesService) DeleteFile(ctx context.Context, owner, repo, path string, opts *RepositoryContentFileOptions) (*RepositoryContentResponse, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/contents/%s", owner, repo, path)
req, err := s.client.NewRequest("DELETE", u, opts)
if err != nil {
return nil, nil, err
}
deleteResponse := new(RepositoryContentResponse)
resp, err := s.client.Do(ctx, req, deleteResponse)
if err != nil {
return nil, resp, err
}
return deleteResponse, resp, nil
}
// archiveFormat is used to define the archive type when calling GetArchiveLink.
type archiveFormat string
const (
// Tarball specifies an archive in gzipped tar format.
Tarball archiveFormat = "tarball"
// Zipball specifies an archive in zip format.
Zipball archiveFormat = "zipball"
)
// GetArchiveLink returns an URL to download a tarball or zipball archive for a
// repository. The archiveFormat can be specified by either the github.Tarball
// or github.Zipball constant.
//
// GitHub API docs: https://developer.github.com/v3/repos/contents/#get-archive-link
func (s *RepositoriesService) GetArchiveLink(ctx context.Context, owner, repo string, archiveformat archiveFormat, opts *RepositoryContentGetOptions, followRedirects bool) (*url.URL, *Response, error) {
u := fmt.Sprintf("repos/%s/%s/%s", owner, repo, archiveformat)
if opts != nil && opts.Ref != "" {
u += fmt.Sprintf("/%s", opts.Ref)
}
resp, err := s.getArchiveLinkFromURL(ctx, u, followRedirects)
if err != nil {
return nil, nil, err
}
if resp.StatusCode != http.StatusFound {
return nil, newResponse(resp), fmt.Errorf("unexpected status code: %s", resp.Status)
}
parsedURL, err := url.Parse(resp.Header.Get("Location"))
return parsedURL, newResponse(resp), err
}
func (s *RepositoriesService) getArchiveLinkFromURL(ctx context.Context, u string, followRedirects bool) (*http.Response, error) {
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, err
}
var resp *http.Response
// Use http.DefaultTransport if no custom Transport is configured
req = withContext(ctx, req)
if s.client.client.Transport == nil {
resp, err = http.DefaultTransport.RoundTrip(req)
} else {
resp, err = s.client.client.Transport.RoundTrip(req)
}
if err != nil {
return nil, err
}
resp.Body.Close()
// If redirect response is returned, follow it
if followRedirects && resp.StatusCode == http.StatusMovedPermanently {
u = resp.Header.Get("Location")
resp, err = s.getArchiveLinkFromURL(ctx, u, false)
}
return resp, err
}

View file

@ -0,0 +1,229 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"encoding/json"
"fmt"
"strings"
)
// Deployment represents a deployment in a repo
type Deployment struct {
URL *string `json:"url,omitempty"`
ID *int64 `json:"id,omitempty"`
SHA *string `json:"sha,omitempty"`
Ref *string `json:"ref,omitempty"`
Task *string `json:"task,omitempty"`
Payload json.RawMessage `json:"payload,omitempty"`
Environment *string `json:"environment,omitempty"`
Description *string `json:"description,omitempty"`
Creator *User `json:"creator,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
StatusesURL *string `json:"statuses_url,omitempty"`
RepositoryURL *string `json:"repository_url,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
// DeploymentRequest represents a deployment request
type DeploymentRequest struct {
Ref *string `json:"ref,omitempty"`
Task *string `json:"task,omitempty"`
AutoMerge *bool `json:"auto_merge,omitempty"`
RequiredContexts *[]string `json:"required_contexts,omitempty"`
Payload interface{} `json:"payload,omitempty"`
Environment *string `json:"environment,omitempty"`
Description *string `json:"description,omitempty"`
TransientEnvironment *bool `json:"transient_environment,omitempty"`
ProductionEnvironment *bool `json:"production_environment,omitempty"`
}
// DeploymentsListOptions specifies the optional parameters to the
// RepositoriesService.ListDeployments method.
type DeploymentsListOptions struct {
// SHA of the Deployment.
SHA string `url:"sha,omitempty"`
// List deployments for a given ref.
Ref string `url:"ref,omitempty"`
// List deployments for a given task.
Task string `url:"task,omitempty"`
// List deployments for a given environment.
Environment string `url:"environment,omitempty"`
ListOptions
}
// ListDeployments lists the deployments of a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployments
func (s *RepositoriesService) ListDeployments(ctx context.Context, owner, repo string, opts *DeploymentsListOptions) ([]*Deployment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var deployments []*Deployment
resp, err := s.client.Do(ctx, req, &deployments)
if err != nil {
return nil, resp, err
}
return deployments, resp, nil
}
// GetDeployment returns a single deployment of a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment
func (s *RepositoriesService) GetDeployment(ctx context.Context, owner, repo string, deploymentID int64) (*Deployment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments/%v", owner, repo, deploymentID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
deployment := new(Deployment)
resp, err := s.client.Do(ctx, req, deployment)
if err != nil {
return nil, resp, err
}
return deployment, resp, nil
}
// CreateDeployment creates a new deployment for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment
func (s *RepositoriesService) CreateDeployment(ctx context.Context, owner, repo string, request *DeploymentRequest) (*Deployment, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments", owner, repo)
req, err := s.client.NewRequest("POST", u, request)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
d := new(Deployment)
resp, err := s.client.Do(ctx, req, d)
if err != nil {
return nil, resp, err
}
return d, resp, nil
}
// DeploymentStatus represents the status of a
// particular deployment.
type DeploymentStatus struct {
ID *int64 `json:"id,omitempty"`
// State is the deployment state.
// Possible values are: "pending", "success", "failure", "error", "inactive".
State *string `json:"state,omitempty"`
Creator *User `json:"creator,omitempty"`
Description *string `json:"description,omitempty"`
TargetURL *string `json:"target_url,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
DeploymentURL *string `json:"deployment_url,omitempty"`
RepositoryURL *string `json:"repository_url,omitempty"`
NodeID *string `json:"node_id,omitempty"`
}
// DeploymentStatusRequest represents a deployment request
type DeploymentStatusRequest struct {
State *string `json:"state,omitempty"`
LogURL *string `json:"log_url,omitempty"`
Description *string `json:"description,omitempty"`
Environment *string `json:"environment,omitempty"`
EnvironmentURL *string `json:"environment_url,omitempty"`
AutoInactive *bool `json:"auto_inactive,omitempty"`
}
// ListDeploymentStatuses lists the statuses of a given deployment of a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#list-deployment-statuses
func (s *RepositoriesService) ListDeploymentStatuses(ctx context.Context, owner, repo string, deployment int64, opts *ListOptions) ([]*DeploymentStatus, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var statuses []*DeploymentStatus
resp, err := s.client.Do(ctx, req, &statuses)
if err != nil {
return nil, resp, err
}
return statuses, resp, nil
}
// GetDeploymentStatus returns a single deployment status of a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#get-a-single-deployment-status
func (s *RepositoriesService) GetDeploymentStatus(ctx context.Context, owner, repo string, deploymentID, deploymentStatusID int64) (*DeploymentStatus, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses/%v", owner, repo, deploymentID, deploymentStatusID)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
d := new(DeploymentStatus)
resp, err := s.client.Do(ctx, req, d)
if err != nil {
return nil, resp, err
}
return d, resp, nil
}
// CreateDeploymentStatus creates a new status for a deployment.
//
// GitHub API docs: https://developer.github.com/v3/repos/deployments/#create-a-deployment-status
func (s *RepositoriesService) CreateDeploymentStatus(ctx context.Context, owner, repo string, deployment int64, request *DeploymentStatusRequest) (*DeploymentStatus, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/deployments/%v/statuses", owner, repo, deployment)
req, err := s.client.NewRequest("POST", u, request)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept headers when APIs fully launch.
acceptHeaders := []string{mediaTypeDeploymentStatusPreview, mediaTypeExpandDeploymentStatusPreview}
req.Header.Set("Accept", strings.Join(acceptHeaders, ", "))
d := new(DeploymentStatus)
resp, err := s.client.Do(ctx, req, d)
if err != nil {
return nil, resp, err
}
return d, resp, nil
}

View file

@ -0,0 +1,96 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"encoding/json"
)
// RepositoryListForksOptions specifies the optional parameters to the
// RepositoriesService.ListForks method.
type RepositoryListForksOptions struct {
// How to sort the forks list. Possible values are: newest, oldest,
// watchers. Default is "newest".
Sort string `url:"sort,omitempty"`
ListOptions
}
// ListForks lists the forks of the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/forks/#list-forks
func (s *RepositoriesService) ListForks(ctx context.Context, owner, repo string, opts *RepositoryListForksOptions) ([]*Repository, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/forks", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when topics API fully launches.
req.Header.Set("Accept", mediaTypeTopicsPreview)
var repos []*Repository
resp, err := s.client.Do(ctx, req, &repos)
if err != nil {
return nil, resp, err
}
return repos, resp, nil
}
// RepositoryCreateForkOptions specifies the optional parameters to the
// RepositoriesService.CreateFork method.
type RepositoryCreateForkOptions struct {
// The organization to fork the repository into.
Organization string `url:"organization,omitempty"`
}
// CreateFork creates a fork of the specified repository.
//
// This method might return an *AcceptedError and a status code of
// 202. This is because this is the status that GitHub returns to signify that
// it is now computing creating the fork in a background task. In this event,
// the Repository value will be returned, which includes the details about the pending fork.
// A follow up request, after a delay of a second or so, should result
// in a successful request.
//
// GitHub API docs: https://developer.github.com/v3/repos/forks/#create-a-fork
func (s *RepositoriesService) CreateFork(ctx context.Context, owner, repo string, opts *RepositoryCreateForkOptions) (*Repository, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/forks", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
fork := new(Repository)
resp, err := s.client.Do(ctx, req, fork)
if err != nil {
// Persist AcceptedError's metadata to the Repository object.
if aerr, ok := err.(*AcceptedError); ok {
if err := json.Unmarshal(aerr.Raw, fork); err != nil {
return fork, resp, err
}
return fork, resp, err
}
return nil, resp, err
}
return fork, resp, nil
}

View file

@ -0,0 +1,226 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
"time"
)
// WebHookPayload represents the data that is received from GitHub when a push
// event hook is triggered. The format of these payloads pre-date most of the
// GitHub v3 API, so there are lots of minor incompatibilities with the types
// defined in the rest of the API. Therefore, several types are duplicated
// here to account for these differences.
//
// GitHub API docs: https://help.github.com/articles/post-receive-hooks
type WebHookPayload struct {
After *string `json:"after,omitempty"`
Before *string `json:"before,omitempty"`
Commits []WebHookCommit `json:"commits,omitempty"`
Compare *string `json:"compare,omitempty"`
Created *bool `json:"created,omitempty"`
Deleted *bool `json:"deleted,omitempty"`
Forced *bool `json:"forced,omitempty"`
HeadCommit *WebHookCommit `json:"head_commit,omitempty"`
Pusher *User `json:"pusher,omitempty"`
Ref *string `json:"ref,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Sender *User `json:"sender,omitempty"`
}
func (w WebHookPayload) String() string {
return Stringify(w)
}
// WebHookCommit represents the commit variant we receive from GitHub in a
// WebHookPayload.
type WebHookCommit struct {
Added []string `json:"added,omitempty"`
Author *WebHookAuthor `json:"author,omitempty"`
Committer *WebHookAuthor `json:"committer,omitempty"`
Distinct *bool `json:"distinct,omitempty"`
ID *string `json:"id,omitempty"`
Message *string `json:"message,omitempty"`
Modified []string `json:"modified,omitempty"`
Removed []string `json:"removed,omitempty"`
Timestamp *time.Time `json:"timestamp,omitempty"`
}
func (w WebHookCommit) String() string {
return Stringify(w)
}
// WebHookAuthor represents the author or committer of a commit, as specified
// in a WebHookCommit. The commit author may not correspond to a GitHub User.
type WebHookAuthor struct {
Email *string `json:"email,omitempty"`
Name *string `json:"name,omitempty"`
Username *string `json:"username,omitempty"`
}
func (w WebHookAuthor) String() string {
return Stringify(w)
}
// Hook represents a GitHub (web and service) hook for a repository.
type Hook struct {
CreatedAt *time.Time `json:"created_at,omitempty"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
URL *string `json:"url,omitempty"`
ID *int64 `json:"id,omitempty"`
// Only the following fields are used when creating a hook.
// Config is required.
Config map[string]interface{} `json:"config,omitempty"`
Events []string `json:"events,omitempty"`
Active *bool `json:"active,omitempty"`
}
func (h Hook) String() string {
return Stringify(h)
}
// createHookRequest is a subset of Hook and is used internally
// by CreateHook to pass only the known fields for the endpoint.
//
// See https://github.com/google/go-github/issues/1015 for more
// information.
type createHookRequest struct {
// Config is required.
Name string `json:"name"`
Config map[string]interface{} `json:"config,omitempty"`
Events []string `json:"events,omitempty"`
Active *bool `json:"active,omitempty"`
}
// CreateHook creates a Hook for the specified repository.
// Config is a required field.
//
// Note that only a subset of the hook fields are used and hook must
// not be nil.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#create-a-hook
func (s *RepositoriesService) CreateHook(ctx context.Context, owner, repo string, hook *Hook) (*Hook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo)
hookReq := &createHookRequest{
Name: "web",
Events: hook.Events,
Active: hook.Active,
Config: hook.Config,
}
req, err := s.client.NewRequest("POST", u, hookReq)
if err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := s.client.Do(ctx, req, h)
if err != nil {
return nil, resp, err
}
return h, resp, nil
}
// ListHooks lists all Hooks for the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#list
func (s *RepositoriesService) ListHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*Hook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var hooks []*Hook
resp, err := s.client.Do(ctx, req, &hooks)
if err != nil {
return nil, resp, err
}
return hooks, resp, nil
}
// GetHook returns a single specified Hook.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#get-single-hook
func (s *RepositoriesService) GetHook(ctx context.Context, owner, repo string, id int64) (*Hook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := s.client.Do(ctx, req, h)
if err != nil {
return nil, resp, err
}
return h, resp, nil
}
// EditHook updates a specified Hook.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#edit-a-hook
func (s *RepositoriesService) EditHook(ctx context.Context, owner, repo string, id int64, hook *Hook) (*Hook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id)
req, err := s.client.NewRequest("PATCH", u, hook)
if err != nil {
return nil, nil, err
}
h := new(Hook)
resp, err := s.client.Do(ctx, req, h)
if err != nil {
return nil, resp, err
}
return h, resp, nil
}
// DeleteHook deletes a specified Hook.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#delete-a-hook
func (s *RepositoriesService) DeleteHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d", owner, repo, id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// PingHook triggers a 'ping' event to be sent to the Hook.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#ping-a-hook
func (s *RepositoriesService) PingHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d/pings", owner, repo, id)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// TestHook triggers a test Hook by github.
//
// GitHub API docs: https://developer.github.com/v3/repos/hooks/#test-a-push-hook
func (s *RepositoriesService) TestHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/hooks/%d/tests", owner, repo, id)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,89 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// RepositoryInvitation represents an invitation to collaborate on a repo.
type RepositoryInvitation struct {
ID *int64 `json:"id,omitempty"`
Repo *Repository `json:"repository,omitempty"`
Invitee *User `json:"invitee,omitempty"`
Inviter *User `json:"inviter,omitempty"`
// Permissions represents the permissions that the associated user will have
// on the repository. Possible values are: "read", "write", "admin".
Permissions *string `json:"permissions,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
URL *string `json:"url,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
}
// ListInvitations lists all currently-open repository invitations.
//
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#list-invitations-for-a-repository
func (s *RepositoriesService) ListInvitations(ctx context.Context, owner, repo string, opts *ListOptions) ([]*RepositoryInvitation, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/invitations", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
invites := []*RepositoryInvitation{}
resp, err := s.client.Do(ctx, req, &invites)
if err != nil {
return nil, resp, err
}
return invites, resp, nil
}
// DeleteInvitation deletes a repository invitation.
//
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#delete-a-repository-invitation
func (s *RepositoriesService) DeleteInvitation(ctx context.Context, owner, repo string, invitationID int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}
// UpdateInvitation updates the permissions associated with a repository
// invitation.
//
// permissions represents the permissions that the associated user will have
// on the repository. Possible values are: "read", "write", "admin".
//
// GitHub API docs: https://developer.github.com/v3/repos/invitations/#update-a-repository-invitation
func (s *RepositoriesService) UpdateInvitation(ctx context.Context, owner, repo string, invitationID int64, permissions string) (*RepositoryInvitation, *Response, error) {
opts := &struct {
Permissions string `json:"permissions"`
}{Permissions: permissions}
u := fmt.Sprintf("repos/%v/%v/invitations/%v", owner, repo, invitationID)
req, err := s.client.NewRequest("PATCH", u, opts)
if err != nil {
return nil, nil, err
}
invite := &RepositoryInvitation{}
resp, err := s.client.Do(ctx, req, invite)
if err != nil {
return nil, resp, err
}
return invite, resp, nil
}

View file

@ -0,0 +1,111 @@
// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// The Key type is defined in users_keys.go
// ListKeys lists the deploy keys for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/keys/#list
func (s *RepositoriesService) ListKeys(ctx context.Context, owner string, repo string, opts *ListOptions) ([]*Key, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var keys []*Key
resp, err := s.client.Do(ctx, req, &keys)
if err != nil {
return nil, resp, err
}
return keys, resp, nil
}
// GetKey fetches a single deploy key.
//
// GitHub API docs: https://developer.github.com/v3/repos/keys/#get
func (s *RepositoriesService) GetKey(ctx context.Context, owner string, repo string, id int64) (*Key, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
key := new(Key)
resp, err := s.client.Do(ctx, req, key)
if err != nil {
return nil, resp, err
}
return key, resp, nil
}
// CreateKey adds a deploy key for a repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/keys/#create
func (s *RepositoriesService) CreateKey(ctx context.Context, owner string, repo string, key *Key) (*Key, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys", owner, repo)
req, err := s.client.NewRequest("POST", u, key)
if err != nil {
return nil, nil, err
}
k := new(Key)
resp, err := s.client.Do(ctx, req, k)
if err != nil {
return nil, resp, err
}
return k, resp, nil
}
// EditKey edits a deploy key.
//
// GitHub API docs: https://developer.github.com/v3/repos/keys/#edit
func (s *RepositoriesService) EditKey(ctx context.Context, owner string, repo string, id int64, key *Key) (*Key, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id)
req, err := s.client.NewRequest("PATCH", u, key)
if err != nil {
return nil, nil, err
}
k := new(Key)
resp, err := s.client.Do(ctx, req, k)
if err != nil {
return nil, resp, err
}
return k, resp, nil
}
// DeleteKey deletes a deploy key.
//
// GitHub API docs: https://developer.github.com/v3/repos/keys/#delete
func (s *RepositoriesService) DeleteKey(ctx context.Context, owner string, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/keys/%v", owner, repo, id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
return s.client.Do(ctx, req, nil)
}

View file

@ -0,0 +1,38 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// RepositoryMergeRequest represents a request to merge a branch in a
// repository.
type RepositoryMergeRequest struct {
Base *string `json:"base,omitempty"`
Head *string `json:"head,omitempty"`
CommitMessage *string `json:"commit_message,omitempty"`
}
// Merge a branch in the specified repository.
//
// GitHub API docs: https://developer.github.com/v3/repos/merging/#perform-a-merge
func (s *RepositoriesService) Merge(ctx context.Context, owner, repo string, request *RepositoryMergeRequest) (*RepositoryCommit, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/merges", owner, repo)
req, err := s.client.NewRequest("POST", u, request)
if err != nil {
return nil, nil, err
}
commit := new(RepositoryCommit)
resp, err := s.client.Do(ctx, req, commit)
if err != nil {
return nil, resp, err
}
return commit, resp, nil
}

View file

@ -0,0 +1,192 @@
// Copyright 2014 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// Pages represents a GitHub Pages site configuration.
type Pages struct {
URL *string `json:"url,omitempty"`
Status *string `json:"status,omitempty"`
CNAME *string `json:"cname,omitempty"`
Custom404 *bool `json:"custom_404,omitempty"`
HTMLURL *string `json:"html_url,omitempty"`
Source *PagesSource `json:"source,omitempty"`
}
// PagesSource represents a GitHub page's source.
type PagesSource struct {
Branch *string `json:"branch,omitempty"`
Path *string `json:"path,omitempty"`
}
// PagesError represents a build error for a GitHub Pages site.
type PagesError struct {
Message *string `json:"message,omitempty"`
}
// PagesBuild represents the build information for a GitHub Pages site.
type PagesBuild struct {
URL *string `json:"url,omitempty"`
Status *string `json:"status,omitempty"`
Error *PagesError `json:"error,omitempty"`
Pusher *User `json:"pusher,omitempty"`
Commit *string `json:"commit,omitempty"`
Duration *int `json:"duration,omitempty"`
CreatedAt *Timestamp `json:"created_at,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
}
// createPagesRequest is a subset of Pages and is used internally
// by EnablePages to pass only the known fields for the endpoint.
type createPagesRequest struct {
Source *PagesSource `json:"source,omitempty"`
}
// EnablePages enables GitHub Pages for the named repo.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#enable-a-pages-site
func (s *RepositoriesService) EnablePages(ctx context.Context, owner, repo string, pages *Pages) (*Pages, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
pagesReq := &createPagesRequest{
Source: pages.Source,
}
req, err := s.client.NewRequest("POST", u, pagesReq)
if err != nil {
return nil, nil, err
}
req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview)
enable := new(Pages)
resp, err := s.client.Do(ctx, req, enable)
if err != nil {
return nil, resp, err
}
return enable, resp, nil
}
// DisablePages disables GitHub Pages for the named repo.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#disable-a-pages-site
func (s *RepositoriesService) DisablePages(ctx context.Context, owner, repo string) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypeEnablePagesAPIPreview)
return s.client.Do(ctx, req, nil)
}
// GetPagesInfo fetches information about a GitHub Pages site.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#get-information-about-a-pages-site
func (s *RepositoriesService) GetPagesInfo(ctx context.Context, owner, repo string) (*Pages, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
site := new(Pages)
resp, err := s.client.Do(ctx, req, site)
if err != nil {
return nil, resp, err
}
return site, resp, nil
}
// ListPagesBuilds lists the builds for a GitHub Pages site.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-pages-builds
func (s *RepositoriesService) ListPagesBuilds(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PagesBuild, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
var pages []*PagesBuild
resp, err := s.client.Do(ctx, req, &pages)
if err != nil {
return nil, resp, err
}
return pages, resp, nil
}
// GetLatestPagesBuild fetches the latest build information for a GitHub pages site.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-latest-pages-build
func (s *RepositoriesService) GetLatestPagesBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages/builds/latest", owner, repo)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
build := new(PagesBuild)
resp, err := s.client.Do(ctx, req, build)
if err != nil {
return nil, resp, err
}
return build, resp, nil
}
// GetPageBuild fetches the specific build information for a GitHub pages site.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#list-a-specific-pages-build
func (s *RepositoriesService) GetPageBuild(ctx context.Context, owner, repo string, id int64) (*PagesBuild, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages/builds/%v", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
build := new(PagesBuild)
resp, err := s.client.Do(ctx, req, build)
if err != nil {
return nil, resp, err
}
return build, resp, nil
}
// RequestPageBuild requests a build of a GitHub Pages site without needing to push new commit.
//
// GitHub API docs: https://developer.github.com/v3/repos/pages/#request-a-page-build
func (s *RepositoriesService) RequestPageBuild(ctx context.Context, owner, repo string) (*PagesBuild, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pages/builds", owner, repo)
req, err := s.client.NewRequest("POST", u, nil)
if err != nil {
return nil, nil, err
}
build := new(PagesBuild)
resp, err := s.client.Do(ctx, req, build)
if err != nil {
return nil, resp, err
}
return build, resp, nil
}

View file

@ -0,0 +1,110 @@
// Copyright 2018 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package github
import (
"context"
"fmt"
)
// PreReceiveHook represents a GitHub pre-receive hook for a repository.
type PreReceiveHook struct {
ID *int64 `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
Enforcement *string `json:"enforcement,omitempty"`
ConfigURL *string `json:"configuration_url,omitempty"`
}
func (p PreReceiveHook) String() string {
return Stringify(p)
}
// ListPreReceiveHooks lists all pre-receive hooks for the specified repository.
//
// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#list-pre-receive-hooks
func (s *RepositoriesService) ListPreReceiveHooks(ctx context.Context, owner, repo string, opts *ListOptions) ([]*PreReceiveHook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks", owner, repo)
u, err := addOptions(u, opts)
if err != nil {
return nil, nil, err
}
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypePreReceiveHooksPreview)
var hooks []*PreReceiveHook
resp, err := s.client.Do(ctx, req, &hooks)
if err != nil {
return nil, resp, err
}
return hooks, resp, nil
}
// GetPreReceiveHook returns a single specified pre-receive hook.
//
// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#get-a-single-pre-receive-hook
func (s *RepositoriesService) GetPreReceiveHook(ctx context.Context, owner, repo string, id int64) (*PreReceiveHook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id)
req, err := s.client.NewRequest("GET", u, nil)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypePreReceiveHooksPreview)
h := new(PreReceiveHook)
resp, err := s.client.Do(ctx, req, h)
if err != nil {
return nil, resp, err
}
return h, resp, nil
}
// UpdatePreReceiveHook updates a specified pre-receive hook.
//
// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#update-pre-receive-hook-enforcement
func (s *RepositoriesService) UpdatePreReceiveHook(ctx context.Context, owner, repo string, id int64, hook *PreReceiveHook) (*PreReceiveHook, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id)
req, err := s.client.NewRequest("PATCH", u, hook)
if err != nil {
return nil, nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypePreReceiveHooksPreview)
h := new(PreReceiveHook)
resp, err := s.client.Do(ctx, req, h)
if err != nil {
return nil, resp, err
}
return h, resp, nil
}
// DeletePreReceiveHook deletes a specified pre-receive hook.
//
// GitHub API docs: https://developer.github.com/enterprise/2.13/v3/repos/pre_receive_hooks/#remove-enforcement-overrides-for-a-pre-receive-hook
func (s *RepositoriesService) DeletePreReceiveHook(ctx context.Context, owner, repo string, id int64) (*Response, error) {
u := fmt.Sprintf("repos/%v/%v/pre-receive-hooks/%d", owner, repo, id)
req, err := s.client.NewRequest("DELETE", u, nil)
if err != nil {
return nil, err
}
// TODO: remove custom Accept header when this API fully launches.
req.Header.Set("Accept", mediaTypePreReceiveHooksPreview)
return s.client.Do(ctx, req, nil)
}

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