diff --git a/.gitignore b/.gitignore index 62df61af..6e404d33 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ Session.vim .netrwhist gdrive gdrive.sh +vendor diff --git a/auth/oauth.go b/auth/oauth.go index bc567385..f1c3e38e 100644 --- a/auth/oauth.go +++ b/auth/oauth.go @@ -4,20 +4,22 @@ import ( "fmt" "golang.org/x/oauth2" "golang.org/x/oauth2/google" + "os" "net/http" "time" ) type authCodeFn func(string) func() string -func NewFileSourceClient(clientId, clientSecret, tokenFile string, authFn authCodeFn) (*http.Client, error) { - conf := getConfig(clientId, clientSecret) - +func NewFileSourceClient(tokenFile string, authFn authCodeFn) (*http.Client, error) { + // Read cached token token, exists, err := ReadToken(tokenFile) if err != nil { return nil, fmt.Errorf("Failed to read token: %s", err) } + clientId, clientSecret := getOauthClientInfo() + conf := getConfig(clientId, clientSecret) // Require auth code if token file does not exist // or refresh token is missing @@ -36,7 +38,8 @@ func NewFileSourceClient(clientId, clientSecret, tokenFile string, authFn authCo ), nil } -func NewRefreshTokenClient(clientId, clientSecret, refreshToken string) *http.Client { +func NewRefreshTokenClient(refreshToken string) *http.Client { + clientId, clientSecret := getOauthClientInfo() conf := getConfig(clientId, clientSecret) token := &oauth2.Token{ @@ -51,7 +54,8 @@ func NewRefreshTokenClient(clientId, clientSecret, refreshToken string) *http.Cl ) } -func NewAccessTokenClient(clientId, clientSecret, accessToken string) *http.Client { +func NewAccessTokenClient(accessToken string) *http.Client { + clientId, clientSecret := getOauthClientInfo() conf := getConfig(clientId, clientSecret) token := &oauth2.Token{ @@ -94,3 +98,10 @@ func getConfig(clientId, clientSecret string) *oauth2.Config { }, } } + +func getOauthClientInfo() (string, string) { + // Use Client Id and Secret from env. + clientId := os.Getenv("OAUTH_CLIENT_ID") + clientSecret := os.Getenv("OAUTH_CLIENT_SECRET") + return clientId, clientSecret +} diff --git a/go.mod b/go.mod new file mode 100644 index 00000000..0916a419 --- /dev/null +++ b/go.mod @@ -0,0 +1,37 @@ +module github.com/prasmussen/gdrive + +go 1.23.4 + +require ( + github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 + github.com/soniakeys/graph v0.0.0 + golang.org/x/net v0.31.0 + golang.org/x/oauth2 v0.24.0 + google.golang.org/api v0.209.0 +) + +require ( + cloud.google.com/go/auth v0.10.2 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect + cloud.google.com/go/compute/metadata v0.5.2 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/s2a-go v0.1.8 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/gax-go/v2 v2.14.0 // indirect + github.com/soniakeys/bits v1.0.0 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect + golang.org/x/crypto v0.29.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f // indirect + google.golang.org/grpc v1.67.1 // indirect + google.golang.org/protobuf v1.35.2 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 00000000..a8fd2477 --- /dev/null +++ b/go.sum @@ -0,0 +1,160 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go/auth v0.10.2 h1:oKF7rgBfSHdp/kuhXtqU/tNDr0mZqhYbEh+6SiqzkKo= +cloud.google.com/go/auth v0.10.2/go.mod h1:xxA5AqpDrvS+Gkmo9RqrGGRh6WSNKKOXhY3zNOr38tI= +cloud.google.com/go/auth/oauth2adapt v0.2.5 h1:2p29+dePqsCHPP1bqDJcKj4qxRyYCcbzKpFyKGt3MTk= +cloud.google.com/go/auth/oauth2adapt v0.2.5/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8= +cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo= +cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/gax-go/v2 v2.14.0 h1:f+jMrjBPl+DL9nI4IQzLUxMq7XrAqFYB7hBPqMNIe8o= +github.com/googleapis/gax-go/v2 v2.14.0/go.mod h1:lhBCnjdLrWRaPvLWhmc8IS24m9mr07qSYnHncrgo+zk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= +github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs= +github.com/soniakeys/bits v1.0.0 h1:Rune9VFefdJvLE0Q5iRCVGiKdSu2iDihs2I6SCm7evw= +github.com/soniakeys/bits v1.0.0/go.mod h1:7yJHB//UizrUr64VFneewK6SX5oeCf0SMbDYe2ey1JA= +github.com/soniakeys/graph v0.0.0 h1:C/Rr8rv9wbhZIsYHcWJFoI84pkipJocMYdRteE+/PQA= +github.com/soniakeys/graph v0.0.0/go.mod h1:lxpIbor/bIzWUAqvt1Dx92Hr63uWeyuEAbPnsjYbVwM= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE= +golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +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= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.209.0 h1:Ja2OXNlyRlWCWu8o+GgI4yUn/wz9h/5ZfFbKz+dQX+w= +google.golang.org/api v0.209.0/go.mod h1:I53S168Yr/PNDNMi5yPnDc0/LGRZO6o7PoEbl/HY3CM= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20241113202542-65e8d215514f h1:zDoHYmMzMacIdjNe+P2XiTmPsLawi/pCbSPfxt6lTfw= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28 h1:M0KvPgPmDZHPlbRbaNU1APr28TvwvvdUPlSv7PUvy8g= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f h1:C1QccEa9kUwvMgEUORqQD9S17QesQijxjZ84sO82mfo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241113202542-65e8d215514f/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io= +google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/handlers_drive.go b/handlers_drive.go index 7bda872f..9b03b0ba 100644 --- a/handlers_drive.go +++ b/handlers_drive.go @@ -14,8 +14,6 @@ import ( "github.com/prasmussen/gdrive/drive" ) -const ClientId = "367116221053-7n0vf5akeru7on6o2fjinrecpdoe99eg.apps.googleusercontent.com" -const ClientSecret = "1qsNodXNaWq1mQuBjUjmvhoO" const TokenFilename = "token_v2.json" const DefaultCacheFileName = "file_cache.json" @@ -346,11 +344,11 @@ func getOauthClient(args cli.Arguments) (*http.Client, error) { } if args.String("refreshToken") != "" { - return auth.NewRefreshTokenClient(ClientId, ClientSecret, args.String("refreshToken")), nil + return auth.NewRefreshTokenClient(args.String("refreshToken")), nil } if args.String("accessToken") != "" { - return auth.NewAccessTokenClient(ClientId, ClientSecret, args.String("accessToken")), nil + return auth.NewAccessTokenClient(args.String("accessToken")), nil } configDir := getConfigDir(args) @@ -365,7 +363,7 @@ func getOauthClient(args cli.Arguments) (*http.Client, error) { } tokenPath := ConfigFilePath(configDir, TokenFilename) - return auth.NewFileSourceClient(ClientId, ClientSecret, tokenPath, authCodePrompt) + return auth.NewFileSourceClient(tokenPath, authCodePrompt) } func getConfigDir(args cli.Arguments) string { diff --git a/vendor/github.com/sabhiram/go-git-ignore/.gitignore b/vendor/github.com/sabhiram/go-git-ignore/.gitignore deleted file mode 100644 index 0e919aff..00000000 --- a/vendor/github.com/sabhiram/go-git-ignore/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -# Package test fixtures -test_fixtures - -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - diff --git a/vendor/github.com/sabhiram/go-git-ignore/.travis.yml b/vendor/github.com/sabhiram/go-git-ignore/.travis.yml deleted file mode 100644 index 24ddadf1..00000000 --- a/vendor/github.com/sabhiram/go-git-ignore/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: go - -go: - - 1.3 - - tip - -env: - - "PATH=$HOME/gopath/bin:$PATH" - -before_install: - - go get github.com/stretchr/testify/assert - - go get github.com/axw/gocov/gocov - - go get github.com/mattn/goveralls - - if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi - -script: - - go test -v -covermode=count -coverprofile=coverage.out - - goveralls -coverprofile=coverage.out -service travis-ci -repotoken $COVERALLS_TOKEN diff --git a/vendor/github.com/sabhiram/go-git-ignore/LICENSE b/vendor/github.com/sabhiram/go-git-ignore/LICENSE deleted file mode 100644 index c606f49e..00000000 --- a/vendor/github.com/sabhiram/go-git-ignore/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Shaba Abhiram - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - diff --git a/vendor/github.com/sabhiram/go-git-ignore/README.md b/vendor/github.com/sabhiram/go-git-ignore/README.md deleted file mode 100644 index fbbb3761..00000000 --- a/vendor/github.com/sabhiram/go-git-ignore/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# go-git-ignore - -[![Build Status](https://travis-ci.org/sabhiram/go-git-ignore.svg)](https://travis-ci.org/sabhiram/go-git-ignore) [![Coverage Status](https://coveralls.io/repos/sabhiram/go-git-ignore/badge.png?branch=master)](https://coveralls.io/r/sabhiram/go-git-ignore?branch=master) - -A gitignore parser for `Go` - -## Install - -```shell -go get github.com/sabhiram/go-git-ignore -``` - -## Usage - -```shell -TODO -``` diff --git a/vendor/github.com/sabhiram/go-git-ignore/ignore.go b/vendor/github.com/sabhiram/go-git-ignore/ignore.go deleted file mode 100644 index e3241b2c..00000000 --- a/vendor/github.com/sabhiram/go-git-ignore/ignore.go +++ /dev/null @@ -1,200 +0,0 @@ -/* -ignore is a library which returns a new ignorer object which can -test against various paths. This is particularly useful when trying -to filter files based on a .gitignore document - -The rules for parsing the input file are the same as the ones listed -in the Git docs here: http://git-scm.com/docs/gitignore - -The summarized version of the same has been copied here: - - 1. A blank line matches no files, so it can serve as a separator - for readability. - 2. A line starting with # serves as a comment. Put a backslash ("\") - in front of the first hash for patterns that begin with a hash. - 3. Trailing spaces are ignored unless they are quoted with backslash ("\"). - 4. An optional prefix "!" which negates the pattern; any matching file - excluded by a previous pattern will become included again. It is not - possible to re-include a file if a parent directory of that file is - excluded. Git doesn’t list excluded directories for performance reasons, - so any patterns on contained files have no effect, no matter where they - are defined. Put a backslash ("\") in front of the first "!" for - patterns that begin with a literal "!", for example, "\!important!.txt". - 5. If the pattern ends with a slash, it is removed for the purpose of the - following description, but it would only find a match with a directory. - In other words, foo/ will match a directory foo and paths underneath it, - but will not match a regular file or a symbolic link foo (this is - consistent with the way how pathspec works in general in Git). - 6. If the pattern does not contain a slash /, Git treats it as a shell glob - pattern and checks for a match against the pathname relative to the - location of the .gitignore file (relative to the toplevel of the work - tree if not from a .gitignore file). - 7. Otherwise, Git treats the pattern as a shell glob suitable for - consumption by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the - pattern will not match a / in the pathname. For example, - "Documentation/*.html" matches "Documentation/git.html" but not - "Documentation/ppc/ppc.html" or "tools/perf/Documentation/perf.html". - 8. A leading slash matches the beginning of the pathname. For example, - "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c". - 9. Two consecutive asterisks ("**") in patterns matched against full - pathname may have special meaning: - i. A leading "**" followed by a slash means match in all directories. - For example, "** /foo" matches file or directory "foo" anywhere, - the same as pattern "foo". "** /foo/bar" matches file or directory - "bar" anywhere that is directly under directory "foo". - ii. A trailing "/**" matches everything inside. For example, "abc/**" - matches all files inside directory "abc", relative to the location - of the .gitignore file, with infinite depth. - iii. A slash followed by two consecutive asterisks then a slash matches - zero or more directories. For example, "a/** /b" matches "a/b", - "a/x/b", "a/x/y/b" and so on. - iv. Other consecutive asterisks are considered invalid. */ -package ignore - -import ( - "io/ioutil" - "os" - "regexp" - "strings" -) - -// An IgnoreParser is an interface which exposes two methods: -// MatchesPath() - Returns true if the path is targeted by the patterns compiled in the GitIgnore structure -type IgnoreParser interface { - IncludesPath(f string) bool - IgnoresPath(f string) bool - MatchesPath(f string) bool -} - -// GitIgnore is a struct which contains a slice of regexp.Regexp -// patterns -type GitIgnore struct { - patterns []*regexp.Regexp // List of regexp patterns which this ignore file applies - negate []bool // List of booleans which determine if the pattern is negated -} - -// This function pretty much attempts to mimic the parsing rules -// listed above at the start of this file -func getPatternFromLine(line string) (*regexp.Regexp, bool) { - // Trim OS-specific carriage returns. - line = strings.TrimRight(line, "\r") - - // Strip comments [Rule 2] - if strings.HasPrefix(line, `#`) { - return nil, false - } - - // Trim string [Rule 3] - // TODO: Handle [Rule 3], when the " " is escaped with a \ - line = strings.Trim(line, " ") - - // Exit for no-ops and return nil which will prevent us from - // appending a pattern against this line - if line == "" { - return nil, false - } - - // TODO: Handle [Rule 4] which negates the match for patterns leading with "!" - negatePattern := false - if line[0] == '!' { - negatePattern = true - line = line[1:] - } - - // Handle [Rule 2, 4], when # or ! is escaped with a \ - // Handle [Rule 4] once we tag negatePattern, strip the leading ! char - if regexp.MustCompile(`^(\#|\!)`).MatchString(line) { - line = line[1:] - } - - // If we encounter a foo/*.blah in a folder, prepend the / char - if regexp.MustCompile(`([^\/+])/.*\*\.`).MatchString(line) && line[0] != '/' { - line = "/" + line - } - - // Handle escaping the "." char - line = regexp.MustCompile(`\.`).ReplaceAllString(line, `\.`) - - magicStar := "#$~" - - // Handle "/**/" usage - if strings.HasPrefix(line, "/**/") { - line = line[1:] - } - line = regexp.MustCompile(`/\*\*/`).ReplaceAllString(line, `(/|/.+/)`) - line = regexp.MustCompile(`\*\*/`).ReplaceAllString(line, `(|.`+magicStar+`/)`) - line = regexp.MustCompile(`/\*\*`).ReplaceAllString(line, `(|/.`+magicStar+`)`) - - // Handle escaping the "*" char - line = regexp.MustCompile(`\\\*`).ReplaceAllString(line, `\`+magicStar) - line = regexp.MustCompile(`\*`).ReplaceAllString(line, `([^/]*)`) - - // Handle escaping the "?" char - line = strings.Replace(line, "?", `\?`, -1) - - line = strings.Replace(line, magicStar, "*", -1) - - // Temporary regex - var expr = "" - if strings.HasSuffix(line, "/") { - expr = line + "(|.*)$" - } else { - expr = line + "(|/.*)$" - } - if strings.HasPrefix(expr, "/") { - expr = "^(|/)" + expr[1:] - } else { - expr = "^(|.*/)" + expr - } - pattern, _ := regexp.Compile(expr) - - return pattern, negatePattern -} - -// Accepts a variadic set of strings, and returns a GitIgnore object which -// converts and appends the lines in the input to regexp.Regexp patterns -// held within the GitIgnore objects "patterns" field -func CompileIgnoreLines(lines ...string) (*GitIgnore, error) { - g := new(GitIgnore) - for _, line := range lines { - pattern, negatePattern := getPatternFromLine(line) - if pattern != nil { - g.patterns = append(g.patterns, pattern) - g.negate = append(g.negate, negatePattern) - } - } - return g, nil -} - -// Accepts a ignore file as the input, parses the lines out of the file -// and invokes the CompileIgnoreLines method -func CompileIgnoreFile(fpath string) (*GitIgnore, error) { - buffer, error := ioutil.ReadFile(fpath) - if error == nil { - s := strings.Split(string(buffer), "\n") - return CompileIgnoreLines(s...) - } - return nil, error -} - -// MatchesPath is an interface function for the IgnoreParser interface. -// It returns true if the given GitIgnore structure would target a given -// path string "f" -func (g GitIgnore) MatchesPath(f string) bool { - // Replace OS-specific path separator. - f = strings.Replace(f, string(os.PathSeparator), "/", -1) - - matchesPath := false - for idx, pattern := range g.patterns { - if pattern.MatchString(f) { - // If this is a regular target (not negated with a gitignore exclude "!" etc) - if !g.negate[idx] { - matchesPath = true - // Negated pattern, and matchesPath is already set - } else if matchesPath { - matchesPath = false - } - } - } - return matchesPath -} diff --git a/vendor/github.com/soniakeys/graph/.gitignore b/vendor/github.com/soniakeys/graph/.gitignore index 3be61584..a93b25f4 100644 --- a/vendor/github.com/soniakeys/graph/.gitignore +++ b/vendor/github.com/soniakeys/graph/.gitignore @@ -1,2 +1,2 @@ *.dot - +anecdote/anecdote diff --git a/vendor/github.com/soniakeys/graph/.travis.yml b/vendor/github.com/soniakeys/graph/.travis.yml index bcc4f9fe..ffc16a19 100644 --- a/vendor/github.com/soniakeys/graph/.travis.yml +++ b/vendor/github.com/soniakeys/graph/.travis.yml @@ -1,8 +1,11 @@ sudo: false language: go -# update travis.sh when changing version number here go: - - 1.2.1 - - 1.6 -install: go get -t ./... -script: ./travis.sh + - "1.9.x" + - master +before_script: + - go tool vet -composites=false -printf=false -shift=false . + - go get github.com/client9/misspell/cmd/misspell + - go get github.com/soniakeys/vetc + - misspell -error * */* */*/* + - vetc diff --git a/vendor/github.com/soniakeys/graph/adj.go b/vendor/github.com/soniakeys/graph/adj.go index 165f365b..dbae4814 100644 --- a/vendor/github.com/soniakeys/graph/adj.go +++ b/vendor/github.com/soniakeys/graph/adj.go @@ -11,33 +11,39 @@ package graph // be left near their use. import ( - "math" "sort" + + "github.com/soniakeys/bits" ) -// HasParallelSort identifies if a graph contains parallel arcs, multiple arcs +// NI is a "node int" +// +// It is a node number or node ID. NIs are used extensively as slice indexes. +// NIs typically account for a significant fraction of the memory footprint of +// a graph. +type NI int32 + +// AnyParallel identifies if a graph contains parallel arcs, multiple arcs // that lead from a node to the same node. // // If the graph has parallel arcs, the results fr and to represent an example -// where there are parallel arcs from node fr to node to. +// where there are parallel arcs from node `fr` to node `to`. // // If there are no parallel arcs, the method returns false -1 -1. // // Multiple loops on a node count as parallel arcs. // -// "Sort" in the method name indicates that sorting is used to detect parallel -// arcs. Compared to method HasParallelMap, this may give better performance -// for small or sparse graphs but will have asymtotically worse performance for -// large dense graphs. -func (g AdjacencyList) HasParallelSort() (has bool, fr, to NI) { - var t NodeList +// See also alt.AnyParallelMap, which can perform better for some large +// or dense graphs. +func (g AdjacencyList) AnyParallel() (has bool, fr, to NI) { + var t []NI for n, to := range g { if len(to) == 0 { continue } // different code in the labeled version, so no code gen. t = append(t[:0], to...) - sort.Sort(t) + sort.Slice(t, func(i, j int) bool { return t[i] < t[j] }) t0 := t[0] for _, to := range t[1:] { if to == t0 { @@ -49,6 +55,33 @@ func (g AdjacencyList) HasParallelSort() (has bool, fr, to NI) { return false, -1, -1 } +// Complement returns the arc-complement of a simple graph. +// +// The result will have an arc for every pair of distinct nodes where there +// is not an arc in g. The complement is valid for both directed and +// undirected graphs. If g is undirected, the complement will be undirected. +// The result will always be a simple graph, having no loops or parallel arcs. +func (g AdjacencyList) Complement() AdjacencyList { + c := make(AdjacencyList, len(g)) + b := bits.New(len(g)) + for n, to := range g { + b.ClearAll() + for _, to := range to { + b.SetBit(int(to), 1) + } + b.SetBit(n, 1) + ct := make([]NI, len(g)-b.OnesCount()) + i := 0 + b.IterateZeros(func(to int) bool { + ct[i] = NI(to) + i++ + return true + }) + c[n] = ct + } + return c +} + // IsUndirected returns true if g represents an undirected graph. // // Returns true when all non-loop arcs are paired in reciprocal pairs. @@ -84,13 +117,25 @@ func (g AdjacencyList) IsUndirected() (u bool, from, to NI) { return true, -1, -1 } -// Edgelist constructs the edge list rerpresentation of a graph. +// SortArcLists sorts the arc lists of each node of receiver g. +// +// Nodes are not relabeled and the graph remains equivalent. +func (g AdjacencyList) SortArcLists() { + for _, to := range g { + sort.Slice(to, func(i, j int) bool { return to[i] < to[j] }) + } +} + +// ------- Labeled methods below ------- + +// ArcsAsEdges constructs an edge list with an edge for each arc, including +// reciprocals. // -// An edge is returned for each arc of the graph. For undirected graphs -// this includes reciprocal edges. +// This is a simple way to construct an edge list for algorithms that allow +// the duplication represented by the reciprocal arcs. (e.g. Kruskal) // -// See also WeightedEdgeList method. -func (g LabeledAdjacencyList) EdgeList() (el []LabeledEdge) { +// See also LabeledUndirected.Edges for the edge list without this duplication. +func (g LabeledAdjacencyList) ArcsAsEdges() (el []LabeledEdge) { for fr, to := range g { for _, to := range to { el = append(el, LabeledEdge{Edge{NI(fr), to.To}, to.Label}) @@ -99,60 +144,34 @@ func (g LabeledAdjacencyList) EdgeList() (el []LabeledEdge) { return } -// FloydWarshall finds all pairs shortest distances for a simple weighted -// graph without negative cycles. +// DistanceMatrix constructs a distance matrix corresponding to the arcs +// of graph g and weight function w. // -// In result array d, d[i][j] will be the shortest distance from node i -// to node j. Any diagonal element < 0 indicates a negative cycle exists. +// An arc from f to t with WeightFunc return w is represented by d[f][t] == w. +// In case of parallel arcs, the lowest weight is stored. The distance from +// any node to itself d[n][n] is 0, unless the node has a loop with a negative +// weight. If g has no arc from f to distinct t, +Inf is stored for d[f][t]. // -// If g is an undirected graph with no negative edge weights, the result -// array will be a distance matrix, for example as used by package -// github.com/soniakeys/cluster. -func (g LabeledAdjacencyList) FloydWarshall(w WeightFunc) (d [][]float64) { - d = newFWd(len(g)) +// The returned DistanceMatrix is suitable for DistanceMatrix.FloydWarshall. +func (g LabeledAdjacencyList) DistanceMatrix(w WeightFunc) (d DistanceMatrix) { + d = newDM(len(g)) for fr, to := range g { for _, to := range to { - d[fr][to.To] = w(to.Label) - } - } - solveFW(d) - return -} - -// little helper function, makes a blank matrix for FloydWarshall. -func newFWd(n int) [][]float64 { - d := make([][]float64, n) - for i := range d { - di := make([]float64, n) - for j := range di { - if j != i { - di[j] = math.Inf(1) - } - } - d[i] = di - } - return d -} - -// Floyd Warshall solver, once the matrix d is initialized by arc weights. -func solveFW(d [][]float64) { - for k, dk := range d { - for _, di := range d { - dik := di[k] - for j := range d { - if d2 := dik + dk[j]; d2 < di[j] { - di[j] = d2 - } + // < to pick min of parallel arcs (also nicely ignores NaN) + if wt := w(to.Label); wt < d[fr][to.To] { + d[fr][to.To] = wt } } } + return } -// HasArcLabel returns true if g has any arc from node fr to node to -// with label l. +// HasArcLabel returns true if g has any arc from node `fr` to node `to` +// with label `l`. // -// Also returned is the index within the slice of arcs from node fr. -// If no arc from fr to to is present, HasArcLabel returns false, -1. +// Also returned is the index within the slice of arcs from node `fr`. +// If no arc from `fr` to `to` with label `l` is present, HasArcLabel returns +// false, -1. func (g LabeledAdjacencyList) HasArcLabel(fr, to NI, l LI) (bool, int) { t := Half{to, l} for x, h := range g[fr] { @@ -163,22 +182,20 @@ func (g LabeledAdjacencyList) HasArcLabel(fr, to NI, l LI) (bool, int) { return false, -1 } -// HasParallelSort identifies if a graph contains parallel arcs, multiple arcs +// AnyParallel identifies if a graph contains parallel arcs, multiple arcs // that lead from a node to the same node. // // If the graph has parallel arcs, the results fr and to represent an example -// where there are parallel arcs from node fr to node to. +// where there are parallel arcs from node `fr` to node `to`. // // If there are no parallel arcs, the method returns -1 -1. // // Multiple loops on a node count as parallel arcs. // -// "Sort" in the method name indicates that sorting is used to detect parallel -// arcs. Compared to method HasParallelMap, this may give better performance -// for small or sparse graphs but will have asymtotically worse performance for -// large dense graphs. -func (g LabeledAdjacencyList) HasParallelSort() (has bool, fr, to NI) { - var t NodeList +// See also alt.AnyParallelMap, which can perform better for some large +// or dense graphs. +func (g LabeledAdjacencyList) AnyParallel() (has bool, fr, to NI) { + var t []NI for n, to := range g { if len(to) == 0 { continue @@ -188,7 +205,7 @@ func (g LabeledAdjacencyList) HasParallelSort() (has bool, fr, to NI) { for _, to := range to { t = append(t, to.To) } - sort.Sort(t) + sort.Slice(t, func(i, j int) bool { return t[i] < t[j] }) t0 := t[0] for _, to := range t[1:] { if to == t0 { @@ -200,6 +217,42 @@ func (g LabeledAdjacencyList) HasParallelSort() (has bool, fr, to NI) { return false, -1, -1 } +// AnyParallelLabel identifies if a graph contains parallel arcs with the same +// label. +// +// If the graph has parallel arcs with the same label, the results fr and to +// represent an example where there are parallel arcs from node `fr` +// to node `to`. +// +// If there are no parallel arcs, the method returns false -1 Half{}. +// +// Multiple loops on a node count as parallel arcs. +func (g LabeledAdjacencyList) AnyParallelLabel() (has bool, fr NI, to Half) { + var t []Half + for n, to := range g { + if len(to) == 0 { + continue + } + // slightly different code needed here compared to AdjacencyList + t = t[:0] + for _, to := range to { + t = append(t, to) + } + sort.Slice(t, func(i, j int) bool { + return t[i].To < t[j].To || + t[i].To == t[j].To && t[i].Label < t[j].Label + }) + t0 := t[0] + for _, to := range t[1:] { + if to == t0 { + return true, NI(n), t0 + } + t0 = to + } + } + return false, -1, Half{} +} + // IsUndirected returns true if g represents an undirected graph. // // Returns true when all non-loop arcs are paired in reciprocal pairs with @@ -209,6 +262,7 @@ func (g LabeledAdjacencyList) HasParallelSort() (has bool, fr, to NI) { // an additional test not present in the otherwise equivalent unlabeled version // of IsUndirected. func (g LabeledAdjacencyList) IsUndirected() (u bool, from NI, to Half) { + // similar code in LabeledAdjacencyList.Edges unpaired := make(LabeledAdjacencyList, len(g)) for fr, to := range g { arc: // for each arc in g @@ -238,6 +292,17 @@ func (g LabeledAdjacencyList) IsUndirected() (u bool, from NI, to Half) { return true, -1, to } +// ArcLabels constructs the multiset of LIs present in g. +func (g LabeledAdjacencyList) ArcLabels() map[LI]int { + s := map[LI]int{} + for _, to := range g { + for _, to := range to { + s[to.Label]++ + } + } + return s +} + // NegativeArc returns true if the receiver graph contains a negative arc. func (g LabeledAdjacencyList) NegativeArc(w WeightFunc) bool { for _, nbs := range g { @@ -250,6 +315,23 @@ func (g LabeledAdjacencyList) NegativeArc(w WeightFunc) bool { return false } +// ParallelArcsLabel identifies all arcs from node `fr` to node `to` with label `l`. +// +// The returned slice contains an element for each arc from node `fr` to node `to` +// with label `l`. The element value is the index within the slice of arcs from node +// `fr`. +// +// See also the method HasArcLabel, which stops after finding a single arc. +func (g LabeledAdjacencyList) ParallelArcsLabel(fr, to NI, l LI) (p []int) { + t := Half{to, l} + for x, h := range g[fr] { + if h == t { + p = append(p, x) + } + } + return +} + // Unlabeled constructs the unlabeled graph corresponding to g. func (g LabeledAdjacencyList) Unlabeled() AdjacencyList { a := make(AdjacencyList, len(g)) @@ -263,16 +345,15 @@ func (g LabeledAdjacencyList) Unlabeled() AdjacencyList { return a } -// WeightedEdgeList constructs a WeightedEdgeList object from a -// LabeledAdjacencyList. +// WeightedArcsAsEdges constructs a WeightedEdgeList object from the receiver. // -// Internally it calls g.EdgeList() to obtain the Edges member. -// See LabeledAdjacencyList.EdgeList(). -func (g LabeledAdjacencyList) WeightedEdgeList(w WeightFunc) *WeightedEdgeList { +// Internally it calls g.ArcsAsEdges() to obtain the Edges member. +// See LabeledAdjacencyList.ArcsAsEdges(). +func (g LabeledAdjacencyList) WeightedArcsAsEdges(w WeightFunc) *WeightedEdgeList { return &WeightedEdgeList{ - Order: len(g), + Order: g.Order(), WeightFunc: w, - Edges: g.EdgeList(), + Edges: g.ArcsAsEdges(), } } diff --git a/vendor/github.com/soniakeys/graph/adj_RO.go b/vendor/github.com/soniakeys/graph/adj_RO.go index 1d37d14e..17df67c5 100644 --- a/vendor/github.com/soniakeys/graph/adj_RO.go +++ b/vendor/github.com/soniakeys/graph/adj_RO.go @@ -8,10 +8,22 @@ package graph // DO NOT EDIT adj_RO.go. The RO is for Read Only. import ( + "errors" + "fmt" "math/rand" - "time" + + "github.com/soniakeys/bits" ) +// ArcDensity returns density for an simple directed graph. +// +// See also ArcDensity function. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) ArcDensity() float64 { + return ArcDensity(len(g), g.ArcSize()) +} + // ArcSize returns the number of arcs in g. // // Note that for an undirected graph without loops, the number of undirected @@ -50,98 +62,34 @@ func (g AdjacencyList) BoundsOk() (ok bool, fr NI, to NI) { return true, -1, to } -// BreadthFirst traverses a directed or undirected graph in breadth first order. -// -// Argument start is the start node for the traversal. If r is nil, nodes are -// visited in deterministic order. If a random number generator is supplied, -// nodes at each level are visited in random order. +// BreadthFirst traverses a directed or undirected graph in breadth +// first order. // -// Argument f can be nil if you have no interest in the FromList path result. -// If FromList f is non-nil, the method populates f.Paths and sets f.MaxLen. -// It does not set f.Leaves. For convenience argument f can be a zero value -// FromList. If f.Paths is nil, the FromList is initialized first. If f.Paths -// is non-nil however, the FromList is used as is. The method uses a value of -// PathEnd.Len == 0 to indentify unvisited nodes. Existing non-zero values -// will limit the traversal. -// -// Traversal calls the visitor function v for each node starting with node -// start. If v returns true, traversal continues. If v returns false, the -// traversal terminates immediately. PathEnd Len and From values are updated -// before calling the visitor function. -// -// On return f.Paths and f.MaxLen are set but not f.Leaves. -// -// Returned is the number of nodes visited and ok = true if the traversal -// ran to completion or ok = false if it was terminated by the visitor -// function returning false. +// Traversal starts at node start and visits the nodes reachable from +// start. The function visit is called for each node visited. Nodes +// not reachable from start are not visited. // // There are equivalent labeled and unlabeled versions of this method. -func (g AdjacencyList) BreadthFirst(start NI, r *rand.Rand, f *FromList, v OkNodeVisitor) (visited int, ok bool) { - switch { - case f == nil: - e := NewFromList(len(g)) - f = &e - case f.Paths == nil: - *f = NewFromList(len(g)) - } - rp := f.Paths - // the frontier consists of nodes all at the same level - frontier := []NI{start} - level := 1 - // assign path when node is put on frontier, - rp[start] = PathEnd{Len: level, From: -1} - for { - f.MaxLen = level - level++ - var next []NI - if r == nil { - for _, n := range frontier { - visited++ - if !v(n) { // visit nodes as they come off frontier - return - } - for _, nb := range g[n] { - if rp[nb].Len == 0 { - next = append(next, nb) - rp[nb] = PathEnd{From: n, Len: level} - } - } - } - } else { // take nodes off frontier at random - for _, i := range r.Perm(len(frontier)) { - n := frontier[i] - // remainder of block same as above - visited++ - if !v(n) { - return - } - for _, nb := range g[n] { - if rp[nb].Len == 0 { - next = append(next, nb) - rp[nb] = PathEnd{From: n, Len: level} - } +// +// See also alt.BreadthFirst, a variant with more options, and +// alt.BreadthFirst2, a direction optimizing variant. +func (g AdjacencyList) BreadthFirst(start NI, visit func(NI)) { + v := bits.New(len(g)) + v.SetBit(int(start), 1) + visit(start) + var next []NI + for frontier := []NI{start}; len(frontier) > 0; { + for _, n := range frontier { + for _, nb := range g[n] { + if v.Bit(int(nb)) == 0 { + v.SetBit(int(nb), 1) + visit(nb) + next = append(next, nb) } } } - if len(next) == 0 { - break - } - frontier = next + frontier, next = next, frontier[:0] } - return visited, true -} - -// BreadthFirstPath finds a single path from start to end with a minimum -// number of nodes. -// -// Returned is the path as list of nodes. -// The result is nil if no path was found. -// -// There are equivalent labeled and unlabeled versions of this method. -func (g AdjacencyList) BreadthFirstPath(start, end NI) []NI { - var f FromList - g.BreadthFirst(start, nil, &f, func(n NI) bool { return n != end }) - return f.PathTo(end, nil) } // Copy makes a deep copy of g. @@ -157,99 +105,40 @@ func (g AdjacencyList) Copy() (c AdjacencyList, ma int) { return } -// DepthFirst traverses a graph depth first. -// -// As it traverses it calls visitor function v for each node. If v returns -// false at any point, the traversal is terminated immediately and DepthFirst -// returns false. Otherwise DepthFirst returns true. -// -// DepthFirst uses argument bm is used as a bitmap to guide the traversal. -// For a complete traversal, bm should be 0 initially. During the -// traversal, bits are set corresponding to each node visited. -// The bit is set before calling the visitor function. -// -// Argument bm can be nil if you have no need for it. -// In this case a bitmap is created internally for one-time use. -// -// Alternatively v can be nil. In this case traversal still proceeds and -// updates the bitmap, which can be a useful result. -// DepthFirst always returns true in this case. +// DepthFirst traverses a directed or undirected graph in depth +// first order. // -// It makes no sense for both bm and v to be nil. In this case DepthFirst -// returns false immediately. +// Traversal starts at node start and visits the nodes reachable from +// start. The function visit is called for each node visited. Nodes +// not reachable from start are not visited. // // There are equivalent labeled and unlabeled versions of this method. -func (g AdjacencyList) DepthFirst(start NI, bm *Bits, v OkNodeVisitor) (ok bool) { - if bm == nil { - if v == nil { - return false - } - bm = &Bits{} - } - var df func(n NI) bool - df = func(n NI) bool { - if bm.Bit(n) == 1 { - return true - } - bm.SetBit(n, 1) - if v != nil && !v(n) { - return false - } - for _, nb := range g[n] { - if !df(nb) { - return false - } - } - return true - } - return df(start) -} - -// DepthFirstRandom traverses a graph depth first, but following arcs in -// random order among arcs from a single node. -// -// If Rand r is nil, the method creates a new source and generator for -// one-time use. // -// Usage is otherwise like the DepthFirst method. See DepthFirst. -// -// There are equivalent labeled and unlabeled versions of this method. -func (g AdjacencyList) DepthFirstRandom(start NI, bm *Bits, v OkNodeVisitor, r *rand.Rand) (ok bool) { - if bm == nil { - if v == nil { - return false - } - bm = &Bits{} - } - if r == nil { - r = rand.New(rand.NewSource(time.Now().UnixNano())) - } - var df func(n NI) bool - df = func(n NI) bool { - if bm.Bit(n) == 1 { - return true - } - bm.SetBit(n, 1) - if v != nil && !v(n) { - return false - } - to := g[n] - for _, i := range r.Perm(len(to)) { - if !df(to[i]) { - return false +// See also alt.DepthFirst, a variant with more options. +func (g AdjacencyList) DepthFirst(start NI, visit func(NI)) { + v := bits.New(len(g)) + var f func(NI) + f = func(n NI) { + visit(n) + v.SetBit(int(n), 1) + for _, to := range g[n] { + if v.Bit(int(to)) == 0 { + f(to) } } - return true } - return df(start) + f(start) } -// HasArc returns true if g has any arc from node fr to node to. +// HasArc returns true if g has any arc from node `fr` to node `to`. // -// Also returned is the index within the slice of arcs from node fr. -// If no arc from fr to to is present, HasArc returns false, -1. +// Also returned is the index within the slice of arcs from node `fr`. +// If no arc from `fr` to `to` is present, HasArc returns false, -1. // // There are equivalent labeled and unlabeled versions of this method. +// +// See also the method ParallelArcs, which finds all parallel arcs from +// `fr` to `to`. func (g AdjacencyList) HasArc(fr, to NI) (bool, int) { for x, h := range g[fr] { if h == to { @@ -259,16 +148,14 @@ func (g AdjacencyList) HasArc(fr, to NI) (bool, int) { return false, -1 } -// HasLoop identifies if a graph contains a loop, an arc that leads from a +// AnyLoop identifies if a graph contains a loop, an arc that leads from a // a node back to the same node. // -// If the graph has a loop, the result is an example node that has a loop. -// // If g contains a loop, the method returns true and an example of a node // with a loop. If there are no loops in g, the method returns false, -1. // // There are equivalent labeled and unlabeled versions of this method. -func (g AdjacencyList) HasLoop() (bool, NI) { +func (g AdjacencyList) AnyLoop() (bool, NI) { for fr, to := range g { for _, to := range to { if NI(fr) == to { @@ -279,37 +166,138 @@ func (g AdjacencyList) HasLoop() (bool, NI) { return false, -1 } -// HasParallelMap identifies if a graph contains parallel arcs, multiple arcs -// that lead from a node to the same node. -// -// If the graph has parallel arcs, the method returns true and -// results fr and to represent an example where there are parallel arcs -// from node fr to node to. +// AddNode maps a node in a supergraph to a subgraph node. // -// If there are no parallel arcs, the method returns false, -1 -1. +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. // -// Multiple loops on a node count as parallel arcs. +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. // -// "Map" in the method name indicates that a Go map is used to detect parallel -// arcs. Compared to method HasParallelSort, this gives better asymtotic -// performance for large dense graphs but may have increased overhead for -// small or sparse graphs. -// -// There are equivalent labeled and unlabeled versions of this method. -func (g AdjacencyList) HasParallelMap() (has bool, fr, to NI) { - for n, to := range g { - if len(to) == 0 { - continue +// The mapped subgraph NI is returned. +func (s *Subgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.AdjacencyList + b = NI(len(a)) + s.AdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// AddArc adds an arc to a subgraph. +// +// Arguments fr, to must be NIs in supergraph s.Super. As with AddNode, +// AddArc panics if fr and to are not valid node indexes of s.Super. +// +// The arc specfied by fr, to must exist in s.Super. Further, the number of +// parallel arcs in the subgraph cannot exceed the number of corresponding +// parallel arcs in the supergraph. That is, each arc already added to the +// subgraph counts against the arcs available in the supergraph. If a matching +// arc is not available, AddArc returns an error. +// +// If a matching arc is available, subgraph nodes are added as needed, the +// subgraph arc is added, and the method returns nil. +func (s *Subgraph) AddArc(fr NI, to NI) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(fr) < 0 || int(fr) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", fr, " not in supergraph")) + } + if int(to) < 0 || int(to) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", to, " not in supergraph")) + } + // count existing matching arcs in subgraph + n := 0 + a := s.AdjacencyList + if bf, ok := s.SubNI[fr]; ok { + if bt, ok := s.SubNI[to]; ok { + // both NIs already exist in subgraph, need to count arcs + bTo := to + bTo = bt + for _, t := range a[bf] { + if t == bTo { + n++ + } + } } - m := map[NI]struct{}{} - for _, to := range to { - if _, ok := m[to]; ok { - return true, NI(n), to + } + // verify matching arcs are available in supergraph + for _, t := range (*s.Super)[fr] { + if t == to { + if n > 0 { + n-- // match existing arc + continue + } + // no more existing arcs need to be matched. nodes can finally + // be added as needed and then the arc can be added. + bf := s.AddNode(fr) + to = s.AddNode(to) + s.AdjacencyList[bf] = append(s.AdjacencyList[bf], to) + return nil // success + } + } + return errors.New("arc not available in supergraph") +} + +func (super AdjacencyList) induceArcs(sub map[NI]NI, sup []NI) AdjacencyList { + s := make(AdjacencyList, len(sup)) + for b, p := range sup { + var a []NI + for _, to := range super[p] { + if bt, ok := sub[to]; ok { + to = bt + a = append(a, to) } - m[to] = struct{}{} } + s[b] = a } - return false, -1, -1 + return s +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *AdjacencyList) InduceList(l []NI) *Subgraph { + sub, sup := mapList(l) + return &Subgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + + AdjacencyList: g.induceArcs(sub, sup)} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *AdjacencyList) InduceBits(t bits.Bits) *Subgraph { + sub, sup := mapBits(t) + return &Subgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + + AdjacencyList: g.induceArcs(sub, sup)} } // IsSimple checks for loops and parallel arcs. @@ -320,14 +308,14 @@ func (g AdjacencyList) HasParallelMap() (has bool, fr, to NI) { // found, simple returns false and a node that represents a counterexample // to the graph being simple. // -// See also separate methods HasLoop and HasParallel. +// See also separate methods AnyLoop and AnyParallel. // // There are equivalent labeled and unlabeled versions of this method. func (g AdjacencyList) IsSimple() (ok bool, n NI) { - if lp, n := g.HasLoop(); lp { + if lp, n := g.AnyLoop(); lp { return false, n } - if pa, n, _ := g.HasParallelSort(); pa { + if pa, n, _ := g.AnyParallel(); pa { return false, n } return true, -1 @@ -338,50 +326,92 @@ func (g AdjacencyList) IsSimple() (ok bool, n NI) { // An isolated node is one with no arcs going to or from it. // // There are equivalent labeled and unlabeled versions of this method. -func (g AdjacencyList) IsolatedNodes() (i Bits) { - i.SetAll(len(g)) +func (g AdjacencyList) IsolatedNodes() (i bits.Bits) { + i = bits.New(len(g)) + i.SetAll() for fr, to := range g { if len(to) > 0 { - i.SetBit(NI(fr), 0) + i.SetBit(fr, 0) for _, to := range to { - i.SetBit(to, 0) + i.SetBit(int(to), 0) } } } return } -/* -MaxmimalClique finds a maximal clique containing the node n. - -Not sure this is good for anything. It produces a single maximal clique -but there can be multiple maximal cliques containing a given node. -This algorithm just returns one of them, not even necessarily the -largest one. +// Order is the number of nodes in receiver g. +// +// It is simply a wrapper method for the Go builtin len(). +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) Order() int { + // Why a wrapper for len()? Mostly for Directed and Undirected. + // u.Order() is a little nicer than len(u.LabeledAdjacencyList). + return len(g) +} -func (g LabeledAdjacencyList) MaximalClique(n int) []int { - c := []int{n} - var m bitset.BitSet - m.Set(uint(n)) - for fr, to := range g { - if fr == n { - continue +// ParallelArcs identifies all arcs from node `fr` to node `to`. +// +// The returned slice contains an element for each arc from node `fr` to node `to`. +// The element value is the index within the slice of arcs from node `fr`. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also the method HasArc, which stops after finding a single arc. +func (g AdjacencyList) ParallelArcs(fr, to NI) (p []int) { + for x, h := range g[fr] { + if h == to { + p = append(p, x) } - if len(to) < len(c) { - continue + } + return +} + +// Permute permutes the node labeling of receiver g. +// +// Argument p must be a permutation of the node numbers of the graph, +// 0 through len(g)-1. A permutation returned by rand.Perm(len(g)) for +// example is acceptable. +// +// The graph is permuted in place. The graph keeps the same underlying +// memory but values of the graph representation are permuted to produce +// an isomorphic graph. The node previously labeled 0 becomes p[0] and so on. +// See example (or the code) for clarification. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) Permute(p []int) { + old := append(AdjacencyList{}, g...) // shallow copy + for fr, arcs := range old { + for i, to := range arcs { + arcs[i] = NI(p[to]) } - f := 0 - for _, to := range to { - if m.Test(uint(to.To)) { - f++ - if f == len(c) { - c = append(c, to.To) - m.Set(uint(to.To)) - break - } - } + g[p[fr]] = arcs + } +} + +// ShuffleArcLists shuffles the arc lists of each node of receiver g. +// +// For example a node with arcs leading to nodes 3 and 7 might have an +// arc list of either [3 7] or [7 3] after calling this method. The +// connectivity of the graph is not changed. The resulting graph stays +// equivalent but a traversal will encounter arcs in a different +// order. +// +// If Rand r is nil, the rand package default shared source is used. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g AdjacencyList) ShuffleArcLists(r *rand.Rand) { + ri := rand.Intn + if r != nil { + ri = r.Intn + } + // Knuth-Fisher-Yates + for _, to := range g { + for i := len(to); i > 1; { + j := ri(i) + i-- + to[i], to[j] = to[j], to[i] } } - return c } -*/ diff --git a/vendor/github.com/soniakeys/graph/adj_cg.go b/vendor/github.com/soniakeys/graph/adj_cg.go index a484ee04..796ced65 100644 --- a/vendor/github.com/soniakeys/graph/adj_cg.go +++ b/vendor/github.com/soniakeys/graph/adj_cg.go @@ -8,10 +8,22 @@ package graph // DO NOT EDIT adj_RO.go. The RO is for Read Only. import ( + "errors" + "fmt" "math/rand" - "time" + + "github.com/soniakeys/bits" ) +// ArcDensity returns density for an simple directed graph. +// +// See also ArcDensity function. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) ArcDensity() float64 { + return ArcDensity(len(g), g.ArcSize()) +} + // ArcSize returns the number of arcs in g. // // Note that for an undirected graph without loops, the number of undirected @@ -50,98 +62,34 @@ func (g LabeledAdjacencyList) BoundsOk() (ok bool, fr NI, to Half) { return true, -1, to } -// BreadthFirst traverses a directed or undirected graph in breadth first order. -// -// Argument start is the start node for the traversal. If r is nil, nodes are -// visited in deterministic order. If a random number generator is supplied, -// nodes at each level are visited in random order. +// BreadthFirst traverses a directed or undirected graph in breadth +// first order. // -// Argument f can be nil if you have no interest in the FromList path result. -// If FromList f is non-nil, the method populates f.Paths and sets f.MaxLen. -// It does not set f.Leaves. For convenience argument f can be a zero value -// FromList. If f.Paths is nil, the FromList is initialized first. If f.Paths -// is non-nil however, the FromList is used as is. The method uses a value of -// PathEnd.Len == 0 to indentify unvisited nodes. Existing non-zero values -// will limit the traversal. -// -// Traversal calls the visitor function v for each node starting with node -// start. If v returns true, traversal continues. If v returns false, the -// traversal terminates immediately. PathEnd Len and From values are updated -// before calling the visitor function. -// -// On return f.Paths and f.MaxLen are set but not f.Leaves. -// -// Returned is the number of nodes visited and ok = true if the traversal -// ran to completion or ok = false if it was terminated by the visitor -// function returning false. +// Traversal starts at node start and visits the nodes reachable from +// start. The function visit is called for each node visited. Nodes +// not reachable from start are not visited. // // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledAdjacencyList) BreadthFirst(start NI, r *rand.Rand, f *FromList, v OkNodeVisitor) (visited int, ok bool) { - switch { - case f == nil: - e := NewFromList(len(g)) - f = &e - case f.Paths == nil: - *f = NewFromList(len(g)) - } - rp := f.Paths - // the frontier consists of nodes all at the same level - frontier := []NI{start} - level := 1 - // assign path when node is put on frontier, - rp[start] = PathEnd{Len: level, From: -1} - for { - f.MaxLen = level - level++ - var next []NI - if r == nil { - for _, n := range frontier { - visited++ - if !v(n) { // visit nodes as they come off frontier - return - } - for _, nb := range g[n] { - if rp[nb.To].Len == 0 { - next = append(next, nb.To) - rp[nb.To] = PathEnd{From: n, Len: level} - } - } - } - } else { // take nodes off frontier at random - for _, i := range r.Perm(len(frontier)) { - n := frontier[i] - // remainder of block same as above - visited++ - if !v(n) { - return - } - for _, nb := range g[n] { - if rp[nb.To].Len == 0 { - next = append(next, nb.To) - rp[nb.To] = PathEnd{From: n, Len: level} - } +// +// See also alt.BreadthFirst, a variant with more options, and +// alt.BreadthFirst2, a direction optimizing variant. +func (g LabeledAdjacencyList) BreadthFirst(start NI, visit func(NI)) { + v := bits.New(len(g)) + v.SetBit(int(start), 1) + visit(start) + var next []NI + for frontier := []NI{start}; len(frontier) > 0; { + for _, n := range frontier { + for _, nb := range g[n] { + if v.Bit(int(nb.To)) == 0 { + v.SetBit(int(nb.To), 1) + visit(nb.To) + next = append(next, nb.To) } } } - if len(next) == 0 { - break - } - frontier = next + frontier, next = next, frontier[:0] } - return visited, true -} - -// BreadthFirstPath finds a single path from start to end with a minimum -// number of nodes. -// -// Returned is the path as list of nodes. -// The result is nil if no path was found. -// -// There are equivalent labeled and unlabeled versions of this method. -func (g LabeledAdjacencyList) BreadthFirstPath(start, end NI) []NI { - var f FromList - g.BreadthFirst(start, nil, &f, func(n NI) bool { return n != end }) - return f.PathTo(end, nil) } // Copy makes a deep copy of g. @@ -157,99 +105,40 @@ func (g LabeledAdjacencyList) Copy() (c LabeledAdjacencyList, ma int) { return } -// DepthFirst traverses a graph depth first. -// -// As it traverses it calls visitor function v for each node. If v returns -// false at any point, the traversal is terminated immediately and DepthFirst -// returns false. Otherwise DepthFirst returns true. -// -// DepthFirst uses argument bm is used as a bitmap to guide the traversal. -// For a complete traversal, bm should be 0 initially. During the -// traversal, bits are set corresponding to each node visited. -// The bit is set before calling the visitor function. -// -// Argument bm can be nil if you have no need for it. -// In this case a bitmap is created internally for one-time use. -// -// Alternatively v can be nil. In this case traversal still proceeds and -// updates the bitmap, which can be a useful result. -// DepthFirst always returns true in this case. +// DepthFirst traverses a directed or undirected graph in depth +// first order. // -// It makes no sense for both bm and v to be nil. In this case DepthFirst -// returns false immediately. +// Traversal starts at node start and visits the nodes reachable from +// start. The function visit is called for each node visited. Nodes +// not reachable from start are not visited. // // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledAdjacencyList) DepthFirst(start NI, bm *Bits, v OkNodeVisitor) (ok bool) { - if bm == nil { - if v == nil { - return false - } - bm = &Bits{} - } - var df func(n NI) bool - df = func(n NI) bool { - if bm.Bit(n) == 1 { - return true - } - bm.SetBit(n, 1) - if v != nil && !v(n) { - return false - } - for _, nb := range g[n] { - if !df(nb.To) { - return false - } - } - return true - } - return df(start) -} - -// DepthFirstRandom traverses a graph depth first, but following arcs in -// random order among arcs from a single node. -// -// If Rand r is nil, the method creates a new source and generator for -// one-time use. // -// Usage is otherwise like the DepthFirst method. See DepthFirst. -// -// There are equivalent labeled and unlabeled versions of this method. -func (g LabeledAdjacencyList) DepthFirstRandom(start NI, bm *Bits, v OkNodeVisitor, r *rand.Rand) (ok bool) { - if bm == nil { - if v == nil { - return false - } - bm = &Bits{} - } - if r == nil { - r = rand.New(rand.NewSource(time.Now().UnixNano())) - } - var df func(n NI) bool - df = func(n NI) bool { - if bm.Bit(n) == 1 { - return true - } - bm.SetBit(n, 1) - if v != nil && !v(n) { - return false - } - to := g[n] - for _, i := range r.Perm(len(to)) { - if !df(to[i].To) { - return false +// See also alt.DepthFirst, a variant with more options. +func (g LabeledAdjacencyList) DepthFirst(start NI, visit func(NI)) { + v := bits.New(len(g)) + var f func(NI) + f = func(n NI) { + visit(n) + v.SetBit(int(n), 1) + for _, to := range g[n] { + if v.Bit(int(to.To)) == 0 { + f(to.To) } } - return true } - return df(start) + f(start) } -// HasArc returns true if g has any arc from node fr to node to. +// HasArc returns true if g has any arc from node `fr` to node `to`. // -// Also returned is the index within the slice of arcs from node fr. -// If no arc from fr to to is present, HasArc returns false, -1. +// Also returned is the index within the slice of arcs from node `fr`. +// If no arc from `fr` to `to` is present, HasArc returns false, -1. // // There are equivalent labeled and unlabeled versions of this method. +// +// See also the method ParallelArcs, which finds all parallel arcs from +// `fr` to `to`. func (g LabeledAdjacencyList) HasArc(fr, to NI) (bool, int) { for x, h := range g[fr] { if h.To == to { @@ -259,16 +148,14 @@ func (g LabeledAdjacencyList) HasArc(fr, to NI) (bool, int) { return false, -1 } -// HasLoop identifies if a graph contains a loop, an arc that leads from a +// AnyLoop identifies if a graph contains a loop, an arc that leads from a // a node back to the same node. // -// If the graph has a loop, the result is an example node that has a loop. -// // If g contains a loop, the method returns true and an example of a node // with a loop. If there are no loops in g, the method returns false, -1. // // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledAdjacencyList) HasLoop() (bool, NI) { +func (g LabeledAdjacencyList) AnyLoop() (bool, NI) { for fr, to := range g { for _, to := range to { if NI(fr) == to.To { @@ -279,37 +166,138 @@ func (g LabeledAdjacencyList) HasLoop() (bool, NI) { return false, -1 } -// HasParallelMap identifies if a graph contains parallel arcs, multiple arcs -// that lead from a node to the same node. -// -// If the graph has parallel arcs, the method returns true and -// results fr and to represent an example where there are parallel arcs -// from node fr to node to. +// AddNode maps a node in a supergraph to a subgraph node. // -// If there are no parallel arcs, the method returns false, -1 -1. +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. // -// Multiple loops on a node count as parallel arcs. +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. // -// "Map" in the method name indicates that a Go map is used to detect parallel -// arcs. Compared to method HasParallelSort, this gives better asymtotic -// performance for large dense graphs but may have increased overhead for -// small or sparse graphs. -// -// There are equivalent labeled and unlabeled versions of this method. -func (g LabeledAdjacencyList) HasParallelMap() (has bool, fr, to NI) { - for n, to := range g { - if len(to) == 0 { - continue +// The mapped subgraph NI is returned. +func (s *LabeledSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.LabeledAdjacencyList + b = NI(len(a)) + s.LabeledAdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// AddArc adds an arc to a subgraph. +// +// Arguments fr, to must be NIs in supergraph s.Super. As with AddNode, +// AddArc panics if fr and to are not valid node indexes of s.Super. +// +// The arc specfied by fr, to must exist in s.Super. Further, the number of +// parallel arcs in the subgraph cannot exceed the number of corresponding +// parallel arcs in the supergraph. That is, each arc already added to the +// subgraph counts against the arcs available in the supergraph. If a matching +// arc is not available, AddArc returns an error. +// +// If a matching arc is available, subgraph nodes are added as needed, the +// subgraph arc is added, and the method returns nil. +func (s *LabeledSubgraph) AddArc(fr NI, to Half) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(fr) < 0 || int(fr) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", fr, " not in supergraph")) + } + if int(to.To) < 0 || int(to.To) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", to.To, " not in supergraph")) + } + // count existing matching arcs in subgraph + n := 0 + a := s.LabeledAdjacencyList + if bf, ok := s.SubNI[fr]; ok { + if bt, ok := s.SubNI[to.To]; ok { + // both NIs already exist in subgraph, need to count arcs + bTo := to + bTo.To = bt + for _, t := range a[bf] { + if t == bTo { + n++ + } + } } - m := map[NI]struct{}{} - for _, to := range to { - if _, ok := m[to.To]; ok { - return true, NI(n), to.To + } + // verify matching arcs are available in supergraph + for _, t := range (*s.Super)[fr] { + if t == to { + if n > 0 { + n-- // match existing arc + continue + } + // no more existing arcs need to be matched. nodes can finally + // be added as needed and then the arc can be added. + bf := s.AddNode(fr) + to.To = s.AddNode(to.To) + s.LabeledAdjacencyList[bf] = append(s.LabeledAdjacencyList[bf], to) + return nil // success + } + } + return errors.New("arc not available in supergraph") +} + +func (super LabeledAdjacencyList) induceArcs(sub map[NI]NI, sup []NI) LabeledAdjacencyList { + s := make(LabeledAdjacencyList, len(sup)) + for b, p := range sup { + var a []Half + for _, to := range super[p] { + if bt, ok := sub[to.To]; ok { + to.To = bt + a = append(a, to) } - m[to.To] = struct{}{} } + s[b] = a } - return false, -1, -1 + return s +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledAdjacencyList) InduceList(l []NI) *LabeledSubgraph { + sub, sup := mapList(l) + return &LabeledSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + + LabeledAdjacencyList: g.induceArcs(sub, sup)} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledAdjacencyList) InduceBits(t bits.Bits) *LabeledSubgraph { + sub, sup := mapBits(t) + return &LabeledSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + + LabeledAdjacencyList: g.induceArcs(sub, sup)} } // IsSimple checks for loops and parallel arcs. @@ -320,14 +308,14 @@ func (g LabeledAdjacencyList) HasParallelMap() (has bool, fr, to NI) { // found, simple returns false and a node that represents a counterexample // to the graph being simple. // -// See also separate methods HasLoop and HasParallel. +// See also separate methods AnyLoop and AnyParallel. // // There are equivalent labeled and unlabeled versions of this method. func (g LabeledAdjacencyList) IsSimple() (ok bool, n NI) { - if lp, n := g.HasLoop(); lp { + if lp, n := g.AnyLoop(); lp { return false, n } - if pa, n, _ := g.HasParallelSort(); pa { + if pa, n, _ := g.AnyParallel(); pa { return false, n } return true, -1 @@ -338,50 +326,92 @@ func (g LabeledAdjacencyList) IsSimple() (ok bool, n NI) { // An isolated node is one with no arcs going to or from it. // // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledAdjacencyList) IsolatedNodes() (i Bits) { - i.SetAll(len(g)) +func (g LabeledAdjacencyList) IsolatedNodes() (i bits.Bits) { + i = bits.New(len(g)) + i.SetAll() for fr, to := range g { if len(to) > 0 { - i.SetBit(NI(fr), 0) + i.SetBit(fr, 0) for _, to := range to { - i.SetBit(to.To, 0) + i.SetBit(int(to.To), 0) } } } return } -/* -MaxmimalClique finds a maximal clique containing the node n. - -Not sure this is good for anything. It produces a single maximal clique -but there can be multiple maximal cliques containing a given node. -This algorithm just returns one of them, not even necessarily the -largest one. +// Order is the number of nodes in receiver g. +// +// It is simply a wrapper method for the Go builtin len(). +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) Order() int { + // Why a wrapper for len()? Mostly for Directed and Undirected. + // u.Order() is a little nicer than len(u.LabeledAdjacencyList). + return len(g) +} -func (g LabeledAdjacencyList) MaximalClique(n int) []int { - c := []int{n} - var m bitset.BitSet - m.Set(uint(n)) - for fr, to := range g { - if fr == n { - continue +// ParallelArcs identifies all arcs from node `fr` to node `to`. +// +// The returned slice contains an element for each arc from node `fr` to node `to`. +// The element value is the index within the slice of arcs from node `fr`. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also the method HasArc, which stops after finding a single arc. +func (g LabeledAdjacencyList) ParallelArcs(fr, to NI) (p []int) { + for x, h := range g[fr] { + if h.To == to { + p = append(p, x) } - if len(to) < len(c) { - continue + } + return +} + +// Permute permutes the node labeling of receiver g. +// +// Argument p must be a permutation of the node numbers of the graph, +// 0 through len(g)-1. A permutation returned by rand.Perm(len(g)) for +// example is acceptable. +// +// The graph is permuted in place. The graph keeps the same underlying +// memory but values of the graph representation are permuted to produce +// an isomorphic graph. The node previously labeled 0 becomes p[0] and so on. +// See example (or the code) for clarification. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) Permute(p []int) { + old := append(LabeledAdjacencyList{}, g...) // shallow copy + for fr, arcs := range old { + for i, to := range arcs { + arcs[i].To = NI(p[to.To]) } - f := 0 - for _, to := range to { - if m.Test(uint(to.To)) { - f++ - if f == len(c) { - c = append(c, to.To) - m.Set(uint(to.To)) - break - } - } + g[p[fr]] = arcs + } +} + +// ShuffleArcLists shuffles the arc lists of each node of receiver g. +// +// For example a node with arcs leading to nodes 3 and 7 might have an +// arc list of either [3 7] or [7 3] after calling this method. The +// connectivity of the graph is not changed. The resulting graph stays +// equivalent but a traversal will encounter arcs in a different +// order. +// +// If Rand r is nil, the rand package default shared source is used. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledAdjacencyList) ShuffleArcLists(r *rand.Rand) { + ri := rand.Intn + if r != nil { + ri = r.Intn + } + // Knuth-Fisher-Yates + for _, to := range g { + for i := len(to); i > 1; { + j := ri(i) + i-- + to[i], to[j] = to[j], to[i] } } - return c } -*/ diff --git a/vendor/github.com/soniakeys/graph/bits.go b/vendor/github.com/soniakeys/graph/bits.go deleted file mode 100644 index b86703ca..00000000 --- a/vendor/github.com/soniakeys/graph/bits.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2014 Sonia Keys -// License MIT: http://opensource.org/licenses/MIT - -package graph - -import ( - "fmt" - "math/big" -) - -// Bits is bitmap, or bitset, intended to store a single bit of information -// per node of a graph. -// -// The current implementation is backed by a big.Int and so is a reference -// type in the same way a big.Int is. -type Bits struct { - i big.Int -} - -// NewBits constructs a Bits value with the bits ns set to 1. -func NewBits(ns ...NI) (b Bits) { - for _, n := range ns { - b.SetBit(n, 1) - } - return -} - -// AllNot sets n bits of z to the complement of x. -// -// It is a convenience method for SetAll followed by AndNot. -func (z *Bits) AllNot(n int, x Bits) { - var y Bits - y.SetAll(n) - z.AndNot(y, x) -} - -// And sets z = x & y. -func (z *Bits) And(x, y Bits) { - z.i.And(&x.i, &y.i) -} - -// AndNot sets z = x &^ y. -func (z *Bits) AndNot(x, y Bits) { - z.i.AndNot(&x.i, &y.i) -} - -// Bit returns the value of the n'th bit of x. -func (b Bits) Bit(n NI) uint { - return b.i.Bit(int(n)) -} - -// Clear sets all bits to 0. -func (z *Bits) Clear() { - *z = Bits{} -} - -// Format satisfies fmt.Formatter for fmt.Printf and related methods. -// -// graph.Bits format exactly like big.Ints. -func (b Bits) Format(s fmt.State, ch rune) { - b.i.Format(s, ch) -} - -// From returns the position of the first 1 bit at or after (from) position n. -// -// It returns -1 if there is no one bit at or after position n. -// -// This provides one way to iterate over one bits. -// To iterate over the one bits, call with n = 0 to get the the first -// one bit, then call with the result + 1 to get successive one bits. -// Unlike the Iterate method, this technique is stateless and so allows -// bits to be changed between successive calls. -// -// See also Iterate. -// -// (From is just a short word that means "at or after" here; -// it has nothing to do with arc direction.) -func (b Bits) From(n NI) NI { - words := b.i.Bits() - i := int(n) - x := i >> wordExp // x now index of word containing bit i. - if x >= len(words) { - return -1 - } - // test for 1 in this word at or after n - if wx := words[x] >> (uint(i) & (wordSize - 1)); wx != 0 { - return n + NI(trailingZeros(wx)) - } - x++ - for y, wy := range words[x:] { - if wy != 0 { - return NI((x+y)<>= uint(t + 1) - if w == 0 { - break - } - t = trailingZeros(w) - i += 1 + t - } - } - } - return true -} - -// Or sets z = x | y. -func (z *Bits) Or(x, y Bits) { - z.i.Or(&x.i, &y.i) -} - -// PopCount returns the number of 1 bits. -func (b Bits) PopCount() (c int) { - // algorithm selected to be efficient for sparse bit sets. - for _, w := range b.i.Bits() { - for w != 0 { - w &= w - 1 - c++ - } - } - return -} - -// Set sets the bits of z to the bits of x. -func (z *Bits) Set(x Bits) { - z.i.Set(&x.i) -} - -var one = big.NewInt(1) - -// SetAll sets z to have n 1 bits. -// -// It's useful for initializing z to have a 1 for each node of a graph. -func (z *Bits) SetAll(n int) { - z.i.Sub(z.i.Lsh(one, uint(n)), one) -} - -// SetBit sets the n'th bit to b, where be is a 0 or 1. -func (z *Bits) SetBit(n NI, b uint) { - z.i.SetBit(&z.i, int(n), b) -} - -// Single returns true if b has exactly one 1 bit. -func (b Bits) Single() bool { - // like PopCount, but stop as soon as two are found - c := 0 - for _, w := range b.i.Bits() { - for w != 0 { - w &= w - 1 - c++ - if c == 2 { - return false - } - } - } - return c == 1 -} - -// Slice returns a slice with the positions of each 1 bit. -func (b Bits) Slice() (s []NI) { - // (alternative implementation might use Popcount and make to get the - // exact cap slice up front. unclear if that would be better.) - b.Iterate(func(n NI) bool { - s = append(s, n) - return true - }) - return -} - -// Xor sets z = x ^ y. -func (z *Bits) Xor(x, y Bits) { - z.i.Xor(&x.i, &y.i) -} - -// Zero returns true if there are no 1 bits. -func (b Bits) Zero() bool { - return len(b.i.Bits()) == 0 -} - -// trailingZeros returns the number of trailing 0 bits in v. -// -// If v is 0, it returns 0. -func trailingZeros(v big.Word) int { - return deBruijnBits[v&-v*deBruijnMultiple>>deBruijnShift] -} diff --git a/vendor/github.com/soniakeys/graph/bits32.go b/vendor/github.com/soniakeys/graph/bits32.go deleted file mode 100644 index 18e07f9a..00000000 --- a/vendor/github.com/soniakeys/graph/bits32.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 Sonia Keys -// License MIT: http://opensource.org/licenses/MIT - -// +build 386 arm - -package graph - -// "word" here is math/big.Word -const ( - wordSize = 32 - wordExp = 5 // 2^5 = 32 -) - -// deBruijn magic numbers used in trailingZeros() -// -// reference: http://graphics.stanford.edu/~seander/bithacks.html -const deBruijnMultiple = 0x077CB531 -const deBruijnShift = 27 - -var deBruijnBits = []int{ - 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, - 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9, -} diff --git a/vendor/github.com/soniakeys/graph/bits64.go b/vendor/github.com/soniakeys/graph/bits64.go deleted file mode 100644 index ab601dd6..00000000 --- a/vendor/github.com/soniakeys/graph/bits64.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2014 Sonia Keys -// License MIT: http://opensource.org/licenses/MIT - -// +build !386,!arm - -package graph - -const ( - wordSize = 64 - wordExp = 6 // 2^6 = 64 -) - -// reference: http://graphics.stanford.edu/~seander/bithacks.html -const deBruijnMultiple = 0x03f79d71b4ca8b09 -const deBruijnShift = 58 - -var deBruijnBits = []int{ - 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, - 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, - 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, - 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, -} diff --git a/vendor/github.com/soniakeys/graph/dir.go b/vendor/github.com/soniakeys/graph/dir.go index 508306d1..a9ce5357 100644 --- a/vendor/github.com/soniakeys/graph/dir.go +++ b/vendor/github.com/soniakeys/graph/dir.go @@ -3,12 +3,125 @@ package graph +import ( + "math" +) + // dir.go has methods specific to directed graphs, types Directed and -// LabeledDirected. +// LabeledDirected, also Dominators. // // Methods on Directed are first, with exported methods alphabetized. +// Dominators type and methods are at the end. +//---------------------------- -import "errors" +// Cycles emits all elementary cycles in a directed graph. +// +// The algorithm here is Johnson's. See also the equivalent but generally +// slower alt.TarjanCycles. +func (g Directed) Cycles(emit func([]NI) bool) { + // Johnsons "Finding all the elementary circuits of a directed graph", + // SIAM J. Comput. Vol. 4, No. 1, March 1975. + a := g.AdjacencyList + k := make(AdjacencyList, len(a)) + B := make([]map[NI]bool, len(a)) + blocked := make([]bool, len(a)) + for i := range a { + blocked[i] = true + B[i] = map[NI]bool{} + } + var s NI + var stack []NI + var unblock func(NI) + unblock = func(u NI) { + blocked[u] = false + for w := range B[u] { + delete(B[u], w) + if blocked[w] { + unblock(w) + } + } + } + var circuit func(NI) (bool, bool) + circuit = func(v NI) (found, ok bool) { + f := false + stack = append(stack, v) + blocked[v] = true + for _, w := range k[v] { + if w == s { + if !emit(stack) { + return + } + f = true + } else if !blocked[w] { + switch found, ok = circuit(w); { + case !ok: + return + case found: + f = true + } + } + } + if f { + unblock(v) + } else { + for _, w := range k[v] { + B[w][v] = true + } + } + stack = stack[:len(stack)-1] + return f, true + } + for s = 0; int(s) < len(a); s++ { + // (so there's a little extra n^2 component introduced here that + // comes from not making a proper subgraph but just removing arcs + // and leaving isolated nodes. Iterating over the isolated nodes + // should be very fast though. It seems like it would be a net win + // over creating a subgraph.) + // shallow subgraph + for z := NI(0); z < s; z++ { + k[z] = nil + } + for z := int(s); z < len(a); z++ { + k[z] = a[z] + } + // find scc in k with s + var scc []NI + Directed{k}.StronglyConnectedComponents(func(c []NI) bool { + for _, n := range c { + if n == s { // this is it + scc = c + return false // stop scc search + } + } + return true // keep looking + }) + // clear k + for n := range k { + k[n] = nil + } + // map component + for _, n := range scc { + blocked[n] = false + } + // copy component to k + for _, fr := range scc { + var kt []NI + for _, to := range a[fr] { + if !blocked[to] { + kt = append(kt, to) + } + } + k[fr] = kt + } + if _, ok := circuit(s); !ok { + return + } + // reblock component + for _, n := range scc { + blocked[n] = true + } + } +} // DAGMaxLenPath finds a maximum length path in a directed acyclic graph. // @@ -20,7 +133,7 @@ func (g Directed) DAGMaxLenPath(ordering []NI) (path []NI) { // // Similar code in label.go var n NI - mlp := make([][]NI, len(g.AdjacencyList)) // index by node number + mlp := make([][]NI, g.Order()) // index by node number for i := len(ordering) - 1; i >= 0; i-- { fr := ordering[i] // node number to := g.AdjacencyList[fr] @@ -43,263 +156,99 @@ func (g Directed) DAGMaxLenPath(ordering []NI) (path []NI) { return append([]NI{n}, path...) } -// EulerianCycle finds an Eulerian cycle in a directed multigraph. -// -// * If g has no nodes, result is nil, nil. -// -// * If g is Eulerian, result is an Eulerian cycle with err = nil. -// The cycle result is a list of nodes, where the first and last -// nodes are the same. -// -// * Otherwise, result is nil, error -// -// Internally, EulerianCycle copies the entire graph g. -// See EulerianCycleD for a more space efficient version. -func (g Directed) EulerianCycle() ([]NI, error) { - c, m := g.Copy() - return c.EulerianCycleD(m) -} - -// EulerianCycleD finds an Eulerian cycle in a directed multigraph. -// -// EulerianCycleD is destructive on its receiver g. See EulerianCycle for -// a non-destructive version. -// -// Argument ma must be the correct arc size, or number of arcs in g. +// FromList creates a spanning forest of a graph. // -// * If g has no nodes, result is nil, nil. +// The method populates the From members in f.Paths and returns the FromList. +// Also returned is a bool, true if the receiver is found to be a simple graph +// representing a tree or forest. Loops, or any case of multiple arcs going to +// a node will cause simpleForest to be false. // -// * If g is Eulerian, result is an Eulerian cycle with err = nil. -// The cycle result is a list of nodes, where the first and last -// nodes are the same. +// The FromList return value f will always be a spanning forest of the entire +// graph. The bool return value simpleForest tells if the receiver graph g +// was a simple forest to begin with. // -// * Otherwise, result is nil, error -func (g Directed) EulerianCycleD(ma int) ([]NI, error) { - if len(g.AdjacencyList) == 0 { - return nil, nil - } - e := newEulerian(g.AdjacencyList, ma) - for e.s >= 0 { - v := e.top() // v is node that starts cycle - e.push() - // if Eulerian, we'll always come back to starting node - if e.top() != v { - return nil, errors.New("not balanced") - } - e.keep() - } - if !e.uv.Zero() { - return nil, errors.New("not strongly connected") +// Other members of the FromList are left as zero values. +// Use FromList.RecalcLen and FromList.RecalcLeaves as needed. +func (g Directed) FromList() (f *FromList, simpleForest bool) { + paths := make([]PathEnd, g.Order()) + for i := range paths { + paths[i].From = -1 } - return e.p, nil -} - -// EulerianPath finds an Eulerian path in a directed multigraph. -// -// * If g has no nodes, result is nil, nil. -// -// * If g has an Eulerian path, result is an Eulerian path with err = nil. -// The path result is a list of nodes, where the first node is start. -// -// * Otherwise, result is nil, error -// -// Internally, EulerianPath copies the entire graph g. -// See EulerianPathD for a more space efficient version. -func (g Directed) EulerianPath() ([]NI, error) { - ind := g.InDegree() - var start NI - for n, to := range g.AdjacencyList { - if len(to) > ind[n] { - start = NI(n) - break + simpleForest = true + for fr, to := range g.AdjacencyList { + for _, to := range to { + if int(to) == fr || paths[to].From >= 0 { + simpleForest = false + } else { + paths[to].From = NI(fr) + } } } - c, m := g.Copy() - return c.EulerianPathD(m, start) + return &FromList{Paths: paths}, simpleForest } -// EulerianPathD finds an Eulerian path in a directed multigraph. +// SpanTree builds a tree spanning nodes reachable from the given root. // -// EulerianPathD is destructive on its receiver g. See EulerianPath for -// a non-destructive version. +// The component is spanned by breadth-first search from root. +// The resulting spanning tree in stored a FromList. // -// Argument ma must be the correct arc size, or number of arcs in g. -// Argument start must be a valid start node for the path. +// If FromList.Paths is not the same length as g, it is allocated and +// initialized. This allows a zero value FromList to be passed as f. +// If FromList.Paths is the same length as g, it is used as is and is not +// reinitialized. This allows multiple trees to be spanned in the same +// FromList with successive calls. // -// * If g has no nodes, result is nil, nil. +// For nodes spanned, the Path member of the returned FromList is populated +// with both From and Len values. The MaxLen member will be updated but +// not Leaves. // -// * If g has an Eulerian path, result is an Eulerian path with err = nil. -// The path result is a list of nodes, where the first node is start. -// -// * Otherwise, result is nil, error -func (g Directed) EulerianPathD(ma int, start NI) ([]NI, error) { - if len(g.AdjacencyList) == 0 { - return nil, nil - } - e := newEulerian(g.AdjacencyList, ma) - e.p[0] = start - // unlike EulerianCycle, the first path doesn't have be a cycle. - e.push() - e.keep() - for e.s >= 0 { - start = e.top() - e.push() - // paths after the first must be cycles though - // (as long as there are nodes on the stack) - if e.top() != start { - return nil, errors.New("no Eulerian path") +// Returned is the number of nodes spanned, which will be the number of nodes +// reachable from root, and a bool indicating if these nodes were found to be +// a simply connected tree in the receiver graph g. Any cycles, loops, +// or parallel arcs in the component will cause simpleTree to be false, but +// FromList f will still be populated with a valid spanning tree. +func (g Directed) SpanTree(root NI, f *FromList) (nSpanned int, simpleTree bool) { + a := g.AdjacencyList + p := f.Paths + if len(p) != len(a) { + p = make([]PathEnd, len(a)) + for i := range p { + p[i].From = -1 } - e.keep() + f.Paths = p } - if !e.uv.Zero() { - return nil, errors.New("no Eulerian path") - } - return e.p, nil -} - -// starting at the node on the top of the stack, follow arcs until stuck. -// mark nodes visited, push nodes on stack, remove arcs from g. -func (e *eulerian) push() { - for u := e.top(); ; { - e.uv.SetBit(u, 0) // reset unvisited bit - arcs := e.g[u] - if len(arcs) == 0 { - return // stuck - } - w := arcs[0] // follow first arc - e.s++ // push followed node on stack - e.p[e.s] = w - e.g[u] = arcs[1:] // consume arc - u = w - } -} - -// like push, but for for undirected graphs. -func (e *eulerian) pushUndir() { - for u := e.top(); ; { - e.uv.SetBit(u, 0) - arcs := e.g[u] - if len(arcs) == 0 { - return - } - w := arcs[0] - e.s++ - e.p[e.s] = w - e.g[u] = arcs[1:] // consume arc - // here is the only difference, consume reciprocal arc as well: - a2 := e.g[w] - for x, rx := range a2 { - if rx == u { // here it is - last := len(a2) - 1 - a2[x] = a2[last] // someone else gets the seat - e.g[w] = a2[:last] // and it's gone. - break - } - } - u = w + simpleTree = true + p[root].Len = 1 + type arc struct { + from, to NI } -} - -// starting with the node on top of the stack, move nodes with no arcs. -func (e *eulerian) keep() { - for e.s >= 0 { - n := e.top() - if len(e.g[n]) > 0 { - break - } - e.p[e.m] = n - e.s-- - e.m-- - } -} - -type eulerian struct { - g AdjacencyList // working copy of graph, it gets consumed - m int // number of arcs in g, updated as g is consumed - uv Bits // unvisited - // low end of p is stack of unfinished nodes - // high end is finished path - p []NI // stack + path - s int // stack pointer -} - -func (e *eulerian) top() NI { - return e.p[e.s] -} - -func newEulerian(g AdjacencyList, m int) *eulerian { - e := &eulerian{ - g: g, - m: m, - p: make([]NI, m+1), - } - e.uv.SetAll(len(g)) - return e -} - -// MaximalNonBranchingPaths finds all paths in a directed graph that are -// "maximal" and "non-branching". -// -// A non-branching path is one where path nodes other than the first and last -// have exactly one arc leading to the node and one arc leading from the node, -// thus there is no possibility to branch away to a different path. -// -// A maximal non-branching path cannot be extended to a longer non-branching -// path by including another node at either end. -// -// In the case of a cyclic non-branching path, the first and last elements -// of the path will be the same node, indicating an isolated cycle. -// -// The method calls the emit argument for each path or isolated cycle in g, -// as long as emit returns true. If emit returns false, -// MaximalNonBranchingPaths returns immediately. -func (g Directed) MaximalNonBranchingPaths(emit func([]NI) bool) { - ind := g.InDegree() - var uv Bits - uv.SetAll(len(g.AdjacencyList)) - for v, vTo := range g.AdjacencyList { - if !(ind[v] == 1 && len(vTo) == 1) { - for _, w := range vTo { - n := []NI{NI(v), w} - uv.SetBit(NI(v), 0) - uv.SetBit(w, 0) - wTo := g.AdjacencyList[w] - for ind[w] == 1 && len(wTo) == 1 { - u := wTo[0] - n = append(n, u) - uv.SetBit(u, 0) - w = u - wTo = g.AdjacencyList[w] + var next []arc + frontier := []arc{{-1, root}} + for len(frontier) > 0 { + for _, fa := range frontier { // fa frontier arc + nSpanned++ + l := p[fa.to].Len + 1 + for _, to := range a[fa.to] { + if p[to].Len > 0 { + simpleTree = false + continue } - if !emit(n) { // n is a path - return + p[to] = PathEnd{From: fa.to, Len: l} + if l > f.MaxLen { + f.MaxLen = l } + next = append(next, arc{fa.to, to}) } } + frontier, next = next, frontier[:0] } - // use uv.From rather than uv.Iterate. - // Iterate doesn't work here because we're modifying uv - for b := uv.From(0); b >= 0; b = uv.From(b + 1) { - v := NI(b) - n := []NI{v} - for w := v; ; { - w = g.AdjacencyList[w][0] - uv.SetBit(w, 0) - n = append(n, w) - if w == v { - break - } - } - if !emit(n) { // n is an isolated cycle - return - } - } + return } // Undirected returns copy of g augmented as needed to make it undirected. func (g Directed) Undirected() Undirected { - c, _ := g.AdjacencyList.Copy() // start with a copy - rw := make(AdjacencyList, len(g.AdjacencyList)) // "reciprocals wanted" + c, _ := g.AdjacencyList.Copy() // start with a copy + rw := make(AdjacencyList, g.Order()) // "reciprocals wanted" for fr, to := range g.AdjacencyList { arc: // for each arc in g for _, to := range to { @@ -327,64 +276,13 @@ func (g Directed) Undirected() Undirected { return Undirected{c} } -// StronglyConnectedComponents identifies strongly connected components -// in a directed graph. -// -// Algorithm by David J. Pearce, from "An Improved Algorithm for Finding the -// Strongly Connected Components of a Directed Graph". It is algorithm 3, -// PEA_FIND_SCC2 in -// http://homepages.mcs.vuw.ac.nz/~djp/files/P05.pdf, accessed 22 Feb 2015. -// -// Returned is a list of components, each component is a list of nodes. -/* -func (g Directed) StronglyConnectedComponents() []int { - rindex := make([]int, len(g)) - S := []int{} - index := 1 - c := len(g) - 1 - visit := func(v int) { - root := true - rindex[v] = index - index++ - for _, w := range g[v] { - if rindex[w] == 0 { - visit(w) - } - if rindex[w] < rindex[v] { - rindex[v] = rindex[w] - root = false - } - } - if root { - index-- - for top := len(S) - 1; top >= 0 && rindex[v] <= rindex[top]; top-- { - w = rindex[top] - S = S[:top] - rindex[w] = c - index-- - } - rindex[v] = c - c-- - } else { - S = append(S, v) - } - } - for v := range g { - if rindex[v] == 0 { - visit(v) - } - } - return rindex -} -*/ - // Transpose constructs a new adjacency list with all arcs reversed. // // For every arc from->to of g, the result will have an arc to->from. // Transpose also counts arcs as it traverses and returns ma the number of arcs // in g (equal to the number of arcs in the result.) func (g Directed) Transpose() (t Directed, ma int) { - ta := make(AdjacencyList, len(g.AdjacencyList)) + ta := make(AdjacencyList, g.Order()) for n, nbs := range g.AdjacencyList { for _, nb := range nbs { ta[nb] = append(ta[nb], NI(n)) @@ -394,6 +292,102 @@ func (g Directed) Transpose() (t Directed, ma int) { return Directed{ta}, ma } +// Cycles emits all elementary cycles in a directed graph. +// +// The algorithm here is Johnson's. See also the equivalent but generally +// slower alt.TarjanCycles. +func (g LabeledDirected) Cycles(emit func([]Half) bool) { + a := g.LabeledAdjacencyList + k := make(LabeledAdjacencyList, len(a)) + B := make([]map[NI]bool, len(a)) + blocked := make([]bool, len(a)) + for i := range a { + blocked[i] = true + B[i] = map[NI]bool{} + } + var s NI + var stack []Half + var unblock func(NI) + unblock = func(u NI) { + blocked[u] = false + for w := range B[u] { + delete(B[u], w) + if blocked[w] { + unblock(w) + } + } + } + var circuit func(NI) (bool, bool) + circuit = func(v NI) (found, ok bool) { + f := false + blocked[v] = true + for _, w := range k[v] { + if w.To == s { + if !emit(append(stack, w)) { + return + } + f = true + } else if !blocked[w.To] { + stack = append(stack, w) + switch found, ok = circuit(w.To); { + case !ok: + return + case found: + f = true + } + stack = stack[:len(stack)-1] + } + } + if f { + unblock(v) + } else { + for _, w := range k[v] { + B[w.To][v] = true + } + } + return f, true + } + for s = 0; int(s) < len(a); s++ { + for z := NI(0); z < s; z++ { + k[z] = nil + } + for z := int(s); z < len(a); z++ { + k[z] = a[z] + } + var scc []NI + LabeledDirected{k}.StronglyConnectedComponents(func(c []NI) bool { + for _, n := range c { + if n == s { + scc = c + return false + } + } + return true + }) + for n := range k { + k[n] = nil + } + for _, n := range scc { + blocked[n] = false + } + for _, fr := range scc { + var kt []Half + for _, to := range a[fr] { + if !blocked[to.To] { + kt = append(kt, to) + } + } + k[fr] = kt + } + if _, ok := circuit(s); !ok { + return + } + for _, n := range scc { + blocked[n] = true + } + } +} + // DAGMaxLenPath finds a maximum length path in a directed acyclic graph. // // Length here means number of nodes or arcs, not a sum of arc weights. @@ -408,7 +402,7 @@ func (g LabeledDirected) DAGMaxLenPath(ordering []NI) (n NI, path []Half) { // Visits each arc once. Time complexity O(m). // // Similar code in dir.go. - mlp := make([][]Half, len(g.LabeledAdjacencyList)) // index by node number + mlp := make([][]Half, g.Order()) // index by node number for i := len(ordering) - 1; i >= 0; i-- { fr := ordering[i] // node number to := g.LabeledAdjacencyList[fr] @@ -431,36 +425,437 @@ func (g LabeledDirected) DAGMaxLenPath(ordering []NI) (n NI, path []Half) { return } -// FromListLabels transposes a labeled graph into a FromList and associated -// list of labels. +// FromList creates a spanning forest of a graph. // -// Receiver g should be connected as a tree or forest. Specifically no node -// can have multiple incoming arcs. If any node n in g has multiple incoming -// arcs, the method returns (nil, nil, n) where n is a node with multiple -// incoming arcs. +// The method populates the From members in f.Paths and returns the FromList. +// Also returned is a list of labels corresponding to the from arcs, and a +// bool, true if the receiver is found to be a simple graph representing +// a tree or forest. Loops, or any case of multiple arcs going to a node +// will cause simpleForest to be false. // -// Otherwise (normally) the method populates the From members in a -// FromList.Path, populates a slice of labels, and returns the FromList, -// labels, and -1. +// The FromList return value f will always be a spanning forest of the entire +// graph. The bool return value simpleForest tells if the receiver graph g +// was a simple forest to begin with. // // Other members of the FromList are left as zero values. // Use FromList.RecalcLen and FromList.RecalcLeaves as needed. -func (g LabeledDirected) FromListLabels() (*FromList, []LI, NI) { - labels := make([]LI, len(g.LabeledAdjacencyList)) - paths := make([]PathEnd, len(g.LabeledAdjacencyList)) +func (g LabeledDirected) FromList() (f *FromList, labels []LI, simpleForest bool) { + labels = make([]LI, g.Order()) + paths := make([]PathEnd, g.Order()) for i := range paths { paths[i].From = -1 } + simpleForest = true for fr, to := range g.LabeledAdjacencyList { for _, to := range to { - if paths[to.To].From >= 0 { - return nil, nil, to.To + if int(to.To) == fr || paths[to.To].From >= 0 { + simpleForest = false + } else { + paths[to.To].From = NI(fr) + labels[to.To] = to.Label } - paths[to.To].From = NI(fr) - labels[to.To] = to.Label } } - return &FromList{Paths: paths}, labels, -1 + return &FromList{Paths: paths}, labels, simpleForest +} + +// NegativeCycles emits all cycles with negative cycle distance. +// +// The emit function is called for each cycle found. Emit must return true +// to continue cycle enumeration. If emit returns false, NegativeCycles +// stops and returns immediately. +// +// The method mutates receiver g while it runs. Access to g before +// NegativeCycles returns, such as during the emit callback, will find +// g altered. G is completely restored when NegativeCycles returns however, +// even if terminated early with a false return from emit. +// +// If mutations on g are unacceptable, use g.Copy and run NegativeCycles on +// the copy. +// +// See also: +// +// * NegativeCycle, which finds a single example of a negative cycle if +// one exists. +// +// * HasNegativeCycle, which detects if a negative cycle exists. +// +// * BellmanFord, which also detects negative cycles. +// +// * Cycles, from which negative cycles can be filtered. +// +// * alt.NegativeCycles, which uses less memory but is generally slower. +func (g LabeledDirected) NegativeCycles(w WeightFunc, emit func([]Half) bool) { + // Implementation of "Finding all the negative cycles in a directed graph" + // by Takeo Yamada and Harunobu Kinoshita, Discrete Applied Mathematics + // 118 (2002) 279–291. + newNegCyc(g, w, emit).all_nc(LabeledPath{}) +} + +type negCyc struct { + g LabeledDirected + w WeightFunc + emit func([]Half) bool + a LabeledAdjacencyList + tr AdjacencyList + d0, d1 []float64 + dc []float64 + bt [][]fromHalf + btLast []int +} + +func newNegCyc(g LabeledDirected, w WeightFunc, emit func([]Half) bool) *negCyc { + nc := &negCyc{g: g, w: w, emit: emit} + nc.a = g.LabeledAdjacencyList + // transpose to make it easier to find from-arcs. + lt, _ := g.UnlabeledTranspose() + nc.tr = lt.AdjacencyList + nc.d0 = make([]float64, len(nc.a)) + nc.d1 = make([]float64, len(nc.a)) + nc.dc = make([]float64, len(nc.a)) + nc.btLast = make([]int, len(nc.a)) + nc.bt = make([][]fromHalf, len(nc.a)) + for i := range nc.bt { + nc.bt[i] = make([]fromHalf, len(nc.a)) + } + return nc +} + +func (nc *negCyc) all_nc(F LabeledPath) bool { + var C []Half + var R LabeledPath + // Step 1 + if len(F.Path) != 0 { + return nc.step2(F) + } + C = nc.g.NegativeCycle(nc.w) + if len(C) == 0 { + return true + } + // prep step 4 with no F: + F.Start = C[len(C)-1].To + R = LabeledPath{F.Start, C} + return nc.step4(C, F, R) +} + +func (nc *negCyc) step2(F LabeledPath) bool { + fEnd := F.Path[len(F.Path)-1].To + wF := F.Distance(nc.w) + dL, Ď€L := nc.zL(F, fEnd, wF) + if !(dL < 0) { + return true + } + if len(Ď€L) > 0 { + C := append(F.Path, Ď€L...) + R := LabeledPath{fEnd, Ď€L} + return nc.step4(C, F, R) + } + return nc.step3(F, fEnd, wF) +} + +func (nc *negCyc) step3(F LabeledPath, fEnd NI, wF float64) bool { + πΓ := nc.zΓ(F, wF) + if len(πΓ) > 0 { + // prep for step 4 + C := append(F.Path, πΓ...) + R := LabeledPath{fEnd, πΓ} + return nc.step4(C, F, R) + } + return nc.step5(F, fEnd) +} + +func (nc *negCyc) step4(C []Half, F, R LabeledPath) (ok bool) { + // C is a new cycle. + // F is fixed path to be extended and is a prefix of C. + // R is the remainder of C + if ok = nc.emit(C); !ok { + return + } + // for each arc in R, if not the first arc, + // extend F by the arc of the previous iteration. + // remove arc from g, + // Then make the recursive call, then put the arc back in g. + // + // after loop, replace arcs from the two stacks. + type frto struct { + fr NI + to []Half + } + var frStack [][]arc + var toStack []frto + var fr0 NI + var to0 Half + for i, h := range R.Path { + if i > 0 { + // extend F by arc {fr0 to0}, the arc of the previous iteration. + // Remove arcs to to0.To and save on stack. + // Remove arcs from arc0.fr and save on stack. + F.Path = append(F.Path, to0) + frStack = append(frStack, nc.cutTo(to0.To)) + toStack = append(toStack, frto{fr0, nc.a[fr0]}) + nc.a[fr0] = nil + } + toList := nc.a[R.Start] + for j, to := range toList { + if to == h { + last := len(toList) - 1 + toList[j], toList[last] = toList[last], toList[j] + nc.a[R.Start] = toList[:last] + ok = nc.all_nc(F) // return value + toList[last], toList[j] = toList[j], toList[last] + nc.a[R.Start] = toList + break + } + } + if !ok { + break + } + fr0 = R.Start + to0 = h + R.Start = h.To + } + for i := len(frStack) - 1; i >= 0; i-- { + nc.a[toStack[i].fr] = toStack[i].to + nc.restore(frStack[i]) + } + return +} + +func (nc *negCyc) step5(F LabeledPath, fEnd NI) (ok bool) { + // Step 5 (uncertain case) + // + // For each arc from end of F, search each case of extending + // F by that arc. + // + // before loop: save arcs from current path end, + // replace them with room for a single arc. + // extend F by room for one more arc, + ok = true + save := nc.a[fEnd] + nc.a[fEnd] = []Half{{}} + last := len(F.Path) + F.Path = append(F.Path, Half{}) + for _, h := range save { + // in each iteration, set the final arc in F, and the single + // outgoing arc, and save and clear all inbound arcs to the + // new end node. make recursive call, then restore saved + // inbound arcs for the node. + F.Path[last] = h + nc.a[fEnd][0] = h + save := nc.cutTo(h.To) + ok = nc.all_nc(F) + nc.restore(save) + if !ok { + break + } + } + // after loop, restore saved outgoing arcs in g. + nc.a[fEnd] = save + return +} + +type arc struct { + n NI // node that had an arc cut from its toList + x int // index of arc that was swapped to the end of the list +} + +// modify a cutting all arcs to node n. return list of cut arcs than +// can be processed in reverse order to restore changes to a +func (nc *negCyc) cutTo(n NI) (c []arc) { + for _, fr := range nc.tr[n] { + toList := nc.a[fr] + for x := 0; x < len(toList); { + to := toList[x] + if to.To == n { + c = append(c, arc{fr, x}) + last := len(toList) - 1 + toList[x], toList[last] = toList[last], toList[x] + toList = toList[:last] + } else { + x++ + } + } + nc.a[fr] = toList + } + return +} + +func (nc *negCyc) restore(c []arc) { + for i := len(c) - 1; i >= 0; i-- { + r := c[i] + toList := nc.a[r.n] + last := len(toList) + toList = toList[:last+1] + toList[r.x], toList[last] = toList[last], toList[r.x] + nc.a[r.n] = toList + } +} + +func (nc *negCyc) zL(F LabeledPath, fEnd NI, wp float64) (float64, []Half) { + Ď€, c, d := nc.Ď€j(len(nc.a)-len(F.Path), F.Start, fEnd) + if c < 0 { + return d + wp, Ď€ + } + j := len(nc.a) - len(F.Path) - 1 + // G1: cut arcs going to c + saveFr := nc.cutTo(c) + for k := 1; k <= j; k++ { + nc.dc[k] = nc.dj(k, F.Start, c) + } + // G0: also cut arcs coming from c + saveTo := nc.a[c] + nc.a[c] = nil + min := nc.dj(j, F.Start, fEnd) + // G2: restore arcs going to c + nc.restore(saveFr) + for k := 1; k <= j; k++ { + d1 := nc.dc[k] + nc.dj(j+1-k, c, fEnd) + if d1 < min { + min = d1 + } + } + nc.a[c] = saveTo + return min + wp, nil +} + +func (nc *negCyc) dj(j int, v, v0 NI) float64 { + for i := range nc.d0 { + nc.d0[i] = math.Inf(1) + } + nc.d0[v0] = 0 + for ; j > 0; j-- { + for i, d := range nc.d0 { + nc.d1[i] = d + } + for vĘą, d0vĘą := range nc.d0 { + if d0vĘą < math.Inf(1) { + for _, to := range nc.a[vĘą] { + if sum := d0vĘą + nc.w(to.Label); sum < nc.d1[to.To] { + nc.d1[to.To] = sum + } + } + } + } + nc.d0, nc.d1 = nc.d1, nc.d0 + } + return nc.d0[v] +} + +func (nc *negCyc) Ď€j(j int, v, v0 NI) ([]Half, NI, float64) { + for i := range nc.d0 { + nc.d0[i] = math.Inf(1) + nc.btLast[i] = -1 + } + nc.d0[v0] = 0 + for k := 0; k < j; k++ { + for i, d := range nc.d0 { + nc.d1[i] = d + } + btk := nc.bt[k] + for vĘą, d0vĘą := range nc.d0 { + if d0vĘą < math.Inf(1) { + for _, to := range nc.a[vĘą] { + if sum := d0vĘą + nc.w(to.Label); sum < nc.d1[to.To] { + nc.d1[to.To] = sum + btk[to.To] = fromHalf{NI(vĘą), to.Label} + nc.btLast[to.To] = k + } + } + } + } + nc.d0, nc.d1 = nc.d1, nc.d0 + } + p := make([]Half, nc.btLast[v]+1) + m := map[NI]bool{} + c := NI(-1) + to := v + for k := nc.btLast[v]; k >= 0; k-- { + fh := nc.bt[k][to] + p[k] = Half{to, fh.Label} + to = fh.From + if c < 0 { + if m[to] { + c = to + } else { + m[to] = true + } + } + } + return p, c, nc.d0[v] +} + +func (nc *negCyc) zΓ(F LabeledPath, wp float64) []Half { + p, d := nc.a.DijkstraPath(F.Path[len(F.Path)-1].To, F.Start, nc.w) + if !(wp+d < 0) { + return nil + } + return p.Path +} + +// SpanTree builds a tree spanning nodes reachable from the given root. +// +// The component is spanned by breadth-first search from root. +// The resulting spanning tree in stored a FromList, and arc labels optionally +// stored in a slice. +// +// If FromList.Paths is not the same length as g, it is allocated and +// initialized. This allows a zero value FromList to be passed as f. +// If FromList.Paths is the same length as g, it is used as is and is not +// reinitialized. This allows multiple trees to be spanned in the same +// FromList with successive calls. +// +// For nodes spanned, the Path member of the returned FromList is populated +// with both From and Len values. The MaxLen member will be updated but +// not Leaves. +// +// The labels slice will be populated only if it is same length as g. +// Nil can be passed for example if labels are not needed. +// +// Returned is the number of nodes spanned, which will be the number of nodes +// reachable from root, and a bool indicating if these nodes were found to be +// a simply connected tree in the receiver graph g. Any cycles, loops, +// or parallel arcs in the component will cause simpleTree to be false, but +// FromList f will still be populated with a valid spanning tree. +func (g LabeledDirected) SpanTree(root NI, f *FromList, labels []LI) (nSpanned int, simpleTree bool) { + a := g.LabeledAdjacencyList + p := f.Paths + if len(p) != len(a) { + p = make([]PathEnd, len(a)) + for i := range p { + p[i].From = -1 + } + f.Paths = p + } + simpleTree = true + p[root].Len = 1 + type arc struct { + from NI + half Half + } + var next []arc + frontier := []arc{{-1, Half{root, -1}}} + for len(frontier) > 0 { + for _, fa := range frontier { // fa frontier arc + nSpanned++ + l := p[fa.half.To].Len + 1 + for _, to := range a[fa.half.To] { + if p[to.To].Len > 0 { + simpleTree = false + continue + } + p[to.To] = PathEnd{From: fa.half.To, Len: l} + if len(labels) == len(p) { + labels[to.To] = to.Label + } + if l > f.MaxLen { + f.MaxLen = l + } + next = append(next, arc{fa.half.To, to}) + } + } + frontier, next = next, frontier[:0] + } + return } // Transpose constructs a new adjacency list that is the transpose of g. @@ -469,7 +864,7 @@ func (g LabeledDirected) FromListLabels() (*FromList, []LI, NI) { // Transpose also counts arcs as it traverses and returns ma the number of // arcs in g (equal to the number of arcs in the result.) func (g LabeledDirected) Transpose() (t LabeledDirected, ma int) { - ta := make(LabeledAdjacencyList, len(g.LabeledAdjacencyList)) + ta := make(LabeledAdjacencyList, g.Order()) for n, nbs := range g.LabeledAdjacencyList { for _, nb := range nbs { ta[nb.To] = append(ta[nb.To], Half{To: NI(n), Label: nb.Label}) @@ -484,7 +879,7 @@ func (g LabeledDirected) Transpose() (t LabeledDirected, ma int) { func (g LabeledDirected) Undirected() LabeledUndirected { c, _ := g.LabeledAdjacencyList.Copy() // start with a copy // "reciprocals wanted" - rw := make(LabeledAdjacencyList, len(g.LabeledAdjacencyList)) + rw := make(LabeledAdjacencyList, g.Order()) for fr, to := range g.LabeledAdjacencyList { arc: // for each arc in g for _, to := range to { @@ -527,7 +922,7 @@ func (g LabeledDirected) Unlabeled() Directed { // It is equivalent to g.Unlabeled().Transpose() but constructs the result // directly. func (g LabeledDirected) UnlabeledTranspose() (t Directed, ma int) { - ta := make(AdjacencyList, len(g.LabeledAdjacencyList)) + ta := make(AdjacencyList, g.Order()) for n, nbs := range g.LabeledAdjacencyList { for _, nb := range nbs { ta[nb.To] = append(ta[nb.To], NI(n)) @@ -536,3 +931,129 @@ func (g LabeledDirected) UnlabeledTranspose() (t Directed, ma int) { } return Directed{ta}, ma } + +// DominanceFrontiers holds dominance frontiers for all nodes in some graph. +// The frontier for a given node is a set of nodes, represented here as a map. +type DominanceFrontiers []map[NI]struct{} + +// Frontier computes the dominance frontier for a node set. +func (d DominanceFrontiers) Frontier(s map[NI]struct{}) map[NI]struct{} { + fs := map[NI]struct{}{} + for n := range s { + for f := range d[n] { + fs[f] = struct{}{} + } + } + return fs +} + +// Closure computes the closure, or iterated dominance frontier for a node set. +func (d DominanceFrontiers) Closure(s map[NI]struct{}) map[NI]struct{} { + c := map[NI]struct{}{} + e := map[NI]struct{}{} + w := map[NI]struct{}{} + var n NI + for n = range s { + e[n] = struct{}{} + w[n] = struct{}{} + } + for len(w) > 0 { + for n = range w { + break + } + delete(w, n) + for f := range d[n] { + if _, ok := c[f]; !ok { + c[f] = struct{}{} + if _, ok := e[f]; !ok { + e[f] = struct{}{} + w[f] = struct{}{} + } + } + } + } + return c +} + +// Dominators holds immediate dominators. +// +// Dominators is a return type from methods Dominators, PostDominators, and +// Doms. See those methods for construction examples. +// +// The list of immediate dominators represents the "dominator tree" +// (in the same way a FromList represents a tree, but somewhat lighter weight.) +// +// In addition to the exported immediate dominators, the type also retains +// the transpose graph that was used to compute the dominators. +// See PostDominators and Doms for a caution about modifying the transpose +// graph. +type Dominators struct { + Immediate []NI + from interface { // either Directed or LabeledDirected + domFrontiers(Dominators) DominanceFrontiers + } +} + +// Frontiers constructs the dominator frontier for each node. +// +// The frontier for a node is a set of nodes, represented as a map. The +// returned slice has the length of d.Immediate, which is the length of +// the original graph. The frontier is valid however only for nodes of the +// reachable subgraph. Nodes not in the reachable subgraph, those with a +// d.Immediate value of -1, will have a nil map. +func (d Dominators) Frontiers() DominanceFrontiers { + return d.from.domFrontiers(d) +} + +// Set constructs the dominator set for a given node. +// +// The dominator set for a node always includes the node itself as the first +// node in the returned slice, as long as the node was in the subgraph +// reachable from the start node used to construct the dominators. +// If the argument n is a node not in the subgraph, Set returns nil. +func (d Dominators) Set(n NI) []NI { + im := d.Immediate + if im[n] < 0 { + return nil + } + for s := []NI{n}; ; { + if p := im[n]; p < 0 || p == n { + return s + } else { + s = append(s, p) + n = p + } + } +} + +// starting at the node on the top of the stack, follow arcs until stuck. +// mark nodes visited, push nodes on stack, remove arcs from g. +func (e *eulerian) push() { + for u := e.top(); ; { + e.uv.SetBit(int(u), 0) // reset unvisited bit + arcs := e.g[u] + if len(arcs) == 0 { + return // stuck + } + w := arcs[0] // follow first arc + e.s++ // push followed node on stack + e.p[e.s] = w + e.g[u] = arcs[1:] // consume arc + u = w + } +} + +func (e *labEulerian) push() { + for u := e.top().To; ; { + e.uv.SetBit(int(u), 0) // reset unvisited bit + arcs := e.g[u] + if len(arcs) == 0 { + return // stuck + } + w := arcs[0] // follow first arc + e.s++ // push followed node on stack + e.p[e.s] = w + e.g[u] = arcs[1:] // consume arc + u = w.To + } +} diff --git a/vendor/github.com/soniakeys/graph/dir_RO.go b/vendor/github.com/soniakeys/graph/dir_RO.go index 77558a96..6d43d12a 100644 --- a/vendor/github.com/soniakeys/graph/dir_RO.go +++ b/vendor/github.com/soniakeys/graph/dir_RO.go @@ -3,6 +3,13 @@ package graph +import ( + "errors" + "fmt" + + "github.com/soniakeys/bits" +) + // dir_RO.go is code generated from dir_cg.go by directives in graph.go. // Editing dir_cg.go is okay. It is the code generation source. // DO NOT EDIT dir_RO.go. @@ -43,9 +50,10 @@ func (g Directed) Copy() (c Directed, ma int) { func (g Directed) Cyclic() (cyclic bool, fr NI, to NI) { a := g.AdjacencyList fr, to = -1, -1 - var temp, perm Bits - var df func(NI) - df = func(n NI) { + temp := bits.New(len(a)) + perm := bits.New(len(a)) + var df func(int) + df = func(n int) { switch { case temp.Bit(n) == 1: cyclic = true @@ -55,10 +63,10 @@ func (g Directed) Cyclic() (cyclic bool, fr NI, to NI) { } temp.SetBit(n, 1) for _, nb := range a[n] { - df(nb) + df(int(nb)) if cyclic { if fr < 0 { - fr, to = n, nb + fr, to = NI(n), nb } return } @@ -67,58 +75,516 @@ func (g Directed) Cyclic() (cyclic bool, fr NI, to NI) { perm.SetBit(n, 1) } for n := range a { - if perm.Bit(NI(n)) == 1 { + if perm.Bit(n) == 1 { continue } - if df(NI(n)); cyclic { // short circuit as soon as a cycle is found + if df(n); cyclic { // short circuit as soon as a cycle is found break } } return } -// FromList transposes a labeled graph into a FromList. +// DegreeCentralization returns out-degree centralization. +// +// Out-degree of a node is one measure of node centrality and is directly +// available from the adjacency list representation. This allows degree +// centralization for the graph to be very efficiently computed. +// +// The value returned is from 0 to 1 inclusive for simple directed graphs of +// two or more nodes. As a special case, 0 is returned for graphs of 0 or 1 +// nodes. The value returned can be > 1 for graphs with loops or parallel +// edges. +// +// In-degree centralization can be computed as DegreeCentralization of the +// transpose. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) DegreeCentralization() float64 { + a := g.AdjacencyList + if len(a) <= 1 { + return 0 + } + var max, sum int + for _, to := range a { + if len(to) > max { + max = len(to) + } + sum += len(to) + } + l1 := len(a) - 1 + return float64(len(a)*max-sum) / float64(l1*l1) +} + +// Dominators computes the immediate dominator for each node reachable from +// start. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// See also the method Doms. Internally Dominators must construct the +// transpose of g and also compute a postordering of a spanning tree of the +// subgraph reachable from start. If you happen to have either of these +// computed anyway, it can be more efficient to call Doms directly. +func (g Directed) Dominators(start NI) Dominators { + a := g.AdjacencyList + l := len(a) + // ExampleDoms shows traditional depth-first postorder, but it works to + // generate a reverse preorder. Also breadth-first works instead of + // depth-first and may allow Doms to run a little faster by presenting + // a shallower tree. + post := make([]NI, l) + a.BreadthFirst(start, func(n NI) { + l-- + post[l] = n + }) + tr, _ := g.Transpose() + return g.Doms(tr, post[l:]) +} + +// Doms computes either immediate dominators or postdominators. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// But see also the simpler methods Dominators and PostDominators. +// +// Doms requires argument tr to be the transpose graph of receiver g, +// and requres argument post to be a post ordering of receiver g. More +// specifically a post ordering of a spanning tree of the subgraph reachable +// from some start node in g. The start node will always be the last node in +// this postordering so it does not need to passed as a separate argument. +// +// Doms can be used to construct either dominators or postdominators. +// To construct dominators on a graph f, generate a postordering p on f +// and call f.Doms(f.Transpose(), p). To construct postdominators, generate +// the transpose t first, then a postordering p on t (not f), and call +// t.Doms(f, p). +// +// Caution: The argument tr is retained in the returned Dominators object +// and is used by the method Dominators.Frontier. It is not deep-copied +// so it is invalid to call Doms, modify the tr graph, and then call Frontier. +func (g Directed) Doms(tr Directed, post []NI) Dominators { + a := g.AdjacencyList + dom := make([]NI, len(a)) + pi := make([]int, len(a)) + for i, n := range post { + pi[n] = i + } + intersect := func(b1, b2 NI) NI { + for b1 != b2 { + for pi[b1] < pi[b2] { + b1 = dom[b1] + } + for pi[b2] < pi[b1] { + b2 = dom[b2] + } + } + return b1 + } + for n := range dom { + dom[n] = -1 + } + start := post[len(post)-1] + dom[start] = start + for changed := false; ; changed = false { + for i := len(post) - 2; i >= 0; i-- { + b := post[i] + var im NI + fr := tr.AdjacencyList[b] + var j int + var fp NI + for j, fp = range fr { + if dom[fp] >= 0 { + im = fp + break + } + } + for _, p := range fr[j:] { + if dom[p] >= 0 { + im = intersect(im, p) + } + } + if dom[b] != im { + dom[b] = im + changed = true + } + } + if !changed { + return Dominators{dom, tr} + } + } +} + +// PostDominators computes the immediate postdominator for each node that can +// reach node end. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// See also the method Doms. Internally Dominators must construct the +// transpose of g and also compute a postordering of a spanning tree of the +// subgraph of the transpose reachable from end. If you happen to have either +// of these computed anyway, it can be more efficient to call Doms directly. +// +// See the method Doms anyway for the caution note. PostDominators calls +// Doms internally, passing receiver g as Doms argument tr. The caution means +// that it is invalid to call PostDominators, modify the graph g, then call +// Frontier. +func (g Directed) PostDominators(end NI) Dominators { + tr, _ := g.Transpose() + a := tr.AdjacencyList + l := len(a) + post := make([]NI, l) + a.BreadthFirst(end, func(n NI) { + l-- + post[l] = n + }) + return tr.Doms(g, post[l:]) +} + +// called from Dominators.Frontier via interface +func (from Directed) domFrontiers(d Dominators) DominanceFrontiers { + im := d.Immediate + f := make(DominanceFrontiers, len(im)) + for i := range f { + if im[i] >= 0 { + f[i] = map[NI]struct{}{} + } + } + for b, fr := range from.AdjacencyList { + if len(fr) < 2 { + continue + } + imb := im[b] + for _, p := range fr { + for runner := p; runner != imb; runner = im[runner] { + f[runner][NI(b)] = struct{}{} + } + } + } + return f +} + +// Eulerian scans a directed graph to determine if it is Eulerian. // -// Receiver g should be connected as a tree or forest. Specifically no node -// can have multiple incoming arcs. If any node n in g has multiple incoming -// arcs, the method returns (nil, n) where n is a node with multiple -// incoming arcs. +// If the graph represents an Eulerian cycle, it returns -1, -1, nil. // -// Otherwise (normally) the method populates the From members in a -// FromList.Path and returns the FromList and -1. +// If the graph does not represent an Eulerian cycle but does represent an +// Eulerian path, it returns the start and end nodes of the path, and nil. // -// Other members of the FromList are left as zero values. -// Use FromList.RecalcLen and FromList.RecalcLeaves as needed. +// Otherwise it returns an error indicating a reason the graph is non-Eulerian. +// Also in this case it returns a relevant node in either start or end. // -// Unusual cases are parallel arcs and loops. A parallel arc represents -// a case of multiple arcs going to some node and so will lead to a (nil, n) -// return, even though a graph might be considered a multigraph tree. -// A single loop on a node that would otherwise be a root node, though, -// is not a case of multiple incoming arcs and so does not force a (nil, n) -// result. +// See also method EulerianStart, which short-circuits when it finds a start +// node whereas this method completely validates a graph as Eulerian. // // There are equivalent labeled and unlabeled versions of this method. -func (g Directed) FromList() (*FromList, NI) { - paths := make([]PathEnd, len(g.AdjacencyList)) - for i := range paths { - paths[i].From = -1 - } - for fr, to := range g.AdjacencyList { - for _, to := range to { - if paths[to].From >= 0 { - return nil, to +func (g Directed) Eulerian() (start, end NI, err error) { + ind := g.InDegree() + start = -1 + end = -1 + for n, to := range g.AdjacencyList { + switch { + case len(to) > ind[n]: + if start >= 0 { + return NI(n), -1, errors.New("multiple start candidates") + } + if len(to) > ind[n]+1 { + return NI(n), -1, errors.New("excessive out-degree") + } + start = NI(n) + case ind[n] > len(to): + if end >= 0 { + return -1, NI(n), errors.New("multiple end candidates") + } + if ind[n] > len(to)+1 { + return -1, NI(n), errors.New("excessive in-degree") } - paths[to].From = NI(fr) + end = NI(n) + } + } + return start, end, nil +} + +// EulerianCycle finds an Eulerian cycle in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianCycle copies the entire graph g. +// See EulerianCycleD for a more space efficient version. +// +// There are nearly equivalent labeled and unlabeled versions of this method. +// In the labeled version the first element of of the +func (g Directed) EulerianCycle() ([]NI, error) { + c, m := g.Copy() + return c.EulerianCycleD(m) +} + +// EulerianCycleD finds an Eulerian cycle in a directed multigraph. +// +// EulerianCycleD is destructive on its receiver g. See EulerianCycle for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) EulerianCycleD(ma int) ([]NI, error) { + // algorithm adapted from "Sketch of Eulerian Circuit Algorithm" by + // Carl Lee, accessed at http://www.ms.uky.edu/~lee/ma515fa10/euler.pdf. + if g.Order() == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, ma) + e.p[0] = 0 + for e.s >= 0 { + v := e.top() // v is node that starts cycle + e.push() + // if Eulerian, we'll always come back to starting node + if e.top() != v { + return nil, errors.New("not Eulerian") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("not strongly connected") + } + return e.p, nil +} + +// EulerianPath finds an Eulerian path in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianPath copies the entire graph g. +// See EulerianPathD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) EulerianPath() ([]NI, error) { + c, m := g.Copy() + start, err := c.EulerianStart() + if err != nil { + return nil, err + } + if start < 0 { + start = 0 + } + return c.EulerianPathD(m, start) +} + +// EulerianPathD finds an Eulerian path in a directed multigraph. +// +// EulerianPathD is destructive on its receiver g. See EulerianPath for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// Argument start must be a valid start node for the path. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path starting at start, result is an Eulerian path +// with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) EulerianPathD(ma int, start NI) ([]NI, error) { + if g.Order() == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, ma) + e.p[0] = start + // unlike EulerianCycle, the first path doesn't have to be a cycle. + e.push() + e.keep() + for e.s >= 0 { + start = e.top() + e.push() + // paths after the first must be cycles though + // (as long as there are nodes on the stack) + if e.top() != start { + return nil, errors.New("no Eulerian path") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("no Eulerian path") + } + return e.p, nil +} + +// EulerianStart finds a candidate start node for an Eulerian path. +// +// A candidate start node in the directed case has out-degree one greater then +// in-degree. EulerianStart scans the graph returning immediately with the +// node (and err == nil) when it finds such a candidate. +// +// EulerianStart also returns immediately with an error if it finds the graph +// cannot contain an Eulerian path. In this case it also returns a relevant +// node. +// +// If the scan completes without finding a candidate start node, the graph +// represents an Eulerian cycle. In this case it returns -1, nil, and any +// node can be chosen as a start node for an eulerian path. +// +// See also method Eulerian, which completely validates a graph as Eulerian +// whereas this method short-curcuits when it finds a start node. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) EulerianStart() (start NI, err error) { + ind := g.InDegree() + end := -1 + for n, to := range g.AdjacencyList { + switch { + case len(to) > ind[n]: + if len(to) == ind[n]+1 { + return NI(n), nil // candidate start + } + return -1, errors.New("excessive out-degree") + case ind[n] > len(to): + if end >= 0 { + return NI(n), errors.New("multiple end candidates") + } + if ind[n] > len(to)+1 { + return NI(n), errors.New("excessive in-degree") + } + end = n + } + } + return -1, nil // cycle +} + +type eulerian struct { + g AdjacencyList // working copy of graph, it gets consumed + m int // number of arcs in g, updated as g is consumed + uv bits.Bits // unvisited + // low end of p is stack of unfinished nodes + // high end is finished path + p []NI // stack + path + s int // stack pointer +} + +func newEulerian(g AdjacencyList, m int) *eulerian { + e := &eulerian{ + g: g, + m: m, + uv: bits.New(len(g)), + p: make([]NI, m+1), + } + e.uv.SetAll() + return e +} + +// starting with the node on top of the stack, move nodes with no arcs. +func (e *eulerian) keep() { + for e.s >= 0 { + n := e.top() + if len(e.g[n]) > 0 { + break + } + e.p[e.m] = n + e.s-- + e.m-- + } +} + +func (e *eulerian) top() NI { + return e.p[e.s] +} + +// MaximalNonBranchingPaths finds all paths in a directed graph that are +// "maximal" and "non-branching". +// +// A non-branching path is one where path nodes other than the first and last +// have exactly one arc leading to the node and one arc leading from the node, +// thus there is no possibility to branch away to a different path. +// +// A maximal non-branching path cannot be extended to a longer non-branching +// path by including another node at either end. +// +// In the case of a cyclic non-branching path, the first and last nodes +// of the path will be the same node, indicating an isolated cycle. +// +// The method calls the emit argument for each path or isolated cycle in g, +// as long as emit returns true. If emit returns false, +// MaximalNonBranchingPaths returns immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) MaximalNonBranchingPaths(emit func([]NI) bool) { + a := g.AdjacencyList + ind := g.InDegree() + uv := bits.New(g.Order()) + uv.SetAll() + for v, vTo := range a { + if !(ind[v] == 1 && len(vTo) == 1) { + for _, w := range vTo { + n := []NI{NI(v), w} + uv.SetBit(v, 0) + uv.SetBit(int(w), 0) + wTo := a[w] + for ind[w] == 1 && len(wTo) == 1 { + u := wTo[0] + n = append(n, u) + uv.SetBit(int(u), 0) + w = u + wTo = a[w] + } + if !emit(n) { // n is a path + return + } + } + } + } + // use uv.From rather than uv.Iterate. + // Iterate doesn't work here because we're modifying uv + for b := uv.OneFrom(0); b >= 0; b = uv.OneFrom(b + 1) { + v := NI(b) + n := []NI{v} + for w := v; ; { + w = a[w][0] + uv.SetBit(int(w), 0) + n = append(n, w) + if w == v { + break + } + } + if !emit(n) { // n is an isolated cycle + return } } - return &FromList{Paths: paths}, -1 } // InDegree computes the in-degree of each node in g // // There are equivalent labeled and unlabeled versions of this method. func (g Directed) InDegree() []int { - ind := make([]int, len(g.AdjacencyList)) + ind := make([]int, g.Order()) for _, nbs := range g.AdjacencyList { for _, nb := range nbs { ind[nb]++ @@ -127,6 +593,128 @@ func (g Directed) InDegree() []int { return ind } +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *DirectedSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.Directed.AdjacencyList + b = NI(len(a)) + s.Directed.AdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// AddArc adds an arc to a subgraph. +// +// Arguments fr, to must be NIs in supergraph s.Super. As with AddNode, +// AddArc panics if fr and to are not valid node indexes of s.Super. +// +// The arc specfied by fr, to must exist in s.Super. Further, the number of +// parallel arcs in the subgraph cannot exceed the number of corresponding +// parallel arcs in the supergraph. That is, each arc already added to the +// subgraph counts against the arcs available in the supergraph. If a matching +// arc is not available, AddArc returns an error. +// +// If a matching arc is available, subgraph nodes are added as needed, the +// subgraph arc is added, and the method returns nil. +func (s *DirectedSubgraph) AddArc(fr NI, to NI) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(fr) < 0 || int(fr) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", fr, " not in supergraph")) + } + if int(to) < 0 || int(to) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", to, " not in supergraph")) + } + // count existing matching arcs in subgraph + n := 0 + a := s.Directed.AdjacencyList + if bf, ok := s.SubNI[fr]; ok { + if bt, ok := s.SubNI[to]; ok { + // both NIs already exist in subgraph, need to count arcs + bTo := to + bTo = bt + for _, t := range a[bf] { + if t == bTo { + n++ + } + } + } + } + // verify matching arcs are available in supergraph + for _, t := range (*s.Super).AdjacencyList[fr] { + if t == to { + if n > 0 { + n-- // match existing arc + continue + } + // no more existing arcs need to be matched. nodes can finally + // be added as needed and then the arc can be added. + bf := s.AddNode(fr) + to = s.AddNode(to) + s.Directed.AdjacencyList[bf] = + append(s.Directed.AdjacencyList[bf], to) + return nil // success + } + } + return errors.New("arc not available in supergraph") +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *Directed) InduceList(l []NI) *DirectedSubgraph { + sub, sup := mapList(l) + return &DirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + Directed: Directed{ + g.AdjacencyList.induceArcs(sub, sup), + }} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *Directed) InduceBits(t bits.Bits) *DirectedSubgraph { + sub, sup := mapBits(t) + return &DirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + Directed: Directed{ + g.AdjacencyList.induceArcs(sub, sup), + }} +} + // IsTree identifies trees in directed graphs. // // Return value isTree is true if the subgraph reachable from root is a tree. @@ -136,14 +724,14 @@ func (g Directed) InDegree() []int { // There are equivalent labeled and unlabeled versions of this method. func (g Directed) IsTree(root NI) (isTree, allTree bool) { a := g.AdjacencyList - var v Bits - v.SetAll(len(a)) + v := bits.New(len(a)) + v.SetAll() var df func(NI) bool df = func(n NI) bool { - if v.Bit(n) == 0 { + if v.Bit(int(n)) == 0 { return false } - v.SetBit(n, 0) + v.SetBit(int(n), 0) for _, to := range a[n] { if !df(to) { return false @@ -152,118 +740,151 @@ func (g Directed) IsTree(root NI) (isTree, allTree bool) { return true } isTree = df(root) - return isTree, isTree && v.Zero() + return isTree, isTree && v.AllZeros() +} + +// PageRank computes a significance score for each node of a graph. +// +// The algorithm is credited to Google founders Brin and Lawrence. +// +// Argument d is a damping factor. Reportedly a value of .85 works well. +// Argument n is a number of iterations. Reportedly values of 20 to 50 +// work well. +// +// Returned is the PageRank score for each node of g. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) PageRank(d float64, n int) []float64 { + // Following "PageRank Explained" by Ian Rogers, accessed at + // http://www.cs.princeton.edu/~chazelle/courses/BIB/pagerank.htm + a := g.AdjacencyList + p0 := make([]float64, len(a)) + p1 := make([]float64, len(a)) + for i := range p0 { + p0[i] = 1 + } + d1 := 1 - d + for ; n > 0; n-- { + for i := range p1 { + p1[i] = d1 + } + for fr, to := range a { + f := d / float64(len(to)) + for _, to := range to { + p1[to] += p0[fr] * f + } + } + p0, p1 = p1, p0 + } + return p0 } -// Tarjan identifies strongly connected components in a directed graph using -// Tarjan's algorithm. +// StronglyConnectedComponents identifies strongly connected components in +// a directed graph. +// +// The method calls the emit function for each component identified. The +// argument to emit is the node list of a component. The emit function must +// return true for the method to continue identifying components. If emit +// returns false, the method returns immediately. +// +// Note well: The backing slice for the node list passed to emit is reused +// across emit calls. If you need to retain the node list you must copy it. // -// The method calls the emit argument for each component identified. Each -// component is a list of nodes. A property of the algorithm is that -// components are emitted in reverse topological order of the condensation. -// (See https://en.wikipedia.org/wiki/Strongly_connected_component#Definitions -// for description of condensation.) +// The components emitted represent a partition of the nodes in g. +// So for example, if the first component emitted has the same length as g +// then it will be the only component and it means the entire graph g is +// strongly connected. +// +// See also Condensation which returns a condensation graph in addition +// to the strongly connected components. // // There are equivalent labeled and unlabeled versions of this method. // -// See also TarjanForward and TarjanCondensation. -func (g Directed) Tarjan(emit func([]NI) bool) { - // See "Depth-first search and linear graph algorithms", Robert Tarjan, - // SIAM J. Comput. Vol. 1, No. 2, June 1972. - // - // Implementation here from Wikipedia pseudocode, - // http://en.wikipedia.org/w/index.php?title=Tarjan%27s_strongly_connected_components_algorithm&direction=prev&oldid=647184742 - var indexed, stacked Bits +// The algorithm here is by David Pearce. See also alt.SCCPathBased and +// alt.SCCTarjan. +func (g Directed) StronglyConnectedComponents(emit func([]NI) bool) { + // See Algorithm 3 PEA FIND SCC2(V,E) in "An Improved Algorithm for + // Finding the Strongly Connected Components of a Directed Graph" + // by David J. Pearce. a := g.AdjacencyList - index := make([]int, len(a)) - lowlink := make([]int, len(a)) - x := 0 - var S []NI - var sc func(NI) bool - sc = func(n NI) bool { - index[n] = x - indexed.SetBit(n, 1) - lowlink[n] = x - x++ - S = append(S, n) - stacked.SetBit(n, 1) - for _, nb := range a[n] { - if indexed.Bit(nb) == 0 { - if !sc(nb) { + rindex := make([]int, len(a)) + var S, scc []NI + index := 1 + c := len(a) - 1 + var visit func(NI) bool + visit = func(v NI) bool { + root := true + rindex[v] = index + index++ + for _, w := range a[v] { + if rindex[w] == 0 { + if !visit(w) { return false } - if lowlink[nb] < lowlink[n] { - lowlink[n] = lowlink[nb] - } - } else if stacked.Bit(nb) == 1 { - if index[nb] < lowlink[n] { - lowlink[n] = index[nb] - } + } + if rindex[w] < rindex[v] { + rindex[v] = rindex[w] + root = false } } - if lowlink[n] == index[n] { - var c []NI - for { - last := len(S) - 1 - w := S[last] - S = S[:last] - stacked.SetBit(w, 0) - c = append(c, w) - if w == n { - if !emit(c) { - return false - } - break - } + if !root { + S = append(S, v) + return true + } + scc = scc[:0] + index-- + for last := len(S) - 1; last >= 0; last-- { + w := S[last] + if rindex[v] > rindex[w] { + break } + S = S[:last] + rindex[w] = c + scc = append(scc, w) + index-- } - return true + rindex[v] = c + c-- + return emit(append(scc, v)) } - for n := range a { - if indexed.Bit(NI(n)) == 0 && !sc(NI(n)) { - return + for v := range a { + if rindex[v] == 0 && !visit(NI(v)) { + break } } } -// TarjanForward returns strongly connected components. +// Condensation returns strongly connected components and their +// condensation graph. +// +// A condensation represents a directed acyclic graph. +// Components are ordered in a reverse topological ordering. +// +// See also StronglyConnectedComponents, which returns the components only. // -// It returns components in the reverse order of Tarjan, for situations -// where a forward topological ordering is easier. -func (g Directed) TarjanForward() [][]NI { - var r [][]NI - g.Tarjan(func(c []NI) bool { - r = append(r, c) +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) Condensation() (scc [][]NI, cd AdjacencyList) { + a := g.AdjacencyList + b := make([]NI, len(a)) // backing slice for scc + g.StronglyConnectedComponents(func(c []NI) bool { + n := copy(b, c) + scc = append(scc, b[:n]) + b = b[n:] return true }) - scc := make([][]NI, len(r)) - last := len(r) - 1 - for i, ci := range r { - scc[last-i] = ci - } - return scc -} - -// TarjanCondensation returns strongly connected components and their -// condensation graph. -// -// Components are ordered in a forward topological ordering. -func (g Directed) TarjanCondensation() (scc [][]NI, cd AdjacencyList) { - scc = g.TarjanForward() - cd = make(AdjacencyList, len(scc)) // return value - cond := make([]NI, len(g.AdjacencyList)) // mapping from g node to cd node - for cn := NI(len(scc) - 1); cn >= 0; cn-- { - c := scc[cn] + cd = make(AdjacencyList, len(scc)) // return value + cond := make([]NI, len(a)) // mapping from g node to cd node + for cn, c := range scc { for _, n := range c { cond[n] = NI(cn) // map g node to cd node } - var tos []NI // list of 'to' nodes - var m Bits // tos map + var tos []NI // list of 'to' nodes + m := bits.New(len(cd)) // tos map m.SetBit(cn, 1) for _, n := range c { - for _, to := range g.AdjacencyList[n] { - if ct := cond[to]; m.Bit(ct) == 0 { - m.SetBit(ct, 1) + for _, to := range a[n] { + if ct := cond[to]; m.Bit(int(ct)) == 0 { + m.SetBit(int(ct), 1) tos = append(tos, ct) } } @@ -282,23 +903,35 @@ func (g Directed) TarjanCondensation() (scc [][]NI, cd AdjacencyList) { // // There are equivalent labeled and unlabeled versions of this method. func (g Directed) Topological() (ordering, cycle []NI) { + i := -1 + return g.dfTopo(func() NI { + i++ + if i < g.Order() { + return NI(i) + } + return -1 + }) +} + +func (g Directed) dfTopo(f func() NI) (ordering, cycle []NI) { a := g.AdjacencyList ordering = make([]NI, len(a)) i := len(ordering) - var temp, perm Bits + temp := bits.New(len(a)) + perm := bits.New(len(a)) var cycleFound bool var cycleStart NI var df func(NI) df = func(n NI) { switch { - case temp.Bit(n) == 1: + case temp.Bit(int(n)) == 1: cycleFound = true cycleStart = n return - case perm.Bit(n) == 1: + case perm.Bit(int(n)) == 1: return } - temp.SetBit(n, 1) + temp.SetBit(int(n), 1) for _, nb := range a[n] { df(nb) if cycleFound { @@ -316,21 +949,24 @@ func (g Directed) Topological() (ordering, cycle []NI) { return } } - temp.SetBit(n, 0) - perm.SetBit(n, 1) + temp.SetBit(int(n), 0) + perm.SetBit(int(n), 1) i-- ordering[i] = n } - for n := range a { - if perm.Bit(NI(n)) == 1 { + for { + n := f() + if n < 0 { + return ordering[i:], nil + } + if perm.Bit(int(n)) == 1 { continue } - df(NI(n)) + df(n) if cycleFound { return nil, cycle } } - return ordering, nil } // TopologicalKahn computes a topological ordering of a directed acyclic graph. @@ -349,7 +985,7 @@ func (g Directed) TopologicalKahn(tr Directed) (ordering, cycle []NI) { var L, S []NI // rem for "remaining edges," this function makes a local copy of the // in-degrees and consumes that instead of consuming an input. - rem := make([]int, len(g.AdjacencyList)) + rem := make([]int, g.Order()) for n, fr := range tr.AdjacencyList { if len(fr) == 0 { // accumulate "set of all nodes with no incoming edges" @@ -393,3 +1029,63 @@ func (g Directed) TopologicalKahn(tr Directed) (ordering, cycle []NI) { } return L, nil } + +// TopologicalSubgraph computes a topological ordering of a subgraph of a +// directed acyclic graph. +// +// The subgraph considered is that reachable from the specified node list. +// +// For an acyclic subgraph, return value ordering is a permutation of reachable +// node numbers in topologically sorted order and cycle will be nil. If the +// subgraph is found to be cyclic, ordering will be nil and cycle will be +// the path of a found cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Directed) TopologicalSubgraph(nodes []NI) (ordering, cycle []NI) { + i := -1 + return g.dfTopo(func() NI { + i++ + if i < len(nodes) { + return nodes[i] + } + return -1 + }) +} + +// TransitiveClosure returns the transitive closure of directed graph g. +// +// The algorithm is Warren's, which works most naturally with an adjacency +// matrix representation. The returned transitive closure is left in this +// adjacency matrix representation. For a graph g of order n, matrix tc +// is returned as a length n slice of length n bits.Bits values, where +// tc[from].Bit(to) == 1 represents an arc of the transitive closure. +func (g Directed) TransitiveClosure() []bits.Bits { + // construct adjacency matrix + a := g.AdjacencyList + t := make([]bits.Bits, len(a)) + for n := range t { + tn := bits.New(len(a)) + for _, to := range a[n] { + tn.SetBit(int(to), 1) + } + t[n] = tn + } + // above diagonal + for i := 1; i < len(a); i++ { + ti := t[i] + for k := 0; k < i; k++ { + if ti.Bit(k) == 1 { + ti.Or(ti, t[k]) + } + } + } + // below diagonal + for i, ti := range t[:len(a)-1] { + for k := i + 1; k < len(a); k++ { + if ti.Bit(k) == 1 { + ti.Or(ti, t[k]) + } + } + } + return t +} diff --git a/vendor/github.com/soniakeys/graph/dir_cg.go b/vendor/github.com/soniakeys/graph/dir_cg.go index 2b82f4f1..07cc9655 100644 --- a/vendor/github.com/soniakeys/graph/dir_cg.go +++ b/vendor/github.com/soniakeys/graph/dir_cg.go @@ -3,6 +3,13 @@ package graph +import ( + "errors" + "fmt" + + "github.com/soniakeys/bits" +) + // dir_RO.go is code generated from dir_cg.go by directives in graph.go. // Editing dir_cg.go is okay. It is the code generation source. // DO NOT EDIT dir_RO.go. @@ -43,9 +50,10 @@ func (g LabeledDirected) Copy() (c LabeledDirected, ma int) { func (g LabeledDirected) Cyclic() (cyclic bool, fr NI, to Half) { a := g.LabeledAdjacencyList fr, to.To = -1, -1 - var temp, perm Bits - var df func(NI) - df = func(n NI) { + temp := bits.New(len(a)) + perm := bits.New(len(a)) + var df func(int) + df = func(n int) { switch { case temp.Bit(n) == 1: cyclic = true @@ -55,10 +63,10 @@ func (g LabeledDirected) Cyclic() (cyclic bool, fr NI, to Half) { } temp.SetBit(n, 1) for _, nb := range a[n] { - df(nb.To) + df(int(nb.To)) if cyclic { if fr < 0 { - fr, to = n, nb + fr, to = NI(n), nb } return } @@ -67,58 +75,516 @@ func (g LabeledDirected) Cyclic() (cyclic bool, fr NI, to Half) { perm.SetBit(n, 1) } for n := range a { - if perm.Bit(NI(n)) == 1 { + if perm.Bit(n) == 1 { continue } - if df(NI(n)); cyclic { // short circuit as soon as a cycle is found + if df(n); cyclic { // short circuit as soon as a cycle is found break } } return } -// FromList transposes a labeled graph into a FromList. +// DegreeCentralization returns out-degree centralization. +// +// Out-degree of a node is one measure of node centrality and is directly +// available from the adjacency list representation. This allows degree +// centralization for the graph to be very efficiently computed. +// +// The value returned is from 0 to 1 inclusive for simple directed graphs of +// two or more nodes. As a special case, 0 is returned for graphs of 0 or 1 +// nodes. The value returned can be > 1 for graphs with loops or parallel +// edges. +// +// In-degree centralization can be computed as DegreeCentralization of the +// transpose. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) DegreeCentralization() float64 { + a := g.LabeledAdjacencyList + if len(a) <= 1 { + return 0 + } + var max, sum int + for _, to := range a { + if len(to) > max { + max = len(to) + } + sum += len(to) + } + l1 := len(a) - 1 + return float64(len(a)*max-sum) / float64(l1*l1) +} + +// Dominators computes the immediate dominator for each node reachable from +// start. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// See also the method Doms. Internally Dominators must construct the +// transpose of g and also compute a postordering of a spanning tree of the +// subgraph reachable from start. If you happen to have either of these +// computed anyway, it can be more efficient to call Doms directly. +func (g LabeledDirected) Dominators(start NI) Dominators { + a := g.LabeledAdjacencyList + l := len(a) + // ExampleDoms shows traditional depth-first postorder, but it works to + // generate a reverse preorder. Also breadth-first works instead of + // depth-first and may allow Doms to run a little faster by presenting + // a shallower tree. + post := make([]NI, l) + a.BreadthFirst(start, func(n NI) { + l-- + post[l] = n + }) + tr, _ := g.Transpose() + return g.Doms(tr, post[l:]) +} + +// Doms computes either immediate dominators or postdominators. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// But see also the simpler methods Dominators and PostDominators. +// +// Doms requires argument tr to be the transpose graph of receiver g, +// and requres argument post to be a post ordering of receiver g. More +// specifically a post ordering of a spanning tree of the subgraph reachable +// from some start node in g. The start node will always be the last node in +// this postordering so it does not need to passed as a separate argument. +// +// Doms can be used to construct either dominators or postdominators. +// To construct dominators on a graph f, generate a postordering p on f +// and call f.Doms(f.Transpose(), p). To construct postdominators, generate +// the transpose t first, then a postordering p on t (not f), and call +// t.Doms(f, p). +// +// Caution: The argument tr is retained in the returned Dominators object +// and is used by the method Dominators.Frontier. It is not deep-copied +// so it is invalid to call Doms, modify the tr graph, and then call Frontier. +func (g LabeledDirected) Doms(tr LabeledDirected, post []NI) Dominators { + a := g.LabeledAdjacencyList + dom := make([]NI, len(a)) + pi := make([]int, len(a)) + for i, n := range post { + pi[n] = i + } + intersect := func(b1, b2 NI) NI { + for b1 != b2 { + for pi[b1] < pi[b2] { + b1 = dom[b1] + } + for pi[b2] < pi[b1] { + b2 = dom[b2] + } + } + return b1 + } + for n := range dom { + dom[n] = -1 + } + start := post[len(post)-1] + dom[start] = start + for changed := false; ; changed = false { + for i := len(post) - 2; i >= 0; i-- { + b := post[i] + var im NI + fr := tr.LabeledAdjacencyList[b] + var j int + var fp Half + for j, fp = range fr { + if dom[fp.To] >= 0 { + im = fp.To + break + } + } + for _, p := range fr[j:] { + if dom[p.To] >= 0 { + im = intersect(im, p.To) + } + } + if dom[b] != im { + dom[b] = im + changed = true + } + } + if !changed { + return Dominators{dom, tr} + } + } +} + +// PostDominators computes the immediate postdominator for each node that can +// reach node end. +// +// The slice returned as Dominators.Immediate will have the length of +// g.AdjacencyList. Nodes without a path to end will have a value of -1. +// +// See also the method Doms. Internally Dominators must construct the +// transpose of g and also compute a postordering of a spanning tree of the +// subgraph of the transpose reachable from end. If you happen to have either +// of these computed anyway, it can be more efficient to call Doms directly. +// +// See the method Doms anyway for the caution note. PostDominators calls +// Doms internally, passing receiver g as Doms argument tr. The caution means +// that it is invalid to call PostDominators, modify the graph g, then call +// Frontier. +func (g LabeledDirected) PostDominators(end NI) Dominators { + tr, _ := g.Transpose() + a := tr.LabeledAdjacencyList + l := len(a) + post := make([]NI, l) + a.BreadthFirst(end, func(n NI) { + l-- + post[l] = n + }) + return tr.Doms(g, post[l:]) +} + +// called from Dominators.Frontier via interface +func (from LabeledDirected) domFrontiers(d Dominators) DominanceFrontiers { + im := d.Immediate + f := make(DominanceFrontiers, len(im)) + for i := range f { + if im[i] >= 0 { + f[i] = map[NI]struct{}{} + } + } + for b, fr := range from.LabeledAdjacencyList { + if len(fr) < 2 { + continue + } + imb := im[b] + for _, p := range fr { + for runner := p.To; runner != imb; runner = im[runner] { + f[runner][NI(b)] = struct{}{} + } + } + } + return f +} + +// Eulerian scans a directed graph to determine if it is Eulerian. // -// Receiver g should be connected as a tree or forest. Specifically no node -// can have multiple incoming arcs. If any node n in g has multiple incoming -// arcs, the method returns (nil, n) where n is a node with multiple -// incoming arcs. +// If the graph represents an Eulerian cycle, it returns -1, -1, nil. // -// Otherwise (normally) the method populates the From members in a -// FromList.Path and returns the FromList and -1. +// If the graph does not represent an Eulerian cycle but does represent an +// Eulerian path, it returns the start and end nodes of the path, and nil. // -// Other members of the FromList are left as zero values. -// Use FromList.RecalcLen and FromList.RecalcLeaves as needed. +// Otherwise it returns an error indicating a reason the graph is non-Eulerian. +// Also in this case it returns a relevant node in either start or end. // -// Unusual cases are parallel arcs and loops. A parallel arc represents -// a case of multiple arcs going to some node and so will lead to a (nil, n) -// return, even though a graph might be considered a multigraph tree. -// A single loop on a node that would otherwise be a root node, though, -// is not a case of multiple incoming arcs and so does not force a (nil, n) -// result. +// See also method EulerianStart, which short-circuits when it finds a start +// node whereas this method completely validates a graph as Eulerian. // // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledDirected) FromList() (*FromList, NI) { - paths := make([]PathEnd, len(g.LabeledAdjacencyList)) - for i := range paths { - paths[i].From = -1 - } - for fr, to := range g.LabeledAdjacencyList { - for _, to := range to { - if paths[to.To].From >= 0 { - return nil, to.To +func (g LabeledDirected) Eulerian() (start, end NI, err error) { + ind := g.InDegree() + start = -1 + end = -1 + for n, to := range g.LabeledAdjacencyList { + switch { + case len(to) > ind[n]: + if start >= 0 { + return NI(n), -1, errors.New("multiple start candidates") + } + if len(to) > ind[n]+1 { + return NI(n), -1, errors.New("excessive out-degree") + } + start = NI(n) + case ind[n] > len(to): + if end >= 0 { + return -1, NI(n), errors.New("multiple end candidates") + } + if ind[n] > len(to)+1 { + return -1, NI(n), errors.New("excessive in-degree") } - paths[to.To].From = NI(fr) + end = NI(n) + } + } + return start, end, nil +} + +// EulerianCycle finds an Eulerian cycle in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianCycle copies the entire graph g. +// See EulerianCycleD for a more space efficient version. +// +// There are nearly equivalent labeled and unlabeled versions of this method. +// In the labeled version the first element of of the +func (g LabeledDirected) EulerianCycle() ([]Half, error) { + c, m := g.Copy() + return c.EulerianCycleD(m) +} + +// EulerianCycleD finds an Eulerian cycle in a directed multigraph. +// +// EulerianCycleD is destructive on its receiver g. See EulerianCycle for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) EulerianCycleD(ma int) ([]Half, error) { + // algorithm adapted from "Sketch of Eulerian Circuit Algorithm" by + // Carl Lee, accessed at http://www.ms.uky.edu/~lee/ma515fa10/euler.pdf. + if g.Order() == 0 { + return nil, nil + } + e := newLabEulerian(g.LabeledAdjacencyList, ma) + e.p[0] = Half{0, -1} + for e.s >= 0 { + v := e.top() // v is node that starts cycle + e.push() + // if Eulerian, we'll always come back to starting node + if e.top().To != v.To { + return nil, errors.New("not Eulerian") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("not strongly connected") + } + return e.p, nil +} + +// EulerianPath finds an Eulerian path in a directed multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianPath copies the entire graph g. +// See EulerianPathD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) EulerianPath() ([]Half, error) { + c, m := g.Copy() + start, err := c.EulerianStart() + if err != nil { + return nil, err + } + if start < 0 { + start = 0 + } + return c.EulerianPathD(m, start) +} + +// EulerianPathD finds an Eulerian path in a directed multigraph. +// +// EulerianPathD is destructive on its receiver g. See EulerianPath for +// a non-destructive version. +// +// Argument ma must be the correct arc size, or number of arcs in g. +// Argument start must be a valid start node for the path. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path starting at start, result is an Eulerian path +// with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) EulerianPathD(ma int, start NI) ([]Half, error) { + if g.Order() == 0 { + return nil, nil + } + e := newLabEulerian(g.LabeledAdjacencyList, ma) + e.p[0] = Half{start, -1} + // unlike EulerianCycle, the first path doesn't have to be a cycle. + e.push() + e.keep() + for e.s >= 0 { + start = e.top().To + e.push() + // paths after the first must be cycles though + // (as long as there are nodes on the stack) + if e.top().To != start { + return nil, errors.New("no Eulerian path") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("no Eulerian path") + } + return e.p, nil +} + +// EulerianStart finds a candidate start node for an Eulerian path. +// +// A candidate start node in the directed case has out-degree one greater then +// in-degree. EulerianStart scans the graph returning immediately with the +// node (and err == nil) when it finds such a candidate. +// +// EulerianStart also returns immediately with an error if it finds the graph +// cannot contain an Eulerian path. In this case it also returns a relevant +// node. +// +// If the scan completes without finding a candidate start node, the graph +// represents an Eulerian cycle. In this case it returns -1, nil, and any +// node can be chosen as a start node for an eulerian path. +// +// See also method Eulerian, which completely validates a graph as Eulerian +// whereas this method short-curcuits when it finds a start node. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) EulerianStart() (start NI, err error) { + ind := g.InDegree() + end := -1 + for n, to := range g.LabeledAdjacencyList { + switch { + case len(to) > ind[n]: + if len(to) == ind[n]+1 { + return NI(n), nil // candidate start + } + return -1, errors.New("excessive out-degree") + case ind[n] > len(to): + if end >= 0 { + return NI(n), errors.New("multiple end candidates") + } + if ind[n] > len(to)+1 { + return NI(n), errors.New("excessive in-degree") + } + end = n + } + } + return -1, nil // cycle +} + +type labEulerian struct { + g LabeledAdjacencyList // working copy of graph, it gets consumed + m int // number of arcs in g, updated as g is consumed + uv bits.Bits // unvisited + // low end of p is stack of unfinished nodes + // high end is finished path + p []Half // stack + path + s int // stack pointer +} + +func newLabEulerian(g LabeledAdjacencyList, m int) *labEulerian { + e := &labEulerian{ + g: g, + m: m, + uv: bits.New(len(g)), + p: make([]Half, m+1), + } + e.uv.SetAll() + return e +} + +// starting with the node on top of the stack, move nodes with no arcs. +func (e *labEulerian) keep() { + for e.s >= 0 { + n := e.top() + if len(e.g[n.To]) > 0 { + break + } + e.p[e.m] = n + e.s-- + e.m-- + } +} + +func (e *labEulerian) top() Half { + return e.p[e.s] +} + +// MaximalNonBranchingPaths finds all paths in a directed graph that are +// "maximal" and "non-branching". +// +// A non-branching path is one where path nodes other than the first and last +// have exactly one arc leading to the node and one arc leading from the node, +// thus there is no possibility to branch away to a different path. +// +// A maximal non-branching path cannot be extended to a longer non-branching +// path by including another node at either end. +// +// In the case of a cyclic non-branching path, the first and last nodes +// of the path will be the same node, indicating an isolated cycle. +// +// The method calls the emit argument for each path or isolated cycle in g, +// as long as emit returns true. If emit returns false, +// MaximalNonBranchingPaths returns immediately. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) MaximalNonBranchingPaths(emit func([]Half) bool) { + a := g.LabeledAdjacencyList + ind := g.InDegree() + uv := bits.New(g.Order()) + uv.SetAll() + for v, vTo := range a { + if !(ind[v] == 1 && len(vTo) == 1) { + for _, w := range vTo { + n := []Half{Half{NI(v), -1}, w} + uv.SetBit(v, 0) + uv.SetBit(int(w.To), 0) + wTo := a[w.To] + for ind[w.To] == 1 && len(wTo) == 1 { + u := wTo[0] + n = append(n, u) + uv.SetBit(int(u.To), 0) + w = u + wTo = a[w.To] + } + if !emit(n) { // n is a path + return + } + } + } + } + // use uv.From rather than uv.Iterate. + // Iterate doesn't work here because we're modifying uv + for b := uv.OneFrom(0); b >= 0; b = uv.OneFrom(b + 1) { + v := Half{NI(b), -1} + n := []Half{v} + for w := v; ; { + w = a[w.To][0] + uv.SetBit(int(w.To), 0) + n = append(n, w) + if w.To == v.To { + break + } + } + if !emit(n) { // n is an isolated cycle + return } } - return &FromList{Paths: paths}, -1 } // InDegree computes the in-degree of each node in g // // There are equivalent labeled and unlabeled versions of this method. func (g LabeledDirected) InDegree() []int { - ind := make([]int, len(g.LabeledAdjacencyList)) + ind := make([]int, g.Order()) for _, nbs := range g.LabeledAdjacencyList { for _, nb := range nbs { ind[nb.To]++ @@ -127,6 +593,128 @@ func (g LabeledDirected) InDegree() []int { return ind } +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *LabeledDirectedSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.LabeledDirected.LabeledAdjacencyList + b = NI(len(a)) + s.LabeledDirected.LabeledAdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// AddArc adds an arc to a subgraph. +// +// Arguments fr, to must be NIs in supergraph s.Super. As with AddNode, +// AddArc panics if fr and to are not valid node indexes of s.Super. +// +// The arc specfied by fr, to must exist in s.Super. Further, the number of +// parallel arcs in the subgraph cannot exceed the number of corresponding +// parallel arcs in the supergraph. That is, each arc already added to the +// subgraph counts against the arcs available in the supergraph. If a matching +// arc is not available, AddArc returns an error. +// +// If a matching arc is available, subgraph nodes are added as needed, the +// subgraph arc is added, and the method returns nil. +func (s *LabeledDirectedSubgraph) AddArc(fr NI, to Half) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(fr) < 0 || int(fr) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", fr, " not in supergraph")) + } + if int(to.To) < 0 || int(to.To) >= s.Super.Order() { + panic(fmt.Sprint("AddArc: NI ", to.To, " not in supergraph")) + } + // count existing matching arcs in subgraph + n := 0 + a := s.LabeledDirected.LabeledAdjacencyList + if bf, ok := s.SubNI[fr]; ok { + if bt, ok := s.SubNI[to.To]; ok { + // both NIs already exist in subgraph, need to count arcs + bTo := to + bTo.To = bt + for _, t := range a[bf] { + if t == bTo { + n++ + } + } + } + } + // verify matching arcs are available in supergraph + for _, t := range (*s.Super).LabeledAdjacencyList[fr] { + if t == to { + if n > 0 { + n-- // match existing arc + continue + } + // no more existing arcs need to be matched. nodes can finally + // be added as needed and then the arc can be added. + bf := s.AddNode(fr) + to.To = s.AddNode(to.To) + s.LabeledDirected.LabeledAdjacencyList[bf] = + append(s.LabeledDirected.LabeledAdjacencyList[bf], to) + return nil // success + } + } + return errors.New("arc not available in supergraph") +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledDirected) InduceList(l []NI) *LabeledDirectedSubgraph { + sub, sup := mapList(l) + return &LabeledDirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + LabeledDirected: LabeledDirected{ + g.LabeledAdjacencyList.induceArcs(sub, sup), + }} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledDirected) InduceBits(t bits.Bits) *LabeledDirectedSubgraph { + sub, sup := mapBits(t) + return &LabeledDirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + LabeledDirected: LabeledDirected{ + g.LabeledAdjacencyList.induceArcs(sub, sup), + }} +} + // IsTree identifies trees in directed graphs. // // Return value isTree is true if the subgraph reachable from root is a tree. @@ -136,14 +724,14 @@ func (g LabeledDirected) InDegree() []int { // There are equivalent labeled and unlabeled versions of this method. func (g LabeledDirected) IsTree(root NI) (isTree, allTree bool) { a := g.LabeledAdjacencyList - var v Bits - v.SetAll(len(a)) + v := bits.New(len(a)) + v.SetAll() var df func(NI) bool df = func(n NI) bool { - if v.Bit(n) == 0 { + if v.Bit(int(n)) == 0 { return false } - v.SetBit(n, 0) + v.SetBit(int(n), 0) for _, to := range a[n] { if !df(to.To) { return false @@ -152,118 +740,151 @@ func (g LabeledDirected) IsTree(root NI) (isTree, allTree bool) { return true } isTree = df(root) - return isTree, isTree && v.Zero() + return isTree, isTree && v.AllZeros() +} + +// PageRank computes a significance score for each node of a graph. +// +// The algorithm is credited to Google founders Brin and Lawrence. +// +// Argument d is a damping factor. Reportedly a value of .85 works well. +// Argument n is a number of iterations. Reportedly values of 20 to 50 +// work well. +// +// Returned is the PageRank score for each node of g. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) PageRank(d float64, n int) []float64 { + // Following "PageRank Explained" by Ian Rogers, accessed at + // http://www.cs.princeton.edu/~chazelle/courses/BIB/pagerank.htm + a := g.LabeledAdjacencyList + p0 := make([]float64, len(a)) + p1 := make([]float64, len(a)) + for i := range p0 { + p0[i] = 1 + } + d1 := 1 - d + for ; n > 0; n-- { + for i := range p1 { + p1[i] = d1 + } + for fr, to := range a { + f := d / float64(len(to)) + for _, to := range to { + p1[to.To] += p0[fr] * f + } + } + p0, p1 = p1, p0 + } + return p0 } -// Tarjan identifies strongly connected components in a directed graph using -// Tarjan's algorithm. +// StronglyConnectedComponents identifies strongly connected components in +// a directed graph. +// +// The method calls the emit function for each component identified. The +// argument to emit is the node list of a component. The emit function must +// return true for the method to continue identifying components. If emit +// returns false, the method returns immediately. +// +// Note well: The backing slice for the node list passed to emit is reused +// across emit calls. If you need to retain the node list you must copy it. // -// The method calls the emit argument for each component identified. Each -// component is a list of nodes. A property of the algorithm is that -// components are emitted in reverse topological order of the condensation. -// (See https://en.wikipedia.org/wiki/Strongly_connected_component#Definitions -// for description of condensation.) +// The components emitted represent a partition of the nodes in g. +// So for example, if the first component emitted has the same length as g +// then it will be the only component and it means the entire graph g is +// strongly connected. +// +// See also Condensation which returns a condensation graph in addition +// to the strongly connected components. // // There are equivalent labeled and unlabeled versions of this method. // -// See also TarjanForward and TarjanCondensation. -func (g LabeledDirected) Tarjan(emit func([]NI) bool) { - // See "Depth-first search and linear graph algorithms", Robert Tarjan, - // SIAM J. Comput. Vol. 1, No. 2, June 1972. - // - // Implementation here from Wikipedia pseudocode, - // http://en.wikipedia.org/w/index.php?title=Tarjan%27s_strongly_connected_components_algorithm&direction=prev&oldid=647184742 - var indexed, stacked Bits +// The algorithm here is by David Pearce. See also alt.SCCPathBased and +// alt.SCCTarjan. +func (g LabeledDirected) StronglyConnectedComponents(emit func([]NI) bool) { + // See Algorithm 3 PEA FIND SCC2(V,E) in "An Improved Algorithm for + // Finding the Strongly Connected Components of a Directed Graph" + // by David J. Pearce. a := g.LabeledAdjacencyList - index := make([]int, len(a)) - lowlink := make([]int, len(a)) - x := 0 - var S []NI - var sc func(NI) bool - sc = func(n NI) bool { - index[n] = x - indexed.SetBit(n, 1) - lowlink[n] = x - x++ - S = append(S, n) - stacked.SetBit(n, 1) - for _, nb := range a[n] { - if indexed.Bit(nb.To) == 0 { - if !sc(nb.To) { + rindex := make([]int, len(a)) + var S, scc []NI + index := 1 + c := len(a) - 1 + var visit func(NI) bool + visit = func(v NI) bool { + root := true + rindex[v] = index + index++ + for _, w := range a[v] { + if rindex[w.To] == 0 { + if !visit(w.To) { return false } - if lowlink[nb.To] < lowlink[n] { - lowlink[n] = lowlink[nb.To] - } - } else if stacked.Bit(nb.To) == 1 { - if index[nb.To] < lowlink[n] { - lowlink[n] = index[nb.To] - } + } + if rindex[w.To] < rindex[v] { + rindex[v] = rindex[w.To] + root = false } } - if lowlink[n] == index[n] { - var c []NI - for { - last := len(S) - 1 - w := S[last] - S = S[:last] - stacked.SetBit(w, 0) - c = append(c, w) - if w == n { - if !emit(c) { - return false - } - break - } + if !root { + S = append(S, v) + return true + } + scc = scc[:0] + index-- + for last := len(S) - 1; last >= 0; last-- { + w := S[last] + if rindex[v] > rindex[w] { + break } + S = S[:last] + rindex[w] = c + scc = append(scc, w) + index-- } - return true + rindex[v] = c + c-- + return emit(append(scc, v)) } - for n := range a { - if indexed.Bit(NI(n)) == 0 && !sc(NI(n)) { - return + for v := range a { + if rindex[v] == 0 && !visit(NI(v)) { + break } } } -// TarjanForward returns strongly connected components. +// Condensation returns strongly connected components and their +// condensation graph. +// +// A condensation represents a directed acyclic graph. +// Components are ordered in a reverse topological ordering. +// +// See also StronglyConnectedComponents, which returns the components only. // -// It returns components in the reverse order of Tarjan, for situations -// where a forward topological ordering is easier. -func (g LabeledDirected) TarjanForward() [][]NI { - var r [][]NI - g.Tarjan(func(c []NI) bool { - r = append(r, c) +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) Condensation() (scc [][]NI, cd AdjacencyList) { + a := g.LabeledAdjacencyList + b := make([]NI, len(a)) // backing slice for scc + g.StronglyConnectedComponents(func(c []NI) bool { + n := copy(b, c) + scc = append(scc, b[:n]) + b = b[n:] return true }) - scc := make([][]NI, len(r)) - last := len(r) - 1 - for i, ci := range r { - scc[last-i] = ci - } - return scc -} - -// TarjanCondensation returns strongly connected components and their -// condensation graph. -// -// Components are ordered in a forward topological ordering. -func (g LabeledDirected) TarjanCondensation() (scc [][]NI, cd AdjacencyList) { - scc = g.TarjanForward() - cd = make(AdjacencyList, len(scc)) // return value - cond := make([]NI, len(g.LabeledAdjacencyList)) // mapping from g node to cd node - for cn := NI(len(scc) - 1); cn >= 0; cn-- { - c := scc[cn] + cd = make(AdjacencyList, len(scc)) // return value + cond := make([]NI, len(a)) // mapping from g node to cd node + for cn, c := range scc { for _, n := range c { cond[n] = NI(cn) // map g node to cd node } - var tos []NI // list of 'to' nodes - var m Bits // tos map + var tos []NI // list of 'to' nodes + m := bits.New(len(cd)) // tos map m.SetBit(cn, 1) for _, n := range c { - for _, to := range g.LabeledAdjacencyList[n] { - if ct := cond[to.To]; m.Bit(ct) == 0 { - m.SetBit(ct, 1) + for _, to := range a[n] { + if ct := cond[to.To]; m.Bit(int(ct)) == 0 { + m.SetBit(int(ct), 1) tos = append(tos, ct) } } @@ -282,23 +903,35 @@ func (g LabeledDirected) TarjanCondensation() (scc [][]NI, cd AdjacencyList) { // // There are equivalent labeled and unlabeled versions of this method. func (g LabeledDirected) Topological() (ordering, cycle []NI) { + i := -1 + return g.dfTopo(func() NI { + i++ + if i < g.Order() { + return NI(i) + } + return -1 + }) +} + +func (g LabeledDirected) dfTopo(f func() NI) (ordering, cycle []NI) { a := g.LabeledAdjacencyList ordering = make([]NI, len(a)) i := len(ordering) - var temp, perm Bits + temp := bits.New(len(a)) + perm := bits.New(len(a)) var cycleFound bool var cycleStart NI var df func(NI) df = func(n NI) { switch { - case temp.Bit(n) == 1: + case temp.Bit(int(n)) == 1: cycleFound = true cycleStart = n return - case perm.Bit(n) == 1: + case perm.Bit(int(n)) == 1: return } - temp.SetBit(n, 1) + temp.SetBit(int(n), 1) for _, nb := range a[n] { df(nb.To) if cycleFound { @@ -316,21 +949,24 @@ func (g LabeledDirected) Topological() (ordering, cycle []NI) { return } } - temp.SetBit(n, 0) - perm.SetBit(n, 1) + temp.SetBit(int(n), 0) + perm.SetBit(int(n), 1) i-- ordering[i] = n } - for n := range a { - if perm.Bit(NI(n)) == 1 { + for { + n := f() + if n < 0 { + return ordering[i:], nil + } + if perm.Bit(int(n)) == 1 { continue } - df(NI(n)) + df(n) if cycleFound { return nil, cycle } } - return ordering, nil } // TopologicalKahn computes a topological ordering of a directed acyclic graph. @@ -349,7 +985,7 @@ func (g LabeledDirected) TopologicalKahn(tr Directed) (ordering, cycle []NI) { var L, S []NI // rem for "remaining edges," this function makes a local copy of the // in-degrees and consumes that instead of consuming an input. - rem := make([]int, len(g.LabeledAdjacencyList)) + rem := make([]int, g.Order()) for n, fr := range tr.AdjacencyList { if len(fr) == 0 { // accumulate "set of all nodes with no incoming edges" @@ -393,3 +1029,63 @@ func (g LabeledDirected) TopologicalKahn(tr Directed) (ordering, cycle []NI) { } return L, nil } + +// TopologicalSubgraph computes a topological ordering of a subgraph of a +// directed acyclic graph. +// +// The subgraph considered is that reachable from the specified node list. +// +// For an acyclic subgraph, return value ordering is a permutation of reachable +// node numbers in topologically sorted order and cycle will be nil. If the +// subgraph is found to be cyclic, ordering will be nil and cycle will be +// the path of a found cycle. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledDirected) TopologicalSubgraph(nodes []NI) (ordering, cycle []NI) { + i := -1 + return g.dfTopo(func() NI { + i++ + if i < len(nodes) { + return nodes[i] + } + return -1 + }) +} + +// TransitiveClosure returns the transitive closure of directed graph g. +// +// The algorithm is Warren's, which works most naturally with an adjacency +// matrix representation. The returned transitive closure is left in this +// adjacency matrix representation. For a graph g of order n, matrix tc +// is returned as a length n slice of length n bits.Bits values, where +// tc[from].Bit(to) == 1 represents an arc of the transitive closure. +func (g LabeledDirected) TransitiveClosure() []bits.Bits { + // construct adjacency matrix + a := g.LabeledAdjacencyList + t := make([]bits.Bits, len(a)) + for n := range t { + tn := bits.New(len(a)) + for _, to := range a[n] { + tn.SetBit(int(to.To), 1) + } + t[n] = tn + } + // above diagonal + for i := 1; i < len(a); i++ { + ti := t[i] + for k := 0; k < i; k++ { + if ti.Bit(k) == 1 { + ti.Or(ti, t[k]) + } + } + } + // below diagonal + for i, ti := range t[:len(a)-1] { + for k := i + 1; k < len(a); k++ { + if ti.Bit(k) == 1 { + ti.Or(ti, t[k]) + } + } + } + return t +} diff --git a/vendor/github.com/soniakeys/graph/doc.go b/vendor/github.com/soniakeys/graph/doc.go index 6d072789..a30b5897 100644 --- a/vendor/github.com/soniakeys/graph/doc.go +++ b/vendor/github.com/soniakeys/graph/doc.go @@ -4,7 +4,7 @@ // Graph algorithms: Dijkstra, A*, Bellman Ford, Floyd Warshall; // Kruskal and Prim minimal spanning tree; topological sort and DAG longest // and shortest paths; Eulerian cycle and path; degeneracy and k-cores; -// Bron Kerbosch clique finding; connected components; and others. +// Bron Kerbosch clique finding; connected components; dominance; and others. // // This is a graph library of integer indexes. To use it with application // data, you associate data with integer indexes, perform searches or other @@ -44,8 +44,8 @@ // // In contrast to Half, the type Edge represents both ends of an edge (but // no label.) The type LabeledEdge adds the label. The type WeightedEdgeList -// bundles a list of LabeledEdges with a WeightFunc. WeightedEdgeList is -// currently only used by Kruskal methods. +// bundles a list of LabeledEdges with a WeightFunc. (WeightedEdgeList has +// few methods. It exists primarily to support the Kruskal algorithm.) // // FromList is a compact rooted tree (or forest) respresentation. Like // AdjacencyList and LabeledAdjacencyList, it is a list with one element for @@ -59,8 +59,7 @@ // simply by ignoring the label. In these cases code generation provides // methods on both types from a single source implementation. These methods // are documented with the sentence "There are equivalent labeled and unlabeled -// versions of this method" and examples are provided only for the unlabeled -// version. +// versions of this method." // // Terminology // @@ -114,15 +113,10 @@ // distance with the same minimum length, search methods are free to return // any of them. // -// Type name Description, methods -// BreadthFirst Unweigted arcs, traversal, single path search or all paths. -// BreadthFirst2 Direction-optimizing variant of BreadthFirst. +// Algorithm Description // Dijkstra Non-negative arc weights, single or all paths. // AStar Non-negative arc weights, heuristic guided, single path. // BellmanFord Negative arc weights allowed, no negative cycles, all paths. // DAGPath O(n) algorithm for DAGs, arc weights of any sign. // FloydWarshall all pairs distances, no negative cycles. -// -// These searches typically have one method that is full-featured and -// then a convenience method with a simpler API targeting a simpler use case. package graph diff --git a/vendor/github.com/soniakeys/graph/fromlist.go b/vendor/github.com/soniakeys/graph/fromlist.go index 31d41fa1..ce8c27f4 100644 --- a/vendor/github.com/soniakeys/graph/fromlist.go +++ b/vendor/github.com/soniakeys/graph/fromlist.go @@ -3,6 +3,8 @@ package graph +import "github.com/soniakeys/bits" + // FromList represents a rooted tree (or forest) where each node is associated // with a half arc identifying an arc "from" another node. // @@ -34,7 +36,7 @@ package graph // useful to validate the acyclic property. type FromList struct { Paths []PathEnd // tree representation - Leaves Bits // leaves of tree + Leaves bits.Bits // leaves of tree MaxLen int // length of longest path, max of all PathEnd.Len values } @@ -46,10 +48,17 @@ type PathEnd struct { Len int // number of nodes in path from start } +/* NewFromList could be confusing now with bits also needing allocation. +maybe best to not have this function. Maybe a more useful new would be +one that took a PathEnd slice and intitialized everything including roots +and max len. Maybe its time for a separate []PathEnd type when that's +all that's needed. (and reconsider the name PathEnd) +*/ + // NewFromList creates a FromList object of given order. // -// The Paths member is allocated to length n but there is no other -// initialization. +// The Paths member is allocated to the specified order n but other members +// are left as zero values. func NewFromList(n int) FromList { return FromList{Paths: make([]PathEnd, n)} } @@ -106,18 +115,18 @@ func (f FromList) CommonStart(a, b NI) NI { // Note that the bool is not an "ok" return. A cyclic FromList is usually // not okay. func (f FromList) Cyclic() (cyclic bool, n NI) { - var vis Bits p := f.Paths + vis := bits.New(len(p)) for i := range p { - var path Bits - for n := NI(i); vis.Bit(n) == 0; { + path := bits.New(len(p)) + for n := i; vis.Bit(n) == 0; { vis.SetBit(n, 1) path.SetBit(n, 1) - if n = p[n].From; n < 0 { + if n = int(p[n].From); n < 0 { break } if path.Bit(n) == 1 { - return true, n + return true, NI(n) } } } @@ -127,13 +136,14 @@ func (f FromList) Cyclic() (cyclic bool, n NI) { // IsolatedNodeBits returns a bitmap of isolated nodes in receiver graph f. // // An isolated node is one with no arcs going to or from it. -func (f FromList) IsolatedNodes() (iso Bits) { +func (f FromList) IsolatedNodes() (iso bits.Bits) { p := f.Paths - iso.SetAll(len(p)) + iso = bits.New(len(p)) + iso.SetAll() for n, e := range p { if e.From >= 0 { - iso.SetBit(NI(n), 0) - iso.SetBit(e.From, 0) + iso.SetBit(n, 0) + iso.SetBit(int(e.From), 0) } } return @@ -170,7 +180,7 @@ func (f FromList) PathTo(end NI, p []NI) []NI { func PathTo(paths []PathEnd, end NI, p []NI) []NI { n := paths[end].Len if n == 0 { - return nil + return p[:0] } if cap(p) >= n { p = p[:n] @@ -187,7 +197,39 @@ func PathTo(paths []PathEnd, end NI, p []NI) []NI { } } -// Preorder traverses f calling Visitor v in preorder. +// PathToLabeled decodes a FromList, recovering a single path. +// +// The start of the returned path will be a root node of the FromList. +// +// Only the Paths member of the receiver is used. Other members of the +// FromList do not need to be valid, however the MaxLen member can be useful +// for allocating argument p. +// +// Argument p can provide the result slice. If p has capacity for the result +// it will be used, otherwise a new slice is created for the result. +// +// See also function PathTo. +func (f FromList) PathToLabeled(end NI, labels []LI, p []Half) LabeledPath { + n := f.Paths[end].Len - 1 + if n <= 0 { + return LabeledPath{end, p[:0]} + } + if cap(p) >= n { + p = p[:n] + } else { + p = make([]Half, n) + } + for { + n-- + p[n] = Half{To: end, Label: labels[end]} + end = f.Paths[end].From + if n == 0 { + return LabeledPath{end, p} + } + } +} + +// Preorder traverses a FromList in preorder. // // Nodes are visited in order such that for any node n with from node fr, // fr is visited before n. Where f represents a tree, the visit ordering @@ -198,16 +240,17 @@ func PathTo(paths []PathEnd, end NI, p []NI) []NI { // Leaves must be set correctly first. Use RecalcLeaves if leaves are not // known to be set correctly. FromList f cannot be cyclic. // -// Traversal continues while v returns true. It terminates if v returns false. -// Preorder returns true if it completes without v returning false. Preorder -// returns false if traversal is terminated by v returning false. -func (f FromList) Preorder(v OkNodeVisitor) bool { +// Traversal continues while visitor function v returns true. It terminates +// if v returns false. Preorder returns true if it completes without v +// returning false. Preorder returns false if traversal is terminated by v +// returning false. +func (f FromList) Preorder(v func(NI) bool) bool { p := f.Paths - var done Bits + done := bits.New(len(p)) var df func(NI) bool df = func(n NI) bool { - done.SetBit(n, 1) - if fr := p[n].From; fr >= 0 && done.Bit(fr) == 0 { + done.SetBit(int(n), 1) + if fr := p[n].From; fr >= 0 && done.Bit(int(fr)) == 0 { df(fr) } return v(n) @@ -215,8 +258,8 @@ func (f FromList) Preorder(v OkNodeVisitor) bool { for n := range f.Paths { p[n].Len = 0 } - return f.Leaves.Iterate(func(n NI) bool { - return df(n) + return f.Leaves.IterateOnes(func(n int) bool { + return df(NI(n)) }) } @@ -224,10 +267,13 @@ func (f FromList) Preorder(v OkNodeVisitor) bool { func (f *FromList) RecalcLeaves() { p := f.Paths lv := &f.Leaves - lv.SetAll(len(p)) + if lv.Num != len(p) { + *lv = bits.New(len(p)) + } + lv.SetAll() for n := range f.Paths { if fr := p[n].From; fr >= 0 { - lv.SetBit(fr, 0) + lv.SetBit(int(fr), 0) } } } @@ -236,6 +282,9 @@ func (f *FromList) RecalcLeaves() { // // RecalcLen relies on the Leaves member being valid. If it is not known // to be valid, call RecalcLeaves before calling RecalcLen. +// +// RecalcLen will panic if the FromList is cyclic. Use the Cyclic method +// if needed to verify that the FromList is acyclic. func (f *FromList) RecalcLen() { p := f.Paths var setLen func(NI) int @@ -255,7 +304,7 @@ func (f *FromList) RecalcLen() { p[n].Len = 0 } f.MaxLen = 0 - f.Leaves.Iterate(func(n NI) bool { + f.Leaves.IterateOnes(func(n int) bool { if l := setLen(NI(n)); l > f.MaxLen { f.MaxLen = l } @@ -301,75 +350,59 @@ func (f FromList) Root(n NI) NI { // Transpose constructs the directed graph corresponding to FromList f // but with arcs in the opposite direction. That is, from roots toward leaves. // +// If non-nil argrument roots is passed, Transpose populates it as roots of +// the resulting forest and returns nRoots as a count of the roots. +// // The method relies only on the From member of f.Paths. Other members of // the FromList are not used. -// -// See FromList.TransposeRoots for a version that also accumulates and returns -// information about the roots. -func (f FromList) Transpose() Directed { - g := make(AdjacencyList, len(f.Paths)) - for n, p := range f.Paths { - if p.From == -1 { - continue +func (f FromList) Transpose(roots *bits.Bits) (forest Directed, nRoots int) { + p := f.Paths + g := make(AdjacencyList, len(p)) + if roots != nil { + nRoots = len(p) + if roots.Num != nRoots { + *roots = bits.New(nRoots) } - g[p.From] = append(g[p.From], NI(n)) + roots.SetAll() } - return Directed{g} -} - -// TransposeLabeled constructs the directed labeled graph corresponding -// to FromList f but with arcs in the opposite direction. That is, from -// roots toward leaves. -// -// The argument labels can be nil. In this case labels are generated matching -// the path indexes. This corresponds to the "to", or child node. -// -// If labels is non-nil, it must be the same length as f.Paths and is used -// to look up label numbers by the path index. -// -// The method relies only on the From member of f.Paths. Other members of -// the FromList are not used. -// -// See FromList.TransposeLabeledRoots for a version that also accumulates -// and returns information about the roots. -func (f FromList) TransposeLabeled(labels []LI) LabeledDirected { - g := make(LabeledAdjacencyList, len(f.Paths)) - for n, p := range f.Paths { - if p.From == -1 { + for i, e := range p { + if e.From == -1 { continue } - l := LI(n) - if labels != nil { - l = labels[n] + g[e.From] = append(g[e.From], NI(i)) + if roots != nil && roots.Bit(i) == 1 { + roots.SetBit(i, 0) + nRoots-- } - g[p.From] = append(g[p.From], Half{NI(n), l}) } - return LabeledDirected{g} + return Directed{g}, nRoots } -// TransposeLabeledRoots constructs the labeled directed graph corresponding +// TransposeLabeled constructs the labeled directed graph corresponding // to FromList f but with arcs in the opposite direction. That is, from // roots toward leaves. // -// TransposeLabeledRoots also returns a count of roots of the resulting forest -// and a bitmap of the roots. -// // The argument labels can be nil. In this case labels are generated matching // the path indexes. This corresponds to the "to", or child node. // // If labels is non-nil, it must be the same length as t.Paths and is used // to look up label numbers by the path index. // +// If non-nil argrument roots is passed, Transpose populates it as roots of +// the resulting forest and returns nRoots as a count of the roots. +// // The method relies only on the From member of f.Paths. Other members of // the FromList are not used. -// -// See FromList.TransposeLabeled for a simpler verstion that returns the -// forest only. -func (f FromList) TransposeLabeledRoots(labels []LI) (forest LabeledDirected, nRoots int, roots Bits) { +func (f FromList) TransposeLabeled(labels []LI, roots *bits.Bits) (forest LabeledDirected, nRoots int) { p := f.Paths - nRoots = len(p) - roots.SetAll(len(p)) g := make(LabeledAdjacencyList, len(p)) + if roots != nil { + nRoots = len(p) + if roots.Num != nRoots { + *roots = bits.New(nRoots) + } + roots.SetAll() + } for i, p := range f.Paths { if p.From == -1 { continue @@ -378,41 +411,88 @@ func (f FromList) TransposeLabeledRoots(labels []LI) (forest LabeledDirected, nR if labels != nil { l = labels[i] } - n := NI(i) - g[p.From] = append(g[p.From], Half{n, l}) - if roots.Bit(n) == 1 { - roots.SetBit(n, 0) + g[p.From] = append(g[p.From], Half{NI(i), l}) + if roots != nil && roots.Bit(i) == 1 { + roots.SetBit(i, 0) nRoots-- } } - return LabeledDirected{g}, nRoots, roots + return LabeledDirected{g}, nRoots } -// TransposeRoots constructs the directed graph corresponding to FromList f -// but with arcs in the opposite direction. That is, from roots toward leaves. +// Undirected constructs the undirected graph corresponding to FromList f. +// +// The resulting graph will be a tree or forest. // -// TransposeRoots also returns a count of roots of the resulting forest and -// a bitmap of the roots. +// If non-nil argrument roots is passed, Transpose populates it as roots of +// the resulting forest and returns nRoots as a count of the roots. // // The method relies only on the From member of f.Paths. Other members of // the FromList are not used. -// -// See FromList.Transpose for a simpler verstion that returns the forest only. -func (f FromList) TransposeRoots() (forest Directed, nRoots int, roots Bits) { +func (f FromList) Undirected(roots *bits.Bits) (forest Undirected, nRoots int) { p := f.Paths - nRoots = len(p) - roots.SetAll(len(p)) g := make(AdjacencyList, len(p)) + if roots != nil { + nRoots = len(p) + if roots.Num != nRoots { + *roots = bits.New(nRoots) + } + roots.SetAll() + } for i, e := range p { if e.From == -1 { continue } - n := NI(i) - g[e.From] = append(g[e.From], n) - if roots.Bit(n) == 1 { - roots.SetBit(n, 0) + g[i] = append(g[i], e.From) + g[e.From] = append(g[e.From], NI(i)) + if roots != nil && roots.Bit(i) == 1 { + roots.SetBit(i, 0) + nRoots-- + } + } + return Undirected{g}, nRoots +} + +// LabeledUndirected constructs the labeled undirected graph corresponding +// to FromList f. +// +// The resulting graph will be a tree or forest. +// +// The argument labels can be nil. In this case labels are generated matching +// the path indexes. This corresponds to the "to", or child node. +// +// If labels is non-nil, it must be the same length as t.Paths and is used +// to look up label numbers by the path index. +// +// If non-nil argrument roots is passed, LabeledUndirected populates it as +// roots of the resulting forest and returns nRoots as a count of the roots. +// +// The method relies only on the From member of f.Paths. Other members of +// the FromList are not used. +func (f FromList) LabeledUndirected(labels []LI, roots *bits.Bits) (forest LabeledUndirected, nRoots int) { + p := f.Paths + g := make(LabeledAdjacencyList, len(p)) + if roots != nil { + nRoots = len(p) + if roots.Num != nRoots { + *roots = bits.New(nRoots) + } + roots.SetAll() + } + for i, p := range f.Paths { + if p.From == -1 { + continue + } + l := LI(i) + if labels != nil { + l = labels[i] + } + g[i] = append(g[i], Half{p.From, l}) + g[p.From] = append(g[p.From], Half{NI(i), l}) + if roots != nil && roots.Bit(i) == 1 { + roots.SetBit(i, 0) nRoots-- } } - return Directed{g}, nRoots, roots + return LabeledUndirected{g}, nRoots } diff --git a/vendor/github.com/soniakeys/graph/graph.go b/vendor/github.com/soniakeys/graph/graph.go index a2044e9a..c21e48a4 100644 --- a/vendor/github.com/soniakeys/graph/graph.go +++ b/vendor/github.com/soniakeys/graph/graph.go @@ -3,57 +3,73 @@ package graph +import ( + "bytes" + "errors" + "fmt" + "math" + "reflect" + "text/template" + + "github.com/soniakeys/bits" +) + // graph.go contains type definitions for all graph types and components. // Also, go generate directives for source transformations. // // For readability, the types are defined in a dependency order: // // NI -// NodeList // AdjacencyList // Directed // Undirected +// Bipartite +// Subgraph +// DirectedSubgraph +// UndirectedSubgraph // LI // Half +// fromHalf // LabeledAdjacencyList // LabeledDirected // LabeledUndirected +// LabeledBipartite +// LabeledSubgraph +// LabeledDirectedSubgraph +// LabeledUndirectedSubgraph // Edge // LabeledEdge +// LabeledPath // WeightFunc // WeightedEdgeList +// TraverseOption //go:generate cp adj_cg.go adj_RO.go //go:generate gofmt -r "LabeledAdjacencyList -> AdjacencyList" -w adj_RO.go //go:generate gofmt -r "n.To -> n" -w adj_RO.go //go:generate gofmt -r "Half -> NI" -w adj_RO.go +//go:generate gofmt -r "LabeledSubgraph -> Subgraph" -w adj_RO.go //go:generate cp dir_cg.go dir_RO.go //go:generate gofmt -r "LabeledDirected -> Directed" -w dir_RO.go +//go:generate gofmt -r "LabeledDirectedSubgraph -> DirectedSubgraph" -w dir_RO.go //go:generate gofmt -r "LabeledAdjacencyList -> AdjacencyList" -w dir_RO.go +//go:generate gofmt -r "labEulerian -> eulerian" -w dir_RO.go +//go:generate gofmt -r "newLabEulerian -> newEulerian" -w dir_RO.go +//go:generate gofmt -r "Half{n, -1} -> n" -w dir_RO.go //go:generate gofmt -r "n.To -> n" -w dir_RO.go //go:generate gofmt -r "Half -> NI" -w dir_RO.go //go:generate cp undir_cg.go undir_RO.go //go:generate gofmt -r "LabeledUndirected -> Undirected" -w undir_RO.go +//go:generate gofmt -r "LabeledBipartite -> Bipartite" -w undir_RO.go +//go:generate gofmt -r "LabeledUndirectedSubgraph -> UndirectedSubgraph" -w undir_RO.go //go:generate gofmt -r "LabeledAdjacencyList -> AdjacencyList" -w undir_RO.go +//go:generate gofmt -r "newLabEulerian -> newEulerian" -w undir_RO.go +//go:generate gofmt -r "Half{n, -1} -> n" -w undir_RO.go //go:generate gofmt -r "n.To -> n" -w undir_RO.go //go:generate gofmt -r "Half -> NI" -w undir_RO.go -// NI is a "node int" -// -// It is a node number or node ID. NIs are used extensively as slice indexes. -// NIs typically account for a significant fraction of the memory footprint of -// a graph. -type NI int32 - -// NodeList satisfies sort.Interface. -type NodeList []NI - -func (l NodeList) Len() int { return len(l) } -func (l NodeList) Less(i, j int) bool { return l[i] < l[j] } -func (l NodeList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } - // An AdjacencyList represents a graph as a list of neighbors for each node. // The "node ID" of a node is simply it's slice index in the AdjacencyList. // For an AdjacencyList g, g[n] represents arcs going from node n to nodes @@ -83,6 +99,82 @@ type Undirected struct { AdjacencyList // embedded to include AdjacencyList methods } +// Bipartite represents a bipartite graph. +// +// In a bipartite graph, nodes are partitioned into two sets, or +// "colors," such that every edge in the graph goes from one set to the +// other. +// +// Member Color represents the partition with a bitmap of length the same +// as the number of nodes in the graph. For convenience N0 stores the number +// of zero bits in Color. +// +// To construct a Bipartite object, if you can easily or efficiently use +// available information to construct the Color member, then you should do +// this and construct a Bipartite object with a Go struct literal. +// +// If partition information is not readily available, see the constructor +// Undirected.Bipartite. +// +// Alternatively, in some cases where the graph may have multiple connected +// components, the lower level Undirected.BipartiteComponent can be used to +// control color assignment by component. +type Bipartite struct { + Undirected + Color bits.Bits + N0 int +} + +// Subgraph represents a subgraph mapped to a supergraph. +// +// The subgraph is the embedded AdjacencyList and so the Subgraph type inherits +// all methods of Adjacency list. +// +// The embedded subgraph mapped relative to a specific supergraph, member +// Super. A subgraph may have fewer nodes than its supergraph. +// Each node of the subgraph must map to a distinct node of the supergraph. +// +// The mapping giving the supergraph node for a given subgraph node is +// represented by member SuperNI, a slice parallel to the the subgraph. +// +// The mapping in the other direction, giving a subgraph NI for a given +// supergraph NI, is represented with map SubNI. +// +// Multiple Subgraphs can be created relative to a single supergraph. +// The Subgraph type represents a mapping to only a single supergraph however. +// +// See graph methods InduceList and InduceBits for construction of +// node-induced subgraphs. +// +// Alternatively an empty subgraph can be constructed with InduceList(nil). +// Arbitrary subgraphs can then be built up with methods AddNode and AddArc. +type Subgraph struct { + AdjacencyList // the subgraph + Super *AdjacencyList // the supergraph + SubNI map[NI]NI // subgraph NIs, indexed by supergraph NIs + SuperNI []NI // supergraph NIs indexed by subgraph NIs +} + +// DirectedSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type DirectedSubgraph struct { + Directed + Super *Directed + SubNI map[NI]NI + SuperNI []NI +} + +// UndirectedSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type UndirectedSubgraph struct { + Undirected + Super *Undirected + SubNI map[NI]NI + SuperNI []NI +} + // LI is a label integer, used for associating labels with arcs. type LI int32 @@ -95,6 +187,16 @@ type Half struct { Label LI // half-arc ID for application data, often a weight } +// fromHalf is a half arc, representing a labeled arc and the "neighbor" node +// that the arc originates from. +// +// This used internally in a couple of places. It used to be exported but is +// not currently needed anwhere in the API. +type fromHalf struct { + From NI + Label LI +} + // A LabeledAdjacencyList represents a graph as a list of neighbors for each // node, connected by labeled arcs. // @@ -133,6 +235,62 @@ type LabeledUndirected struct { LabeledAdjacencyList // embedded to include LabeledAdjacencyList methods } +// LabeledBipartite represents a bipartite graph. +// +// In a bipartite graph, nodes are partitioned into two sets, or +// "colors," such that every edge in the graph goes from one set to the +// other. +// +// Member Color represents the partition with a bitmap of length the same +// as the number of nodes in the graph. For convenience N0 stores the number +// of zero bits in Color. +// +// To construct a LabeledBipartite object, if you can easily or efficiently use +// available information to construct the Color member, then you should do +// this and construct a LabeledBipartite object with a Go struct literal. +// +// If partition information is not readily available, see the constructor +// Undirected.LabeledBipartite. +// +// Alternatively, in some cases where the graph may have multiple connected +// components, the lower level LabeledUndirected.BipartiteComponent can be used +// to control color assignment by component. +type LabeledBipartite struct { + LabeledUndirected + Color bits.Bits + N0 int +} + +// LabeledSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type LabeledSubgraph struct { + LabeledAdjacencyList + Super *LabeledAdjacencyList + SubNI map[NI]NI + SuperNI []NI +} + +// LabeledDirectedSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type LabeledDirectedSubgraph struct { + LabeledDirected + Super *LabeledDirected + SubNI map[NI]NI + SuperNI []NI +} + +// LabeledUndirectedSubgraph represents a subgraph mapped to a supergraph. +// +// See additional doc at Subgraph type. +type LabeledUndirectedSubgraph struct { + LabeledUndirected + Super *LabeledUndirected + SubNI map[NI]NI + SuperNI []NI +} + // Edge is an undirected edge between nodes N1 and N2. type Edge struct{ N1, N2 NI } @@ -142,6 +300,21 @@ type LabeledEdge struct { LI } +// LabeledPath is a start node and a path of half arcs leading from start. +type LabeledPath struct { + Start NI + Path []Half +} + +// Distance returns total path distance given WeightFunc w. +func (p LabeledPath) Distance(w WeightFunc) float64 { + d := 0. + for _, h := range p.Path { + d += w(h.Label) + } + return d +} + // WeightFunc returns a weight for a given label. // // WeightFunc is a parameter type for various search functions. The intent @@ -167,15 +340,428 @@ type WeightedEdgeList struct { Edges []LabeledEdge } -// Len implements sort.Interface. -func (l WeightedEdgeList) Len() int { return len(l.Edges) } +// DistanceMatrix constructs a distance matrix corresponding to the weighted +// edges of l. +// +// An edge n1, n2 with WeightFunc return w is represented by both +// d[n1][n2] == w and d[n2][n1] = w. In case of parallel edges, the lowest +// weight is stored. The distance from any node to itself d[n][n] is 0, unless +// the node has a loop with a negative weight. If g has no edge between n1 and +// distinct n2, +Inf is stored for d[n1][n2] and d[n2][n1]. +// +// The returned DistanceMatrix is suitable for DistanceMatrix.FloydWarshall. +func (l WeightedEdgeList) DistanceMatrix() (d DistanceMatrix) { + d = newDM(l.Order) + for _, e := range l.Edges { + n1 := e.Edge.N1 + n2 := e.Edge.N2 + wt := l.WeightFunc(e.LI) + // < to pick min of parallel arcs (also nicely ignores NaN) + if wt < d[n1][n2] { + d[n1][n2] = wt + d[n2][n1] = wt + } + } + return +} + +// A DistanceMatrix is a square matrix representing some distance between +// nodes of a graph. If the graph is directected, d[from][to] represents +// some distance from node 'from' to node 'to'. Depending on context, the +// distance may be an arc weight or path distance. A value of +Inf typically +// means no arc or no path between the nodes. +type DistanceMatrix [][]float64 + +// little helper function, makes a blank distance matrix for FloydWarshall. +// could be exported? +func newDM(n int) DistanceMatrix { + inf := math.Inf(1) + d := make(DistanceMatrix, n) + for i := range d { + di := make([]float64, n) + for j := range di { + di[j] = inf + } + di[i] = 0 + d[i] = di + } + return d +} + +// FloydWarshall finds all pairs shortest distances for a weighted graph +// without negative cycles. +// +// It operates on a distance matrix representing arcs of a graph and +// destructively replaces arc weights with shortest path distances. +// +// In receiver d, d[fr][to] will be the shortest distance from node +// 'fr' to node 'to'. An element value of +Inf means no path exists. +// Any diagonal element < 0 indicates a negative cycle exists. +// +// See DistanceMatrix constructor methods of LabeledAdjacencyList and +// WeightedEdgeList for suitable inputs. +func (d DistanceMatrix) FloydWarshall() { + for k, dk := range d { + for _, di := range d { + dik := di[k] + for j := range d { + if d2 := dik + dk[j]; d2 < di[j] { + di[j] = d2 + } + } + } + } +} + +// PathMatrix is a return type for FloydWarshallPaths. +// +// It encodes all pairs shortest paths. +type PathMatrix [][]NI -// Less implements sort.Interface. -func (l WeightedEdgeList) Less(i, j int) bool { - return l.WeightFunc(l.Edges[i].LI) < l.WeightFunc(l.Edges[j].LI) +// Path returns a shortest path from node start to end. +// +// Argument p is truncated, appended to, and returned as the result. +// Thus the underlying allocation is reused if possible. +// If there is no path from start to end, p is returned truncated to +// zero length. +// +// If receiver m is not a valid populated PathMatrix as returned by +// FloydWarshallPaths, behavior is undefined and a panic is likely. +func (m PathMatrix) Path(start, end NI, p []NI) []NI { + p = p[:0] + for { + p = append(p, start) + if start == end { + return p + } + start = m[start][end] + if start < 0 { + return p[:0] + } + } } -// Swap implements sort.Interface. -func (l WeightedEdgeList) Swap(i, j int) { - l.Edges[i], l.Edges[j] = l.Edges[j], l.Edges[i] +// FloydWarshallPaths finds all pairs shortest paths for a weighted graph +// without negative cycles. +// +// It operates on a distance matrix representing arcs of a graph and +// destructively replaces arc weights with shortest path distances. +// +// In receiver d, d[fr][to] will be the shortest distance from node +// 'fr' to node 'to'. An element value of +Inf means no path exists. +// Any diagonal element < 0 indicates a negative cycle exists. +// +// The return value encodes the paths. See PathMatrix.Path. +// +// See DistanceMatrix constructor methods of LabeledAdjacencyList and +// WeightedEdgeList for suitable inputs. +// +// See also similar method FloydWarshallFromLists which has a richer +// return value. +func (d DistanceMatrix) FloydWarshallPaths() PathMatrix { + m := make(PathMatrix, len(d)) + inf := math.Inf(1) + for i, di := range d { + mi := make([]NI, len(d)) + for j, dij := range di { + if dij == inf { + mi[j] = -1 + } else { + mi[j] = NI(j) + } + } + m[i] = mi + } + for k, dk := range d { + for i, di := range d { + mi := m[i] + dik := di[k] + for j := range d { + if d2 := dik + dk[j]; d2 < di[j] { + di[j] = d2 + mi[j] = mi[k] + } + } + } + } + return m +} + +// FloydWarshallFromLists finds all pairs shortest paths for a weighted +// graph without negative cycles. +// +// It operates on a distance matrix representing arcs of a graph and +// destructively replaces arc weights with shortest path distances. +// +// In receiver d, d[fr][to] will be the shortest distance from node +// 'fr' to node 'to'. An element value of +Inf means no path exists. +// Any diagonal element < 0 indicates a negative cycle exists. +// +// The return value encodes the paths. The FromLists are fully populated +// with Leaves and Len values. See for example FromList.PathTo for +// extracting paths. Note though that for i'th FromList of the return +// value, PathTo(j) will return the path from j's root, which will not +// be i in the case that there is no path from i to j. You must check +// the first node of the path to see if it is i. If not, there is no +// path from i to j. See example. +// +// See DistanceMatrix constructor methods of LabeledAdjacencyList and +// WeightedEdgeList for suitable inputs. +// +// See also similar method FloydWarshallPaths, which has a lighter +// weight return value. +func (d DistanceMatrix) FloydWarshallFromLists() []FromList { + l := make([]FromList, len(d)) + inf := math.Inf(1) + for i, di := range d { + li := NewFromList(len(d)) + p := li.Paths + for j, dij := range di { + if i == j || dij == inf { + p[j] = PathEnd{From: -1} + } else { + p[j] = PathEnd{From: NI(i)} + } + } + l[i] = li + } + for k, dk := range d { + pk := l[k].Paths + for i, di := range d { + dik := di[k] + pi := l[i].Paths + for j := range d { + if d2 := dik + dk[j]; d2 < di[j] { + di[j] = d2 + pi[j] = pk[j] + } + } + } + } + for _, li := range l { + li.RecalcLeaves() + li.RecalcLen() + } + return l +} + +// AddEdge adds an edge to a subgraph. +// +// For argument e, e.N1 and e.N2 must be NIs in supergraph s.Super. As with +// AddNode, AddEdge panics if e.N1 and e.N2 are not valid node indexes of +// s.Super. +// +// Edge e must exist in s.Super. Further, the number of +// parallel edges in the subgraph cannot exceed the number of corresponding +// parallel edges in the supergraph. That is, each edge already added to the +// subgraph counts against the edges available in the supergraph. If a matching +// edge is not available, AddEdge returns an error. +// +// If a matching edge is available, subgraph nodes are added as needed, the +// subgraph edge is added, and the method returns nil. +func (s *UndirectedSubgraph) AddEdge(n1, n2 NI) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(n1) < 0 || int(n1) >= s.Super.Order() { + panic(fmt.Sprint("AddEdge: NI ", n1, " not in supergraph")) + } + if int(n2) < 0 || int(n2) >= s.Super.Order() { + panic(fmt.Sprint("AddEdge: NI ", n2, " not in supergraph")) + } + // count existing matching edges in subgraph + n := 0 + a := s.Undirected.AdjacencyList + if b1, ok := s.SubNI[n1]; ok { + if b2, ok := s.SubNI[n2]; ok { + // both NIs already exist in subgraph, need to count edges + for _, t := range a[b1] { + if t == b2 { + n++ + } + } + if b1 != b2 { + // verify reciprocal arcs exist + r := 0 + for _, t := range a[b2] { + if t == b1 { + r++ + } + } + if r < n { + n = r + } + } + } + } + // verify matching edges are available in supergraph + m := 0 + for _, t := range (*s.Super).AdjacencyList[n1] { + if t == n2 { + if m == n { + goto r // arc match after all existing arcs matched + } + m++ + } + } + return errors.New("edge not available in supergraph") +r: + if n1 != n2 { + // verify reciprocal arcs + m = 0 + for _, t := range (*s.Super).AdjacencyList[n2] { + if t == n1 { + if m == n { + goto good + } + m++ + } + } + return errors.New("edge not available in supergraph") + } +good: + // matched enough edges. nodes can finally + // be added as needed and then the edge can be added. + b1 := s.AddNode(n1) + b2 := s.AddNode(n2) + s.Undirected.AddEdge(b1, b2) + return nil // success +} + +// AddEdge adds an edge to a subgraph. +// +// For argument e, e.N1 and e.N2 must be NIs in supergraph s.Super. As with +// AddNode, AddEdge panics if e.N1 and e.N2 are not valid node indexes of +// s.Super. +// +// Edge e must exist in s.Super with label l. Further, the number of +// parallel edges in the subgraph cannot exceed the number of corresponding +// parallel edges in the supergraph. That is, each edge already added to the +// subgraph counts against the edges available in the supergraph. If a matching +// edge is not available, AddEdge returns an error. +// +// If a matching edge is available, subgraph nodes are added as needed, the +// subgraph edge is added, and the method returns nil. +func (s *LabeledUndirectedSubgraph) AddEdge(e Edge, l LI) error { + // verify supergraph NIs first, but without adding subgraph nodes just yet. + if int(e.N1) < 0 || int(e.N1) >= s.Super.Order() { + panic(fmt.Sprint("AddEdge: NI ", e.N1, " not in supergraph")) + } + if int(e.N2) < 0 || int(e.N2) >= s.Super.Order() { + panic(fmt.Sprint("AddEdge: NI ", e.N2, " not in supergraph")) + } + // count existing matching edges in subgraph + n := 0 + a := s.LabeledUndirected.LabeledAdjacencyList + if b1, ok := s.SubNI[e.N1]; ok { + if b2, ok := s.SubNI[e.N2]; ok { + // both NIs already exist in subgraph, need to count edges + h := Half{b2, l} + for _, t := range a[b1] { + if t == h { + n++ + } + } + if b1 != b2 { + // verify reciprocal arcs exist + r := 0 + h.To = b1 + for _, t := range a[b2] { + if t == h { + r++ + } + } + if r < n { + n = r + } + } + } + } + // verify matching edges are available in supergraph + m := 0 + h := Half{e.N2, l} + for _, t := range (*s.Super).LabeledAdjacencyList[e.N1] { + if t == h { + if m == n { + goto r // arc match after all existing arcs matched + } + m++ + } + } + return errors.New("edge not available in supergraph") +r: + if e.N1 != e.N2 { + // verify reciprocal arcs + m = 0 + h.To = e.N1 + for _, t := range (*s.Super).LabeledAdjacencyList[e.N2] { + if t == h { + if m == n { + goto good + } + m++ + } + } + return errors.New("edge not available in supergraph") + } +good: + // matched enough edges. nodes can finally + // be added as needed and then the edge can be added. + n1 := s.AddNode(e.N1) + n2 := s.AddNode(e.N2) + s.LabeledUndirected.AddEdge(Edge{n1, n2}, l) + return nil // success +} + +// utility function called from all of the InduceList methods. +func mapList(l []NI) (sub map[NI]NI, sup []NI) { + sub = map[NI]NI{} + // one pass to collect unique NIs + for _, p := range l { + sub[NI(p)] = -1 + } + if len(sub) == len(l) { // NIs in l are unique + sup = append([]NI{}, l...) // just copy them + for b, p := range l { + sub[p] = NI(b) // and fill in map + } + } else { // NIs in l not unique + sup = make([]NI, 0, len(sub)) + for _, p := range l { // preserve ordering of first occurrences in l + if sub[p] < 0 { + sub[p] = NI(len(sup)) + sup = append(sup, p) + } + } + } + return +} + +// utility function called from all of the InduceBits methods. +func mapBits(t bits.Bits) (sub map[NI]NI, sup []NI) { + sup = make([]NI, 0, t.OnesCount()) + sub = make(map[NI]NI, cap(sup)) + t.IterateOnes(func(n int) bool { + sub[NI(n)] = NI(len(sup)) + sup = append(sup, NI(n)) + return true + }) + return +} + +// OrderMap formats maps for testable examples. +// +// OrderMap provides simple, no-frills formatting of maps in sorted order, +// convenient in some cases for output of testable examples. +func OrderMap(m interface{}) string { + // in particular exclude slices, which template would happily accept but + // which would probably represent a coding mistake + if reflect.TypeOf(m).Kind() != reflect.Map { + panic("not a map") + } + t := template.Must(template.New("").Parse( + `map[{{range $k, $v := .}}{{$k}}:{{$v}} {{end}}]`)) + var b bytes.Buffer + if err := t.Execute(&b, m); err != nil { + panic(err) + } + return b.String() } diff --git a/vendor/github.com/soniakeys/graph/hacking.md b/vendor/github.com/soniakeys/graph/hacking.md deleted file mode 100644 index 30d2d7c5..00000000 --- a/vendor/github.com/soniakeys/graph/hacking.md +++ /dev/null @@ -1,37 +0,0 @@ -#Hacking - -Basic use of the package is just go get, or git clone; go install. There are -no dependencies outside the standard library. - -The primary to-do list is the issue tracker on Github. I maintained a -journal on google drive for a while but at some point filed issues for all -remaining ideas in that document that still seemed relevant. So currently -there is no other roadmap or planning document. - -CI is currently on travis-ci.org. The .travis.yml builds for go 1.2.1 -following https://github.com/soniakeys/graph/issues/49, and it currently builds -for go 1.6 as well. The travis script calls a shell script right away because -I didn’t see a way to get it to do different steps for the different go -versions. For 1.2.1, I just wanted the basic tests. For a current go version -such as 1.6, there’s a growing list of checks. - -The GOARCH=386 test is for https://github.com/soniakeys/graph/issues/41. -The problem is the architecture specific code in bits32.go and bits64.go. -Yes, there are architecture independent algorithms. There is also assembly -to access machine instructions. Anyway, it’s the way it is for now. - -Im not big on making go vet happy just for a badge but I really like the -example check that I believe appeared with go 1.6. (I think it will be a -standard check with 1.7, so the test script will have to change then.) - -https://github.com/client9/misspell has been valuable. - -Also I wrote https://github.com/soniakeys/vetc to validate that each source -file has copyright/license statement. - -Then, it’s not in the ci script, but I wrote https://github.com/soniakeys/rcv -to put coverage stats in the readme. Maybe it could be commit hook or -something but for now I’ll try just running it manually now and then. - -Go fmt is not in the ci script, but I have at least one editor set up to run -it on save, so code should stay formatted pretty well. diff --git a/vendor/github.com/soniakeys/graph/mst.go b/vendor/github.com/soniakeys/graph/mst.go index 028e680c..92a9175c 100644 --- a/vendor/github.com/soniakeys/graph/mst.go +++ b/vendor/github.com/soniakeys/graph/mst.go @@ -6,6 +6,8 @@ package graph import ( "container/heap" "sort" + + "github.com/soniakeys/bits" ) type dsElement struct { @@ -82,35 +84,47 @@ func (ds disjointSet) find(n NI) NI { // Kruskal implements Kruskal's algorithm for constructing a minimum spanning // forest on an undirected graph. // -// While the input graph is interpreted as undirected, the receiver edge list -// does not actually need to contain reciprocal arcs. A property of the -// algorithm is that arc direction is ignored. Thus only a single arc out of -// a reciprocal pair must be present in the edge list. Reciprocal arcs (and -// parallel arcs) are allowed though, and do not affect the result. +// The forest is returned as an undirected graph. +// +// Also returned is a total distance for the returned forest. +// +// This method is a convenience wrapper for LabeledEdgeList.Kruskal. +// If you have no need for the input graph as a LabeledUndirected, it may be +// more efficient to construct a LabeledEdgeList directly. +func (g LabeledUndirected) Kruskal(w WeightFunc) (spanningForest LabeledUndirected, dist float64) { + return g.WeightedArcsAsEdges(w).Kruskal() +} + +// Kruskal implements Kruskal's algorithm for constructing a minimum spanning +// forest on an undirected graph. +// +// The algorithm allows parallel edges, thus it is acceptable to construct +// the receiver with LabeledUndirected.WeightedArcsAsEdges. It may be more +// efficient though, if you can construct the receiver WeightedEdgeList +// directly without parallel edges. // // The forest is returned as an undirected graph. // // Also returned is a total distance for the returned forest. // -// The edge list of the receiver is sorted as a side effect of this method. -// See KruskalSorted for a version that relies on the edge list being already -// sorted. +// The edge list of the receiver is sorted in place as a side effect of this +// method. See KruskalSorted for a version that relies on the edge list being +// already sorted. This method is a wrapper for KruskalSorted. If you can +// generate the input graph sorted as required for KruskalSorted, you can +// call that method directly and avoid the overhead of the sort. func (l WeightedEdgeList) Kruskal() (g LabeledUndirected, dist float64) { - sort.Sort(l) + e := l.Edges + w := l.WeightFunc + sort.Slice(e, func(i, j int) bool { return w(e[i].LI) < w(e[j].LI) }) return l.KruskalSorted() } // KruskalSorted implements Kruskal's algorithm for constructing a minimum // spanning tree on an undirected graph. // -// While the input graph is interpreted as undirected, the receiver edge list -// does not actually need to contain reciprocal arcs. A property of the -// algorithm is that arc direction is ignored. Thus only a single arc out of -// a reciprocal pair must be present in the edge list. Reciprocal arcs (and -// parallel arcs) are allowed though, and do not affect the result. -// // When called, the edge list of the receiver must be already sorted by weight. -// See Kruskal for a version that accepts an unsorted edge list. +// See the Kruskal method for a version that accepts an unsorted edge list. +// As with Kruskal, parallel edges are allowed. // // The forest is returned as an undirected graph. // @@ -148,11 +162,14 @@ func (l WeightedEdgeList) KruskalSorted() (g LabeledUndirected, dist float64) { // Returned are the number of nodes spanned for the single tree (which will be // the order of the connected component) and the total spanned distance for the // single tree. -func (g LabeledUndirected) Prim(start NI, w WeightFunc, f *FromList, labels []LI, componentLeaves *Bits) (numSpanned int, dist float64) { +func (g LabeledUndirected) Prim(start NI, w WeightFunc, f *FromList, labels []LI, componentLeaves *bits.Bits) (numSpanned int, dist float64) { al := g.LabeledAdjacencyList if len(f.Paths) != len(al) { *f = NewFromList(len(al)) } + if f.Leaves.Num != len(al) { + f.Leaves = bits.New(len(al)) + } b := make([]prNode, len(al)) // "best" for n := range b { b[n].nx = NI(n) @@ -163,9 +180,12 @@ func (g LabeledUndirected) Prim(start NI, w WeightFunc, f *FromList, labels []LI rp[start] = PathEnd{From: -1, Len: 1} numSpanned = 1 fLeaves := &f.Leaves - fLeaves.SetBit(start, 1) + fLeaves.SetBit(int(start), 1) if componentLeaves != nil { - componentLeaves.SetBit(start, 1) + if componentLeaves.Num != len(al) { + *componentLeaves = bits.New(len(al)) + } + componentLeaves.SetBit(int(start), 1) } for a := start; ; { for _, nb := range al[a] { @@ -194,27 +214,17 @@ func (g LabeledUndirected) Prim(start NI, w WeightFunc, f *FromList, labels []LI labels[a] = bp.from.Label } dist += bp.wt - fLeaves.SetBit(bp.from.From, 0) - fLeaves.SetBit(a, 1) + fLeaves.SetBit(int(bp.from.From), 0) + fLeaves.SetBit(int(a), 1) if componentLeaves != nil { - componentLeaves.SetBit(bp.from.From, 0) - componentLeaves.SetBit(a, 1) + componentLeaves.SetBit(int(bp.from.From), 0) + componentLeaves.SetBit(int(a), 1) } numSpanned++ } return } -// fromHalf is a half arc, representing a labeled arc and the "neighbor" node -// that the arc originates from. -// -// (This used to be exported when there was a LabeledFromList. Currently -// unexported now that it seems to have much more limited use.) -type fromHalf struct { - From NI - Label LI -} - type prNode struct { nx NI from fromHalf diff --git a/vendor/github.com/soniakeys/graph/random.go b/vendor/github.com/soniakeys/graph/random.go index 99f04458..e4bbe30c 100644 --- a/vendor/github.com/soniakeys/graph/random.go +++ b/vendor/github.com/soniakeys/graph/random.go @@ -7,9 +7,67 @@ import ( "errors" "math" "math/rand" - "time" + + "github.com/soniakeys/bits" ) +// ChungLu constructs a random simple undirected graph. +// +// The Chung Lu model is similar to a "configuration model" where each +// node has a specified degree. In the Chung Lu model the degree specified +// for each node is taken as an expected degree, not an exact degree. +// +// Argument w is "weight," the expected degree for each node. +// The values of w must be given in decreasing order. +// +// The constructed graph will have node 0 with expected degree w[0] and so on +// so degree will decrease with node number. To randomize degree across +// node numbers, consider using the Permute method with a rand.Perm. +// +// Also returned is the actual size m of constructed graph g. +// +// If Rand r is nil, the rand package default shared source is used. +func ChungLu(w []float64, rr *rand.Rand) (g Undirected, m int) { + // Ref: "Efficient Generation of Networks with Given Expected Degrees" + // Joel C. Miller and Aric Hagberg + // accessed at http://aric.hagberg.org/papers/miller-2011-efficient.pdf + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 + } + a := make(AdjacencyList, len(w)) + S := 0. + for i := len(w) - 1; i >= 0; i-- { + S += w[i] + } + for u := 0; u < len(w)-1; u++ { + v := u + 1 + p := w[u] * w[v] / S + if p > 1 { + p = 1 + } + for v < len(w) && p > 0 { + if p != 1 { + v += int(math.Log(rf()) / math.Log(1-p)) + } + if v < len(w) { + q := w[u] * w[v] / S + if q > 1 { + q = 1 + } + if rf() < q/p { + a[u] = append(a[u], NI(v)) + a[v] = append(a[v], NI(u)) + m++ + } + p = q + v++ + } + } + } + return Undirected{a}, m +} + // Euclidean generates a random simple graph on the Euclidean plane. // // Nodes are associated with coordinates uniformly distributed on a unit @@ -28,23 +86,24 @@ import ( // combinations of nNodes and nArcs cannot be achieved with any amount of // patience given that the returned graph must be simple. // -// If Rand r is nil, the method creates a new source and generator for -// one-time use. +// If Rand r is nil, the rand package default shared source is used. // // Returned is a directed simple graph and associated positions indexed by -// node number. +// node number. In the arc list for each node, to-nodes are in random +// order. // // See also LabeledEuclidean. -func Euclidean(nNodes, nArcs int, affinity float64, patience int, r *rand.Rand) (g Directed, pos []struct{ X, Y float64 }, err error) { +func Euclidean(nNodes, nArcs int, affinity float64, patience int, rr *rand.Rand) (g Directed, pos []struct{ X, Y float64 }, err error) { a := make(AdjacencyList, nNodes) // graph - // generate random positions - if r == nil { - r = rand.New(rand.NewSource(time.Now().UnixNano())) + ri, rf, re := rand.Intn, rand.Float64, rand.ExpFloat64 + if rr != nil { + ri, rf, re = rr.Intn, rr.Float64, rr.ExpFloat64 } + // generate random positions pos = make([]struct{ X, Y float64 }, nNodes) for i := range pos { - pos[i].X = r.Float64() - pos[i].Y = r.Float64() + pos[i].X = rf() + pos[i].Y = rf() } // arcs var tooFar, dup int @@ -58,10 +117,10 @@ arc: err = errors.New("overcrowding") return } - n1 := NI(r.Intn(nNodes)) + n1 := NI(ri(nNodes)) var n2 NI for { - n2 = NI(r.Intn(nNodes)) + n2 = NI(ri(nNodes)) if n2 != n1 { // no graph loops break } @@ -69,7 +128,7 @@ arc: c1 := &pos[n1] c2 := &pos[n2] dist := math.Hypot(c2.X-c1.X, c2.Y-c1.Y) - if dist*affinity > r.ExpFloat64() { // favor near nodes + if dist*affinity > re() { // favor near nodes tooFar++ continue } @@ -93,17 +152,18 @@ arc: // // Otherwise the function arguments and return values are the same as for // function Euclidean. See Euclidean. -func LabeledEuclidean(nNodes, nArcs int, affinity float64, patience int, r *rand.Rand) (g LabeledDirected, pos []struct{ X, Y float64 }, wt []float64, err error) { +func LabeledEuclidean(nNodes, nArcs int, affinity float64, patience int, rr *rand.Rand) (g LabeledDirected, pos []struct{ X, Y float64 }, wt []float64, err error) { a := make(LabeledAdjacencyList, nNodes) // graph wt = make([]float64, nArcs) // arc weights - // generate random positions - if r == nil { - r = rand.New(rand.NewSource(time.Now().UnixNano())) + ri, rf, re := rand.Intn, rand.Float64, rand.ExpFloat64 + if rr != nil { + ri, rf, re = rr.Intn, rr.Float64, rr.ExpFloat64 } + // generate random positions pos = make([]struct{ X, Y float64 }, nNodes) for i := range pos { - pos[i].X = r.Float64() - pos[i].Y = r.Float64() + pos[i].X = rf() + pos[i].Y = rf() } // arcs var tooFar, dup int @@ -117,10 +177,10 @@ arc: err = errors.New("overcrowding") return } - n1 := NI(r.Intn(nNodes)) + n1 := NI(ri(nNodes)) var n2 NI for { - n2 = NI(r.Intn(nNodes)) + n2 = NI(ri(nNodes)) if n2 != n1 { // no graph loops break } @@ -128,7 +188,7 @@ arc: c1 := &pos[n1] c2 := &pos[n2] dist := math.Hypot(c2.X-c1.X, c2.Y-c1.Y) - if dist*affinity > r.ExpFloat64() { // favor near nodes + if dist*affinity > re() { // favor near nodes tooFar++ continue } @@ -154,27 +214,36 @@ arc: // // The resulting number of edges is somewhat random but asymptotically // approaches m = Ď€r²n²/2. The method accumulates and returns the actual -// number of edges constructed. +// number of edges constructed. In the arc list for each node, to-nodes are +// ordered. Consider using ShuffleArcLists if random order is important. // -// If Rand r is nil, the method creates a new source and generator for -// one-time use. +// If Rand r is nil, the rand package default shared source is used. // // See also LabeledGeometric. -func Geometric(nNodes int, radius float64, r *rand.Rand) (g Undirected, pos []struct{ X, Y float64 }, m int) { +func Geometric(nNodes int, radius float64, rr *rand.Rand) (g Undirected, pos []struct{ X, Y float64 }, m int) { // Expected degree is approximately nĎ€r². a := make(AdjacencyList, nNodes) - if r == nil { - r = rand.New(rand.NewSource(time.Now().UnixNano())) + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 } pos = make([]struct{ X, Y float64 }, nNodes) for i := range pos { - pos[i].X = r.Float64() - pos[i].Y = r.Float64() + pos[i].X = rf() + pos[i].Y = rf() } for u, up := range pos { for v := u + 1; v < len(pos); v++ { vp := pos[v] - if math.Hypot(up.X-vp.X, up.Y-vp.Y) < radius { + dx := math.Abs(up.X - vp.X) + if dx >= radius { + continue + } + dy := math.Abs(up.Y - vp.Y) + if dy >= radius { + continue + } + if math.Hypot(dx, dy) < radius { a[u] = append(a[u], NI(v)) a[v] = append(a[v], NI(u)) m++ @@ -193,15 +262,16 @@ func Geometric(nNodes int, radius float64, r *rand.Rand) (g Undirected, pos []st // size m is len(wt). // // See Geometric for additional description. -func LabeledGeometric(nNodes int, radius float64, r *rand.Rand) (g LabeledUndirected, pos []struct{ X, Y float64 }, wt []float64) { +func LabeledGeometric(nNodes int, radius float64, rr *rand.Rand) (g LabeledUndirected, pos []struct{ X, Y float64 }, wt []float64) { a := make(LabeledAdjacencyList, nNodes) - if r == nil { - r = rand.New(rand.NewSource(time.Now().UnixNano())) + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 } pos = make([]struct{ X, Y float64 }, nNodes) for i := range pos { - pos[i].X = r.Float64() - pos[i].Y = r.Float64() + pos[i].X = rf() + pos[i].Y = rf() } for u, up := range pos { for v := u + 1; v < len(pos); v++ { @@ -217,20 +287,332 @@ func LabeledGeometric(nNodes int, radius float64, r *rand.Rand) (g LabeledUndire return } +// GnmUndirected constructs a random simple undirected graph. +// +// Construction is by the ErdĹ‘s–RĂ©nyi model where the specified number of +// distinct edges is selected from all possible edges with equal probability. +// +// Argument n is number of nodes, m is number of edges and must be <= n(n-1)/2. +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// See also Gnm3Undirected, a method producing a statistically equivalent +// result, but by an algorithm with somewhat different performance properties. +// Performance of the two methods is expected to be similar in most cases but +// it may be worth trying both with your data to see if one has a clear +// advantage. +func GnmUndirected(n, m int, rr *rand.Rand) Undirected { + // based on Alg. 2 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + ri := rand.Intn + if rr != nil { + ri = rr.Intn + } + re := n * (n - 1) / 2 + ml := m + if m*2 > re { + ml = re - m + } + e := map[int]struct{}{} + for len(e) < ml { + e[ri(re)] = struct{}{} + } + a := make(AdjacencyList, n) + if m*2 > re { + i := 0 + for v := 1; v < n; v++ { + for w := 0; w < v; w++ { + if _, ok := e[i]; !ok { + a[v] = append(a[v], NI(w)) + a[w] = append(a[w], NI(v)) + } + i++ + } + } + } else { + for i := range e { + v := 1 + int(math.Sqrt(.25+float64(2*i))-.5) + w := i - (v * (v - 1) / 2) + a[v] = append(a[v], NI(w)) + a[w] = append(a[w], NI(v)) + } + } + return Undirected{a} +} + +// GnmDirected constructs a random simple directed graph. +// +// Construction is by the ErdĹ‘s–RĂ©nyi model where the specified number of +// distinct arcs is selected from all possible arcs with equal probability. +// +// Argument n is number of nodes, ma is number of arcs and must be <= n(n-1). +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// See also Gnm3Directed, a method producing a statistically equivalent +// result, but by +// an algorithm with somewhat different performance properties. Performance +// of the two methods is expected to be similar in most cases but it may be +// worth trying both with your data to see if one has a clear advantage. +func GnmDirected(n, ma int, rr *rand.Rand) Directed { + // based on Alg. 2 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + ri := rand.Intn + if rr != nil { + ri = rr.Intn + } + re := n * (n - 1) + ml := ma + if ma*2 > re { + ml = re - ma + } + e := map[int]struct{}{} + for len(e) < ml { + e[ri(re)] = struct{}{} + } + a := make(AdjacencyList, n) + if ma*2 > re { + i := 0 + for v := 0; v < n; v++ { + for w := 0; w < n; w++ { + if w == v { + continue + } + if _, ok := e[i]; !ok { + a[v] = append(a[v], NI(w)) + } + i++ + } + } + } else { + for i := range e { + v := i / (n - 1) + w := i % (n - 1) + if w >= v { + w++ + } + a[v] = append(a[v], NI(w)) + } + } + return Directed{a} +} + +// Gnm3Undirected constructs a random simple undirected graph. +// +// Construction is by the ErdĹ‘s–RĂ©nyi model where the specified number of +// distinct edges is selected from all possible edges with equal probability. +// +// Argument n is number of nodes, m is number of edges and must be <= n(n-1)/2. +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// See also GnmUndirected, a method producing a statistically equivalent +// result, but by an algorithm with somewhat different performance properties. +// Performance of the two methods is expected to be similar in most cases but +// it may be worth trying both with your data to see if one has a clear +// advantage. +func Gnm3Undirected(n, m int, rr *rand.Rand) Undirected { + // based on Alg. 3 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + // + // I like this algorithm for its elegance. Pitty it tends to run a + // a little slower than the retry algorithm of Gnm. + ri := rand.Intn + if rr != nil { + ri = rr.Intn + } + a := make(AdjacencyList, n) + re := n * (n - 1) / 2 + rm := map[int]int{} + for i := 0; i < m; i++ { + er := i + ri(re-i) + eNew := er + if rp, ok := rm[er]; ok { + eNew = rp + } + if rp, ok := rm[i]; !ok { + rm[er] = i + } else { + rm[er] = rp + } + v := 1 + int(math.Sqrt(.25+float64(2*eNew))-.5) + w := eNew - (v * (v - 1) / 2) + a[v] = append(a[v], NI(w)) + a[w] = append(a[w], NI(v)) + } + return Undirected{a} +} + +// Gnm3Directed constructs a random simple directed graph. +// +// Construction is by the ErdĹ‘s–RĂ©nyi model where the specified number of +// distinct arcs is selected from all possible arcs with equal probability. +// +// Argument n is number of nodes, ma is number of arcs and must be <= n(n-1). +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// See also GnmDirected, a method producing a statistically equivalent result, +// but by an algorithm with somewhat different performance properties. +// Performance of the two methods is expected to be similar in most cases +// but it may be worth trying both with your data to see if one has a clear +// advantage. +func Gnm3Directed(n, ma int, rr *rand.Rand) Directed { + // based on Alg. 3 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + ri := rand.Intn + if rr != nil { + ri = rr.Intn + } + a := make(AdjacencyList, n) + re := n * (n - 1) + rm := map[int]int{} + for i := 0; i < ma; i++ { + er := i + ri(re-i) + eNew := er + if rp, ok := rm[er]; ok { + eNew = rp + } + if rp, ok := rm[i]; !ok { + rm[er] = i + } else { + rm[er] = rp + } + v := eNew / (n - 1) + w := eNew % (n - 1) + if w >= v { + w++ + } + a[v] = append(a[v], NI(w)) + } + return Directed{a} +} + +// GnpUndirected constructs a random simple undirected graph. +// +// Construction is by the Gilbert model, an ErdĹ‘s–RĂ©nyi like model where +// distinct edges are independently selected from all possible edges with +// the specified probability. +// +// Argument n is number of nodes, p is probability for selecting an edge. +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// Also returned is the actual size m of constructed graph g. +func GnpUndirected(n int, p float64, rr *rand.Rand) (g Undirected, m int) { + a := make(AdjacencyList, n) + if n < 2 { + return Undirected{a}, 0 + } + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 + } + // based on Alg. 1 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + var v, w NI = 1, -1 +g: + for c := 1 / math.Log(1-p); ; { + w += 1 + NI(c*math.Log(1-rf())) + for { + if w < v { + a[v] = append(a[v], w) + a[w] = append(a[w], v) + m++ + continue g + } + w -= v + v++ + if v == NI(n) { + break g + } + } + } + return Undirected{a}, m +} + +// GnpDirected constructs a random simple directed graph. +// +// Construction is by the Gilbert model, an ErdĹ‘s–RĂ©nyi like model where +// distinct arcs are independently selected from all possible arcs with +// the specified probability. +// +// Argument n is number of nodes, p is probability for selecting an arc. +// +// If Rand r is nil, the rand package default shared source is used. +// +// In the generated arc list for each node, to-nodes are ordered. +// Consider using ShuffleArcLists if random order is important. +// +// Also returned is the actual arc size m of constructed graph g. +func GnpDirected(n int, p float64, rr *rand.Rand) (g Directed, ma int) { + a := make(AdjacencyList, n) + if n < 2 { + return Directed{a}, 0 + } + rf := rand.Float64 + if rr != nil { + rf = rr.Float64 + } + // based on Alg. 1 from "Efficient Generation of Large Random Networks", + // Vladimir Batagelj and Ulrik Brandes. + // accessed at http://algo.uni-konstanz.de/publications/bb-eglrn-05.pdf + var v, w NI = 0, -1 +g: + for c := 1 / math.Log(1-p); ; { + w += 1 + NI(c*math.Log(1-rf())) + for ; ; w -= NI(n) { + if w == v { + w++ + } + if w < NI(n) { + a[v] = append(a[v], w) + ma++ + continue g + } + v++ + if v == NI(n) { + break g + } + } + } + return Directed{a}, ma +} + // KroneckerDirected generates a Kronecker-like random directed graph. // // The returned graph g is simple and has no isolated nodes but is not // necessarily fully connected. The number of of nodes will be <= 2^scale, // and will be near 2^scale for typical values of arcFactor, >= 2. // ArcFactor * 2^scale arcs are generated, although loops and duplicate arcs -// are rejected. +// are rejected. In the arc list for each node, to-nodes are in random +// order. // -// If Rand r is nil, the method creates a new source and generator for -// one-time use. +// If Rand r is nil, the rand package default shared source is used. // // Return value ma is the number of arcs retained in the result graph. -func KroneckerDirected(scale uint, arcFactor float64, r *rand.Rand) (g Directed, ma int) { - a, m := kronecker(scale, arcFactor, true, r) +func KroneckerDirected(scale uint, arcFactor float64, rr *rand.Rand) (g Directed, ma int) { + a, m := kronecker(scale, arcFactor, true, rr) return Directed{a}, m } @@ -240,15 +622,15 @@ func KroneckerDirected(scale uint, arcFactor float64, r *rand.Rand) (g Directed, // necessarily fully connected. The number of of nodes will be <= 2^scale, // and will be near 2^scale for typical values of edgeFactor, >= 2. // EdgeFactor * 2^scale edges are generated, although loops and duplicate edges -// are rejected. +// are rejected. In the arc list for each node, to-nodes are in random +// order. // -// If Rand r is nil, the method creates a new source and generator for -// one-time use. +// If Rand r is nil, the rand package default shared source is used. // // Return value m is the true number of edges--not arcs--retained in the result // graph. -func KroneckerUndirected(scale uint, edgeFactor float64, r *rand.Rand) (g Undirected, m int) { - al, s := kronecker(scale, edgeFactor, false, r) +func KroneckerUndirected(scale uint, edgeFactor float64, rr *rand.Rand) (g Undirected, m int) { + al, s := kronecker(scale, edgeFactor, false, rr) return Undirected{al}, s } @@ -257,28 +639,29 @@ func KroneckerUndirected(scale uint, edgeFactor float64, r *rand.Rand) (g Undire // here is meaningful or not. // // note mma returns arc size ma for dir=true, but returns size m for dir=false -func kronecker(scale uint, edgeFactor float64, dir bool, r *rand.Rand) (g AdjacencyList, mma int) { - if r == nil { - r = rand.New(rand.NewSource(time.Now().UnixNano())) +func kronecker(scale uint, edgeFactor float64, dir bool, rr *rand.Rand) (g AdjacencyList, mma int) { + rf, ri, rp := rand.Float64, rand.Intn, rand.Perm + if rr != nil { + rf, ri, rp = rr.Float64, rr.Intn, rr.Perm } - N := NI(1 << scale) // node extent + N := 1 << scale // node extent M := int(edgeFactor*float64(N) + .5) // number of arcs/edges to generate a, b, c := 0.57, 0.19, 0.19 // initiator probabilities ab := a + b cNorm := c / (1 - ab) aNorm := a / ab ij := make([][2]NI, M) - var bm Bits + bm := bits.New(N) var nNodes int for k := range ij { - var i, j NI - for b := NI(1); b < N; b <<= 1 { - if r.Float64() > ab { + var i, j int + for b := 1; b < N; b <<= 1 { + if rf() > ab { i |= b - if r.Float64() > cNorm { + if rf() > cNorm { j |= b } - } else if r.Float64() > aNorm { + } else if rf() > aNorm { j |= b } } @@ -290,15 +673,15 @@ func kronecker(scale uint, edgeFactor float64, dir bool, r *rand.Rand) (g Adjace bm.SetBit(j, 1) nNodes++ } - r := r.Intn(k + 1) // shuffle edges as they are generated + r := ri(k + 1) // shuffle edges as they are generated ij[k] = ij[r] - ij[r] = [2]NI{i, j} + ij[r] = [2]NI{NI(i), NI(j)} } - p := r.Perm(nNodes) // mapping to shuffle IDs of non-isolated nodes + p := rp(nNodes) // mapping to shuffle IDs of non-isolated nodes px := 0 rn := make([]NI, N) for i := range rn { - if bm.Bit(NI(i)) == 1 { + if bm.Bit(i) == 1 { rn[i] = NI(p[px]) // fill lookup table px++ } diff --git a/vendor/github.com/soniakeys/graph/readme.md b/vendor/github.com/soniakeys/graph/readme.md deleted file mode 100644 index 539670ff..00000000 --- a/vendor/github.com/soniakeys/graph/readme.md +++ /dev/null @@ -1,38 +0,0 @@ -#Graph - -A graph library with goals of speed and simplicity, Graph implements -graph algorithms on graphs of zero-based integer node IDs. - -[![GoDoc](https://godoc.org/github.com/soniakeys/graph?status.svg)](https://godoc.org/github.com/soniakeys/graph) [![Go Walker](http://gowalker.org/api/v1/badge)](https://gowalker.org/github.com/soniakeys/graph) [![GoSearch](http://go-search.org/badge?id=github.com%2Fsoniakeys%2Fgraph)](http://go-search.org/view?id=github.com%2Fsoniakeys%2Fgraph)[![Build Status](https://travis-ci.org/soniakeys/graph.svg?branch=master)](https://travis-ci.org/soniakeys/graph) - -Status, 4 Apr 2016: The repo has benefitted recently from being included -in another package. In response to users of that package, this repo now -builds for 32 bit Windows and ARM, and for Go versions back to 1.2.1. -Thank you all who have filed issues. - -###Non-source files of interest - -The directory [tutorials](tutorials) is a work in progress - there are only -a couple of tutorials there yet - but the concept is to provide some topical -walk-throughs to supplement godoc. The source-based godoc documentation -remains the primary documentation. - -* [Dijkstra's algorithm](tutorials/dijkstra.md) -* [AdjacencyList types](tutorials/adjacencylist.md) - -The directory [bench](bench) is another work in progress. The concept is -to present some plots showing benchmark performance approaching some -theoretical asymptote. - -[hacking.md](hacking.md) has some information about how the library is -developed, built, and tested. It might be of interest if for example you -plan to fork or contribute to the the repository. - -###Test coverage -8 Apr 2016 -``` -graph 95.3% -graph/df 20.7% -graph/dot 77.5% -graph/treevis 79.4% -``` diff --git a/vendor/github.com/soniakeys/graph/sssp.go b/vendor/github.com/soniakeys/graph/sssp.go index 32cc192e..88e9d517 100644 --- a/vendor/github.com/soniakeys/graph/sssp.go +++ b/vendor/github.com/soniakeys/graph/sssp.go @@ -7,6 +7,8 @@ import ( "container/heap" "fmt" "math" + + "github.com/soniakeys/bits" ) // rNode holds data for a "reached" node @@ -60,7 +62,7 @@ func (h Heuristic) Admissible(g LabeledAdjacencyList, w WeightFunc, end NI) (boo // run dijkstra // Dijkstra.AllPaths takes a start node but after inverting the graph // argument end now represents the start node of the inverted graph. - f, dist, _ := inv.Dijkstra(end, -1, w) + f, _, dist, _ := inv.Dijkstra(end, -1, w) // compare h to found shortest paths for n := range inv { if f.Paths[n].Len == 0 { @@ -204,9 +206,9 @@ func (g LabeledAdjacencyList) AStarA(w WeightFunc, start, end NI, h Heuristic) ( // // If a path is found, the non-nil node path is returned with the total path // distance. Otherwise the returned path will be nil. -func (g LabeledAdjacencyList) AStarAPath(start, end NI, h Heuristic, w WeightFunc) ([]NI, float64) { - f, _, d, _ := g.AStarA(w, start, end, h) - return f.PathTo(end, nil), d +func (g LabeledAdjacencyList) AStarAPath(start, end NI, h Heuristic, w WeightFunc) (LabeledPath, float64) { + f, labels, d, _ := g.AStarA(w, start, end, h) + return f.PathToLabeled(end, labels, nil), d } // AStarM is AStarA optimized for monotonic heuristic estimates. @@ -305,9 +307,9 @@ func (g LabeledAdjacencyList) AStarM(w WeightFunc, start, end NI, h Heuristic) ( // // If a path is found, the non-nil node path is returned with the total path // distance. Otherwise the returned path will be nil. -func (g LabeledAdjacencyList) AStarMPath(start, end NI, h Heuristic, w WeightFunc) ([]NI, float64) { - f, _, d, _ := g.AStarM(w, start, end, h) - return f.PathTo(end, nil), d +func (g LabeledAdjacencyList) AStarMPath(start, end NI, h Heuristic, w WeightFunc) (LabeledPath, float64) { + f, labels, d, _ := g.AStarM(w, start, end, h) + return f.PathToLabeled(end, labels, nil), d } // implement container/heap @@ -342,8 +344,8 @@ func (p *openHeap) Pop() interface{} { // Loops and parallel arcs are allowed. // // If the algorithm completes without encountering a negative cycle the method -// returns shortest paths encoded in a FromList, path distances indexed by -// node, and return value end = -1. +// returns shortest paths encoded in a FromList, labels and path distances +// indexed by node, and return value end = -1. // // If it encounters a negative cycle reachable from start it returns end >= 0. // In this case the cycle can be obtained by calling f.BellmanFordCycle(end). @@ -352,11 +354,13 @@ func (p *openHeap) Pop() interface{} { // cycle not reachable from start will not prevent the algorithm from finding // shortest paths from start. // -// See also NegativeCycle to find a cycle anywhere in the graph, and see +// See also NegativeCycle to find a cycle anywhere in the graph, see +// NegativeCycles for enumerating all negative cycles, and see // HasNegativeCycle for lighter-weight negative cycle detection, -func (g LabeledDirected) BellmanFord(w WeightFunc, start NI) (f FromList, dist []float64, end NI) { +func (g LabeledDirected) BellmanFord(w WeightFunc, start NI) (f FromList, labels []LI, dist []float64, end NI) { a := g.LabeledAdjacencyList f = NewFromList(len(a)) + labels = make([]LI, len(a)) dist = make([]float64, len(a)) inf := math.Inf(1) for i := range dist { @@ -376,6 +380,7 @@ func (g LabeledDirected) BellmanFord(w WeightFunc, start NI) (f FromList, dist [ // TODO improve to break ties if fp.Len > 0 && d2 < dist[nb.To] { *to = PathEnd{From: NI(from), Len: fp.Len + 1} + labels[nb.To] = nb.Label dist[nb.To] = d2 imp = true } @@ -390,11 +395,11 @@ func (g LabeledDirected) BellmanFord(w WeightFunc, start NI) (f FromList, dist [ for _, nb := range nbs { if d1+w(nb.Label) < dist[nb.To] { // return nb as end of a path with negative cycle at root - return f, dist, NI(from) + return f, labels, dist, NI(from) } } } - return f, dist, -1 + return f, labels, dist, -1 } // BellmanFordCycle decodes a negative cycle detected by BellmanFord. @@ -402,14 +407,14 @@ func (g LabeledDirected) BellmanFord(w WeightFunc, start NI) (f FromList, dist [ // Receiver f and argument end must be results returned from BellmanFord. func (f FromList) BellmanFordCycle(end NI) (c []NI) { p := f.Paths - var b Bits - for b.Bit(end) == 0 { - b.SetBit(end, 1) + b := bits.New(len(p)) + for b.Bit(int(end)) == 0 { + b.SetBit(int(end), 1) end = p[end].From } - for b.Bit(end) == 1 { + for b.Bit(int(end)) == 1 { c = append(c, end) - b.SetBit(end, 0) + b.SetBit(int(end), 0) end = p[end].From } for i, j := 0, len(c)-1; i < j; i, j = i+1, j-1 { @@ -424,8 +429,9 @@ func (f FromList) BellmanFordCycle(end NI) (c []NI) { // cycles anywhere in the graph. Also path information is not computed, // reducing memory use somewhat compared to BellmanFord. // -// See also NegativeCycle to obtain the cycle, and see BellmanFord for -// single source shortest path searches. +// See also NegativeCycle to obtain the cycle, see NegativeCycles for +// enumerating all negative cycles, and see BellmanFord for single source +// shortest path searches with negative cycle detection. func (g LabeledDirected) HasNegativeCycle(w WeightFunc) bool { a := g.LabeledAdjacencyList dist := make([]float64, len(a)) @@ -462,15 +468,18 @@ func (g LabeledDirected) HasNegativeCycle(w WeightFunc) bool { // cycles anywhere in the graph. If a negative cycle exists, one will be // returned. The result is nil if no negative cycle exists. // -// See also HasNegativeCycle for lighter-weight cycle detection, and see -// BellmanFord for single source shortest paths. -func (g LabeledDirected) NegativeCycle(w WeightFunc) (c []NI) { +// See also NegativeCycles for enumerating all negative cycles, see +// HasNegativeCycle for lighter-weight cycle detection, and see +// BellmanFord for single source shortest paths, also with negative cycle +// detection. +func (g LabeledDirected) NegativeCycle(w WeightFunc) (c []Half) { a := g.LabeledAdjacencyList f := NewFromList(len(a)) p := f.Paths for n := range p { p[n] = PathEnd{From: -1, Len: 1} } + labels := make([]LI, len(a)) dist := make([]float64, len(a)) for _ = range a { imp := false @@ -482,6 +491,7 @@ func (g LabeledDirected) NegativeCycle(w WeightFunc) (c []NI) { to := &p[nb.To] if fp.Len > 0 && d2 < dist[nb.To] { *to = PathEnd{From: NI(from), Len: fp.Len + 1} + labels[nb.To] = nb.Label dist[nb.To] = d2 imp = true } @@ -491,26 +501,26 @@ func (g LabeledDirected) NegativeCycle(w WeightFunc) (c []NI) { return nil } } - var vis Bits + vis := bits.New(len(a)) a: for n := range a { - end := NI(n) - var b Bits + end := n + b := bits.New(len(a)) for b.Bit(end) == 0 { if vis.Bit(end) == 1 { continue a } vis.SetBit(end, 1) b.SetBit(end, 1) - end = p[end].From + end = int(p[end].From) if end < 0 { continue a } } for b.Bit(end) == 1 { - c = append(c, end) + c = append(c, Half{NI(end), labels[end]}) b.SetBit(end, 0) - end = p[end].From + end = int(p[end].From) } for i, j := 0, len(c)-1; i < j; i, j = i+1, j-1 { c[i], c[j] = c[j], c[i] @@ -520,147 +530,6 @@ a: return nil // no negative cycle } -// A NodeVisitor is an argument to some graph traversal methods. -// -// Graph traversal methods call the visitor function for each node visited. -// Argument n is the node being visited. -type NodeVisitor func(n NI) - -// An OkNodeVisitor function is an argument to some graph traversal methods. -// -// Graph traversal methods call the visitor function for each node visited. -// The argument n is the node being visited. If the visitor function -// returns true, the traversal will continue. If the visitor function -// returns false, the traversal will terminate immediately. -type OkNodeVisitor func(n NI) (ok bool) - -// BreadthFirst2 traverses a graph breadth first using a direction -// optimizing algorithm. -// -// The code is experimental and currently seems no faster than the -// conventional breadth first code. -// -// Use AdjacencyList.BreadthFirst instead. -func BreadthFirst2(g, tr AdjacencyList, ma int, start NI, f *FromList, v OkNodeVisitor) int { - if tr == nil { - var d Directed - d, ma = Directed{g}.Transpose() - tr = d.AdjacencyList - } - switch { - case f == nil: - e := NewFromList(len(g)) - f = &e - case f.Paths == nil: - *f = NewFromList(len(g)) - } - if ma <= 0 { - ma = g.ArcSize() - } - rp := f.Paths - level := 1 - rp[start] = PathEnd{Len: level, From: -1} - if !v(start) { - f.MaxLen = level - return -1 - } - nReached := 1 // accumulated for a return value - // the frontier consists of nodes all at the same level - frontier := []NI{start} - mf := len(g[start]) // number of arcs leading out from frontier - ctb := ma / 10 // threshold change from top-down to bottom-up - k14 := 14 * ma / len(g) // 14 * mean degree - cbt := len(g) / k14 // threshold change from bottom-up to top-down - // var fBits, nextb big.Int - fBits := make([]bool, len(g)) - nextb := make([]bool, len(g)) - zBits := make([]bool, len(g)) - for { - // top down step - level++ - var next []NI - for _, n := range frontier { - for _, nb := range g[n] { - if rp[nb].Len == 0 { - rp[nb] = PathEnd{From: n, Len: level} - if !v(nb) { - f.MaxLen = level - return -1 - } - next = append(next, nb) - nReached++ - } - } - } - if len(next) == 0 { - break - } - frontier = next - if mf > ctb { - // switch to bottom up! - } else { - // stick with top down - continue - } - // convert frontier representation - nf := 0 // number of vertices on the frontier - for _, n := range frontier { - // fBits.SetBit(&fBits, n, 1) - fBits[n] = true - nf++ - } - bottomUpLoop: - level++ - nNext := 0 - for n := range tr { - if rp[n].Len == 0 { - for _, nb := range tr[n] { - // if fBits.Bit(nb) == 1 { - if fBits[nb] { - rp[n] = PathEnd{From: nb, Len: level} - if !v(nb) { - f.MaxLen = level - return -1 - } - // nextb.SetBit(&nextb, n, 1) - nextb[n] = true - nReached++ - nNext++ - break - } - } - } - } - if nNext == 0 { - break - } - fBits, nextb = nextb, fBits - // nextb.SetInt64(0) - copy(nextb, zBits) - nf = nNext - if nf < cbt { - // switch back to top down! - } else { - // stick with bottom up - goto bottomUpLoop - } - // convert frontier representation - mf = 0 - frontier = frontier[:0] - for n := range g { - // if fBits.Bit(n) == 1 { - if fBits[n] { - frontier = append(frontier, NI(n)) - mf += len(g[n]) - fBits[n] = false - } - } - // fBits.SetInt64(0) - } - f.MaxLen = level - 1 - return nReached -} - // DAGMinDistPath finds a single shortest path. // // Shortest means minimum sum of arc weights. @@ -668,7 +537,7 @@ func BreadthFirst2(g, tr AdjacencyList, ma int, start NI, f *FromList, v OkNodeV // Returned is the path and distance as returned by FromList.PathTo. // // This is a convenience method. See DAGOptimalPaths for more options. -func (g LabeledDirected) DAGMinDistPath(start, end NI, w WeightFunc) ([]NI, float64, error) { +func (g LabeledDirected) DAGMinDistPath(start, end NI, w WeightFunc) (LabeledPath, float64, error) { return g.dagPath(start, end, w, false) } @@ -679,20 +548,20 @@ func (g LabeledDirected) DAGMinDistPath(start, end NI, w WeightFunc) ([]NI, floa // Returned is the path and distance as returned by FromList.PathTo. // // This is a convenience method. See DAGOptimalPaths for more options. -func (g LabeledDirected) DAGMaxDistPath(start, end NI, w WeightFunc) ([]NI, float64, error) { +func (g LabeledDirected) DAGMaxDistPath(start, end NI, w WeightFunc) (LabeledPath, float64, error) { return g.dagPath(start, end, w, true) } -func (g LabeledDirected) dagPath(start, end NI, w WeightFunc, longest bool) ([]NI, float64, error) { +func (g LabeledDirected) dagPath(start, end NI, w WeightFunc, longest bool) (LabeledPath, float64, error) { o, _ := g.Topological() if o == nil { - return nil, 0, fmt.Errorf("not a DAG") + return LabeledPath{}, 0, fmt.Errorf("not a DAG") } - f, dist, _ := g.DAGOptimalPaths(start, end, o, w, longest) + f, labels, dist, _ := g.DAGOptimalPaths(start, end, o, w, longest) if f.Paths[end].Len == 0 { - return nil, 0, fmt.Errorf("no path from %d to %d", start, end) + return LabeledPath{}, 0, fmt.Errorf("no path from %d to %d", start, end) } - return f.PathTo(end, nil), dist[end], nil + return f.PathToLabeled(end, labels, nil), dist[end], nil } // DAGOptimalPaths finds either longest or shortest distance paths in a @@ -712,11 +581,13 @@ func (g LabeledDirected) dagPath(start, end NI, w WeightFunc, longest bool) ([]N // is a valid node number, the method returns as soon as the optimal path // to end is found. If end is -1, all optimal paths from start are found. // -// Paths and path distances are encoded in the returned FromList and dist -// slice. The number of nodes reached is returned as nReached. -func (g LabeledDirected) DAGOptimalPaths(start, end NI, ordering []NI, w WeightFunc, longest bool) (f FromList, dist []float64, nReached int) { +// Paths and path distances are encoded in the returned FromList, labels, +// and dist slices. The number of nodes reached is returned as nReached. +func (g LabeledDirected) DAGOptimalPaths(start, end NI, ordering []NI, w WeightFunc, longest bool) (f FromList, labels []LI, dist []float64, nReached int) { a := g.LabeledAdjacencyList f = NewFromList(len(a)) + f.Leaves = bits.New(len(a)) + labels = make([]LI, len(a)) dist = make([]float64, len(a)) if ordering == nil { ordering, _ = g.Topological() @@ -739,14 +610,14 @@ func (g LabeledDirected) DAGOptimalPaths(start, end NI, ordering []NI, w WeightF p[start] = PathEnd{From: -1, Len: 1} f.MaxLen = 1 leaves := &f.Leaves - leaves.SetBit(start, 1) + leaves.SetBit(int(start), 1) nReached = 1 for n := start; n != end; n = ordering[o] { if p[n].Len > 0 && len(a[n]) > 0 { nDist := dist[n] candLen := p[n].Len + 1 // len for any candidate arc followed from n for _, to := range a[n] { - leaves.SetBit(to.To, 1) + leaves.SetBit(int(to.To), 1) candDist := nDist + w(to.Label) switch { case p[to.To].Len == 0: // first path to node to.To @@ -758,11 +629,12 @@ func (g LabeledDirected) DAGOptimalPaths(start, end NI, ordering []NI, w WeightF } dist[to.To] = candDist p[to.To] = PathEnd{From: n, Len: candLen} + labels[to.To] = to.Label if candLen > f.MaxLen { f.MaxLen = candLen } } - leaves.SetBit(n, 0) + leaves.SetBit(int(n), 0) } o++ if o == len(ordering) { @@ -781,12 +653,17 @@ func (g LabeledDirected) DAGOptimalPaths(start, end NI, ordering []NI, w WeightF // As usual for Dijkstra's algorithm, arc weights must be non-negative. // Graphs may be directed or undirected. Loops and parallel arcs are // allowed. -func (g LabeledAdjacencyList) Dijkstra(start, end NI, w WeightFunc) (f FromList, dist []float64, reached int) { +// +// Paths and path distances are encoded in the returned FromList and dist +// slice. Returned labels are the labels of arcs followed to each node. +// The number of nodes reached is returned as nReached. +func (g LabeledAdjacencyList) Dijkstra(start, end NI, w WeightFunc) (f FromList, labels []LI, dist []float64, nReached int) { r := make([]tentResult, len(g)) for i := range r { r[i].nx = NI(i) } f = NewFromList(len(g)) + labels = make([]LI, len(g)) dist = make([]float64, len(g)) current := start rp := f.Paths @@ -822,6 +699,7 @@ func (g LabeledAdjacencyList) Dijkstra(start, end NI, w WeightFunc) (f FromList, hr.dist = dist rp[nb.To].Len = nextLen rp[nb.To].From = current + labels[nb.To] = nb.Label if visited { heap.Fix(&t, hr.fx) } else { @@ -830,7 +708,8 @@ func (g LabeledAdjacencyList) Dijkstra(start, end NI, w WeightFunc) (f FromList, } //d.ndVis++ if len(t) == 0 { - return f, dist, nDone // no more reachable nodes. AllPaths normal return + // no more reachable nodes. AllPaths normal return + return f, labels, dist, nDone } // new current is node with smallest tentative distance cr = heap.Pop(&t).(*tentResult) @@ -840,15 +719,16 @@ func (g LabeledAdjacencyList) Dijkstra(start, end NI, w WeightFunc) (f FromList, dist[current] = cr.dist // store final distance } // normal return for single shortest path search - return f, dist, -1 + return f, labels, dist, -1 } // DijkstraPath finds a single shortest path. // -// Returned is the path and distance as returned by FromList.PathTo. -func (g LabeledAdjacencyList) DijkstraPath(start, end NI, w WeightFunc) ([]NI, float64) { - f, dist, _ := g.Dijkstra(start, end, w) - return f.PathTo(end, nil), dist[end] +// Returned is the path as returned by FromList.LabeledPathTo and the total +// path distance. +func (g LabeledAdjacencyList) DijkstraPath(start, end NI, w WeightFunc) (LabeledPath, float64) { + f, labels, dist, _ := g.Dijkstra(start, end, w) + return f.PathToLabeled(end, labels, nil), dist[end] } // tent implements container/heap diff --git a/vendor/github.com/soniakeys/graph/travis.sh b/vendor/github.com/soniakeys/graph/travis.sh deleted file mode 100644 index 5a8030ac..00000000 --- a/vendor/github.com/soniakeys/graph/travis.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -ex -go test ./... -if [ "$TRAVIS_GO_VERSION" = "1.6" ]; then - GOARCH=386 go test ./... - go tool vet -example . - go get github.com/client9/misspell/cmd/misspell - go get github.com/soniakeys/vetc - misspell -error * */* */*/* - vetc -fi diff --git a/vendor/github.com/soniakeys/graph/undir.go b/vendor/github.com/soniakeys/graph/undir.go index 75a7f248..21ef7b59 100644 --- a/vendor/github.com/soniakeys/graph/undir.go +++ b/vendor/github.com/soniakeys/graph/undir.go @@ -6,7 +6,11 @@ package graph // undir.go has methods specific to undirected graphs, Undirected and // LabeledUndirected. -import "errors" +import ( + "fmt" + + "github.com/soniakeys/bits" +) // AddEdge adds an edge to a graph. // @@ -18,6 +22,10 @@ import "errors" // The pointer receiver allows the method to expand the graph as needed // to include the values n1 and n2. If n1 or n2 happen to be greater than // len(*p) the method does not panic, but simply expands the graph. +// +// If you know or can compute the final graph order however, consider +// preallocating to avoid any overhead of expanding the graph. +// See second example, "More". func (p *Undirected) AddEdge(n1, n2 NI) { // Similar code in LabeledAdjacencyList.AddEdge. @@ -41,34 +49,238 @@ func (p *Undirected) AddEdge(n1, n2 NI) { } } -// EulerianCycleD for undirected graphs is a bit of an experiment. -// -// It is about the same as the directed version, but modified for an undirected -// multigraph. -// -// Parameter m in this case must be the size of the undirected graph -- the -// number of edges. Use Undirected.Size if the size is unknown. -// -// It works, but contains an extra loop that I think spoils the time -// complexity. Probably still pretty fast in practice, but a different -// graph representation might be better. -func (g Undirected) EulerianCycleD(m int) ([]NI, error) { - if len(g.AdjacencyList) == 0 { - return nil, nil - } - e := newEulerian(g.AdjacencyList, m) - for e.s >= 0 { - v := e.top() - e.pushUndir() // call modified method - if e.top() != v { - return nil, errors.New("not balanced") +// RemoveEdge removes a single edge between nodes n1 and n2. +// +// It removes reciprocal arcs in the case of distinct n1 and n2 or removes +// a single arc loop in the case of n1 == n2. +// +// Returns true if the specified edge is found and successfully removed, +// false if the edge does not exist. +func (g Undirected) RemoveEdge(n1, n2 NI) (ok bool) { + ok, x1, x2 := g.HasEdge(n1, n2) + if !ok { + return + } + a := g.AdjacencyList + to := a[n1] + last := len(to) - 1 + to[x1] = to[last] + a[n1] = to[:last] + if n1 == n2 { + return + } + to = a[n2] + last = len(to) - 1 + to[x2] = to[last] + a[n2] = to[:last] + return +} + +// ArcDensity returns density for a simple directed graph. +// +// Parameter n is order, or number of nodes of a simple directed graph. +// Parameter a is the arc size, or number of directed arcs. +// +// Returned density is the fraction `a` over the total possible number of arcs +// or a / (n * (n-1)). +// +// See also Density for density of a simple undirected graph. +// +// See also the corresponding methods AdjacencyList.ArcDensity and +// LabeledAdjacencyList.ArcDensity. +func ArcDensity(n, a int) float64 { + return float64(a) / (float64(n) * float64(n-1)) +} + +// Density returns density for a simple undirected graph. +// +// Parameter n is order, or number of nodes of a simple undirected graph. +// Parameter m is the size, or number of undirected edges. +// +// Returned density is the fraction m over the total possible number of edges +// or m / ((n * (n-1))/2). +// +// See also ArcDensity for simple directed graphs. +// +// See also the corresponding methods AdjacencyList.Density and +// LabeledAdjacencyList.Density. +func Density(n, m int) float64 { + return float64(m) * 2 / (float64(n) * float64(n-1)) +} + +// An EdgeVisitor is an argument to some traversal methods. +// +// Traversal methods call the visitor function for each edge visited. +// Argument e is the edge being visited. +type EdgeVisitor func(e Edge) + +// Edges iterates over the edges of an undirected graph. +// +// Edge visitor v is called for each edge of the graph. That is, it is called +// once for each reciprocal arc pair and once for each loop. +// +// See also LabeledUndirected.Edges for a labeled version. +// See also Undirected.SimpleEdges for a version that emits only the simple +// subgraph. +func (g Undirected) Edges(v EdgeVisitor) { + a := g.AdjacencyList + unpaired := make(AdjacencyList, len(a)) + for fr, to := range a { + arc: // for each arc in a + for _, to := range to { + if to == NI(fr) { + v(Edge{NI(fr), to}) // output loop + continue + } + // search unpaired arcs + ut := unpaired[to] + for i, u := range ut { + if u == NI(fr) { // found reciprocal + v(Edge{u, to}) // output edge + last := len(ut) - 1 + ut[i] = ut[last] + unpaired[to] = ut[:last] + continue arc + } + } + // reciprocal not found + unpaired[fr] = append(unpaired[fr], to) + } + } + // undefined behavior is that unpaired arcs are silently ignored. +} + +// FromList builds a forest with a tree spanning each connected component. +// +// For each component a root is chosen and spanning is done with the method +// Undirected.SpanTree, and so is breadth-first. Returned is a FromList with +// all spanned trees, a list of roots chosen, and a bool indicating if the +// receiver graph g was found to be a simple graph connected as a forest. +// Any cycles, loops, or parallel edges in any component will cause +// simpleForest to be false, but FromList f will still be populated with +// a valid and complete spanning forest. +func (g Undirected) FromList() (f FromList, roots []NI, simpleForest bool) { + p := make([]PathEnd, g.Order()) + for i := range p { + p[i].From = -1 + } + f.Paths = p + simpleForest = true + ts := 0 + for n := range g.AdjacencyList { + if p[n].From >= 0 { + continue } - e.keep() + roots = append(roots, NI(n)) + ns, st := g.SpanTree(NI(n), &f) + if !st { + simpleForest = false + } + ts += ns + if ts == len(p) { + break + } + } + return +} + +// HasEdge returns true if g has any edge between nodes n1 and n2. +// +// Also returned are indexes x1 and x2 such that g[n1][x1] == n2 +// and g[n2][x2] == n1. If no edge between n1 and n2 is present HasArc +// returns `has` == false. +// +// See also HasArc. If you are interested only in the boolean result and +// g is a well formed (passes IsUndirected) then HasArc is an adequate test. +func (g Undirected) HasEdge(n1, n2 NI) (has bool, x1, x2 int) { + if has, x1 = g.HasArc(n1, n2); !has { + return has, x1, x1 } - if !e.uv.Zero() { - return nil, errors.New("not strongly connected") + has, x2 = g.HasArc(n2, n1) + return +} + +// SimpleEdges iterates over the edges of the simple subgraph of an undirected +// graph. +// +// Edge visitor v is called for each pair of distinct nodes that is connected +// with an edge. That is, loops are ignored and parallel edges are reduced to +// a single edge. +// +// See also Undirected.Edges for a version that emits all edges. +func (g Undirected) SimpleEdges(v EdgeVisitor) { + for fr, to := range g.AdjacencyList { + e := bits.New(len(g.AdjacencyList)) + for _, to := range to { + if to > NI(fr) && e.Bit(int(to)) == 0 { + e.SetBit(int(to), 1) + v(Edge{NI(fr), to}) + } + } } - return e.p, nil + // undefined behavior is that unpaired arcs may or may not be emitted. +} + +// SpanTree builds a tree spanning a connected component. +// +// The component is spanned by breadth-first search from the given root. +// The resulting spanning tree in stored a FromList. +// +// If FromList.Paths is not the same length as g, it is allocated and +// initialized. This allows a zero value FromList to be passed as f. +// If FromList.Paths is the same length as g, it is used as is and is not +// reinitialized. This allows multiple trees to be spanned in the same +// FromList with successive calls. +// +// For nodes spanned, the Path member of the returned FromList is populated +// with both From and Len values. The MaxLen member will be updated but +// not Leaves. +// +// Returned is the number of nodes spanned, which will be the number of nodes +// in the component, and a bool indicating if the component was found to be a +// simply connected unrooted tree in the receiver graph g. Any cycles, loops, +// or parallel edges in the component will cause simpleTree to be false, but +// FromList f will still be populated with a valid and complete spanning tree. +func (g Undirected) SpanTree(root NI, f *FromList) (nSpanned int, simpleTree bool) { + a := g.AdjacencyList + p := f.Paths + if len(p) != len(a) { + p = make([]PathEnd, len(a)) + for i := range p { + p[i].From = -1 + } + f.Paths = p + } + simpleTree = true + p[root] = PathEnd{From: -1, Len: 1} + type arc struct { + from NI + half NI + } + var next []arc + frontier := []arc{{-1, root}} + for len(frontier) > 0 { + for _, fa := range frontier { // fa frontier arc + nSpanned++ + l := p[fa.half].Len + 1 + for _, to := range a[fa.half] { + if to == fa.from { + continue + } + if p[to].Len > 0 { + simpleTree = false + continue + } + p[to] = PathEnd{From: fa.half, Len: l} + if l > f.MaxLen { + f.MaxLen = l + } + next = append(next, arc{fa.half, to}) + } + } + frontier, next = next, frontier[:0] + } + return } // TarjanBiconnectedComponents decomposes a graph into maximal biconnected @@ -88,8 +300,9 @@ func (g Undirected) TarjanBiconnectedComponents(emit func([]Edge) bool) { // Note Tarjan's "adjacency structure" is graph.AdjacencyList, // His "adjacency list" is an element of a graph.AdjacencyList, also // termed a "to-list", "neighbor list", or "child list." - number := make([]int, len(g.AdjacencyList)) - lowpt := make([]int, len(g.AdjacencyList)) + a := g.AdjacencyList + number := make([]int, len(a)) + lowpt := make([]int, len(a)) var stack []Edge var i int var biconnect func(NI, NI) bool @@ -97,7 +310,7 @@ func (g Undirected) TarjanBiconnectedComponents(emit func([]Edge) bool) { i++ number[v] = i lowpt[v] = i - for _, w := range g.AdjacencyList[v] { + for _, w := range a[v] { if number[w] == 0 { stack = append(stack, Edge{v, w}) if !biconnect(w, v) { @@ -130,92 +343,82 @@ func (g Undirected) TarjanBiconnectedComponents(emit func([]Edge) bool) { } return true } - for w := range g.AdjacencyList { - if number[w] == 0 && !biconnect(NI(w), 0) { + for w := range a { + if number[w] == 0 && !biconnect(NI(w), -1) { return } } } -/* half-baked. Read the 72 paper. Maybe revisit at some point. -type BiconnectedComponents struct { - Graph AdjacencyList - Start int - Cuts big.Int // bitmap of node cuts - From []int // from-tree - Leaves []int // leaves of from-tree -} - -func NewBiconnectedComponents(g Undirected) *BiconnectedComponents { - return &BiconnectedComponents{ - Graph: g, - From: make([]int, len(g)), - } -} - -func (b *BiconnectedComponents) Find(start int) { - g := b.Graph - depth := make([]int, len(g)) - low := make([]int, len(g)) - // reset from any previous run - b.Cuts.SetInt64(0) - bf := b.From - for n := range bf { - bf[n] = -1 - } - b.Leaves = b.Leaves[:0] - d := 1 // depth. d > 0 means visited - depth[start] = d - low[start] = d - d++ - var df func(int, int) - df = func(from, n int) { - bf[n] = from - depth[n] = d - dn := d - l := d - d++ - cut := false - leaf := true - for _, nb := range g[n] { - if depth[nb] == 0 { - leaf = false - df(n, nb) - if low[nb] < l { - l = low[nb] +func (g Undirected) BlockCut(block func([]Edge) bool, cut func(NI) bool, isolated func(NI) bool) { + a := g.AdjacencyList + number := make([]int, len(a)) + lowpt := make([]int, len(a)) + var stack []Edge + var i, rc int + var biconnect func(NI, NI) bool + biconnect = func(v, u NI) bool { + i++ + number[v] = i + lowpt[v] = i + for _, w := range a[v] { + if number[w] == 0 { + if u < 0 { + rc++ } - if low[nb] >= dn { - cut = true + stack = append(stack, Edge{v, w}) + if !biconnect(w, v) { + return false + } + if lowpt[w] < lowpt[v] { + lowpt[v] = lowpt[w] + } + if lowpt[w] >= number[v] { + if u >= 0 && !cut(v) { + return false + } + var bcc []Edge + top := len(stack) - 1 + for number[stack[top].N1] >= number[w] { + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + } + bcc = append(bcc, stack[top]) + stack = stack[:top] + top-- + if !block(bcc) { + return false + } + } + } else if number[w] < number[v] && w != u { + stack = append(stack, Edge{v, w}) + if number[w] < lowpt[v] { + lowpt[v] = number[w] } - } else if nb != from && depth[nb] < l { - l = depth[nb] } } - low[n] = l - if cut { - b.Cuts.SetBit(&b.Cuts, n, 1) - } - if leaf { - b.Leaves = append(b.Leaves, n) + if u < 0 && rc > 1 { + return cut(v) } - d-- - } - nbs := g[start] - if len(nbs) == 0 { - return + return true } - df(start, nbs[0]) - var rc uint - for _, nb := range nbs[1:] { - if depth[nb] == 0 { - rc = 1 - df(start, nb) + for w := range a { + if number[w] > 0 { + continue + } + if len(a[w]) == 0 { + if !isolated(NI(w)) { + return + } + continue + } + rc = 0 + if !biconnect(NI(w), -1) { + return } } - b.Cuts.SetBit(&b.Cuts, start, rc) - return } -*/ // AddEdge adds an edge to a labeled graph. // @@ -252,6 +455,247 @@ func (p *LabeledUndirected) AddEdge(e Edge, l LI) { } } +// A LabeledEdgeVisitor is an argument to some traversal methods. +// +// Traversal methods call the visitor function for each edge visited. +// Argument e is the edge being visited. +type LabeledEdgeVisitor func(e LabeledEdge) + +// Edges iterates over the edges of a labeled undirected graph. +// +// Edge visitor v is called for each edge of the graph. That is, it is called +// once for each reciprocal arc pair and once for each loop. +// +// See also Undirected.Edges for an unlabeled version. +// See also the more simplistic LabeledAdjacencyList.ArcsAsEdges. +func (g LabeledUndirected) Edges(v LabeledEdgeVisitor) { + // similar code in LabeledAdjacencyList.InUndirected + a := g.LabeledAdjacencyList + unpaired := make(LabeledAdjacencyList, len(a)) + for fr, to := range a { + arc: // for each arc in a + for _, to := range to { + if to.To == NI(fr) { + v(LabeledEdge{Edge{NI(fr), to.To}, to.Label}) // output loop + continue + } + // search unpaired arcs + ut := unpaired[to.To] + for i, u := range ut { + if u.To == NI(fr) && u.Label == to.Label { // found reciprocal + v(LabeledEdge{Edge{NI(fr), to.To}, to.Label}) // output edge + last := len(ut) - 1 + ut[i] = ut[last] + unpaired[to.To] = ut[:last] + continue arc + } + } + // reciprocal not found + unpaired[fr] = append(unpaired[fr], to) + } + } +} + +// FromList builds a forest with a tree spanning each connected component in g. +// +// A root is chosen and spanning is done with the LabeledUndirected.SpanTree +// method, and so is breadth-first. Returned is a FromList with all spanned +// trees, labels corresponding to arcs in f, +// a list of roots chosen, and a bool indicating if the receiver graph g was +// found to be a simple graph connected as a forest. Any cycles, loops, or +// parallel edges in any component will cause simpleForest to be false, but +// FromList f will still be populated with a valid and complete spanning forest. + +// FromList builds a forest with a tree spanning each connected component. +// +// For each component a root is chosen and spanning is done with the method +// Undirected.SpanTree, and so is breadth-first. Returned is a FromList with +// all spanned trees, labels corresponding to arcs in f, a list of roots +// chosen, and a bool indicating if the receiver graph g was found to be a +// simple graph connected as a forest. Any cycles, loops, or parallel edges +// in any component will cause simpleForest to be false, but FromList f will +// still be populated with a valid and complete spanning forest. +func (g LabeledUndirected) FromList() (f FromList, labels []LI, roots []NI, simpleForest bool) { + p := make([]PathEnd, g.Order()) + for i := range p { + p[i].From = -1 + } + f.Paths = p + labels = make([]LI, len(p)) + simpleForest = true + ts := 0 + for n := range g.LabeledAdjacencyList { + if p[n].From >= 0 { + continue + } + roots = append(roots, NI(n)) + ns, st := g.SpanTree(NI(n), &f, labels) + if !st { + simpleForest = false + } + ts += ns + if ts == len(p) { + break + } + } + return +} + +// SpanTree builds a tree spanning a connected component. +// +// The component is spanned by breadth-first search from the given root. +// The resulting spanning tree in stored a FromList, and arc labels optionally +// stored in a slice. +// +// If FromList.Paths is not the same length as g, it is allocated and +// initialized. This allows a zero value FromList to be passed as f. +// If FromList.Paths is the same length as g, it is used as is and is not +// reinitialized. This allows multiple trees to be spanned in the same +// FromList with successive calls. +// +// For nodes spanned, the Path member of returned FromList f is populated +// populated with both From and Len values. The MaxLen member will be +// updated but not Leaves. +// +// The labels slice will be populated only if it is same length as g. +// Nil can be passed for example if labels are not needed. +// +// Returned is the number of nodes spanned, which will be the number of nodes +// in the component, and a bool indicating if the component was found to be a +// simply connected unrooted tree in the receiver graph g. Any cycles, loops, +// or parallel edges in the component will cause simpleTree to be false, but +// FromList f will still be populated with a valid and complete spanning tree. +func (g LabeledUndirected) SpanTree(root NI, f *FromList, labels []LI) (nSpanned int, simple bool) { + a := g.LabeledAdjacencyList + p := f.Paths + if len(p) != len(a) { + p = make([]PathEnd, len(a)) + for i := range p { + p[i].From = -1 + } + f.Paths = p + } + simple = true + p[root].Len = 1 + type arc struct { + from NI + half Half + } + var next []arc + frontier := []arc{{-1, Half{root, -1}}} + for len(frontier) > 0 { + for _, fa := range frontier { // fa frontier arc + nSpanned++ + l := p[fa.half.To].Len + 1 + for _, to := range a[fa.half.To] { + if to.To == fa.from && to.Label == fa.half.Label { + continue + } + if p[to.To].Len > 0 { + simple = false + continue + } + p[to.To] = PathEnd{From: fa.half.To, Len: l} + if len(labels) == len(p) { + labels[to.To] = to.Label + } + if l > f.MaxLen { + f.MaxLen = l + } + next = append(next, arc{fa.half.To, to}) + } + } + frontier, next = next, frontier[:0] + } + return +} + +// HasEdge returns true if g has any edge between nodes n1 and n2. +// +// Also returned are indexes x1 and x2 such that g[n1][x1] == Half{n2, l} +// and g[n2][x2] == {n1, l} for some label l. If no edge between n1 and n2 +// exists, HasArc returns `has` == false. +// +// See also HasArc. If you are only interested in the boolean result then +// HasArc is an adequate test. +func (g LabeledUndirected) HasEdge(n1, n2 NI) (has bool, x1, x2 int) { + if has, x1 = g.HasArc(n1, n2); !has { + return has, x1, x1 + } + has, x2 = g.HasArcLabel(n2, n1, g.LabeledAdjacencyList[n1][x1].Label) + return +} + +// HasEdgeLabel returns true if g has any edge between nodes n1 and n2 with +// label l. +// +// Also returned are indexes x1 and x2 such that g[n1][x1] == Half{n2, l} +// and g[n2][x2] == Half{n1, l}. If no edge between n1 and n2 with label l +// is present HasArc returns `has` == false. +func (g LabeledUndirected) HasEdgeLabel(n1, n2 NI, l LI) (has bool, x1, x2 int) { + if has, x1 = g.HasArcLabel(n1, n2, l); !has { + return has, x1, x1 + } + has, x2 = g.HasArcLabel(n2, n1, l) + return +} + +// RemoveEdge removes a single edge between nodes n1 and n2. +// +// It removes reciprocal arcs in the case of distinct n1 and n2 or removes +// a single arc loop in the case of n1 == n2. +// +// If the specified edge is found and successfully removed, RemoveEdge returns +// true and the label of the edge removed. If no edge exists between n1 and n2, +// RemoveEdge returns false, 0. +func (g LabeledUndirected) RemoveEdge(n1, n2 NI) (ok bool, label LI) { + ok, x1, x2 := g.HasEdge(n1, n2) + if !ok { + return + } + a := g.LabeledAdjacencyList + to := a[n1] + label = to[x1].Label // return value + last := len(to) - 1 + to[x1] = to[last] + a[n1] = to[:last] + if n1 == n2 { + return + } + to = a[n2] + last = len(to) - 1 + to[x2] = to[last] + a[n2] = to[:last] + return +} + +// RemoveEdgeLabel removes a single edge between nodes n1 and n2 with label l. +// +// It removes reciprocal arcs in the case of distinct n1 and n2 or removes +// a single arc loop in the case of n1 == n2. +// +// Returns true if the specified edge is found and successfully removed, +// false if the edge does not exist. +func (g LabeledUndirected) RemoveEdgeLabel(n1, n2 NI, l LI) (ok bool) { + ok, x1, x2 := g.HasEdgeLabel(n1, n2, l) + if !ok { + return + } + a := g.LabeledAdjacencyList + to := a[n1] + last := len(to) - 1 + to[x1] = to[last] + a[n1] = to[:last] + if n1 == n2 { + return + } + to = a[n2] + last = len(to) - 1 + to[x2] = to[last] + a[n2] = to[:last] + return +} + // TarjanBiconnectedComponents decomposes a graph into maximal biconnected // components, components for which if any node were removed the component // would remain connected. @@ -262,17 +706,9 @@ func (p *LabeledUndirected) AddEdge(e Edge, l LI) { // // See also the eqivalent unlabeled TarjanBiconnectedComponents. func (g LabeledUndirected) TarjanBiconnectedComponents(emit func([]LabeledEdge) bool) { - // Implemented closely to pseudocode in "Depth-first search and linear - // graph algorithms", Robert Tarjan, SIAM J. Comput. Vol. 1, No. 2, - // June 1972. - // - // Note Tarjan's "adjacency structure" is graph.AdjacencyList, - // His "adjacency list" is an element of a graph.AdjacencyList, also - // termed a "to-list", "neighbor list", or "child list." - // - // Nearly identical code in undir.go. - number := make([]int, len(g.LabeledAdjacencyList)) - lowpt := make([]int, len(g.LabeledAdjacencyList)) + // Code nearly identical to unlabled version. + number := make([]int, g.Order()) + lowpt := make([]int, g.Order()) var stack []LabeledEdge var i int var biconnect func(NI, NI) bool @@ -314,8 +750,68 @@ func (g LabeledUndirected) TarjanBiconnectedComponents(emit func([]LabeledEdge) return true } for w := range g.LabeledAdjacencyList { - if number[w] == 0 && !biconnect(NI(w), 0) { + if number[w] == 0 && !biconnect(NI(w), -1) { return } } } + +func (e *eulerian) pushUndir() error { + for u := e.top(); ; { + e.uv.SetBit(int(u), 0) + arcs := e.g[u] + if len(arcs) == 0 { + return nil + } + w := arcs[0] + e.s++ + e.p[e.s] = w + e.g[u] = arcs[1:] // consume arc + // difference from directed counterpart in dir.go: + // as long as it's not a loop, consume reciprocal arc as well + if w != u { + a2 := e.g[w] + for x, rx := range a2 { + if rx == u { // here it is + last := len(a2) - 1 + a2[x] = a2[last] // someone else gets the seat + e.g[w] = a2[:last] // and it's gone. + goto l + } + } + return fmt.Errorf("graph not undirected. %d -> %d reciprocal not found", u, w) + } + l: + u = w + } +} + +func (e *labEulerian) pushUndir() error { + for u := e.top(); ; { + e.uv.SetBit(int(u.To), 0) + arcs := e.g[u.To] + if len(arcs) == 0 { + return nil + } + w := arcs[0] + e.s++ + e.p[e.s] = w + e.g[u.To] = arcs[1:] // consume arc + // difference from directed counterpart in dir.go: + // as long as it's not a loop, consume reciprocal arc as well + if w.To != u.To { + a2 := e.g[w.To] + for x, rx := range a2 { + if rx.To == u.To && rx.Label == w.Label { // here it is + last := len(a2) - 1 + a2[x] = a2[last] // someone else can have the seat + e.g[w.To] = a2[:last] // and it's gone. + goto l + } + } + return fmt.Errorf("graph not undirected. %d -> %v reciprocal not found", u.To, w) + } + l: + u = w + } +} diff --git a/vendor/github.com/soniakeys/graph/undir_RO.go b/vendor/github.com/soniakeys/graph/undir_RO.go index fd8e3778..7707daf1 100644 --- a/vendor/github.com/soniakeys/graph/undir_RO.go +++ b/vendor/github.com/soniakeys/graph/undir_RO.go @@ -3,40 +3,97 @@ package graph +import ( + "errors" + "fmt" + + "github.com/soniakeys/bits" +) + // undir_RO.go is code generated from undir_cg.go by directives in graph.go. // Editing undir_cg.go is okay. It is the code generation source. // DO NOT EDIT undir_RO.go. // The RO means read only and it is upper case RO to slow you down a bit // in case you start to edit the file. +//------------------- + +// Bipartite constructs an object indexing the bipartite structure of a graph. +// +// In a bipartite component, nodes can be partitioned into two sets, or +// "colors," such that every edge in the component goes from one set to the +// other. +// +// If the graph is bipartite, the method constructs and returns a new +// Bipartite object as b and returns ok = true. +// +// If the component is not bipartite, a representative odd cycle as oc and +// returns ok = false. +// +// In the case of a graph with mulitiple connected components, this method +// provides no control over the color orientation by component. See +// Undirected.BipartiteComponent if this control is needed. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Bipartite() (b *Bipartite, oc []NI, ok bool) { + c1 := bits.New(g.Order()) + c2 := bits.New(g.Order()) + r, _, _ := g.ConnectedComponentReps() + // accumulate n2 number of zero bits in c2 as number of one bits in n1 + var n, n2 int + for _, r := range r { + ok, n, _, oc = g.BipartiteComponent(r, c1, c2) + if !ok { + return + } + n2 += n + } + return &Bipartite{g, c2, n2}, nil, true +} -// Bipartite determines if a connected component of an undirected graph -// is bipartite, a component where nodes can be partitioned into two sets -// such that every edge in the component goes from one set to the other. +// BipartiteComponent analyzes the bipartite structure of a connected component +// of an undirected graph. // -// Argument n can be any representative node of the component. +// In a bipartite component, nodes can be partitioned into two sets, or +// "colors," such that every edge in the component goes from one set to the +// other. // -// If the component is bipartite, Bipartite returns true and a two-coloring -// of the component. Each color set is returned as a bitmap. If the component -// is not bipartite, Bipartite returns false and a representative odd cycle. +// Argument n can be any representative node of the component to be analyzed. +// Arguments c1 and c2 must be separate bits.Bits objects constructed to be +// of length of the number of nodes of g. These bitmaps are used in the +// component traversal and the bits of the component must be zero when the +// method is called. +// +// If the component is bipartite, BipartiteComponent populates bitmaps +// c1 and c2 with the two-coloring of the component, always assigning the set +// with representative node n to bitmap c1. It returns b = true, +// and also returns the number of bits set in c1 and c2 as n1 and n2 +// respectively. +// +// If the component is not bipartite, BipartiteComponent returns b = false +// and a representative odd cycle as oc. +// +// See also method Bipartite. // // There are equivalent labeled and unlabeled versions of this method. -func (g Undirected) Bipartite(n NI) (b bool, c1, c2 Bits, oc []NI) { +func (g Undirected) BipartiteComponent(n NI, c1, c2 bits.Bits) (b bool, n1, n2 int, oc []NI) { + a := g.AdjacencyList b = true var open bool - var df func(n NI, c1, c2 *Bits) - df = func(n NI, c1, c2 *Bits) { - c1.SetBit(n, 1) - for _, nb := range g.AdjacencyList[n] { - if c1.Bit(nb) == 1 { + var df func(n NI, c1, c2 *bits.Bits, n1, n2 *int) + df = func(n NI, c1, c2 *bits.Bits, n1, n2 *int) { + c1.SetBit(int(n), 1) + *n1++ + for _, nb := range a[n] { + if c1.Bit(int(nb)) == 1 { b = false oc = []NI{nb, n} open = true return } - if c2.Bit(nb) == 1 { + if c2.Bit(int(nb)) == 1 { continue } - df(nb, c2, c1) + df(nb, c2, c1, n2, n1) if b { continue } @@ -50,11 +107,11 @@ func (g Undirected) Bipartite(n NI) (b bool, c1, c2 Bits, oc []NI) { return } } - df(n, &c1, &c2) + df(n, &c1, &c2, &n1, &n2) if b { - return b, c1, c2, nil + return b, n1, n2, nil } - return b, Bits{}, Bits{}, oc + return b, 0, 0, oc } // BronKerbosch1 finds maximal cliques in an undirected graph. @@ -74,44 +131,49 @@ func (g Undirected) Bipartite(n NI) (b bool, c1, c2 Bits, oc []NI) { // There are equivalent labeled and unlabeled versions of this method. // // See also more sophisticated variants BronKerbosch2 and BronKerbosch3. -func (g Undirected) BronKerbosch1(emit func([]NI) bool) { +func (g Undirected) BronKerbosch1(emit func(bits.Bits) bool) { a := g.AdjacencyList - var f func(R, P, X *Bits) bool - f = func(R, P, X *Bits) bool { + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { switch { - case !P.Zero(): - var r2, p2, x2 Bits - pf := func(n NI) bool { - r2.Set(*R) + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pf := func(n int) bool { + r2.Set(R) r2.SetBit(n, 1) - p2.Clear() - x2.Clear() + p2.ClearAll() + x2.ClearAll() for _, to := range a[n] { - if P.Bit(to) == 1 { - p2.SetBit(to, 1) + if P.Bit(int(to)) == 1 { + p2.SetBit(int(to), 1) } - if X.Bit(to) == 1 { - x2.SetBit(to, 1) + if X.Bit(int(to)) == 1 { + x2.SetBit(int(to), 1) } } - if !f(&r2, &p2, &x2) { + if !f(r2, p2, x2) { return false } P.SetBit(n, 0) X.SetBit(n, 1) return true } - if !P.Iterate(pf) { + if !P.IterateOnes(pf) { return false } - case X.Zero(): - return emit(R.Slice()) + case X.AllZeros(): + return emit(R) } return true } - var R, P, X Bits - P.SetAll(len(a)) - f(&R, &P, &X) + var R, P, X bits.Bits + R = bits.New(len(a)) + P = bits.New(len(a)) + X = bits.New(len(a)) + P.SetAll() + f(R, P, X) } // BKPivotMaxDegree is a strategy for BronKerbosch methods. @@ -124,20 +186,20 @@ func (g Undirected) BronKerbosch1(emit func([]NI) bool) { // in P. // // There are equivalent labeled and unlabeled versions of this method. -func (g Undirected) BKPivotMaxDegree(P, X *Bits) (p NI) { +func (g Undirected) BKPivotMaxDegree(P, X bits.Bits) (p NI) { // choose pivot u as highest degree node from P or X a := g.AdjacencyList maxDeg := -1 - P.Iterate(func(n NI) bool { // scan P + P.IterateOnes(func(n int) bool { // scan P if d := len(a[n]); d > maxDeg { - p = n + p = NI(n) maxDeg = d } return true }) - X.Iterate(func(n NI) bool { // scan X + X.IterateOnes(func(n int) bool { // scan X if d := len(a[n]); d > maxDeg { - p = n + p = NI(n) maxDeg = d } return true @@ -153,8 +215,8 @@ func (g Undirected) BKPivotMaxDegree(P, X *Bits) (p NI) { // The strategy is to simply pick the first node in P. // // There are equivalent labeled and unlabeled versions of this method. -func (g Undirected) BKPivotMinP(P, X *Bits) NI { - return P.From(0) +func (g Undirected) BKPivotMinP(P, X bits.Bits) NI { + return NI(P.OneFrom(0)) } // BronKerbosch2 finds maximal cliques in an undirected graph. @@ -179,50 +241,55 @@ func (g Undirected) BKPivotMinP(P, X *Bits) NI { // // See also simpler variant BronKerbosch1 and more sophisticated variant // BronKerbosch3. -func (g Undirected) BronKerbosch2(pivot func(P, X *Bits) NI, emit func([]NI) bool) { +func (g Undirected) BronKerbosch2(pivot func(P, X bits.Bits) NI, emit func(bits.Bits) bool) { a := g.AdjacencyList - var f func(R, P, X *Bits) bool - f = func(R, P, X *Bits) bool { + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { switch { - case !P.Zero(): - var r2, p2, x2, pnu Bits + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pnu := bits.New(len(a)) // compute P \ N(u). next 5 lines are only difference from BK1 - pnu.Set(*P) + pnu.Set(P) for _, to := range a[pivot(P, X)] { - pnu.SetBit(to, 0) + pnu.SetBit(int(to), 0) } // remaining code like BK1 - pf := func(n NI) bool { - r2.Set(*R) + pf := func(n int) bool { + r2.Set(R) r2.SetBit(n, 1) - p2.Clear() - x2.Clear() + p2.ClearAll() + x2.ClearAll() for _, to := range a[n] { - if P.Bit(to) == 1 { - p2.SetBit(to, 1) + if P.Bit(int(to)) == 1 { + p2.SetBit(int(to), 1) } - if X.Bit(to) == 1 { - x2.SetBit(to, 1) + if X.Bit(int(to)) == 1 { + x2.SetBit(int(to), 1) } } - if !f(&r2, &p2, &x2) { + if !f(r2, p2, x2) { return false } P.SetBit(n, 0) X.SetBit(n, 1) return true } - if !pnu.Iterate(pf) { + if !pnu.IterateOnes(pf) { return false } - case X.Zero(): - return emit(R.Slice()) + case X.AllZeros(): + return emit(R) } return true } - var R, P, X Bits - P.SetAll(len(a)) - f(&R, &P, &X) + R := bits.New(len(a)) + P := bits.New(len(a)) + X := bits.New(len(a)) + P.SetAll() + f(R, P, X) } // BronKerbosch3 finds maximal cliques in an undirected graph. @@ -246,150 +313,196 @@ func (g Undirected) BronKerbosch2(pivot func(P, X *Bits) NI, emit func([]NI) boo // There are equivalent labeled and unlabeled versions of this method. // // See also simpler variants BronKerbosch1 and BronKerbosch2. -func (g Undirected) BronKerbosch3(pivot func(P, X *Bits) NI, emit func([]NI) bool) { +func (g Undirected) BronKerbosch3(pivot func(P, X bits.Bits) NI, emit func(bits.Bits) bool) { a := g.AdjacencyList - var f func(R, P, X *Bits) bool - f = func(R, P, X *Bits) bool { + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { switch { - case !P.Zero(): - var r2, p2, x2, pnu Bits + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pnu := bits.New(len(a)) // compute P \ N(u). next lines are only difference from BK1 - pnu.Set(*P) + pnu.Set(P) for _, to := range a[pivot(P, X)] { - pnu.SetBit(to, 0) + pnu.SetBit(int(to), 0) } // remaining code like BK2 - pf := func(n NI) bool { - r2.Set(*R) + pf := func(n int) bool { + r2.Set(R) r2.SetBit(n, 1) - p2.Clear() - x2.Clear() + p2.ClearAll() + x2.ClearAll() for _, to := range a[n] { - if P.Bit(to) == 1 { - p2.SetBit(to, 1) + if P.Bit(int(to)) == 1 { + p2.SetBit(int(to), 1) } - if X.Bit(to) == 1 { - x2.SetBit(to, 1) + if X.Bit(int(to)) == 1 { + x2.SetBit(int(to), 1) } } - if !f(&r2, &p2, &x2) { + if !f(r2, p2, x2) { return false } P.SetBit(n, 0) X.SetBit(n, 1) return true } - if !pnu.Iterate(pf) { + if !pnu.IterateOnes(pf) { return false } - case X.Zero(): - return emit(R.Slice()) + case X.AllZeros(): + return emit(R) } return true } - var R, P, X Bits - P.SetAll(len(a)) + R := bits.New(len(a)) + P := bits.New(len(a)) + X := bits.New(len(a)) + P.SetAll() // code above same as BK2 // code below new to BK3 - _, ord, _ := g.Degeneracy() - var p2, x2 Bits + ord, _ := g.DegeneracyOrdering() + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) for _, n := range ord { - R.SetBit(n, 1) - p2.Clear() - x2.Clear() + R.SetBit(int(n), 1) + p2.ClearAll() + x2.ClearAll() for _, to := range a[n] { - if P.Bit(to) == 1 { - p2.SetBit(to, 1) + if P.Bit(int(to)) == 1 { + p2.SetBit(int(to), 1) } - if X.Bit(to) == 1 { - x2.SetBit(to, 1) + if X.Bit(int(to)) == 1 { + x2.SetBit(int(to), 1) } } - if !f(&R, &p2, &x2) { + if !f(R, p2, x2) { return } - R.SetBit(n, 0) - P.SetBit(n, 0) - X.SetBit(n, 1) + R.SetBit(int(n), 0) + P.SetBit(int(n), 0) + X.SetBit(int(n), 1) } } // ConnectedComponentBits returns a function that iterates over connected // components of g, returning a member bitmap for each. // -// Each call of the returned function returns the order (number of nodes) -// and bits of a connected component. The returned function returns zeros -// after returning all connected components. +// Each call of the returned function returns the order, arc size, +// and bits of a connected component. The underlying bits allocation is +// the same for each call and is overwritten on subsequent calls. Use or +// save the bits before calling the function again. The function returns +// zeros after returning all connected components. // // There are equivalent labeled and unlabeled versions of this method. // -// See also ConnectedComponentReps, which has lighter weight return values. -func (g Undirected) ConnectedComponentBits() func() (order int, bits Bits) { +// See also ConnectedComponentInts, ConnectedComponentReps, and +// ConnectedComponentReps. +func (g Undirected) ConnectedComponentBits() func() (order, arcSize int, bits bits.Bits) { a := g.AdjacencyList - var vg Bits // nodes visited in graph - var vc *Bits // nodes visited in current component - var nc int + vg := bits.New(len(a)) // nodes visited in graph + vc := bits.New(len(a)) // nodes visited in current component + var order, arcSize int var df func(NI) df = func(n NI) { - vg.SetBit(n, 1) - vc.SetBit(n, 1) - nc++ + vg.SetBit(int(n), 1) + vc.SetBit(int(n), 1) + order++ + arcSize += len(a[n]) for _, nb := range a[n] { - if vg.Bit(nb) == 0 { + if vg.Bit(int(nb)) == 0 { df(nb) } } return } - var n NI - return func() (o int, bits Bits) { - for ; n < NI(len(a)); n++ { + var n int + return func() (o, ma int, b bits.Bits) { + for ; n < len(a); n++ { if vg.Bit(n) == 0 { - vc = &bits - nc = 0 - df(n) - return nc, bits + vc.ClearAll() + order, arcSize = 0, 0 + df(NI(n)) + return order, arcSize, vc + } + } + return // return zeros signalling no more components + } +} + +// ConnectedComponenInts returns a list of component numbers (ints) for each +// node of graph g. +// +// The method assigns numbers to components 1-based, 1 through the number of +// components. Return value ci contains the component number for each node. +// Return value nc is the number of components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits, ConnectedComponentLists, and +// ConnectedComponentReps. +func (g Undirected) ConnectedComponentInts() (ci []int, nc int) { + a := g.AdjacencyList + ci = make([]int, len(a)) + var df func(NI) + df = func(nd NI) { + ci[nd] = nc + for _, to := range a[nd] { + if ci[to] == 0 { + df(to) } } return } + for nd := range a { + if ci[nd] == 0 { + nc++ + df(NI(nd)) + } + } + return } // ConnectedComponentLists returns a function that iterates over connected // components of g, returning the member list of each. // // Each call of the returned function returns a node list of a connected -// component. The returned function returns nil after returning all connected -// components. +// component and the arc size of the component. The returned function returns +// nil, 0 after returning all connected components. // // There are equivalent labeled and unlabeled versions of this method. // -// See also ConnectedComponentReps, which has lighter weight return values. -func (g Undirected) ConnectedComponentLists() func() []NI { +// See also ConnectedComponentBits, ConnectedComponentInts, and +// ConnectedComponentReps. +func (g Undirected) ConnectedComponentLists() func() (nodes []NI, arcSize int) { a := g.AdjacencyList - var vg Bits // nodes visited in graph - var m []NI // members of current component + vg := bits.New(len(a)) // nodes visited in graph + var l []NI // accumulated node list of current component + var ma int // accumulated arc size of current component var df func(NI) df = func(n NI) { - vg.SetBit(n, 1) - m = append(m, n) + vg.SetBit(int(n), 1) + l = append(l, n) + ma += len(a[n]) for _, nb := range a[n] { - if vg.Bit(nb) == 0 { + if vg.Bit(int(nb)) == 0 { df(nb) } } return } - var n NI - return func() []NI { - for ; n < NI(len(a)); n++ { + var n int + return func() ([]NI, int) { + for ; n < len(a); n++ { if vg.Bit(n) == 0 { - m = nil - df(n) - return m + l, ma = nil, 0 + df(NI(n)) + return l, ma } } - return nil + return nil, 0 } } @@ -397,8 +510,8 @@ func (g Undirected) ConnectedComponentLists() func() []NI { // component of g. // // Returned is a slice with a single representative node from each connected -// component and also a parallel slice with the order, or number of nodes, -// in the corresponding component. +// component and also parallel slices with the orders and arc sizes +// in the corresponding components. // // This is fairly minimal information describing connected components. // From a representative node, other nodes in the component can be reached @@ -409,27 +522,29 @@ func (g Undirected) ConnectedComponentLists() func() []NI { // See also ConnectedComponentBits and ConnectedComponentLists which can // collect component members in a single traversal, and IsConnected which // is an even simpler boolean test. -func (g Undirected) ConnectedComponentReps() (reps []NI, orders []int) { +func (g Undirected) ConnectedComponentReps() (reps []NI, orders, arcSizes []int) { a := g.AdjacencyList - var c Bits - var o int + c := bits.New(len(a)) + var o, ma int var df func(NI) df = func(n NI) { - c.SetBit(n, 1) + c.SetBit(int(n), 1) o++ + ma += len(a[n]) for _, nb := range a[n] { - if c.Bit(nb) == 0 { + if c.Bit(int(nb)) == 0 { df(nb) } } return } for n := range a { - if c.Bit(NI(n)) == 0 { - reps = append(reps, NI(n)) - o = 0 + if c.Bit(n) == 0 { + o, ma = 0, 0 df(NI(n)) + reps = append(reps, NI(n)) orders = append(orders, o) + arcSizes = append(arcSizes, ma) } } return @@ -444,16 +559,97 @@ func (g Undirected) Copy() (c Undirected, ma int) { return Undirected{l}, s } -// Degeneracy computes k-degeneracy, vertex ordering and k-cores. +// Degeneracy is a measure of dense subgraphs within a graph. // // See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) // +// See also method DegeneracyOrdering which returns a degeneracy node +// ordering and k-core breaks. +// // There are equivalent labeled and unlabeled versions of this method. -func (g Undirected) Degeneracy() (k int, ordering []NI, cores []int) { +func (g Undirected) Degeneracy() (k int) { + a := g.AdjacencyList + // WP algorithm, attributed to Matula and Beck. + L := bits.New(len(a)) + d := make([]int, len(a)) + var D [][]NI + for v, nb := range a { + dv := len(nb) + d[v] = dv + for len(D) <= dv { + D = append(D, nil) + } + D[dv] = append(D[dv], NI(v)) + } + for range a { + // find a non-empty D + i := 0 + for len(D[i]) == 0 { + i++ + } + // k is max(i, k) + if i > k { + k = i + } + // select from D[i] + Di := D[i] + last := len(Di) - 1 + v := Di[last] + // Add v to ordering, remove from Di + L.SetBit(int(v), 1) + D[i] = Di[:last] + // move neighbors + for _, nb := range a[v] { + if L.Bit(int(nb)) == 1 { + continue + } + dn := d[nb] // old number of neighbors of nb + Ddn := D[dn] // nb is in this list + // remove it from the list + for wx, w := range Ddn { + if w == nb { + last := len(Ddn) - 1 + Ddn[wx], Ddn[last] = Ddn[last], Ddn[wx] + D[dn] = Ddn[:last] + } + } + dn-- // new number of neighbors + d[nb] = dn + // re--add it to it's new list + D[dn] = append(D[dn], nb) + } + } + return +} + +// DegeneracyOrdering computes degeneracy node ordering and k-core breaks. +// +// See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) +// +// In return value ordering, nodes are ordered by their "coreness" as +// defined at https://en.wikipedia.org/wiki/Degeneracy_(graph_theory)#k-Cores. +// +// Return value kbreaks indexes ordering by coreness number. len(kbreaks) +// will be one more than the graph degeneracy as returned by the Degeneracy +// method. If degeneracy is d, d = len(kbreaks) - 1, kbreaks[d] is the last +// value in kbreaks and ordering[:kbreaks[d]] contains nodes of the d-cores +// of the graph. kbreaks[0] is always the number of nodes in g as all nodes +// are in in a 0-core. +// +// Note that definitions of "k-core" differ on whether a k-core must be a +// single connected component. This method does not resolve individual +// connected components. +// +// See also method Degeneracy which returns just the degeneracy number. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) DegeneracyOrdering() (ordering []NI, kbreaks []int) { a := g.AdjacencyList // WP algorithm + k := 0 ordering = make([]NI, len(a)) - var L Bits + kbreaks = []int{len(a)} + L := bits.New(len(a)) d := make([]int, len(a)) var D [][]NI for v, nb := range a { @@ -464,7 +660,7 @@ func (g Undirected) Degeneracy() (k int, ordering []NI, cores []int) { } D[dv] = append(D[dv], NI(v)) } - for ox := range a { + for ox := len(a) - 1; ox >= 0; ox-- { // find a non-empty D i := 0 for len(D[i]) == 0 { @@ -472,10 +668,9 @@ func (g Undirected) Degeneracy() (k int, ordering []NI, cores []int) { } // k is max(i, k) if i > k { - for len(cores) <= i { - cores = append(cores, 0) + for len(kbreaks) <= i { + kbreaks = append(kbreaks, ox+1) } - cores[k] = ox k = i } // select from D[i] @@ -484,11 +679,11 @@ func (g Undirected) Degeneracy() (k int, ordering []NI, cores []int) { v := Di[last] // Add v to ordering, remove from Di ordering[ox] = v - L.SetBit(v, 1) + L.SetBit(int(v), 1) D[i] = Di[:last] // move neighbors for _, nb := range a[v] { - if L.Bit(nb) == 1 { + if L.Bit(int(nb)) == 1 { continue } dn := d[nb] // old number of neighbors of nb @@ -507,7 +702,9 @@ func (g Undirected) Degeneracy() (k int, ordering []NI, cores []int) { D[dn] = append(D[dn], nb) } } - cores[k] = len(ordering) + //for i, j := 0, k; i < j; i, j = i+1, j-1 { + // kbreaks[i], kbreaks[j] = kbreaks[j], kbreaks[i] + //} return } @@ -531,57 +728,291 @@ func (g Undirected) Degree(n NI) int { return d } -// FromList constructs a FromList representing the tree reachable from -// the given root. +// DegreeCentralization returns the degree centralization metric of a graph. +// +// Degree of a node is one measure of node centrality and is directly +// available from the adjacency list representation. This allows degree +// centralization for the graph to be very efficiently computed. +// +// The value returned is from 0 to 1 inclusive for simple graphs of three or +// more nodes. As a special case, 0 is returned for graphs of two or fewer +// nodes. The value returned can be > 1 for graphs with loops or parallel +// edges. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) DegreeCentralization() float64 { + a := g.AdjacencyList + if len(a) <= 2 { + return 0 + } + var max, sum int + for _, to := range a { + if len(to) > max { + max = len(to) + } + sum += len(to) + } + return float64(len(a)*max-sum) / float64((len(a)-1)*(len(a)-2)) +} + +// Density returns density for a simple graph. // -// The connected component containing root should represent a simple graph, -// connected as a tree. +// See also Density function. // -// For nodes connected as a tree, the Path member of the returned FromList -// will be populated with both From and Len values. The MaxLen member will be -// set but Leaves will be left a zero value. Return value cycle will be -1. +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) Density() float64 { + return Density(g.Order(), g.Size()) +} + +// Eulerian scans an undirected graph to determine if it is Eulerian. +// +// If the graph represents an Eulerian cycle, it returns -1, -1, nil. // -// If the connected component containing root is not connected as a tree, -// a cycle will be detected. The returned FromList will be a zero value and -// return value cycle will be a node involved in the cycle. +// If the graph does not represent an Eulerian cycle but does represent an +// Eulerian path, it returns the two end nodes of the path, and nil. // -// Loops and parallel edges will be detected as cycles, however only in the -// connected component containing root. If g is not fully connected, nodes -// not reachable from root will have PathEnd values of {From: -1, Len: 0}. +// Otherwise it returns an error. +// +// See also method EulerianStart, which short-circuits as soon as it finds +// a node that must be a start or end node of an Eulerian path. // // There are equivalent labeled and unlabeled versions of this method. -func (g Undirected) FromList(root NI) (f FromList, cycle NI) { - p := make([]PathEnd, len(g.AdjacencyList)) - for i := range p { - p[i].From = -1 +func (g Undirected) Eulerian() (end1, end2 NI, err error) { + end1 = -1 + end2 = -1 + for n := range g.AdjacencyList { + switch { + case g.Degree(NI(n))%2 == 0: + case end1 < 0: + end1 = NI(n) + case end2 < 0: + end2 = NI(n) + default: + err = errors.New("non-Eulerian") + return + } } - ml := 0 - var df func(NI, NI) bool - df = func(fr, n NI) bool { - l := p[n].Len + 1 - for _, to := range g.AdjacencyList[n] { - if to == fr { - continue - } - if p[to].Len > 0 { - cycle = to - return false - } - p[to] = PathEnd{From: n, Len: l} - if l > ml { - ml = l - } - if !df(n, to) { - return false - } + return +} + +// EulerianCycle finds an Eulerian cycle in an undirected multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianCycle copies the entire graph g. +// See EulerianCycleD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianCycle() ([]NI, error) { + c, _ := g.Copy() + return c.EulerianCycleD(c.Size()) +} + +// EulerianCycleD finds an Eulerian cycle in an undirected multigraph. +// +// EulerianCycleD is destructive on its receiver g. See EulerianCycle for +// a non-destructive version. +// +// Parameter m must be the size of the undirected graph -- the +// number of edges. Use Undirected.Size if the size is unknown. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianCycleD(m int) ([]NI, error) { + if g.Order() == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, m) + e.p[0] = 0 + for e.s >= 0 { + v := e.top() + if err := e.pushUndir(); err != nil { + return nil, err } - return true + if e.top() != v { + return nil, errors.New("not Eulerian") + } + e.keep() } - p[root].Len = 1 - if !df(-1, root) { - return + if !e.uv.AllZeros() { + return nil, errors.New("not strongly connected") } - return FromList{Paths: p, MaxLen: ml}, -1 + return e.p, nil +} + +// EulerianPath finds an Eulerian path in an undirected multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianPath copies the entire graph g. +// See EulerianPathD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianPath() ([]NI, error) { + c, _ := g.Copy() + start := c.EulerianStart() + if start < 0 { + start = 0 + } + return c.EulerianPathD(c.Size(), start) +} + +// EulerianPathD finds an Eulerian path in a undirected multigraph. +// +// EulerianPathD is destructive on its receiver g. See EulerianPath for +// a non-destructive version. +// +// Argument m must be the correct size, or number of edges in g. +// Argument start must be a valid start node for the path. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path starting at start, result is an Eulerian path +// with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianPathD(m int, start NI) ([]NI, error) { + if g.Order() == 0 { + return nil, nil + } + e := newEulerian(g.AdjacencyList, m) + e.p[0] = start + // unlike EulerianCycle, the first path doesn't have to be a cycle. + if err := e.pushUndir(); err != nil { + return nil, err + } + e.keep() + for e.s >= 0 { + start = e.top() + e.push() + // paths after the first must be cycles though + // (as long as there are nodes on the stack) + if e.top() != start { + return nil, errors.New("no Eulerian path") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("no Eulerian path") + } + return e.p, nil +} + +// EulerianStart finds a candidate start node for an Eulerian path. +// +// A graph representing an Eulerian path can have two nodes with odd degree. +// If it does, these must be the end nodes of the path. EulerianEnd scans +// for a node with an odd degree, returning immediately with the first one +// it finds. +// +// If the scan completes without finding a node with odd degree the method +// returns -1. +// +// See also method Eulerian, which completely validates a graph as representing +// an Eulerian path. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g Undirected) EulerianStart() NI { + for n := range g.AdjacencyList { + if g.Degree(NI(n))%2 != 0 { + return NI(n) + } + } + return -1 +} + +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *UndirectedSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.Undirected.AdjacencyList + b = NI(len(a)) + s.Undirected.AdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *Undirected) InduceList(l []NI) *UndirectedSubgraph { + sub, sup := mapList(l) + return &UndirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + Undirected: Undirected{ + g.AdjacencyList.induceArcs(sub, sup), + }} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *Undirected) InduceBits(t bits.Bits) *UndirectedSubgraph { + sub, sup := mapBits(t) + return &UndirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + Undirected: Undirected{ + g.AdjacencyList.induceArcs(sub, sup), + }} } // IsConnected tests if an undirected graph is a single connected component. @@ -594,19 +1025,18 @@ func (g Undirected) IsConnected() bool { if len(a) == 0 { return true } - var b Bits - b.SetAll(len(a)) + b := bits.New(len(a)) var df func(NI) df = func(n NI) { - b.SetBit(n, 0) + b.SetBit(int(n), 1) for _, to := range a[n] { - if b.Bit(to) == 1 { + if b.Bit(int(to)) == 0 { df(to) } } } df(0) - return b.Zero() + return b.AllOnes() } // IsTree identifies trees in undirected graphs. @@ -618,14 +1048,14 @@ func (g Undirected) IsConnected() bool { // There are equivalent labeled and unlabeled versions of this method. func (g Undirected) IsTree(root NI) (isTree, allTree bool) { a := g.AdjacencyList - var v Bits - v.SetAll(len(a)) + v := bits.New(len(a)) + v.SetAll() var df func(NI, NI) bool df = func(fr, n NI) bool { - if v.Bit(n) == 0 { + if v.Bit(int(n)) == 0 { return false } - v.SetBit(n, 0) + v.SetBit(int(n), 0) for _, to := range a[n] { if to != fr && !df(n, to) { return false @@ -633,18 +1063,18 @@ func (g Undirected) IsTree(root NI) (isTree, allTree bool) { } return true } - v.SetBit(root, 0) + v.SetBit(int(root), 0) for _, to := range a[root] { if !df(root, to) { return false, false } } - return true, v.Zero() + return true, v.AllZeros() } // Size returns the number of edges in g. // -// See also ArcSize and HasLoop. +// See also ArcSize and AnyLoop. func (g Undirected) Size() int { m2 := 0 for fr, to := range g.AdjacencyList { @@ -657,3 +1087,52 @@ func (g Undirected) Size() int { } return m2 / 2 } + +// Density returns edge density of a bipartite graph. +// +// Edge density is number of edges over maximum possible number of edges. +// Maximum possible number of edges in a bipartite graph is number of +// nodes of one color times number of nodes of the other color. +func (g Bipartite) Density() float64 { + a := g.Undirected.AdjacencyList + s := 0 + g.Color.IterateOnes(func(n int) bool { + s += len(a[n]) + return true + }) + return float64(s) / float64(g.N0*(len(a)-g.N0)) +} + +// PermuteBiadjacency permutes a bipartite graph in place so that a prefix +// of the adjacency list encodes a biadjacency matrix. +// +// The permutation applied is returned. This would be helpful in referencing +// any externally stored node information. +// +// The biadjacency matrix is encoded as the prefix AdjacencyList[:g.N0]. +// Note though that this slice does not represent a valid complete +// AdjacencyList. BoundsOk would return false, for example. +// +// In adjacency list terms, the result of the permutation is that nodes of +// the prefix only have arcs to the suffix and nodes of the suffix only have +// arcs to the prefix. +func (g Bipartite) PermuteBiadjacency() []int { + p := make([]int, g.Order()) + i := 0 + g.Color.IterateZeros(func(n int) bool { + p[n] = i + i++ + return true + }) + g.Color.IterateOnes(func(n int) bool { + p[n] = i + i++ + return true + }) + g.Permute(p) + g.Color.ClearAll() + for i := g.N0; i < g.Order(); i++ { + g.Color.SetBit(i, 1) + } + return p +} diff --git a/vendor/github.com/soniakeys/graph/undir_cg.go b/vendor/github.com/soniakeys/graph/undir_cg.go index 35b5b97d..ed932241 100644 --- a/vendor/github.com/soniakeys/graph/undir_cg.go +++ b/vendor/github.com/soniakeys/graph/undir_cg.go @@ -3,40 +3,97 @@ package graph +import ( + "errors" + "fmt" + + "github.com/soniakeys/bits" +) + // undir_RO.go is code generated from undir_cg.go by directives in graph.go. // Editing undir_cg.go is okay. It is the code generation source. // DO NOT EDIT undir_RO.go. // The RO means read only and it is upper case RO to slow you down a bit // in case you start to edit the file. +//------------------- + +// Bipartite constructs an object indexing the bipartite structure of a graph. +// +// In a bipartite component, nodes can be partitioned into two sets, or +// "colors," such that every edge in the component goes from one set to the +// other. +// +// If the graph is bipartite, the method constructs and returns a new +// Bipartite object as b and returns ok = true. +// +// If the component is not bipartite, a representative odd cycle as oc and +// returns ok = false. +// +// In the case of a graph with mulitiple connected components, this method +// provides no control over the color orientation by component. See +// Undirected.BipartiteComponent if this control is needed. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Bipartite() (b *LabeledBipartite, oc []NI, ok bool) { + c1 := bits.New(g.Order()) + c2 := bits.New(g.Order()) + r, _, _ := g.ConnectedComponentReps() + // accumulate n2 number of zero bits in c2 as number of one bits in n1 + var n, n2 int + for _, r := range r { + ok, n, _, oc = g.BipartiteComponent(r, c1, c2) + if !ok { + return + } + n2 += n + } + return &LabeledBipartite{g, c2, n2}, nil, true +} -// Bipartite determines if a connected component of an undirected graph -// is bipartite, a component where nodes can be partitioned into two sets -// such that every edge in the component goes from one set to the other. +// BipartiteComponent analyzes the bipartite structure of a connected component +// of an undirected graph. // -// Argument n can be any representative node of the component. +// In a bipartite component, nodes can be partitioned into two sets, or +// "colors," such that every edge in the component goes from one set to the +// other. // -// If the component is bipartite, Bipartite returns true and a two-coloring -// of the component. Each color set is returned as a bitmap. If the component -// is not bipartite, Bipartite returns false and a representative odd cycle. +// Argument n can be any representative node of the component to be analyzed. +// Arguments c1 and c2 must be separate bits.Bits objects constructed to be +// of length of the number of nodes of g. These bitmaps are used in the +// component traversal and the bits of the component must be zero when the +// method is called. +// +// If the component is bipartite, BipartiteComponent populates bitmaps +// c1 and c2 with the two-coloring of the component, always assigning the set +// with representative node n to bitmap c1. It returns b = true, +// and also returns the number of bits set in c1 and c2 as n1 and n2 +// respectively. +// +// If the component is not bipartite, BipartiteComponent returns b = false +// and a representative odd cycle as oc. +// +// See also method Bipartite. // // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledUndirected) Bipartite(n NI) (b bool, c1, c2 Bits, oc []NI) { +func (g LabeledUndirected) BipartiteComponent(n NI, c1, c2 bits.Bits) (b bool, n1, n2 int, oc []NI) { + a := g.LabeledAdjacencyList b = true var open bool - var df func(n NI, c1, c2 *Bits) - df = func(n NI, c1, c2 *Bits) { - c1.SetBit(n, 1) - for _, nb := range g.LabeledAdjacencyList[n] { - if c1.Bit(nb.To) == 1 { + var df func(n NI, c1, c2 *bits.Bits, n1, n2 *int) + df = func(n NI, c1, c2 *bits.Bits, n1, n2 *int) { + c1.SetBit(int(n), 1) + *n1++ + for _, nb := range a[n] { + if c1.Bit(int(nb.To)) == 1 { b = false oc = []NI{nb.To, n} open = true return } - if c2.Bit(nb.To) == 1 { + if c2.Bit(int(nb.To)) == 1 { continue } - df(nb.To, c2, c1) + df(nb.To, c2, c1, n2, n1) if b { continue } @@ -50,11 +107,11 @@ func (g LabeledUndirected) Bipartite(n NI) (b bool, c1, c2 Bits, oc []NI) { return } } - df(n, &c1, &c2) + df(n, &c1, &c2, &n1, &n2) if b { - return b, c1, c2, nil + return b, n1, n2, nil } - return b, Bits{}, Bits{}, oc + return b, 0, 0, oc } // BronKerbosch1 finds maximal cliques in an undirected graph. @@ -74,44 +131,49 @@ func (g LabeledUndirected) Bipartite(n NI) (b bool, c1, c2 Bits, oc []NI) { // There are equivalent labeled and unlabeled versions of this method. // // See also more sophisticated variants BronKerbosch2 and BronKerbosch3. -func (g LabeledUndirected) BronKerbosch1(emit func([]NI) bool) { +func (g LabeledUndirected) BronKerbosch1(emit func(bits.Bits) bool) { a := g.LabeledAdjacencyList - var f func(R, P, X *Bits) bool - f = func(R, P, X *Bits) bool { + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { switch { - case !P.Zero(): - var r2, p2, x2 Bits - pf := func(n NI) bool { - r2.Set(*R) + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pf := func(n int) bool { + r2.Set(R) r2.SetBit(n, 1) - p2.Clear() - x2.Clear() + p2.ClearAll() + x2.ClearAll() for _, to := range a[n] { - if P.Bit(to.To) == 1 { - p2.SetBit(to.To, 1) + if P.Bit(int(to.To)) == 1 { + p2.SetBit(int(to.To), 1) } - if X.Bit(to.To) == 1 { - x2.SetBit(to.To, 1) + if X.Bit(int(to.To)) == 1 { + x2.SetBit(int(to.To), 1) } } - if !f(&r2, &p2, &x2) { + if !f(r2, p2, x2) { return false } P.SetBit(n, 0) X.SetBit(n, 1) return true } - if !P.Iterate(pf) { + if !P.IterateOnes(pf) { return false } - case X.Zero(): - return emit(R.Slice()) + case X.AllZeros(): + return emit(R) } return true } - var R, P, X Bits - P.SetAll(len(a)) - f(&R, &P, &X) + var R, P, X bits.Bits + R = bits.New(len(a)) + P = bits.New(len(a)) + X = bits.New(len(a)) + P.SetAll() + f(R, P, X) } // BKPivotMaxDegree is a strategy for BronKerbosch methods. @@ -124,20 +186,20 @@ func (g LabeledUndirected) BronKerbosch1(emit func([]NI) bool) { // in P. // // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledUndirected) BKPivotMaxDegree(P, X *Bits) (p NI) { +func (g LabeledUndirected) BKPivotMaxDegree(P, X bits.Bits) (p NI) { // choose pivot u as highest degree node from P or X a := g.LabeledAdjacencyList maxDeg := -1 - P.Iterate(func(n NI) bool { // scan P + P.IterateOnes(func(n int) bool { // scan P if d := len(a[n]); d > maxDeg { - p = n + p = NI(n) maxDeg = d } return true }) - X.Iterate(func(n NI) bool { // scan X + X.IterateOnes(func(n int) bool { // scan X if d := len(a[n]); d > maxDeg { - p = n + p = NI(n) maxDeg = d } return true @@ -153,8 +215,8 @@ func (g LabeledUndirected) BKPivotMaxDegree(P, X *Bits) (p NI) { // The strategy is to simply pick the first node in P. // // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledUndirected) BKPivotMinP(P, X *Bits) NI { - return P.From(0) +func (g LabeledUndirected) BKPivotMinP(P, X bits.Bits) NI { + return NI(P.OneFrom(0)) } // BronKerbosch2 finds maximal cliques in an undirected graph. @@ -179,50 +241,55 @@ func (g LabeledUndirected) BKPivotMinP(P, X *Bits) NI { // // See also simpler variant BronKerbosch1 and more sophisticated variant // BronKerbosch3. -func (g LabeledUndirected) BronKerbosch2(pivot func(P, X *Bits) NI, emit func([]NI) bool) { +func (g LabeledUndirected) BronKerbosch2(pivot func(P, X bits.Bits) NI, emit func(bits.Bits) bool) { a := g.LabeledAdjacencyList - var f func(R, P, X *Bits) bool - f = func(R, P, X *Bits) bool { + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { switch { - case !P.Zero(): - var r2, p2, x2, pnu Bits + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pnu := bits.New(len(a)) // compute P \ N(u). next 5 lines are only difference from BK1 - pnu.Set(*P) + pnu.Set(P) for _, to := range a[pivot(P, X)] { - pnu.SetBit(to.To, 0) + pnu.SetBit(int(to.To), 0) } // remaining code like BK1 - pf := func(n NI) bool { - r2.Set(*R) + pf := func(n int) bool { + r2.Set(R) r2.SetBit(n, 1) - p2.Clear() - x2.Clear() + p2.ClearAll() + x2.ClearAll() for _, to := range a[n] { - if P.Bit(to.To) == 1 { - p2.SetBit(to.To, 1) + if P.Bit(int(to.To)) == 1 { + p2.SetBit(int(to.To), 1) } - if X.Bit(to.To) == 1 { - x2.SetBit(to.To, 1) + if X.Bit(int(to.To)) == 1 { + x2.SetBit(int(to.To), 1) } } - if !f(&r2, &p2, &x2) { + if !f(r2, p2, x2) { return false } P.SetBit(n, 0) X.SetBit(n, 1) return true } - if !pnu.Iterate(pf) { + if !pnu.IterateOnes(pf) { return false } - case X.Zero(): - return emit(R.Slice()) + case X.AllZeros(): + return emit(R) } return true } - var R, P, X Bits - P.SetAll(len(a)) - f(&R, &P, &X) + R := bits.New(len(a)) + P := bits.New(len(a)) + X := bits.New(len(a)) + P.SetAll() + f(R, P, X) } // BronKerbosch3 finds maximal cliques in an undirected graph. @@ -246,150 +313,196 @@ func (g LabeledUndirected) BronKerbosch2(pivot func(P, X *Bits) NI, emit func([] // There are equivalent labeled and unlabeled versions of this method. // // See also simpler variants BronKerbosch1 and BronKerbosch2. -func (g LabeledUndirected) BronKerbosch3(pivot func(P, X *Bits) NI, emit func([]NI) bool) { +func (g LabeledUndirected) BronKerbosch3(pivot func(P, X bits.Bits) NI, emit func(bits.Bits) bool) { a := g.LabeledAdjacencyList - var f func(R, P, X *Bits) bool - f = func(R, P, X *Bits) bool { + var f func(R, P, X bits.Bits) bool + f = func(R, P, X bits.Bits) bool { switch { - case !P.Zero(): - var r2, p2, x2, pnu Bits + case !P.AllZeros(): + r2 := bits.New(len(a)) + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) + pnu := bits.New(len(a)) // compute P \ N(u). next lines are only difference from BK1 - pnu.Set(*P) + pnu.Set(P) for _, to := range a[pivot(P, X)] { - pnu.SetBit(to.To, 0) + pnu.SetBit(int(to.To), 0) } // remaining code like BK2 - pf := func(n NI) bool { - r2.Set(*R) + pf := func(n int) bool { + r2.Set(R) r2.SetBit(n, 1) - p2.Clear() - x2.Clear() + p2.ClearAll() + x2.ClearAll() for _, to := range a[n] { - if P.Bit(to.To) == 1 { - p2.SetBit(to.To, 1) + if P.Bit(int(to.To)) == 1 { + p2.SetBit(int(to.To), 1) } - if X.Bit(to.To) == 1 { - x2.SetBit(to.To, 1) + if X.Bit(int(to.To)) == 1 { + x2.SetBit(int(to.To), 1) } } - if !f(&r2, &p2, &x2) { + if !f(r2, p2, x2) { return false } P.SetBit(n, 0) X.SetBit(n, 1) return true } - if !pnu.Iterate(pf) { + if !pnu.IterateOnes(pf) { return false } - case X.Zero(): - return emit(R.Slice()) + case X.AllZeros(): + return emit(R) } return true } - var R, P, X Bits - P.SetAll(len(a)) + R := bits.New(len(a)) + P := bits.New(len(a)) + X := bits.New(len(a)) + P.SetAll() // code above same as BK2 // code below new to BK3 - _, ord, _ := g.Degeneracy() - var p2, x2 Bits + ord, _ := g.DegeneracyOrdering() + p2 := bits.New(len(a)) + x2 := bits.New(len(a)) for _, n := range ord { - R.SetBit(n, 1) - p2.Clear() - x2.Clear() + R.SetBit(int(n), 1) + p2.ClearAll() + x2.ClearAll() for _, to := range a[n] { - if P.Bit(to.To) == 1 { - p2.SetBit(to.To, 1) + if P.Bit(int(to.To)) == 1 { + p2.SetBit(int(to.To), 1) } - if X.Bit(to.To) == 1 { - x2.SetBit(to.To, 1) + if X.Bit(int(to.To)) == 1 { + x2.SetBit(int(to.To), 1) } } - if !f(&R, &p2, &x2) { + if !f(R, p2, x2) { return } - R.SetBit(n, 0) - P.SetBit(n, 0) - X.SetBit(n, 1) + R.SetBit(int(n), 0) + P.SetBit(int(n), 0) + X.SetBit(int(n), 1) } } // ConnectedComponentBits returns a function that iterates over connected // components of g, returning a member bitmap for each. // -// Each call of the returned function returns the order (number of nodes) -// and bits of a connected component. The returned function returns zeros -// after returning all connected components. +// Each call of the returned function returns the order, arc size, +// and bits of a connected component. The underlying bits allocation is +// the same for each call and is overwritten on subsequent calls. Use or +// save the bits before calling the function again. The function returns +// zeros after returning all connected components. // // There are equivalent labeled and unlabeled versions of this method. // -// See also ConnectedComponentReps, which has lighter weight return values. -func (g LabeledUndirected) ConnectedComponentBits() func() (order int, bits Bits) { +// See also ConnectedComponentInts, ConnectedComponentReps, and +// ConnectedComponentReps. +func (g LabeledUndirected) ConnectedComponentBits() func() (order, arcSize int, bits bits.Bits) { a := g.LabeledAdjacencyList - var vg Bits // nodes visited in graph - var vc *Bits // nodes visited in current component - var nc int + vg := bits.New(len(a)) // nodes visited in graph + vc := bits.New(len(a)) // nodes visited in current component + var order, arcSize int var df func(NI) df = func(n NI) { - vg.SetBit(n, 1) - vc.SetBit(n, 1) - nc++ + vg.SetBit(int(n), 1) + vc.SetBit(int(n), 1) + order++ + arcSize += len(a[n]) for _, nb := range a[n] { - if vg.Bit(nb.To) == 0 { + if vg.Bit(int(nb.To)) == 0 { df(nb.To) } } return } - var n NI - return func() (o int, bits Bits) { - for ; n < NI(len(a)); n++ { + var n int + return func() (o, ma int, b bits.Bits) { + for ; n < len(a); n++ { if vg.Bit(n) == 0 { - vc = &bits - nc = 0 - df(n) - return nc, bits + vc.ClearAll() + order, arcSize = 0, 0 + df(NI(n)) + return order, arcSize, vc + } + } + return // return zeros signalling no more components + } +} + +// ConnectedComponenInts returns a list of component numbers (ints) for each +// node of graph g. +// +// The method assigns numbers to components 1-based, 1 through the number of +// components. Return value ci contains the component number for each node. +// Return value nc is the number of components. +// +// There are equivalent labeled and unlabeled versions of this method. +// +// See also ConnectedComponentBits, ConnectedComponentLists, and +// ConnectedComponentReps. +func (g LabeledUndirected) ConnectedComponentInts() (ci []int, nc int) { + a := g.LabeledAdjacencyList + ci = make([]int, len(a)) + var df func(NI) + df = func(nd NI) { + ci[nd] = nc + for _, to := range a[nd] { + if ci[to.To] == 0 { + df(to.To) } } return } + for nd := range a { + if ci[nd] == 0 { + nc++ + df(NI(nd)) + } + } + return } // ConnectedComponentLists returns a function that iterates over connected // components of g, returning the member list of each. // // Each call of the returned function returns a node list of a connected -// component. The returned function returns nil after returning all connected -// components. +// component and the arc size of the component. The returned function returns +// nil, 0 after returning all connected components. // // There are equivalent labeled and unlabeled versions of this method. // -// See also ConnectedComponentReps, which has lighter weight return values. -func (g LabeledUndirected) ConnectedComponentLists() func() []NI { +// See also ConnectedComponentBits, ConnectedComponentInts, and +// ConnectedComponentReps. +func (g LabeledUndirected) ConnectedComponentLists() func() (nodes []NI, arcSize int) { a := g.LabeledAdjacencyList - var vg Bits // nodes visited in graph - var m []NI // members of current component + vg := bits.New(len(a)) // nodes visited in graph + var l []NI // accumulated node list of current component + var ma int // accumulated arc size of current component var df func(NI) df = func(n NI) { - vg.SetBit(n, 1) - m = append(m, n) + vg.SetBit(int(n), 1) + l = append(l, n) + ma += len(a[n]) for _, nb := range a[n] { - if vg.Bit(nb.To) == 0 { + if vg.Bit(int(nb.To)) == 0 { df(nb.To) } } return } - var n NI - return func() []NI { - for ; n < NI(len(a)); n++ { + var n int + return func() ([]NI, int) { + for ; n < len(a); n++ { if vg.Bit(n) == 0 { - m = nil - df(n) - return m + l, ma = nil, 0 + df(NI(n)) + return l, ma } } - return nil + return nil, 0 } } @@ -397,8 +510,8 @@ func (g LabeledUndirected) ConnectedComponentLists() func() []NI { // component of g. // // Returned is a slice with a single representative node from each connected -// component and also a parallel slice with the order, or number of nodes, -// in the corresponding component. +// component and also parallel slices with the orders and arc sizes +// in the corresponding components. // // This is fairly minimal information describing connected components. // From a representative node, other nodes in the component can be reached @@ -409,27 +522,29 @@ func (g LabeledUndirected) ConnectedComponentLists() func() []NI { // See also ConnectedComponentBits and ConnectedComponentLists which can // collect component members in a single traversal, and IsConnected which // is an even simpler boolean test. -func (g LabeledUndirected) ConnectedComponentReps() (reps []NI, orders []int) { +func (g LabeledUndirected) ConnectedComponentReps() (reps []NI, orders, arcSizes []int) { a := g.LabeledAdjacencyList - var c Bits - var o int + c := bits.New(len(a)) + var o, ma int var df func(NI) df = func(n NI) { - c.SetBit(n, 1) + c.SetBit(int(n), 1) o++ + ma += len(a[n]) for _, nb := range a[n] { - if c.Bit(nb.To) == 0 { + if c.Bit(int(nb.To)) == 0 { df(nb.To) } } return } for n := range a { - if c.Bit(NI(n)) == 0 { - reps = append(reps, NI(n)) - o = 0 + if c.Bit(n) == 0 { + o, ma = 0, 0 df(NI(n)) + reps = append(reps, NI(n)) orders = append(orders, o) + arcSizes = append(arcSizes, ma) } } return @@ -444,16 +559,97 @@ func (g LabeledUndirected) Copy() (c LabeledUndirected, ma int) { return LabeledUndirected{l}, s } -// Degeneracy computes k-degeneracy, vertex ordering and k-cores. +// Degeneracy is a measure of dense subgraphs within a graph. // // See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) // +// See also method DegeneracyOrdering which returns a degeneracy node +// ordering and k-core breaks. +// // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledUndirected) Degeneracy() (k int, ordering []NI, cores []int) { +func (g LabeledUndirected) Degeneracy() (k int) { + a := g.LabeledAdjacencyList + // WP algorithm, attributed to Matula and Beck. + L := bits.New(len(a)) + d := make([]int, len(a)) + var D [][]NI + for v, nb := range a { + dv := len(nb) + d[v] = dv + for len(D) <= dv { + D = append(D, nil) + } + D[dv] = append(D[dv], NI(v)) + } + for range a { + // find a non-empty D + i := 0 + for len(D[i]) == 0 { + i++ + } + // k is max(i, k) + if i > k { + k = i + } + // select from D[i] + Di := D[i] + last := len(Di) - 1 + v := Di[last] + // Add v to ordering, remove from Di + L.SetBit(int(v), 1) + D[i] = Di[:last] + // move neighbors + for _, nb := range a[v] { + if L.Bit(int(nb.To)) == 1 { + continue + } + dn := d[nb.To] // old number of neighbors of nb + Ddn := D[dn] // nb is in this list + // remove it from the list + for wx, w := range Ddn { + if w == nb.To { + last := len(Ddn) - 1 + Ddn[wx], Ddn[last] = Ddn[last], Ddn[wx] + D[dn] = Ddn[:last] + } + } + dn-- // new number of neighbors + d[nb.To] = dn + // re--add it to it's new list + D[dn] = append(D[dn], nb.To) + } + } + return +} + +// DegeneracyOrdering computes degeneracy node ordering and k-core breaks. +// +// See Wikipedia https://en.wikipedia.org/wiki/Degeneracy_(graph_theory) +// +// In return value ordering, nodes are ordered by their "coreness" as +// defined at https://en.wikipedia.org/wiki/Degeneracy_(graph_theory)#k-Cores. +// +// Return value kbreaks indexes ordering by coreness number. len(kbreaks) +// will be one more than the graph degeneracy as returned by the Degeneracy +// method. If degeneracy is d, d = len(kbreaks) - 1, kbreaks[d] is the last +// value in kbreaks and ordering[:kbreaks[d]] contains nodes of the d-cores +// of the graph. kbreaks[0] is always the number of nodes in g as all nodes +// are in in a 0-core. +// +// Note that definitions of "k-core" differ on whether a k-core must be a +// single connected component. This method does not resolve individual +// connected components. +// +// See also method Degeneracy which returns just the degeneracy number. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) DegeneracyOrdering() (ordering []NI, kbreaks []int) { a := g.LabeledAdjacencyList // WP algorithm + k := 0 ordering = make([]NI, len(a)) - var L Bits + kbreaks = []int{len(a)} + L := bits.New(len(a)) d := make([]int, len(a)) var D [][]NI for v, nb := range a { @@ -464,7 +660,7 @@ func (g LabeledUndirected) Degeneracy() (k int, ordering []NI, cores []int) { } D[dv] = append(D[dv], NI(v)) } - for ox := range a { + for ox := len(a) - 1; ox >= 0; ox-- { // find a non-empty D i := 0 for len(D[i]) == 0 { @@ -472,10 +668,9 @@ func (g LabeledUndirected) Degeneracy() (k int, ordering []NI, cores []int) { } // k is max(i, k) if i > k { - for len(cores) <= i { - cores = append(cores, 0) + for len(kbreaks) <= i { + kbreaks = append(kbreaks, ox+1) } - cores[k] = ox k = i } // select from D[i] @@ -484,11 +679,11 @@ func (g LabeledUndirected) Degeneracy() (k int, ordering []NI, cores []int) { v := Di[last] // Add v to ordering, remove from Di ordering[ox] = v - L.SetBit(v, 1) + L.SetBit(int(v), 1) D[i] = Di[:last] // move neighbors for _, nb := range a[v] { - if L.Bit(nb.To) == 1 { + if L.Bit(int(nb.To)) == 1 { continue } dn := d[nb.To] // old number of neighbors of nb @@ -507,7 +702,9 @@ func (g LabeledUndirected) Degeneracy() (k int, ordering []NI, cores []int) { D[dn] = append(D[dn], nb.To) } } - cores[k] = len(ordering) + //for i, j := 0, k; i < j; i, j = i+1, j-1 { + // kbreaks[i], kbreaks[j] = kbreaks[j], kbreaks[i] + //} return } @@ -531,57 +728,291 @@ func (g LabeledUndirected) Degree(n NI) int { return d } -// FromList constructs a FromList representing the tree reachable from -// the given root. +// DegreeCentralization returns the degree centralization metric of a graph. +// +// Degree of a node is one measure of node centrality and is directly +// available from the adjacency list representation. This allows degree +// centralization for the graph to be very efficiently computed. +// +// The value returned is from 0 to 1 inclusive for simple graphs of three or +// more nodes. As a special case, 0 is returned for graphs of two or fewer +// nodes. The value returned can be > 1 for graphs with loops or parallel +// edges. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) DegreeCentralization() float64 { + a := g.LabeledAdjacencyList + if len(a) <= 2 { + return 0 + } + var max, sum int + for _, to := range a { + if len(to) > max { + max = len(to) + } + sum += len(to) + } + return float64(len(a)*max-sum) / float64((len(a)-1)*(len(a)-2)) +} + +// Density returns density for a simple graph. // -// The connected component containing root should represent a simple graph, -// connected as a tree. +// See also Density function. // -// For nodes connected as a tree, the Path member of the returned FromList -// will be populated with both From and Len values. The MaxLen member will be -// set but Leaves will be left a zero value. Return value cycle will be -1. +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) Density() float64 { + return Density(g.Order(), g.Size()) +} + +// Eulerian scans an undirected graph to determine if it is Eulerian. +// +// If the graph represents an Eulerian cycle, it returns -1, -1, nil. // -// If the connected component containing root is not connected as a tree, -// a cycle will be detected. The returned FromList will be a zero value and -// return value cycle will be a node involved in the cycle. +// If the graph does not represent an Eulerian cycle but does represent an +// Eulerian path, it returns the two end nodes of the path, and nil. // -// Loops and parallel edges will be detected as cycles, however only in the -// connected component containing root. If g is not fully connected, nodes -// not reachable from root will have PathEnd values of {From: -1, Len: 0}. +// Otherwise it returns an error. +// +// See also method EulerianStart, which short-circuits as soon as it finds +// a node that must be a start or end node of an Eulerian path. // // There are equivalent labeled and unlabeled versions of this method. -func (g LabeledUndirected) FromList(root NI) (f FromList, cycle NI) { - p := make([]PathEnd, len(g.LabeledAdjacencyList)) - for i := range p { - p[i].From = -1 +func (g LabeledUndirected) Eulerian() (end1, end2 NI, err error) { + end1 = -1 + end2 = -1 + for n := range g.LabeledAdjacencyList { + switch { + case g.Degree(NI(n))%2 == 0: + case end1 < 0: + end1 = NI(n) + case end2 < 0: + end2 = NI(n) + default: + err = errors.New("non-Eulerian") + return + } } - ml := 0 - var df func(NI, NI) bool - df = func(fr, n NI) bool { - l := p[n].Len + 1 - for _, to := range g.LabeledAdjacencyList[n] { - if to.To == fr { - continue - } - if p[to.To].Len > 0 { - cycle = to.To - return false - } - p[to.To] = PathEnd{From: n, Len: l} - if l > ml { - ml = l - } - if !df(n, to.To) { - return false - } + return +} + +// EulerianCycle finds an Eulerian cycle in an undirected multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianCycle copies the entire graph g. +// See EulerianCycleD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianCycle() ([]Half, error) { + c, _ := g.Copy() + return c.EulerianCycleD(c.Size()) +} + +// EulerianCycleD finds an Eulerian cycle in an undirected multigraph. +// +// EulerianCycleD is destructive on its receiver g. See EulerianCycle for +// a non-destructive version. +// +// Parameter m must be the size of the undirected graph -- the +// number of edges. Use Undirected.Size if the size is unknown. +// +// * If g has no nodes, result is nil, nil. +// +// * If g is Eulerian, result is an Eulerian cycle with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the cycle. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianCycleD(m int) ([]Half, error) { + if g.Order() == 0 { + return nil, nil + } + e := newLabEulerian(g.LabeledAdjacencyList, m) + e.p[0] = Half{0, -1} + for e.s >= 0 { + v := e.top() + if err := e.pushUndir(); err != nil { + return nil, err } - return true + if e.top().To != v.To { + return nil, errors.New("not Eulerian") + } + e.keep() } - p[root].Len = 1 - if !df(-1, root) { - return + if !e.uv.AllZeros() { + return nil, errors.New("not strongly connected") } - return FromList{Paths: p, MaxLen: ml}, -1 + return e.p, nil +} + +// EulerianPath finds an Eulerian path in an undirected multigraph. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path, result is an Eulerian path with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// Internally, EulerianPath copies the entire graph g. +// See EulerianPathD for a more space efficient version. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianPath() ([]Half, error) { + c, _ := g.Copy() + start := c.EulerianStart() + if start < 0 { + start = 0 + } + return c.EulerianPathD(c.Size(), start) +} + +// EulerianPathD finds an Eulerian path in a undirected multigraph. +// +// EulerianPathD is destructive on its receiver g. See EulerianPath for +// a non-destructive version. +// +// Argument m must be the correct size, or number of edges in g. +// Argument start must be a valid start node for the path. +// +// * If g has no nodes, result is nil, nil. +// +// * If g has an Eulerian path starting at start, result is an Eulerian path +// with err = nil. +// The first element of the result represents only a start node. +// The remaining elements represent the half arcs of the path. +// +// * Otherwise, result is nil, with a non-nil error giving a reason the graph +// is not Eulerian. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianPathD(m int, start NI) ([]Half, error) { + if g.Order() == 0 { + return nil, nil + } + e := newLabEulerian(g.LabeledAdjacencyList, m) + e.p[0] = Half{start, -1} + // unlike EulerianCycle, the first path doesn't have to be a cycle. + if err := e.pushUndir(); err != nil { + return nil, err + } + e.keep() + for e.s >= 0 { + start = e.top().To + e.push() + // paths after the first must be cycles though + // (as long as there are nodes on the stack) + if e.top().To != start { + return nil, errors.New("no Eulerian path") + } + e.keep() + } + if !e.uv.AllZeros() { + return nil, errors.New("no Eulerian path") + } + return e.p, nil +} + +// EulerianStart finds a candidate start node for an Eulerian path. +// +// A graph representing an Eulerian path can have two nodes with odd degree. +// If it does, these must be the end nodes of the path. EulerianEnd scans +// for a node with an odd degree, returning immediately with the first one +// it finds. +// +// If the scan completes without finding a node with odd degree the method +// returns -1. +// +// See also method Eulerian, which completely validates a graph as representing +// an Eulerian path. +// +// There are equivalent labeled and unlabeled versions of this method. +func (g LabeledUndirected) EulerianStart() NI { + for n := range g.LabeledAdjacencyList { + if g.Degree(NI(n))%2 != 0 { + return NI(n) + } + } + return -1 +} + +// AddNode maps a node in a supergraph to a subgraph node. +// +// Argument p must be an NI in supergraph s.Super. AddNode panics if +// p is not a valid node index of s.Super. +// +// AddNode is idempotent in that it does not add a new node to the subgraph if +// a subgraph node already exists mapped to supergraph node p. +// +// The mapped subgraph NI is returned. +func (s *LabeledUndirectedSubgraph) AddNode(p NI) (b NI) { + if int(p) < 0 || int(p) >= s.Super.Order() { + panic(fmt.Sprint("AddNode: NI ", p, " not in supergraph")) + } + if b, ok := s.SubNI[p]; ok { + return b + } + a := s.LabeledUndirected.LabeledAdjacencyList + b = NI(len(a)) + s.LabeledUndirected.LabeledAdjacencyList = append(a, nil) + s.SuperNI = append(s.SuperNI, p) + s.SubNI[p] = b + return +} + +// InduceList constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument l must be a list of +// NIs in receiver graph g. Receiver g becomes the supergraph of the induced +// subgraph. +// +// Duplicate NIs are allowed in list l. The duplicates are effectively removed +// and only a single corresponding node is created in the subgraph. Subgraph +// NIs are mapped in the order of list l, execpt for ignoring duplicates. +// NIs in l that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledUndirected) InduceList(l []NI) *LabeledUndirectedSubgraph { + sub, sup := mapList(l) + return &LabeledUndirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + LabeledUndirected: LabeledUndirected{ + g.LabeledAdjacencyList.induceArcs(sub, sup), + }} +} + +// InduceBits constructs a node-induced subgraph. +// +// The subgraph is induced on receiver graph g. Argument t must be a bitmap +// representing NIs in receiver graph g. Receiver g becomes the supergraph +// of the induced subgraph. NIs in t that are not in g will panic. +// +// Returned is the constructed Subgraph object containing the induced subgraph +// and the mappings to the supergraph. +func (g *LabeledUndirected) InduceBits(t bits.Bits) *LabeledUndirectedSubgraph { + sub, sup := mapBits(t) + return &LabeledUndirectedSubgraph{ + Super: g, + SubNI: sub, + SuperNI: sup, + LabeledUndirected: LabeledUndirected{ + g.LabeledAdjacencyList.induceArcs(sub, sup), + }} } // IsConnected tests if an undirected graph is a single connected component. @@ -594,19 +1025,18 @@ func (g LabeledUndirected) IsConnected() bool { if len(a) == 0 { return true } - var b Bits - b.SetAll(len(a)) + b := bits.New(len(a)) var df func(NI) df = func(n NI) { - b.SetBit(n, 0) + b.SetBit(int(n), 1) for _, to := range a[n] { - if b.Bit(to.To) == 1 { + if b.Bit(int(to.To)) == 0 { df(to.To) } } } df(0) - return b.Zero() + return b.AllOnes() } // IsTree identifies trees in undirected graphs. @@ -618,14 +1048,14 @@ func (g LabeledUndirected) IsConnected() bool { // There are equivalent labeled and unlabeled versions of this method. func (g LabeledUndirected) IsTree(root NI) (isTree, allTree bool) { a := g.LabeledAdjacencyList - var v Bits - v.SetAll(len(a)) + v := bits.New(len(a)) + v.SetAll() var df func(NI, NI) bool df = func(fr, n NI) bool { - if v.Bit(n) == 0 { + if v.Bit(int(n)) == 0 { return false } - v.SetBit(n, 0) + v.SetBit(int(n), 0) for _, to := range a[n] { if to.To != fr && !df(n, to.To) { return false @@ -633,18 +1063,18 @@ func (g LabeledUndirected) IsTree(root NI) (isTree, allTree bool) { } return true } - v.SetBit(root, 0) + v.SetBit(int(root), 0) for _, to := range a[root] { if !df(root, to.To) { return false, false } } - return true, v.Zero() + return true, v.AllZeros() } // Size returns the number of edges in g. // -// See also ArcSize and HasLoop. +// See also ArcSize and AnyLoop. func (g LabeledUndirected) Size() int { m2 := 0 for fr, to := range g.LabeledAdjacencyList { @@ -657,3 +1087,52 @@ func (g LabeledUndirected) Size() int { } return m2 / 2 } + +// Density returns edge density of a bipartite graph. +// +// Edge density is number of edges over maximum possible number of edges. +// Maximum possible number of edges in a bipartite graph is number of +// nodes of one color times number of nodes of the other color. +func (g LabeledBipartite) Density() float64 { + a := g.LabeledUndirected.LabeledAdjacencyList + s := 0 + g.Color.IterateOnes(func(n int) bool { + s += len(a[n]) + return true + }) + return float64(s) / float64(g.N0*(len(a)-g.N0)) +} + +// PermuteBiadjacency permutes a bipartite graph in place so that a prefix +// of the adjacency list encodes a biadjacency matrix. +// +// The permutation applied is returned. This would be helpful in referencing +// any externally stored node information. +// +// The biadjacency matrix is encoded as the prefix AdjacencyList[:g.N0]. +// Note though that this slice does not represent a valid complete +// AdjacencyList. BoundsOk would return false, for example. +// +// In adjacency list terms, the result of the permutation is that nodes of +// the prefix only have arcs to the suffix and nodes of the suffix only have +// arcs to the prefix. +func (g LabeledBipartite) PermuteBiadjacency() []int { + p := make([]int, g.Order()) + i := 0 + g.Color.IterateZeros(func(n int) bool { + p[n] = i + i++ + return true + }) + g.Color.IterateOnes(func(n int) bool { + p[n] = i + i++ + return true + }) + g.Permute(p) + g.Color.ClearAll() + for i := g.N0; i < g.Order(); i++ { + g.Color.SetBit(i, 1) + } + return p +} diff --git a/vendor/golang.org/x/net/LICENSE b/vendor/golang.org/x/net/LICENSE index 6a66aea5..2a7cf70d 100644 --- a/vendor/golang.org/x/net/LICENSE +++ b/vendor/golang.org/x/net/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. 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 + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go index 56efb95b..cf66309c 100644 --- a/vendor/golang.org/x/net/context/context.go +++ b/vendor/golang.org/x/net/context/context.go @@ -5,9 +5,11 @@ // Package context defines the Context type, which carries deadlines, // cancelation signals, and other request-scoped values across API boundaries // and between processes. +// As of Go 1.7 this package is available in the standard library under the +// name context. https://golang.org/pkg/context. // // Incoming requests to a server should create a Context, and outgoing calls to -// servers should accept a Context. The chain of function calls between must +// servers should accept a Context. The chain of function calls between must // propagate the Context, optionally replacing it with a modified copy created // using WithDeadline, WithTimeout, WithCancel, or WithValue. // @@ -16,14 +18,14 @@ // propagation: // // Do not store Contexts inside a struct type; instead, pass a Context -// explicitly to each function that needs it. The Context should be the first +// explicitly to each function that needs it. The Context should be the first // parameter, typically named ctx: // -// func DoSomething(ctx context.Context, arg Arg) error { -// // ... use ctx ... -// } +// func DoSomething(ctx context.Context, arg Arg) error { +// // ... use ctx ... +// } // -// Do not pass a nil Context, even if a function permits it. Pass context.TODO +// Do not pass a nil Context, even if a function permits it. Pass context.TODO // if you are unsure about which Context to use. // // Use context Values only for request-scoped data that transits processes and @@ -34,114 +36,17 @@ // // See http://blog.golang.org/context for example code for a server that uses // Contexts. -package context - -import "time" - -// A Context carries a deadline, a cancelation signal, and other values across -// API boundaries. -// -// Context's methods may be called by multiple goroutines simultaneously. -type Context interface { - // Deadline returns the time when work done on behalf of this context - // should be canceled. Deadline returns ok==false when no deadline is - // set. Successive calls to Deadline return the same results. - Deadline() (deadline time.Time, ok bool) - - // Done returns a channel that's closed when work done on behalf of this - // context should be canceled. Done may return nil if this context can - // never be canceled. Successive calls to Done return the same value. - // - // WithCancel arranges for Done to be closed when cancel is called; - // WithDeadline arranges for Done to be closed when the deadline - // expires; WithTimeout arranges for Done to be closed when the timeout - // elapses. - // - // Done is provided for use in select statements: - // - // // Stream generates values with DoSomething and sends them to out - // // until DoSomething returns an error or ctx.Done is closed. - // func Stream(ctx context.Context, out <-chan Value) error { - // for { - // v, err := DoSomething(ctx) - // if err != nil { - // return err - // } - // select { - // case <-ctx.Done(): - // return ctx.Err() - // case out <- v: - // } - // } - // } - // - // See http://blog.golang.org/pipelines for more examples of how to use - // a Done channel for cancelation. - Done() <-chan struct{} - - // Err returns a non-nil error value after Done is closed. Err returns - // Canceled if the context was canceled or DeadlineExceeded if the - // context's deadline passed. No other values for Err are defined. - // After Done is closed, successive calls to Err return the same value. - Err() error - - // Value returns the value associated with this context for key, or nil - // if no value is associated with key. Successive calls to Value with - // the same key returns the same result. - // - // Use context values only for request-scoped data that transits - // processes and API boundaries, not for passing optional parameters to - // functions. - // - // A key identifies a specific value in a Context. Functions that wish - // to store values in Context typically allocate a key in a global - // variable then use that key as the argument to context.WithValue and - // Context.Value. A key can be any type that supports equality; - // packages should define keys as an unexported type to avoid - // collisions. - // - // Packages that define a Context key should provide type-safe accessors - // for the values stores using that key: - // - // // Package user defines a User type that's stored in Contexts. - // package user - // - // import "golang.org/x/net/context" - // - // // User is the type of value stored in the Contexts. - // type User struct {...} - // - // // key is an unexported type for keys defined in this package. - // // This prevents collisions with keys defined in other packages. - // type key int - // - // // userKey is the key for user.User values in Contexts. It is - // // unexported; clients use user.NewContext and user.FromContext - // // instead of using this key directly. - // var userKey key = 0 - // - // // NewContext returns a new Context that carries value u. - // func NewContext(ctx context.Context, u *User) context.Context { - // return context.WithValue(ctx, userKey, u) - // } - // - // // FromContext returns the User value stored in ctx, if any. - // func FromContext(ctx context.Context) (*User, bool) { - // u, ok := ctx.Value(userKey).(*User) - // return u, ok - // } - Value(key interface{}) interface{} -} +package context // import "golang.org/x/net/context" // Background returns a non-nil, empty Context. It is never canceled, has no -// values, and has no deadline. It is typically used by the main function, +// values, and has no deadline. It is typically used by the main function, // initialization, and tests, and as the top-level Context for incoming // requests. func Background() Context { return background } -// TODO returns a non-nil, empty Context. Code should use context.TODO when +// TODO returns a non-nil, empty Context. Code should use context.TODO when // it's unclear which Context to use or it is not yet available (because the // surrounding function has not yet been extended to accept a Context // parameter). TODO is recognized by static analysis tools that determine @@ -149,8 +54,3 @@ func Background() Context { func TODO() Context { return todo } - -// A CancelFunc tells an operation to abandon its work. -// A CancelFunc does not wait for the work to stop. -// After the first call, subsequent calls to a CancelFunc do nothing. -type CancelFunc func() diff --git a/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go b/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go deleted file mode 100644 index e3170e33..00000000 --- a/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build go1.5 - -package ctxhttp - -import "net/http" - -func canceler(client *http.Client, req *http.Request) func() { - // TODO(djd): Respect any existing value of req.Cancel. - ch := make(chan struct{}) - req.Cancel = ch - - return func() { - close(ch) - } -} diff --git a/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go b/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go deleted file mode 100644 index 56bcbadb..00000000 --- a/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build !go1.5 - -package ctxhttp - -import "net/http" - -type requestCanceler interface { - CancelRequest(*http.Request) -} - -func canceler(client *http.Client, req *http.Request) func() { - rc, ok := client.Transport.(requestCanceler) - if !ok { - return func() {} - } - return func() { - rc.CancelRequest(req) - } -} diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go deleted file mode 100644 index e35860a7..00000000 --- a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2015 The Go 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 ctxhttp provides helper functions for performing context-aware HTTP requests. -package ctxhttp - -import ( - "io" - "net/http" - "net/url" - "strings" - - "golang.org/x/net/context" -) - -func nop() {} - -var ( - testHookContextDoneBeforeHeaders = nop - testHookDoReturned = nop - testHookDidBodyClose = nop -) - -// Do sends an HTTP request with the provided http.Client and returns an HTTP response. -// If the client is nil, http.DefaultClient is used. -// If the context is canceled or times out, ctx.Err() will be returned. -func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) { - if client == nil { - client = http.DefaultClient - } - - // Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go. - cancel := canceler(client, req) - - type responseAndError struct { - resp *http.Response - err error - } - result := make(chan responseAndError, 1) - - // Make local copies of test hooks closed over by goroutines below. - // Prevents data races in tests. - testHookDoReturned := testHookDoReturned - testHookDidBodyClose := testHookDidBodyClose - - go func() { - resp, err := client.Do(req) - testHookDoReturned() - result <- responseAndError{resp, err} - }() - - var resp *http.Response - - select { - case <-ctx.Done(): - testHookContextDoneBeforeHeaders() - cancel() - // Clean up after the goroutine calling client.Do: - go func() { - if r := <-result; r.resp != nil { - testHookDidBodyClose() - r.resp.Body.Close() - } - }() - return nil, ctx.Err() - case r := <-result: - var err error - resp, err = r.resp, r.err - if err != nil { - return resp, err - } - } - - c := make(chan struct{}) - go func() { - select { - case <-ctx.Done(): - cancel() - case <-c: - // The response's Body is closed. - } - }() - resp.Body = ¬ifyingReader{resp.Body, c} - - return resp, nil -} - -// Get issues a GET request via the Do function. -func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) { - req, err := http.NewRequest("GET", url, nil) - if err != nil { - return nil, err - } - return Do(ctx, client, req) -} - -// Head issues a HEAD request via the Do function. -func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) { - req, err := http.NewRequest("HEAD", url, nil) - if err != nil { - return nil, err - } - return Do(ctx, client, req) -} - -// Post issues a POST request via the Do function. -func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) { - req, err := http.NewRequest("POST", url, body) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", bodyType) - return Do(ctx, client, req) -} - -// PostForm issues a POST request via the Do function. -func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) { - return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode())) -} - -// notifyingReader is an io.ReadCloser that closes the notify channel after -// Close is called or a Read fails on the underlying ReadCloser. -type notifyingReader struct { - io.ReadCloser - notify chan<- struct{} -} - -func (r *notifyingReader) Read(p []byte) (int, error) { - n, err := r.ReadCloser.Read(p) - if err != nil && r.notify != nil { - close(r.notify) - r.notify = nil - } - return n, err -} - -func (r *notifyingReader) Close() error { - err := r.ReadCloser.Close() - if r.notify != nil { - close(r.notify) - r.notify = nil - } - return err -} diff --git a/vendor/golang.org/x/net/context/go17.go b/vendor/golang.org/x/net/context/go17.go index f8cda19a..0c1b8679 100644 --- a/vendor/golang.org/x/net/context/go17.go +++ b/vendor/golang.org/x/net/context/go17.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build go1.7 +//go:build go1.7 package context @@ -31,12 +31,12 @@ var DeadlineExceeded = context.DeadlineExceeded // call cancel as soon as the operations running in this Context complete. func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { ctx, f := context.WithCancel(parent) - return ctx, CancelFunc(f) + return ctx, f } // WithDeadline returns a copy of the parent context with the deadline adjusted -// to be no later than d. If the parent's deadline is already earlier than d, -// WithDeadline(parent, d) is semantically equivalent to parent. The returned +// to be no later than d. If the parent's deadline is already earlier than d, +// WithDeadline(parent, d) is semantically equivalent to parent. The returned // context's Done channel is closed when the deadline expires, when the returned // cancel function is called, or when the parent context's Done channel is // closed, whichever happens first. @@ -45,7 +45,7 @@ func WithCancel(parent Context) (ctx Context, cancel CancelFunc) { // call cancel as soon as the operations running in this Context complete. func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { ctx, f := context.WithDeadline(parent, deadline) - return ctx, CancelFunc(f) + return ctx, f } // WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)). @@ -53,11 +53,11 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { // Canceling this context releases resources associated with it, so code should // call cancel as soon as the operations running in this Context complete: // -// func slowOperationWithTimeout(ctx context.Context) (Result, error) { -// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) -// defer cancel() // releases resources if slowOperation completes before timeout elapses -// return slowOperation(ctx) -// } +// func slowOperationWithTimeout(ctx context.Context) (Result, error) { +// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) +// defer cancel() // releases resources if slowOperation completes before timeout elapses +// return slowOperation(ctx) +// } func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { return WithDeadline(parent, time.Now().Add(timeout)) } diff --git a/vendor/golang.org/x/net/context/pre_go17.go b/vendor/golang.org/x/net/context/pre_go17.go index 5a30acab..065ff3df 100644 --- a/vendor/golang.org/x/net/context/pre_go17.go +++ b/vendor/golang.org/x/net/context/pre_go17.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !go1.7 +//go:build !go1.7 package context @@ -13,7 +13,7 @@ import ( "time" ) -// An emptyCtx is never canceled, has no values, and has no deadline. It is not +// An emptyCtx is never canceled, has no values, and has no deadline. It is not // struct{}, since vars of this type must have distinct addresses. type emptyCtx int @@ -104,7 +104,7 @@ func propagateCancel(parent Context, child canceler) { } // parentCancelCtx follows a chain of parent references until it finds a -// *cancelCtx. This function understands how each of the concrete types in this +// *cancelCtx. This function understands how each of the concrete types in this // package represents its parent. func parentCancelCtx(parent Context) (*cancelCtx, bool) { for { @@ -134,14 +134,14 @@ func removeChild(parent Context, child canceler) { p.mu.Unlock() } -// A canceler is a context type that can be canceled directly. The +// A canceler is a context type that can be canceled directly. The // implementations are *cancelCtx and *timerCtx. type canceler interface { cancel(removeFromParent bool, err error) Done() <-chan struct{} } -// A cancelCtx can be canceled. When canceled, it also cancels any children +// A cancelCtx can be canceled. When canceled, it also cancels any children // that implement canceler. type cancelCtx struct { Context @@ -193,8 +193,8 @@ func (c *cancelCtx) cancel(removeFromParent bool, err error) { } // WithDeadline returns a copy of the parent context with the deadline adjusted -// to be no later than d. If the parent's deadline is already earlier than d, -// WithDeadline(parent, d) is semantically equivalent to parent. The returned +// to be no later than d. If the parent's deadline is already earlier than d, +// WithDeadline(parent, d) is semantically equivalent to parent. The returned // context's Done channel is closed when the deadline expires, when the returned // cancel function is called, or when the parent context's Done channel is // closed, whichever happens first. @@ -226,8 +226,8 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) { return c, func() { c.cancel(true, Canceled) } } -// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to -// implement Done and Err. It implements cancel by stopping its timer then +// A timerCtx carries a timer and a deadline. It embeds a cancelCtx to +// implement Done and Err. It implements cancel by stopping its timer then // delegating to cancelCtx.cancel. type timerCtx struct { *cancelCtx @@ -263,11 +263,11 @@ func (c *timerCtx) cancel(removeFromParent bool, err error) { // Canceling this context releases resources associated with it, so code should // call cancel as soon as the operations running in this Context complete: // -// func slowOperationWithTimeout(ctx context.Context) (Result, error) { -// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) -// defer cancel() // releases resources if slowOperation completes before timeout elapses -// return slowOperation(ctx) -// } +// func slowOperationWithTimeout(ctx context.Context) (Result, error) { +// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) +// defer cancel() // releases resources if slowOperation completes before timeout elapses +// return slowOperation(ctx) +// } func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) { return WithDeadline(parent, time.Now().Add(timeout)) } @@ -281,7 +281,7 @@ func WithValue(parent Context, key interface{}, val interface{}) Context { return &valueCtx{parent, key, val} } -// A valueCtx carries a key-value pair. It implements Value for that key and +// A valueCtx carries a key-value pair. It implements Value for that key and // delegates all other calls to the embedded Context. type valueCtx struct { Context diff --git a/vendor/golang.org/x/oauth2/.travis.yml b/vendor/golang.org/x/oauth2/.travis.yml index a035125c..fa139db2 100644 --- a/vendor/golang.org/x/oauth2/.travis.yml +++ b/vendor/golang.org/x/oauth2/.travis.yml @@ -1,8 +1,7 @@ language: go go: - - 1.3 - - 1.4 + - tip install: - export GOPATH="$HOME/gopath" diff --git a/vendor/golang.org/x/oauth2/AUTHORS b/vendor/golang.org/x/oauth2/AUTHORS deleted file mode 100644 index 15167cd7..00000000 --- a/vendor/golang.org/x/oauth2/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -# 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. diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/vendor/golang.org/x/oauth2/CONTRIBUTING.md index 46aa2b12..dfbed62c 100644 --- a/vendor/golang.org/x/oauth2/CONTRIBUTING.md +++ b/vendor/golang.org/x/oauth2/CONTRIBUTING.md @@ -4,16 +4,15 @@ Go is an open source project. It is the work of hundreds of contributors. We appreciate your help! - ## Filing issues When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions: -1. What version of Go are you using (`go version`)? -2. What operating system and processor architecture are you using? -3. What did you do? -4. What did you expect to see? -5. What did you see instead? +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. The gophers there will answer or ask you to file an issue if you've tripped over a bug. @@ -23,9 +22,5 @@ The gophers there will answer or ask you to file an issue if you've tripped over Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) before sending patches. -**We do not accept GitHub pull requests** -(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review). - Unless otherwise noted, the Go source files are distributed under the BSD-style license found in the LICENSE file. - diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTORS b/vendor/golang.org/x/oauth2/CONTRIBUTORS deleted file mode 100644 index 1c4577e9..00000000 --- a/vendor/golang.org/x/oauth2/CONTRIBUTORS +++ /dev/null @@ -1,3 +0,0 @@ -# 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. diff --git a/vendor/golang.org/x/oauth2/LICENSE b/vendor/golang.org/x/oauth2/LICENSE index d02f24fd..2a7cf70d 100644 --- a/vendor/golang.org/x/oauth2/LICENSE +++ b/vendor/golang.org/x/oauth2/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009 The oauth2 Authors. All rights reserved. +Copyright 2009 The Go Authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -10,7 +10,7 @@ notice, this list of conditions and the following disclaimer. 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 + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md index 0d514173..48dbb9d8 100644 --- a/vendor/golang.org/x/oauth2/README.md +++ b/vendor/golang.org/x/oauth2/README.md @@ -1,64 +1,35 @@ # OAuth2 for Go +[![Go Reference](https://pkg.go.dev/badge/golang.org/x/oauth2.svg)](https://pkg.go.dev/golang.org/x/oauth2) [![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2) oauth2 package contains a client implementation for OAuth 2.0 spec. -## Installation +See pkg.go.dev for further documentation and examples. -~~~~ -go get golang.org/x/oauth2 -~~~~ +* [pkg.go.dev/golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) +* [pkg.go.dev/golang.org/x/oauth2/google](https://pkg.go.dev/golang.org/x/oauth2/google) -See godoc for further documentation and examples. +## Policy for new endpoints -* [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2) -* [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google) +We no longer accept new provider-specific packages in this repo if all +they do is add a single endpoint variable. If you just want to add a +single endpoint, add it to the +[pkg.go.dev/golang.org/x/oauth2/endpoints](https://pkg.go.dev/golang.org/x/oauth2/endpoints) +package. +## Report Issues / Send Patches -## App Engine +The main issue tracker for the oauth2 repository is located at +https://github.com/golang/oauth2/issues. -In change 96e89be (March 2015) we removed the `oauth2.Context2` type in favor -of the [`context.Context`](https://golang.org/x/net/context#Context) type from -the `golang.org/x/net/context` package +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://go.dev/doc/contribute. -This means its no longer possible to use the "Classic App Engine" -`appengine.Context` type with the `oauth2` package. (You're using -Classic App Engine if you import the package `"appengine"`.) +The git repository is https://go.googlesource.com/oauth2. -To work around this, you may use the new `"google.golang.org/appengine"` -package. This package has almost the same API as the `"appengine"` package, -but it can be fetched with `go get` and used on "Managed VMs" and well as -Classic App Engine. - -See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app) -for information on updating your app. - -If you don't want to update your entire app to use the new App Engine packages, -you may use both sets of packages in parallel, using only the new packages -with the `oauth2` package. - - import ( - "golang.org/x/net/context" - "golang.org/x/oauth2" - "golang.org/x/oauth2/google" - newappengine "google.golang.org/appengine" - newurlfetch "google.golang.org/appengine/urlfetch" - - "appengine" - ) - - func handler(w http.ResponseWriter, r *http.Request) { - var c appengine.Context = appengine.NewContext(r) - c.Infof("Logging a message with the old package") - - var ctx context.Context = newappengine.NewContext(r) - client := &http.Client{ - Transport: &oauth2.Transport{ - Source: google.AppEngineTokenSource(ctx, "scope"), - Base: &newurlfetch.Transport{Context: ctx}, - }, - } - client.Get("...") - } +Note: +* Excluding trivial changes, all contributions should be connected to an existing issue. +* API changes must go through the [change proposal process](https://go.dev/s/proposal-process) before they can be accepted. +* The code owners are listed at [dev.golang.org/owners](https://dev.golang.org/owners#:~:text=x/oauth2). diff --git a/vendor/golang.org/x/oauth2/client_appengine.go b/vendor/golang.org/x/oauth2/client_appengine.go deleted file mode 100644 index 8962c49d..00000000 --- a/vendor/golang.org/x/oauth2/client_appengine.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// +build appengine - -// App Engine hooks. - -package oauth2 - -import ( - "net/http" - - "golang.org/x/net/context" - "golang.org/x/oauth2/internal" - "google.golang.org/appengine/urlfetch" -) - -func init() { - internal.RegisterContextClientFunc(contextClientAppEngine) -} - -func contextClientAppEngine(ctx context.Context) (*http.Client, error) { - return urlfetch.Client(ctx), nil -} diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go index fbe1028d..14989bea 100644 --- a/vendor/golang.org/x/oauth2/internal/oauth2.go +++ b/vendor/golang.org/x/oauth2/internal/oauth2.go @@ -2,23 +2,19 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. package internal import ( - "bufio" "crypto/rsa" "crypto/x509" "encoding/pem" "errors" "fmt" - "io" - "strings" ) // ParseKey converts the binary contents of a private key file // to an *rsa.PrivateKey. It detects whether the private key is in a -// PEM container or not. If so, it extracts the the private key +// PEM container or not. If so, it extracts the private key // from PEM container before conversion. It only supports PEM // containers with no passphrase. func ParseKey(key []byte) (*rsa.PrivateKey, error) { @@ -30,7 +26,7 @@ func ParseKey(key []byte) (*rsa.PrivateKey, error) { if err != nil { parsedKey, err = x509.ParsePKCS1PrivateKey(key) if err != nil { - return nil, fmt.Errorf("private key should be a PEM or plain PKSC1 or PKCS8; parse error: %v", err) + return nil, fmt.Errorf("private key should be a PEM or plain PKCS1 or PKCS8; parse error: %v", err) } } parsed, ok := parsedKey.(*rsa.PrivateKey) @@ -39,38 +35,3 @@ func ParseKey(key []byte) (*rsa.PrivateKey, error) { } return parsed, nil } - -func ParseINI(ini io.Reader) (map[string]map[string]string, error) { - result := map[string]map[string]string{ - "": map[string]string{}, // root section - } - scanner := bufio.NewScanner(ini) - currentSection := "" - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, ";") { - // comment. - continue - } - if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") { - currentSection = strings.TrimSpace(line[1 : len(line)-1]) - result[currentSection] = map[string]string{} - continue - } - parts := strings.SplitN(line, "=", 2) - if len(parts) == 2 && parts[0] != "" { - result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1]) - } - } - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("error scanning ini: %v", err) - } - return result, nil -} - -func CondVal(v string) []string { - if v == "" { - return nil - } - return []string{v} -} diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go index a6ed3cc7..e83ddeef 100644 --- a/vendor/golang.org/x/oauth2/internal/token.go +++ b/vendor/golang.org/x/oauth2/internal/token.go @@ -2,25 +2,27 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. package internal import ( + "context" "encoding/json" + "errors" "fmt" "io" "io/ioutil" + "math" "mime" "net/http" "net/url" "strconv" "strings" + "sync" + "sync/atomic" "time" - - "golang.org/x/net/context" ) -// Token represents the crendentials used to authorize +// Token represents the credentials used to authorize // the requests to access protected resources on the OAuth 2.0 // provider's backend. // @@ -54,28 +56,33 @@ type Token struct { } // tokenJSON is the struct representing the HTTP response from OAuth2 -// providers returning a token in JSON form. +// providers returning a token or error in JSON form. +// https://datatracker.ietf.org/doc/html/rfc6749#section-5.1 type tokenJSON struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` RefreshToken string `json:"refresh_token"` ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number - Expires expirationTime `json:"expires"` // broken Facebook spelling of expires_in + // error fields + // https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 + ErrorCode string `json:"error"` + ErrorDescription string `json:"error_description"` + ErrorURI string `json:"error_uri"` } func (e *tokenJSON) expiry() (t time.Time) { if v := e.ExpiresIn; v != 0 { return time.Now().Add(time.Duration(v) * time.Second) } - if v := e.Expires; v != 0 { - return time.Now().Add(time.Duration(v) * time.Second) - } return } type expirationTime int32 func (e *expirationTime) UnmarshalJSON(b []byte) error { + if len(b) == 0 || string(b) == "null" { + return nil + } var n json.Number err := json.Unmarshal(b, &n) if err != nil { @@ -85,106 +92,199 @@ func (e *expirationTime) UnmarshalJSON(b []byte) error { if err != nil { return err } + if i > math.MaxInt32 { + i = math.MaxInt32 + } *e = expirationTime(i) return nil } -var brokenAuthHeaderProviders = []string{ - "https://accounts.google.com/", - "https://api.dropbox.com/", - "https://api.dropboxapi.com/", - "https://api.instagram.com/", - "https://api.netatmo.net/", - "https://api.odnoklassniki.ru/", - "https://api.pushbullet.com/", - "https://api.soundcloud.com/", - "https://api.twitch.tv/", - "https://app.box.com/", - "https://connect.stripe.com/", - "https://login.microsoftonline.com/", - "https://login.salesforce.com/", - "https://oauth.sandbox.trainingpeaks.com/", - "https://oauth.trainingpeaks.com/", - "https://oauth.vk.com/", - "https://openapi.baidu.com/", - "https://slack.com/", - "https://test-sandbox.auth.corp.google.com", - "https://test.salesforce.com/", - "https://user.gini.net/", - "https://www.douban.com/", - "https://www.googleapis.com/", - "https://www.linkedin.com/", - "https://www.strava.com/oauth/", - "https://www.wunderlist.com/oauth/", - "https://api.patreon.com/", -} +// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. +// +// Deprecated: this function no longer does anything. Caller code that +// wants to avoid potential extra HTTP requests made during +// auto-probing of the provider's auth style should set +// Endpoint.AuthStyle. +func RegisterBrokenAuthHeaderProvider(tokenURL string) {} -func RegisterBrokenAuthHeaderProvider(tokenURL string) { - brokenAuthHeaderProviders = append(brokenAuthHeaderProviders, tokenURL) +// AuthStyle is a copy of the golang.org/x/oauth2 package's AuthStyle type. +type AuthStyle int + +const ( + AuthStyleUnknown AuthStyle = 0 + AuthStyleInParams AuthStyle = 1 + AuthStyleInHeader AuthStyle = 2 +) + +// LazyAuthStyleCache is a backwards compatibility compromise to let Configs +// have a lazily-initialized AuthStyleCache. +// +// The two users of this, oauth2.Config and oauth2/clientcredentials.Config, +// both would ideally just embed an unexported AuthStyleCache but because both +// were historically allowed to be copied by value we can't retroactively add an +// uncopyable Mutex to them. +// +// We could use an atomic.Pointer, but that was added recently enough (in Go +// 1.18) that we'd break Go 1.17 users where the tests as of 2023-08-03 +// still pass. By using an atomic.Value, it supports both Go 1.17 and +// copying by value, even if that's not ideal. +type LazyAuthStyleCache struct { + v atomic.Value // of *AuthStyleCache } -// providerAuthHeaderWorks reports whether the OAuth2 server identified by the tokenURL -// implements the OAuth2 spec correctly -// See https://code.google.com/p/goauth2/issues/detail?id=31 for background. -// In summary: -// - Reddit only accepts client secret in the Authorization header -// - Dropbox accepts either it in URL param or Auth header, but not both. -// - Google only accepts URL param (not spec compliant?), not Auth header -// - Stripe only accepts client secret in Auth header with Bearer method, not Basic -func providerAuthHeaderWorks(tokenURL string) bool { - for _, s := range brokenAuthHeaderProviders { - if strings.HasPrefix(tokenURL, s) { - // Some sites fail to implement the OAuth2 spec fully. - return false - } +func (lc *LazyAuthStyleCache) Get() *AuthStyleCache { + if c, ok := lc.v.Load().(*AuthStyleCache); ok { + return c + } + c := new(AuthStyleCache) + if !lc.v.CompareAndSwap(nil, c) { + c = lc.v.Load().(*AuthStyleCache) } + return c +} + +// AuthStyleCache is the set of tokenURLs we've successfully used via +// RetrieveToken and which style auth we ended up using. +// It's called a cache, but it doesn't (yet?) shrink. It's expected that +// the set of OAuth2 servers a program contacts over time is fixed and +// small. +type AuthStyleCache struct { + mu sync.Mutex + m map[string]AuthStyle // keyed by tokenURL +} - // Assume the provider implements the spec properly - // otherwise. We can add more exceptions as they're - // discovered. We will _not_ be adding configurable hooks - // to this package to let users select server bugs. - return true +// lookupAuthStyle reports which auth style we last used with tokenURL +// when calling RetrieveToken and whether we have ever done so. +func (c *AuthStyleCache) lookupAuthStyle(tokenURL string) (style AuthStyle, ok bool) { + c.mu.Lock() + defer c.mu.Unlock() + style, ok = c.m[tokenURL] + return +} + +// setAuthStyle adds an entry to authStyleCache, documented above. +func (c *AuthStyleCache) setAuthStyle(tokenURL string, v AuthStyle) { + c.mu.Lock() + defer c.mu.Unlock() + if c.m == nil { + c.m = make(map[string]AuthStyle) + } + c.m[tokenURL] = v } -func RetrieveToken(ctx context.Context, ClientID, ClientSecret, TokenURL string, v url.Values) (*Token, error) { - hc, err := ContextClient(ctx) +// newTokenRequest returns a new *http.Request to retrieve a new token +// from tokenURL using the provided clientID, clientSecret, and POST +// body parameters. +// +// inParams is whether the clientID & clientSecret should be encoded +// as the POST body. An 'inParams' value of true means to send it in +// the POST body (along with any values in v); false means to send it +// in the Authorization header. +func newTokenRequest(tokenURL, clientID, clientSecret string, v url.Values, authStyle AuthStyle) (*http.Request, error) { + if authStyle == AuthStyleInParams { + v = cloneURLValues(v) + if clientID != "" { + v.Set("client_id", clientID) + } + if clientSecret != "" { + v.Set("client_secret", clientSecret) + } + } + req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode())) if err != nil { return nil, err } - v.Set("client_id", ClientID) - bustedAuth := !providerAuthHeaderWorks(TokenURL) - if bustedAuth && ClientSecret != "" { - v.Set("client_secret", ClientSecret) + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + if authStyle == AuthStyleInHeader { + req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret)) + } + return req, nil +} + +func cloneURLValues(v url.Values) url.Values { + v2 := make(url.Values, len(v)) + for k, vv := range v { + v2[k] = append([]string(nil), vv...) } - req, err := http.NewRequest("POST", TokenURL, strings.NewReader(v.Encode())) + return v2 +} + +func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values, authStyle AuthStyle, styleCache *AuthStyleCache) (*Token, error) { + needsAuthStyleProbe := authStyle == 0 + if needsAuthStyleProbe { + if style, ok := styleCache.lookupAuthStyle(tokenURL); ok { + authStyle = style + needsAuthStyleProbe = false + } else { + authStyle = AuthStyleInHeader // the first way we'll try + } + } + req, err := newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) if err != nil { return nil, err } - req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - if !bustedAuth { - req.SetBasicAuth(ClientID, ClientSecret) + token, err := doTokenRoundTrip(ctx, req) + if err != nil && needsAuthStyleProbe { + // If we get an error, assume the server wants the + // clientID & clientSecret in a different form. + // See https://code.google.com/p/goauth2/issues/detail?id=31 for background. + // In summary: + // - Reddit only accepts client secret in the Authorization header + // - Dropbox accepts either it in URL param or Auth header, but not both. + // - Google only accepts URL param (not spec compliant?), not Auth header + // - Stripe only accepts client secret in Auth header with Bearer method, not Basic + // + // We used to maintain a big table in this code of all the sites and which way + // they went, but maintaining it didn't scale & got annoying. + // So just try both ways. + authStyle = AuthStyleInParams // the second way we'll try + req, _ = newTokenRequest(tokenURL, clientID, clientSecret, v, authStyle) + token, err = doTokenRoundTrip(ctx, req) } - r, err := hc.Do(req) + if needsAuthStyleProbe && err == nil { + styleCache.setAuthStyle(tokenURL, authStyle) + } + // Don't overwrite `RefreshToken` with an empty value + // if this was a token refreshing request. + if token != nil && token.RefreshToken == "" { + token.RefreshToken = v.Get("refresh_token") + } + return token, err +} + +func doTokenRoundTrip(ctx context.Context, req *http.Request) (*Token, error) { + r, err := ContextClient(ctx).Do(req.WithContext(ctx)) if err != nil { return nil, err } - defer r.Body.Close() body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20)) + r.Body.Close() if err != nil { return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err) } - if code := r.StatusCode; code < 200 || code > 299 { - return nil, fmt.Errorf("oauth2: cannot fetch token: %v\nResponse: %s", r.Status, body) + + failureStatus := r.StatusCode < 200 || r.StatusCode > 299 + retrieveError := &RetrieveError{ + Response: r, + Body: body, + // attempt to populate error detail below } var token *Token content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type")) switch content { case "application/x-www-form-urlencoded", "text/plain": + // some endpoints return a query string vals, err := url.ParseQuery(string(body)) if err != nil { - return nil, err + if failureStatus { + return nil, retrieveError + } + return nil, fmt.Errorf("oauth2: cannot parse response: %v", err) } + retrieveError.ErrorCode = vals.Get("error") + retrieveError.ErrorDescription = vals.Get("error_description") + retrieveError.ErrorURI = vals.Get("error_uri") token = &Token{ AccessToken: vals.Get("access_token"), TokenType: vals.Get("token_type"), @@ -192,12 +292,6 @@ func RetrieveToken(ctx context.Context, ClientID, ClientSecret, TokenURL string, Raw: vals, } e := vals.Get("expires_in") - if e == "" { - // TODO(jbd): Facebook's OAuth2 implementation is broken and - // returns expires_in field in expires. Remove the fallback to expires, - // when Facebook fixes their implementation. - e = vals.Get("expires") - } expires, _ := strconv.Atoi(e) if expires != 0 { token.Expiry = time.Now().Add(time.Duration(expires) * time.Second) @@ -205,8 +299,14 @@ func RetrieveToken(ctx context.Context, ClientID, ClientSecret, TokenURL string, default: var tj tokenJSON if err = json.Unmarshal(body, &tj); err != nil { - return nil, err + if failureStatus { + return nil, retrieveError + } + return nil, fmt.Errorf("oauth2: cannot parse json: %v", err) } + retrieveError.ErrorCode = tj.ErrorCode + retrieveError.ErrorDescription = tj.ErrorDescription + retrieveError.ErrorURI = tj.ErrorURI token = &Token{ AccessToken: tj.AccessToken, TokenType: tj.TokenType, @@ -216,10 +316,37 @@ func RetrieveToken(ctx context.Context, ClientID, ClientSecret, TokenURL string, } json.Unmarshal(body, &token.Raw) // no error checks for optional fields } - // Don't overwrite `RefreshToken` with an empty value - // if this was a token refreshing request. - if token.RefreshToken == "" { - token.RefreshToken = v.Get("refresh_token") + // according to spec, servers should respond status 400 in error case + // https://www.rfc-editor.org/rfc/rfc6749#section-5.2 + // but some unorthodox servers respond 200 in error case + if failureStatus || retrieveError.ErrorCode != "" { + return nil, retrieveError + } + if token.AccessToken == "" { + return nil, errors.New("oauth2: server response missing access_token") } return token, nil } + +// mirrors oauth2.RetrieveError +type RetrieveError struct { + Response *http.Response + Body []byte + ErrorCode string + ErrorDescription string + ErrorURI string +} + +func (r *RetrieveError) Error() string { + if r.ErrorCode != "" { + s := fmt.Sprintf("oauth2: %q", r.ErrorCode) + if r.ErrorDescription != "" { + s += fmt.Sprintf(" %q", r.ErrorDescription) + } + if r.ErrorURI != "" { + s += fmt.Sprintf(" %q", r.ErrorURI) + } + return s + } + return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) +} diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go index f1f173e3..b9db01dd 100644 --- a/vendor/golang.org/x/oauth2/internal/transport.go +++ b/vendor/golang.org/x/oauth2/internal/transport.go @@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package internal contains support packages for oauth2 package. package internal import ( + "context" "net/http" - - "golang.org/x/net/context" ) // HTTPClient is the context key to use with golang.org/x/net/context's @@ -20,50 +18,11 @@ var HTTPClient ContextKey // because nobody else can create a ContextKey, being unexported. type ContextKey struct{} -// ContextClientFunc is a func which tries to return an *http.Client -// given a Context value. If it returns an error, the search stops -// with that error. If it returns (nil, nil), the search continues -// down the list of registered funcs. -type ContextClientFunc func(context.Context) (*http.Client, error) - -var contextClientFuncs []ContextClientFunc - -func RegisterContextClientFunc(fn ContextClientFunc) { - contextClientFuncs = append(contextClientFuncs, fn) -} - -func ContextClient(ctx context.Context) (*http.Client, error) { +func ContextClient(ctx context.Context) *http.Client { if ctx != nil { if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok { - return hc, nil - } - } - for _, fn := range contextClientFuncs { - c, err := fn(ctx) - if err != nil { - return nil, err + return hc } - if c != nil { - return c, nil - } - } - return http.DefaultClient, nil -} - -func ContextTransport(ctx context.Context) http.RoundTripper { - hc, err := ContextClient(ctx) - // This is a rare error case (somebody using nil on App Engine). - if err != nil { - return ErrorTransport{err} } - return hc.Transport -} - -// ErrorTransport returns the specified error on RoundTrip. -// This RoundTripper should be used in rare error cases where -// error handling can be postponed to response handling time. -type ErrorTransport struct{ Err error } - -func (t ErrorTransport) RoundTrip(*http.Request) (*http.Response, error) { - return nil, t.Err + return http.DefaultClient } diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go index 9b7b977d..09f6a49b 100644 --- a/vendor/golang.org/x/oauth2/oauth2.go +++ b/vendor/golang.org/x/oauth2/oauth2.go @@ -3,40 +3,42 @@ // license that can be found in the LICENSE file. // Package oauth2 provides support for making -// OAuth2 authorized and authenticated HTTP requests. +// OAuth2 authorized and authenticated HTTP requests, +// as specified in RFC 6749. // It can additionally grant authorization with Bearer JWT. -package oauth2 +package oauth2 // import "golang.org/x/oauth2" import ( "bytes" + "context" "errors" "net/http" "net/url" "strings" "sync" + "time" - "golang.org/x/net/context" "golang.org/x/oauth2/internal" ) // NoContext is the default context you should supply if not using // your own context.Context (see https://golang.org/x/net/context). +// +// Deprecated: Use context.Background() or context.TODO() instead. var NoContext = context.TODO() -// RegisterBrokenAuthHeaderProvider registers an OAuth2 server -// identified by the tokenURL prefix as an OAuth2 implementation -// which doesn't support the HTTP Basic authentication -// scheme to authenticate with the authorization server. -// Once a server is registered, credentials (client_id and client_secret) -// will be passed as query parameters rather than being present -// in the Authorization header. -// See https://code.google.com/p/goauth2/issues/detail?id=31 for background. -func RegisterBrokenAuthHeaderProvider(tokenURL string) { - internal.RegisterBrokenAuthHeaderProvider(tokenURL) -} +// RegisterBrokenAuthHeaderProvider previously did something. It is now a no-op. +// +// Deprecated: this function no longer does anything. Caller code that +// wants to avoid potential extra HTTP requests made during +// auto-probing of the provider's auth style should set +// Endpoint.AuthStyle. +func RegisterBrokenAuthHeaderProvider(tokenURL string) {} // Config describes a typical 3-legged OAuth2 flow, with both the // client application information and the server's endpoint URLs. +// For the client credentials 2-legged OAuth2 flow, see the clientcredentials +// package (https://golang.org/x/oauth2/clientcredentials). type Config struct { // ClientID is the application's ID. ClientID string @@ -56,6 +58,10 @@ type Config struct { // Scope specifies optional requested permissions. Scopes []string + + // authStyleCache caches which auth style to use when Endpoint.AuthStyle is + // the zero value (AuthStyleAutoDetect). + authStyleCache internal.LazyAuthStyleCache } // A TokenSource is anything that can return a token. @@ -66,13 +72,39 @@ type TokenSource interface { Token() (*Token, error) } -// Endpoint contains the OAuth 2.0 provider's authorization and token +// Endpoint represents an OAuth 2.0 provider's authorization and token // endpoint URLs. type Endpoint struct { - AuthURL string - TokenURL string + AuthURL string + DeviceAuthURL string + TokenURL string + + // AuthStyle optionally specifies how the endpoint wants the + // client ID & client secret sent. The zero value means to + // auto-detect. + AuthStyle AuthStyle } +// AuthStyle represents how requests for tokens are authenticated +// to the server. +type AuthStyle int + +const ( + // AuthStyleAutoDetect means to auto-detect which authentication + // style the provider wants by trying both ways and caching + // the successful way for the future. + AuthStyleAutoDetect AuthStyle = 0 + + // AuthStyleInParams sends the "client_id" and "client_secret" + // in the POST body as application/x-www-form-urlencoded parameters. + AuthStyleInParams AuthStyle = 1 + + // AuthStyleInHeader sends the client_id and client_password + // using HTTP Basic Authorization. This is an optional style + // described in the OAuth2 RFC 6749 section 2.3.1. + AuthStyleInHeader AuthStyle = 2 +) + var ( // AccessTypeOnline and AccessTypeOffline are options passed // to the Options.AuthCodeURL method. They modify the @@ -91,7 +123,7 @@ var ( // ApprovalForce forces the users to view the consent dialog // and confirm the permissions request at the URL returned // from AuthCodeURL, even if they've already done so. - ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force") + ApprovalForce AuthCodeOption = SetAuthURLParam("prompt", "consent") ) // An AuthCodeOption is passed to Config.AuthCodeURL. @@ -112,22 +144,34 @@ func SetAuthURLParam(key, value string) AuthCodeOption { // AuthCodeURL returns a URL to OAuth 2.0 provider's consent page // that asks for permissions for the required scopes explicitly. // -// State is a token to protect the user from CSRF attacks. You must -// always provide a non-zero string and validate that it matches the -// the state query parameter on your redirect callback. -// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info. +// State is an opaque value used by the client to maintain state between the +// request and callback. The authorization server includes this value when +// redirecting the user agent back to the client. // // Opts may include AccessTypeOnline or AccessTypeOffline, as well // as ApprovalForce. +// +// To protect against CSRF attacks, opts should include a PKCE challenge +// (S256ChallengeOption). Not all servers support PKCE. An alternative is to +// generate a random state parameter and verify it after exchange. +// See https://datatracker.ietf.org/doc/html/rfc6749#section-10.12 (predating +// PKCE), https://www.oauth.com/oauth2-servers/pkce/ and +// https://www.ietf.org/archive/id/draft-ietf-oauth-v2-1-09.html#name-cross-site-request-forgery (describing both approaches) func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { var buf bytes.Buffer buf.WriteString(c.Endpoint.AuthURL) v := url.Values{ "response_type": {"code"}, "client_id": {c.ClientID}, - "redirect_uri": internal.CondVal(c.RedirectURL), - "scope": internal.CondVal(strings.Join(c.Scopes, " ")), - "state": internal.CondVal(state), + } + if c.RedirectURL != "" { + v.Set("redirect_uri", c.RedirectURL) + } + if len(c.Scopes) > 0 { + v.Set("scope", strings.Join(c.Scopes, " ")) + } + if state != "" { + v.Set("state", state) } for _, opt := range opts { opt.setValue(v) @@ -150,15 +194,17 @@ func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string { // and when other authorization grant types are not available." // See https://tools.ietf.org/html/rfc6749#section-4.3 for more info. // -// The HTTP client to use is derived from the context. -// If nil, http.DefaultClient is used. +// The provided context optionally controls which HTTP client is used. See the HTTPClient variable. func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) { - return retrieveToken(ctx, c, url.Values{ + v := url.Values{ "grant_type": {"password"}, "username": {username}, "password": {password}, - "scope": internal.CondVal(strings.Join(c.Scopes, " ")), - }) + } + if len(c.Scopes) > 0 { + v.Set("scope", strings.Join(c.Scopes, " ")) + } + return retrieveToken(ctx, c, v) } // Exchange converts an authorization code into a token. @@ -166,18 +212,26 @@ func (c *Config) PasswordCredentialsToken(ctx context.Context, username, passwor // It is used after a resource provider redirects the user back // to the Redirect URI (the URL obtained from AuthCodeURL). // -// The HTTP client to use is derived from the context. -// If a client is not provided via the context, http.DefaultClient is used. +// The provided context optionally controls which HTTP client is used. See the HTTPClient variable. // // The code will be in the *http.Request.FormValue("code"). Before -// calling Exchange, be sure to validate FormValue("state"). -func (c *Config) Exchange(ctx context.Context, code string) (*Token, error) { - return retrieveToken(ctx, c, url.Values{ - "grant_type": {"authorization_code"}, - "code": {code}, - "redirect_uri": internal.CondVal(c.RedirectURL), - "scope": internal.CondVal(strings.Join(c.Scopes, " ")), - }) +// calling Exchange, be sure to validate FormValue("state") if you are +// using it to protect against CSRF attacks. +// +// If using PKCE to protect against CSRF attacks, opts should include a +// VerifierOption. +func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) { + v := url.Values{ + "grant_type": {"authorization_code"}, + "code": {code}, + } + if c.RedirectURL != "" { + v.Set("redirect_uri", c.RedirectURL) + } + for _, opt := range opts { + opt.setValue(v) + } + return retrieveToken(ctx, c, v) } // Client returns an HTTP client using the provided token. @@ -246,6 +300,8 @@ type reuseTokenSource struct { mu sync.Mutex // guards t t *Token + + expiryDelta time.Duration } // Token returns the current token if it's still valid, else will @@ -261,6 +317,7 @@ func (s *reuseTokenSource) Token() (*Token, error) { if err != nil { return nil, err } + t.expiryDelta = s.expiryDelta s.t = t return t, nil } @@ -288,20 +345,20 @@ var HTTPClient internal.ContextKey // NewClient creates an *http.Client from a Context and TokenSource. // The returned client is not valid beyond the lifetime of the context. // +// Note that if a custom *http.Client is provided via the Context it +// is used only for token acquisition and is not used to configure the +// *http.Client returned from NewClient. +// // As a special case, if src is nil, a non-OAuth2 client is returned // using the provided context. This exists to support related OAuth2 // packages. func NewClient(ctx context.Context, src TokenSource) *http.Client { if src == nil { - c, err := internal.ContextClient(ctx) - if err != nil { - return &http.Client{Transport: internal.ErrorTransport{err}} - } - return c + return internal.ContextClient(ctx) } return &http.Client{ Transport: &Transport{ - Base: internal.ContextTransport(ctx), + Base: internal.ContextClient(ctx).Transport, Source: ReuseTokenSource(nil, src), }, } @@ -335,3 +392,30 @@ func ReuseTokenSource(t *Token, src TokenSource) TokenSource { new: src, } } + +// ReuseTokenSourceWithExpiry returns a TokenSource that acts in the same manner as the +// TokenSource returned by ReuseTokenSource, except the expiry buffer is +// configurable. The expiration time of a token is calculated as +// t.Expiry.Add(-earlyExpiry). +func ReuseTokenSourceWithExpiry(t *Token, src TokenSource, earlyExpiry time.Duration) TokenSource { + // Don't wrap a reuseTokenSource in itself. That would work, + // but cause an unnecessary number of mutex operations. + // Just build the equivalent one. + if rt, ok := src.(*reuseTokenSource); ok { + if t == nil { + // Just use it directly, but set the expiryDelta to earlyExpiry, + // so the behavior matches what the user expects. + rt.expiryDelta = earlyExpiry + return rt + } + src = rt.new + } + if t != nil { + t.expiryDelta = earlyExpiry + } + return &reuseTokenSource{ + t: t, + new: src, + expiryDelta: earlyExpiry, + } +} diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go index 7a3167f1..109997d7 100644 --- a/vendor/golang.org/x/oauth2/token.go +++ b/vendor/golang.org/x/oauth2/token.go @@ -5,22 +5,23 @@ package oauth2 import ( + "context" + "fmt" "net/http" "net/url" "strconv" "strings" "time" - "golang.org/x/net/context" "golang.org/x/oauth2/internal" ) -// expiryDelta determines how earlier a token should be considered +// defaultExpiryDelta determines how earlier a token should be considered // expired than its actual expiration time. It is used to avoid late // expirations due to client-server time mismatches. -const expiryDelta = 10 * time.Second +const defaultExpiryDelta = 10 * time.Second -// Token represents the crendentials used to authorize +// Token represents the credentials used to authorize // the requests to access protected resources on the OAuth 2.0 // provider's backend. // @@ -48,9 +49,21 @@ type Token struct { // mechanisms for that TokenSource will not be used. Expiry time.Time `json:"expiry,omitempty"` + // ExpiresIn is the OAuth2 wire format "expires_in" field, + // which specifies how many seconds later the token expires, + // relative to an unknown time base approximately around "now". + // It is the application's responsibility to populate + // `Expiry` from `ExpiresIn` when required. + ExpiresIn int64 `json:"expires_in,omitempty"` + // raw optionally contains extra metadata from the server // when updating a token. raw interface{} + + // expiryDelta is used to calculate when a token is considered + // expired, by subtracting from Expiry. If zero, defaultExpiryDelta + // is used. + expiryDelta time.Duration } // Type returns t.TokenType if non-empty, else "Bearer". @@ -117,13 +130,21 @@ func (t *Token) Extra(key string) interface{} { return v } +// timeNow is time.Now but pulled out as a variable for tests. +var timeNow = time.Now + // expired reports whether the token is expired. // t must be non-nil. func (t *Token) expired() bool { if t.Expiry.IsZero() { return false } - return t.Expiry.Add(-expiryDelta).Before(time.Now()) + + expiryDelta := defaultExpiryDelta + if t.expiryDelta != 0 { + expiryDelta = t.expiryDelta + } + return t.Expiry.Round(0).Add(-expiryDelta).Before(timeNow()) } // Valid reports whether t is non-nil, has an AccessToken, and is not expired. @@ -150,9 +171,42 @@ func tokenFromInternal(t *internal.Token) *Token { // This token is then mapped from *internal.Token into an *oauth2.Token which is returned along // with an error.. func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) { - tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v) + tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v, internal.AuthStyle(c.Endpoint.AuthStyle), c.authStyleCache.Get()) if err != nil { + if rErr, ok := err.(*internal.RetrieveError); ok { + return nil, (*RetrieveError)(rErr) + } return nil, err } return tokenFromInternal(tk), nil } + +// RetrieveError is the error returned when the token endpoint returns a +// non-2XX HTTP status code or populates RFC 6749's 'error' parameter. +// https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 +type RetrieveError struct { + Response *http.Response + // Body is the body that was consumed by reading Response.Body. + // It may be truncated. + Body []byte + // ErrorCode is RFC 6749's 'error' parameter. + ErrorCode string + // ErrorDescription is RFC 6749's 'error_description' parameter. + ErrorDescription string + // ErrorURI is RFC 6749's 'error_uri' parameter. + ErrorURI string +} + +func (r *RetrieveError) Error() string { + if r.ErrorCode != "" { + s := fmt.Sprintf("oauth2: %q", r.ErrorCode) + if r.ErrorDescription != "" { + s += fmt.Sprintf(" %q", r.ErrorDescription) + } + if r.ErrorURI != "" { + s += fmt.Sprintf(" %q", r.ErrorURI) + } + return s + } + return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body) +} diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go index 92ac7e25..90657915 100644 --- a/vendor/golang.org/x/oauth2/transport.go +++ b/vendor/golang.org/x/oauth2/transport.go @@ -6,7 +6,7 @@ package oauth2 import ( "errors" - "io" + "log" "net/http" "sync" ) @@ -25,15 +25,20 @@ type Transport struct { // Base is the base RoundTripper used to make HTTP requests. // If nil, http.DefaultTransport is used. Base http.RoundTripper - - mu sync.Mutex // guards modReq - modReq map[*http.Request]*http.Request // original -> modified } // RoundTrip authorizes and authenticates the request with an -// access token. If no token exists or token is expired, -// tries to refresh/fetch a new token. +// access token from Transport's Source. func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { + reqBodyClosed := false + if req.Body != nil { + defer func() { + if !reqBodyClosed { + req.Body.Close() + } + }() + } + if t.Source == nil { return nil, errors.New("oauth2: Transport's Source is nil") } @@ -44,31 +49,22 @@ func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) { req2 := cloneRequest(req) // per RoundTripper contract token.SetAuthHeader(req2) - t.setModReq(req, req2) - res, err := t.base().RoundTrip(req2) - if err != nil { - t.setModReq(req, nil) - return nil, err - } - res.Body = &onEOFReader{ - rc: res.Body, - fn: func() { t.setModReq(req, nil) }, - } - return res, nil + + // req.Body is assumed to be closed by the base RoundTripper. + reqBodyClosed = true + return t.base().RoundTrip(req2) } -// CancelRequest cancels an in-flight request by closing its connection. +var cancelOnce sync.Once + +// CancelRequest does nothing. It used to be a legacy cancellation mechanism +// but now only it only logs on first use to warn that it's deprecated. +// +// Deprecated: use contexts for cancellation instead. func (t *Transport) CancelRequest(req *http.Request) { - type canceler interface { - CancelRequest(*http.Request) - } - if cr, ok := t.base().(canceler); ok { - t.mu.Lock() - modReq := t.modReq[req] - delete(t.modReq, req) - t.mu.Unlock() - cr.CancelRequest(modReq) - } + cancelOnce.Do(func() { + log.Printf("deprecated: golang.org/x/oauth2: Transport.CancelRequest no longer does anything; use contexts") + }) } func (t *Transport) base() http.RoundTripper { @@ -78,19 +74,6 @@ func (t *Transport) base() http.RoundTripper { return http.DefaultTransport } -func (t *Transport) setModReq(orig, mod *http.Request) { - t.mu.Lock() - defer t.mu.Unlock() - if t.modReq == nil { - t.modReq = make(map[*http.Request]*http.Request) - } - if mod == nil { - delete(t.modReq, orig) - } else { - t.modReq[orig] = mod - } -} - // cloneRequest returns a clone of the provided *http.Request. // The clone is a shallow copy of the struct and its Header map. func cloneRequest(r *http.Request) *http.Request { @@ -104,29 +87,3 @@ func cloneRequest(r *http.Request) *http.Request { } return r2 } - -type onEOFReader struct { - rc io.ReadCloser - fn func() -} - -func (r *onEOFReader) Read(p []byte) (n int, err error) { - n, err = r.rc.Read(p) - if err == io.EOF { - r.runFunc() - } - return -} - -func (r *onEOFReader) Close() error { - err := r.rc.Close() - r.runFunc() - return err -} - -func (r *onEOFReader) runFunc() { - if fn := r.fn; fn != nil { - fn() - r.fn = nil - } -} diff --git a/vendor/google.golang.org/api/drive/v3/drive-api.json b/vendor/google.golang.org/api/drive/v3/drive-api.json index 896d44e3..1a8350e3 100644 --- a/vendor/google.golang.org/api/drive/v3/drive-api.json +++ b/vendor/google.golang.org/api/drive/v3/drive-api.json @@ -1,2410 +1,5259 @@ { - "kind": "discovery#restDescription", - "etag": "\"bRFOOrZKfO9LweMbPqu0kcu6De8/O9_NbpoVnW5GMGl7qWBIajcyrt8\"", - "discoveryVersion": "v1", - "id": "drive:v3", - "name": "drive", - "version": "v3", - "revision": "20160303", - "title": "Drive API", - "description": "The API to interact with Drive.", - "ownerDomain": "google.com", - "ownerName": "Google", - "icons": { - "x16": "https://ssl.gstatic.com/docs/doclist/images/drive_icon_16.png", - "x32": "https://ssl.gstatic.com/docs/doclist/images/drive_icon_32.png" - }, - "documentationLink": "https://developers.google.com/drive/", - "protocol": "rest", - "baseUrl": "https://www.googleapis.com/drive/v3/", - "basePath": "/drive/v3/", - "rootUrl": "https://www.googleapis.com/", - "servicePath": "drive/v3/", - "batchPath": "batch", - "parameters": { - "alt": { - "type": "string", - "description": "Data format for the response.", - "default": "json", - "enum": [ - "json" - ], - "enumDescriptions": [ - "Responses with Content-Type of application/json" - ], - "location": "query" - }, - "fields": { - "type": "string", - "description": "Selector specifying which fields to include in a partial response.", - "location": "query" - }, - "key": { - "type": "string", - "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.", - "location": "query" - }, - "oauth_token": { - "type": "string", - "description": "OAuth 2.0 token for the current user.", - "location": "query" - }, - "prettyPrint": { - "type": "boolean", - "description": "Returns response with indentations and line breaks.", - "default": "true", - "location": "query" - }, - "quotaUser": { - "type": "string", - "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters. Overrides userIp if both are provided.", - "location": "query" - }, - "userIp": { - "type": "string", - "description": "IP address of the site where the request originates. Use this if you want to enforce per-user limits.", - "location": "query" - } - }, - "auth": { - "oauth2": { - "scopes": { - "https://www.googleapis.com/auth/drive": { - "description": "View and manage the files in your Google Drive" - }, - "https://www.googleapis.com/auth/drive.appdata": { - "description": "View and manage its own configuration data in your Google Drive" - }, - "https://www.googleapis.com/auth/drive.file": { - "description": "View and manage Google Drive files and folders that you have opened or created with this app" - }, - "https://www.googleapis.com/auth/drive.metadata": { - "description": "View and manage metadata of files in your Google Drive" - }, - "https://www.googleapis.com/auth/drive.metadata.readonly": { - "description": "View metadata for files in your Google Drive" - }, - "https://www.googleapis.com/auth/drive.photos.readonly": { - "description": "View the photos, videos and albums in your Google Photos" - }, - "https://www.googleapis.com/auth/drive.readonly": { - "description": "View the files in your Google Drive" - }, - "https://www.googleapis.com/auth/drive.scripts": { - "description": "Modify your Google Apps Script scripts' behavior" - } - } - } - }, - "schemas": { - "About": { - "id": "About", - "type": "object", - "description": "Information about the user, the user's Drive, and system capabilities.", - "properties": { - "appInstalled": { - "type": "boolean", - "description": "Whether the user has installed the requesting app." - }, - "exportFormats": { - "type": "object", - "description": "A map of source MIME type to possible targets for all supported exports.", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "folderColorPalette": { - "type": "array", - "description": "The currently supported folder colors as RGB hex strings.", - "items": { - "type": "string" - } - }, - "importFormats": { - "type": "object", - "description": "A map of source MIME type to possible targets for all supported imports.", - "additionalProperties": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "kind": { - "type": "string", - "description": "This is always drive#about.", - "default": "drive#about" - }, - "maxImportSizes": { - "type": "object", - "description": "A map of maximum import sizes by MIME type, in bytes.", - "additionalProperties": { - "type": "string", - "format": "int64" - } - }, - "maxUploadSize": { - "type": "string", - "description": "The maximum upload size in bytes.", - "format": "int64" - }, - "storageQuota": { - "type": "object", - "description": "The user's storage quota limits and usage. All fields are measured in bytes.", - "properties": { - "limit": { - "type": "string", - "description": "The usage limit, if applicable. This will not be present if the user has unlimited storage.", - "format": "int64" - }, - "usage": { - "type": "string", - "description": "The total usage across all services.", - "format": "int64" - }, - "usageInDrive": { - "type": "string", - "description": "The usage by all files in Google Drive.", - "format": "int64" - }, - "usageInDriveTrash": { - "type": "string", - "description": "The usage by trashed files in Google Drive.", - "format": "int64" + "auth": { + "oauth2": { + "scopes": { + "https://www.googleapis.com/auth/drive": { + "description": "See, edit, create, and delete all of your Google Drive files" + }, + "https://www.googleapis.com/auth/drive.appdata": { + "description": "See, create, and delete its own configuration data in your Google Drive" + }, + "https://www.googleapis.com/auth/drive.apps.readonly": { + "description": "View your Google Drive apps" + }, + "https://www.googleapis.com/auth/drive.file": { + "description": "See, edit, create, and delete only the specific Google Drive files you use with this app" + }, + "https://www.googleapis.com/auth/drive.meet.readonly": { + "description": "See and download your Google Drive files that were created or edited by Google Meet." + }, + "https://www.googleapis.com/auth/drive.metadata": { + "description": "View and manage metadata of files in your Google Drive" + }, + "https://www.googleapis.com/auth/drive.metadata.readonly": { + "description": "See information about your Google Drive files" + }, + "https://www.googleapis.com/auth/drive.photos.readonly": { + "description": "View the photos, videos and albums in your Google Photos" + }, + "https://www.googleapis.com/auth/drive.readonly": { + "description": "See and download all your Google Drive files" + }, + "https://www.googleapis.com/auth/drive.scripts": { + "description": "Modify your Google Apps Script scripts' behavior" + } } - } - }, - "user": { - "$ref": "User", - "description": "The authenticated user." } - } }, - "Change": { - "id": "Change", - "type": "object", - "description": "A change to a file.", - "properties": { - "file": { - "$ref": "File", - "description": "The updated state of the file. Present if the file has not been removed." - }, - "fileId": { - "type": "string", - "description": "The ID of the file which has changed." - }, - "kind": { - "type": "string", - "description": "This is always drive#change.", - "default": "drive#change" - }, - "removed": { - "type": "boolean", - "description": "Whether the file has been removed from the view of the changes list, for example by deletion or lost access." - }, - "time": { - "type": "string", - "description": "The time of this change (RFC 3339 date-time).", - "format": "date-time" - } - } + "basePath": "/drive/v3/", + "baseUrl": "https://www.googleapis.com/drive/v3/", + "batchPath": "batch/drive/v3", + "description": "The Google Drive API allows clients to access resources from Google Drive.", + "discoveryVersion": "v1", + "documentationLink": "https://developers.google.com/drive/", + "icons": { + "x16": "http://www.google.com/images/icons/product/search-16.gif", + "x32": "http://www.google.com/images/icons/product/search-32.gif" }, - "ChangeList": { - "id": "ChangeList", - "type": "object", - "description": "A list of changes for a user.", - "properties": { - "changes": { - "type": "array", - "description": "The page of changes.", - "items": { - "$ref": "Change" - } - }, - "kind": { - "type": "string", - "description": "This is always drive#changeList.", - "default": "drive#changeList" - }, - "newStartPageToken": { - "type": "string", - "description": "The starting page token for future changes. This will be present only if the end of the current changes list has been reached." + "id": "drive:v3", + "kind": "discovery#restDescription", + "mtlsRootUrl": "https://www.mtls.googleapis.com/", + "name": "drive", + "ownerDomain": "google.com", + "ownerName": "Google", + "parameters": { + "$.xgafv": { + "description": "V1 error format.", + "enum": [ + "1", + "2" + ], + "enumDescriptions": [ + "v1 error format", + "v2 error format" + ], + "location": "query", + "type": "string" }, - "nextPageToken": { - "type": "string", - "description": "The page token for the next page of changes. This will be absent if the end of the current changes list has been reached." - } - } - }, - "Channel": { - "id": "Channel", - "type": "object", - "description": "An notification channel used to watch for resource changes.", - "properties": { - "address": { - "type": "string", - "description": "The address where notifications are delivered for this channel." + "access_token": { + "description": "OAuth access token.", + "location": "query", + "type": "string" }, - "expiration": { - "type": "string", - "description": "Date and time of notification channel expiration, expressed as a Unix timestamp, in milliseconds. Optional.", - "format": "int64" + "alt": { + "default": "json", + "description": "Data format for response.", + "enum": [ + "json", + "media", + "proto" + ], + "enumDescriptions": [ + "Responses with Content-Type of application/json", + "Media download with context-dependent Content-Type", + "Responses with Content-Type of application/x-protobuf" + ], + "location": "query", + "type": "string" }, - "id": { - "type": "string", - "description": "A UUID or similar unique string that identifies this channel." + "callback": { + "description": "JSONP", + "location": "query", + "type": "string" }, - "kind": { - "type": "string", - "description": "Identifies this as a notification channel used to watch for changes to a resource. Value: the fixed string \"api#channel\".", - "default": "api#channel" + "fields": { + "description": "Selector specifying which fields to include in a partial response.", + "location": "query", + "type": "string" }, - "params": { - "type": "object", - "description": "Additional parameters controlling delivery channel behavior. Optional.", - "additionalProperties": { - "type": "string", - "description": "Declares a new parameter by name." - } + "key": { + "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.", + "location": "query", + "type": "string" }, - "payload": { - "type": "boolean", - "description": "A Boolean value to indicate whether payload is wanted. Optional." + "oauth_token": { + "description": "OAuth 2.0 token for the current user.", + "location": "query", + "type": "string" }, - "resourceId": { - "type": "string", - "description": "An opaque ID that identifies the resource being watched on this channel. Stable across different API versions." + "prettyPrint": { + "default": "true", + "description": "Returns response with indentations and line breaks.", + "location": "query", + "type": "boolean" }, - "resourceUri": { - "type": "string", - "description": "A version-specific identifier for the watched resource." + "quotaUser": { + "description": "Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.", + "location": "query", + "type": "string" }, - "token": { - "type": "string", - "description": "An arbitrary string delivered to the target address with each notification delivered over this channel. Optional." + "uploadType": { + "description": "Legacy upload protocol for media (e.g. \"media\", \"multipart\").", + "location": "query", + "type": "string" }, - "type": { - "type": "string", - "description": "The type of delivery mechanism used for this channel." + "upload_protocol": { + "description": "Upload protocol for media (e.g. \"raw\", \"multipart\").", + "location": "query", + "type": "string" } - } }, - "Comment": { - "id": "Comment", - "type": "object", - "description": "A comment on a file.", - "properties": { - "anchor": { - "type": "string", - "description": "A region of the document represented as a JSON string. See anchor documentation for details on how to define and interpret anchor properties." - }, - "author": { - "$ref": "User", - "description": "The user who created the comment." - }, - "content": { - "type": "string", - "description": "The plain text content of the comment. This field is used for setting the content, while htmlContent should be displayed.", - "annotations": { - "required": [ - "drive.comments.create", - "drive.comments.update" - ] - } - }, - "createdTime": { - "type": "string", - "description": "The time at which the comment was created (RFC 3339 date-time).", - "format": "date-time" - }, - "deleted": { - "type": "boolean", - "description": "Whether the comment has been deleted. A deleted comment has no content." - }, - "htmlContent": { - "type": "string", - "description": "The content of the comment with HTML formatting." - }, - "id": { - "type": "string", - "description": "The ID of the comment." + "protocol": "rest", + "resources": { + "about": { + "methods": { + "get": { + "description": "Gets information about the user, the user's Drive, and system capabilities.", + "flatPath": "about", + "httpMethod": "GET", + "id": "drive.about.get", + "parameterOrder": [], + "parameters": {}, + "path": "about", + "response": { + "$ref": "About" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + } + } }, - "kind": { - "type": "string", - "description": "This is always drive#comment.", - "default": "drive#comment" + "accessproposals": { + "methods": { + "get": { + "description": "Retrieves an AccessProposal by ID.", + "flatPath": "files/{fileId}/accessproposals/{proposalId}", + "httpMethod": "GET", + "id": "drive.accessproposals.get", + "parameterOrder": [ + "fileId", + "proposalId" + ], + "parameters": { + "fileId": { + "description": "Required. The id of the item the request is on.", + "location": "path", + "required": true, + "type": "string" + }, + "proposalId": { + "description": "Required. The id of the access proposal to resolve.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/accessproposals/{proposalId}", + "response": { + "$ref": "AccessProposal" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "list": { + "description": "List the AccessProposals on a file. Note: Only approvers are able to list AccessProposals on a file. If the user is not an approver, returns a 403.", + "flatPath": "files/{fileId}/accessproposals", + "httpMethod": "GET", + "id": "drive.accessproposals.list", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "fileId": { + "description": "Required. The id of the item the request is on.", + "location": "path", + "required": true, + "type": "string" + }, + "pageSize": { + "description": "Optional. The number of results per page", + "format": "int32", + "location": "query", + "type": "integer" + }, + "pageToken": { + "description": "Optional. The continuation token on the list of access requests.", + "location": "query", + "type": "string" + } + }, + "path": "files/{fileId}/accessproposals", + "response": { + "$ref": "ListAccessProposalsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "resolve": { + "description": "Used to approve or deny an Access Proposal.", + "flatPath": "files/{fileId}/accessproposals/{proposalId}:resolve", + "httpMethod": "POST", + "id": "drive.accessproposals.resolve", + "parameterOrder": [ + "fileId", + "proposalId" + ], + "parameters": { + "fileId": { + "description": "Required. The id of the item the request is on.", + "location": "path", + "required": true, + "type": "string" + }, + "proposalId": { + "description": "Required. The id of the access proposal to resolve.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/accessproposals/{proposalId}:resolve", + "request": { + "$ref": "ResolveAccessProposalRequest" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + } + } }, - "modifiedTime": { - "type": "string", - "description": "The last time the comment or any of its replies was modified (RFC 3339 date-time).", - "format": "date-time" + "apps": { + "methods": { + "get": { + "description": "Gets a specific app.", + "flatPath": "apps/{appId}", + "httpMethod": "GET", + "id": "drive.apps.get", + "parameterOrder": [ + "appId" + ], + "parameters": { + "appId": { + "description": "The ID of the app.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "apps/{appId}", + "response": { + "$ref": "App" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.apps.readonly", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "list": { + "description": "Lists a user's installed apps.", + "flatPath": "apps", + "httpMethod": "GET", + "id": "drive.apps.list", + "parameterOrder": [], + "parameters": { + "appFilterExtensions": { + "default": "", + "description": "A comma-separated list of file extensions to limit returned results. All results within the given app query scope which can open any of the given file extensions are included in the response. If `appFilterMimeTypes` are provided as well, the result is a union of the two resulting app lists.", + "location": "query", + "type": "string" + }, + "appFilterMimeTypes": { + "default": "", + "description": "A comma-separated list of file extensions to limit returned results. All results within the given app query scope which can open any of the given MIME types will be included in the response. If `appFilterExtensions` are provided as well, the result is a union of the two resulting app lists.", + "location": "query", + "type": "string" + }, + "languageCode": { + "description": "A language or locale code, as defined by BCP 47, with some extensions from Unicode's LDML format (http://www.unicode.org/reports/tr35/).", + "location": "query", + "type": "string" + } + }, + "path": "apps", + "response": { + "$ref": "AppList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive.apps.readonly" + ] + } + } }, - "quotedFileContent": { - "type": "object", - "description": "The file content to which the comment refers, typically within the anchor region. For a text file, for example, this would be the text at the location of the comment.", - "properties": { - "mimeType": { - "type": "string", - "description": "The MIME type of the quoted content." - }, - "value": { - "type": "string", - "description": "The quoted content itself. This is interpreted as plain text if set through the API." + "changes": { + "methods": { + "getStartPageToken": { + "description": "Gets the starting pageToken for listing future changes.", + "flatPath": "changes/startPageToken", + "httpMethod": "GET", + "id": "drive.changes.getStartPageToken", + "parameterOrder": [], + "parameters": { + "driveId": { + "description": "The ID of the shared drive for which the starting pageToken for listing future changes from that shared drive will be returned.", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "teamDriveId": { + "deprecated": true, + "description": "Deprecated: Use `driveId` instead.", + "location": "query", + "type": "string" + } + }, + "path": "changes/startPageToken", + "response": { + "$ref": "StartPageToken" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "list": { + "description": "Lists the changes for a user or shared drive.", + "flatPath": "changes", + "httpMethod": "GET", + "id": "drive.changes.list", + "parameterOrder": [ + "pageToken" + ], + "parameters": { + "driveId": { + "description": "The shared drive from which changes will be returned. If specified the change IDs will be reflective of the shared drive; use the combined drive ID and change ID as an identifier.", + "location": "query", + "type": "string" + }, + "includeCorpusRemovals": { + "default": "false", + "description": "Whether changes should include the file resource if the file is still accessible by the user at the time of the request, even when a file was removed from the list of changes and there will be no further change entries for this file.", + "location": "query", + "type": "boolean" + }, + "includeItemsFromAllDrives": { + "default": "false", + "description": "Whether both My Drive and shared drive items should be included in results.", + "location": "query", + "type": "boolean" + }, + "includeLabels": { + "description": "A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.", + "location": "query", + "type": "string" + }, + "includePermissionsForView": { + "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.", + "location": "query", + "type": "string" + }, + "includeRemoved": { + "default": "true", + "description": "Whether to include changes indicating that items have been removed from the list of changes, for example by deletion or loss of access.", + "location": "query", + "type": "boolean" + }, + "includeTeamDriveItems": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `includeItemsFromAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "pageSize": { + "default": "100", + "description": "The maximum number of changes to return per page.", + "format": "int32", + "location": "query", + "maximum": "1000", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response or to the response from the getStartPageToken method.", + "location": "query", + "required": true, + "type": "string" + }, + "restrictToMyDrive": { + "default": "false", + "description": "Whether to restrict the results to changes inside the My Drive hierarchy. This omits changes to files such as those in the Application Data folder or shared files which have not been added to My Drive.", + "location": "query", + "type": "boolean" + }, + "spaces": { + "default": "drive", + "description": "A comma-separated list of spaces to query within the corpora. Supported values are 'drive' and 'appDataFolder'.", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "teamDriveId": { + "deprecated": true, + "description": "Deprecated: Use `driveId` instead.", + "location": "query", + "type": "string" + } + }, + "path": "changes", + "response": { + "$ref": "ChangeList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ], + "supportsSubscription": true + }, + "watch": { + "description": "Subscribes to changes for a user.", + "flatPath": "changes/watch", + "httpMethod": "POST", + "id": "drive.changes.watch", + "parameterOrder": [ + "pageToken" + ], + "parameters": { + "driveId": { + "description": "The shared drive from which changes will be returned. If specified the change IDs will be reflective of the shared drive; use the combined drive ID and change ID as an identifier.", + "location": "query", + "type": "string" + }, + "includeCorpusRemovals": { + "default": "false", + "description": "Whether changes should include the file resource if the file is still accessible by the user at the time of the request, even when a file was removed from the list of changes and there will be no further change entries for this file.", + "location": "query", + "type": "boolean" + }, + "includeItemsFromAllDrives": { + "default": "false", + "description": "Whether both My Drive and shared drive items should be included in results.", + "location": "query", + "type": "boolean" + }, + "includeLabels": { + "description": "A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.", + "location": "query", + "type": "string" + }, + "includePermissionsForView": { + "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.", + "location": "query", + "type": "string" + }, + "includeRemoved": { + "default": "true", + "description": "Whether to include changes indicating that items have been removed from the list of changes, for example by deletion or loss of access.", + "location": "query", + "type": "boolean" + }, + "includeTeamDriveItems": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `includeItemsFromAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "pageSize": { + "default": "100", + "description": "The maximum number of changes to return per page.", + "format": "int32", + "location": "query", + "maximum": "1000", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response or to the response from the getStartPageToken method.", + "location": "query", + "required": true, + "type": "string" + }, + "restrictToMyDrive": { + "default": "false", + "description": "Whether to restrict the results to changes inside the My Drive hierarchy. This omits changes to files such as those in the Application Data folder or shared files which have not been added to My Drive.", + "location": "query", + "type": "boolean" + }, + "spaces": { + "default": "drive", + "description": "A comma-separated list of spaces to query within the corpora. Supported values are 'drive' and 'appDataFolder'.", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "teamDriveId": { + "deprecated": true, + "description": "Deprecated: Use `driveId` instead.", + "location": "query", + "type": "string" + } + }, + "path": "changes/watch", + "request": { + "$ref": "Channel", + "parameterName": "resource" + }, + "response": { + "$ref": "Channel" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ], + "supportsSubscription": true + } } - } }, - "replies": { - "type": "array", - "description": "The full list of replies to the comment in chronological order.", - "items": { - "$ref": "Reply" - } + "channels": { + "methods": { + "stop": { + "description": "Stops watching resources through this channel.", + "flatPath": "channels/stop", + "httpMethod": "POST", + "id": "drive.channels.stop", + "parameterOrder": [], + "parameters": {}, + "path": "channels/stop", + "request": { + "$ref": "Channel", + "parameterName": "resource" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + } + } }, - "resolved": { - "type": "boolean", - "description": "Whether the comment has been resolved by one of its replies." - } - } - }, - "CommentList": { - "id": "CommentList", - "type": "object", - "description": "A list of comments on a file.", - "properties": { "comments": { - "type": "array", - "description": "The page of comments.", - "items": { - "$ref": "Comment" - } - }, - "kind": { - "type": "string", - "description": "This is always drive#commentList.", - "default": "drive#commentList" - }, - "nextPageToken": { - "type": "string", - "description": "The page token for the next page of comments. This will be absent if the end of the comments list has been reached." - } - } - }, - "File": { - "id": "File", - "type": "object", - "description": "The metadata for a file.", - "properties": { - "appProperties": { - "type": "object", - "description": "A collection of arbitrary key-value pairs which are private to the requesting app.\nEntries with null values are cleared in update and copy requests.", - "additionalProperties": { - "type": "string" - } - }, - "capabilities": { - "type": "object", - "description": "Capabilities the current user has on the file.", - "properties": { - "canComment": { - "type": "boolean", - "description": "Whether the user can comment on the file." - }, - "canCopy": { - "type": "boolean", - "description": "Whether the user can copy the file." - }, - "canEdit": { - "type": "boolean", - "description": "Whether the user can edit the file's content." - }, - "canReadRevisions": { - "type": "boolean", - "description": "Whether the current user has read access to the Revisions resource of the file." - }, - "canShare": { - "type": "boolean", - "description": "Whether the user can modify the file's permissions and sharing settings." + "methods": { + "create": { + "description": "Creates a comment on a file.", + "flatPath": "files/{fileId}/comments", + "httpMethod": "POST", + "id": "drive.comments.create", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/comments", + "request": { + "$ref": "Comment" + }, + "response": { + "$ref": "Comment" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + }, + "delete": { + "description": "Deletes a comment.", + "flatPath": "files/{fileId}/comments/{commentId}", + "httpMethod": "DELETE", + "id": "drive.comments.delete", + "parameterOrder": [ + "fileId", + "commentId" + ], + "parameters": { + "commentId": { + "description": "The ID of the comment.", + "location": "path", + "required": true, + "type": "string" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/comments/{commentId}", + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + }, + "get": { + "description": "Gets a comment by ID.", + "flatPath": "files/{fileId}/comments/{commentId}", + "httpMethod": "GET", + "id": "drive.comments.get", + "parameterOrder": [ + "fileId", + "commentId" + ], + "parameters": { + "commentId": { + "description": "The ID of the comment.", + "location": "path", + "required": true, + "type": "string" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "includeDeleted": { + "default": "false", + "description": "Whether to return deleted comments. Deleted comments will not include their original content.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}/comments/{commentId}", + "response": { + "$ref": "Comment" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "list": { + "description": "Lists a file's comments.", + "flatPath": "files/{fileId}/comments", + "httpMethod": "GET", + "id": "drive.comments.list", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "includeDeleted": { + "default": "false", + "description": "Whether to include deleted comments. Deleted comments will not include their original content.", + "location": "query", + "type": "boolean" + }, + "pageSize": { + "default": "20", + "description": "The maximum number of comments to return per page.", + "format": "int32", + "location": "query", + "maximum": "100", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", + "location": "query", + "type": "string" + }, + "startModifiedTime": { + "description": "The minimum value of 'modifiedTime' for the result comments (RFC 3339 date-time).", + "location": "query", + "type": "string" + } + }, + "path": "files/{fileId}/comments", + "response": { + "$ref": "CommentList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "update": { + "description": "Updates a comment with patch semantics.", + "flatPath": "files/{fileId}/comments/{commentId}", + "httpMethod": "PATCH", + "id": "drive.comments.update", + "parameterOrder": [ + "fileId", + "commentId" + ], + "parameters": { + "commentId": { + "description": "The ID of the comment.", + "location": "path", + "required": true, + "type": "string" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/comments/{commentId}", + "request": { + "$ref": "Comment" + }, + "response": { + "$ref": "Comment" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + } } - } }, - "contentHints": { - "type": "object", - "description": "Additional information about the content of the file. These fields are never populated in responses.", - "properties": { - "indexableText": { - "type": "string", - "description": "Text to be indexed for the file to improve fullText queries. This is limited to 128KB in length and may contain HTML elements." - }, - "thumbnail": { - "type": "object", - "description": "A thumbnail for the file. This will only be used if Drive cannot generate a standard thumbnail.", - "properties": { - "image": { - "type": "string", - "description": "The thumbnail data encoded with URL-safe Base64 (RFC 4648 section 5).", - "format": "byte" + "drives": { + "methods": { + "create": { + "description": "Creates a shared drive.", + "flatPath": "drives", + "httpMethod": "POST", + "id": "drive.drives.create", + "parameterOrder": [ + "requestId" + ], + "parameters": { + "requestId": { + "description": "Required. An ID, such as a random UUID, which uniquely identifies this user's request for idempotent creation of a shared drive. A repeated request by the same user and with the same request ID will avoid creating duplicates by attempting to create the same shared drive. If the shared drive already exists a 409 error will be returned.", + "location": "query", + "required": true, + "type": "string" + } + }, + "path": "drives", + "request": { + "$ref": "Drive" + }, + "response": { + "$ref": "Drive" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive" + ] }, - "mimeType": { - "type": "string", - "description": "The MIME type of the thumbnail." + "delete": { + "description": "Permanently deletes a shared drive for which the user is an `organizer`. The shared drive cannot contain any untrashed items.", + "flatPath": "drives/{driveId}", + "httpMethod": "DELETE", + "id": "drive.drives.delete", + "parameterOrder": [ + "driveId" + ], + "parameters": { + "allowItemDeletion": { + "default": "false", + "description": "Whether any items inside the shared drive should also be deleted. This option is only supported when `useDomainAdminAccess` is also set to `true`.", + "location": "query", + "type": "boolean" + }, + "driveId": { + "description": "The ID of the shared drive.", + "location": "path", + "required": true, + "type": "string" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the shared drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "drives/{driveId}", + "scopes": [ + "https://www.googleapis.com/auth/drive" + ] + }, + "get": { + "description": "Gets a shared drive's metadata by ID.", + "flatPath": "drives/{driveId}", + "httpMethod": "GET", + "id": "drive.drives.get", + "parameterOrder": [ + "driveId" + ], + "parameters": { + "driveId": { + "description": "The ID of the shared drive.", + "location": "path", + "required": true, + "type": "string" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the shared drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "drives/{driveId}", + "response": { + "$ref": "Drive" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "hide": { + "description": "Hides a shared drive from the default view.", + "flatPath": "drives/{driveId}/hide", + "httpMethod": "POST", + "id": "drive.drives.hide", + "parameterOrder": [ + "driveId" + ], + "parameters": { + "driveId": { + "description": "The ID of the shared drive.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "drives/{driveId}/hide", + "response": { + "$ref": "Drive" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive" + ] + }, + "list": { + "description": " Lists the user's shared drives. This method accepts the `q` parameter, which is a search query combining one or more search terms. For more information, see the [Search for shared drives](/drive/api/guides/search-shareddrives) guide.", + "flatPath": "drives", + "httpMethod": "GET", + "id": "drive.drives.list", + "parameterOrder": [], + "parameters": { + "pageSize": { + "default": "10", + "description": "Maximum number of shared drives to return per page.", + "format": "int32", + "location": "query", + "maximum": "100", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "Page token for shared drives.", + "location": "query", + "type": "string" + }, + "q": { + "description": "Query string for searching shared drives.", + "location": "query", + "type": "string" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then all shared drives of the domain in which the requester is an administrator are returned.", + "location": "query", + "type": "boolean" + } + }, + "path": "drives", + "response": { + "$ref": "DriveList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "unhide": { + "description": "Restores a shared drive to the default view.", + "flatPath": "drives/{driveId}/unhide", + "httpMethod": "POST", + "id": "drive.drives.unhide", + "parameterOrder": [ + "driveId" + ], + "parameters": { + "driveId": { + "description": "The ID of the shared drive.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "drives/{driveId}/unhide", + "response": { + "$ref": "Drive" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive" + ] + }, + "update": { + "description": "Updates the metadata for a shared drive.", + "flatPath": "drives/{driveId}", + "httpMethod": "PATCH", + "id": "drive.drives.update", + "parameterOrder": [ + "driveId" + ], + "parameters": { + "driveId": { + "description": "The ID of the shared drive.", + "location": "path", + "required": true, + "type": "string" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the shared drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "drives/{driveId}", + "request": { + "$ref": "Drive" + }, + "response": { + "$ref": "Drive" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive" + ] } - } } - } - }, - "createdTime": { - "type": "string", - "description": "The time at which the file was created (RFC 3339 date-time).", - "format": "date-time" - }, - "description": { - "type": "string", - "description": "A short description of the file." - }, - "explicitlyTrashed": { - "type": "boolean", - "description": "Whether the file has been explicitly trashed, as opposed to recursively trashed from a parent folder." }, - "fileExtension": { - "type": "string", - "description": "The final component of fullFileExtension. This is only available for files with binary content in Drive." + "files": { + "methods": { + "copy": { + "description": "Creates a copy of a file and applies any requested updates with patch semantics.", + "flatPath": "files/{fileId}/copy", + "httpMethod": "POST", + "id": "drive.files.copy", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "enforceSingleParent": { + "default": "false", + "description": "Deprecated. Copying files into multiple folders is no longer supported. Use shortcuts instead.", + "location": "query", + "type": "boolean" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "ignoreDefaultVisibility": { + "default": "false", + "description": "Whether to ignore the domain's default visibility settings for the created file. Domain administrators can choose to make all uploaded files visible to the domain by default; this parameter bypasses that behavior for the request. Permissions are still inherited from parent folders.", + "location": "query", + "type": "boolean" + }, + "includeLabels": { + "description": "A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.", + "location": "query", + "type": "string" + }, + "includePermissionsForView": { + "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.", + "location": "query", + "type": "string" + }, + "keepRevisionForever": { + "default": "false", + "description": "Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Google Drive. Only 200 revisions for the file can be kept forever. If the limit is reached, try deleting pinned revisions.", + "location": "query", + "type": "boolean" + }, + "ocrLanguage": { + "description": "A language hint for OCR processing during image import (ISO 639-1 code).", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}/copy", + "request": { + "$ref": "File" + }, + "response": { + "$ref": "File" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.photos.readonly" + ] + }, + "create": { + "description": " Creates a new file. This method supports an */upload* URI and accepts uploaded media with the following characteristics: - *Maximum file size:* 5,120 GB - *Accepted Media MIME types:*`*/*` Note: Specify a valid MIME type, rather than the literal `*/*` value. The literal `*/*` is only used to indicate that any valid MIME type can be uploaded. For more information on uploading files, see [Upload file data](/drive/api/guides/manage-uploads). Apps creating shortcuts with `files.create` must specify the MIME type `application/vnd.google-apps.shortcut`. Apps should specify a file extension in the `name` property when inserting files with the API. For example, an operation to insert a JPEG file should specify something like `\"name\": \"cat.jpg\"` in the metadata. Subsequent `GET` requests include the read-only `fileExtension` property populated with the extension originally specified in the `title` property. When a Google Drive user requests to download a file, or when the file is downloaded through the sync client, Drive builds a full filename (with extension) based on the title. In cases where the extension is missing, Drive attempts to determine the extension based on the file's MIME type.", + "flatPath": "files", + "httpMethod": "POST", + "id": "drive.files.create", + "mediaUpload": { + "accept": [ + "*/*" + ], + "maxSize": "5497558138880", + "protocols": { + "resumable": { + "multipart": true, + "path": "/resumable/upload/drive/v3/files" + }, + "simple": { + "multipart": true, + "path": "/upload/drive/v3/files" + } + } + }, + "parameterOrder": [], + "parameters": { + "enforceSingleParent": { + "default": "false", + "description": "Deprecated. Creating files in multiple folders is no longer supported.", + "location": "query", + "type": "boolean" + }, + "ignoreDefaultVisibility": { + "default": "false", + "description": "Whether to ignore the domain's default visibility settings for the created file. Domain administrators can choose to make all uploaded files visible to the domain by default; this parameter bypasses that behavior for the request. Permissions are still inherited from parent folders.", + "location": "query", + "type": "boolean" + }, + "includeLabels": { + "description": "A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.", + "location": "query", + "type": "string" + }, + "includePermissionsForView": { + "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.", + "location": "query", + "type": "string" + }, + "keepRevisionForever": { + "default": "false", + "description": "Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Google Drive. Only 200 revisions for the file can be kept forever. If the limit is reached, try deleting pinned revisions.", + "location": "query", + "type": "boolean" + }, + "ocrLanguage": { + "description": "A language hint for OCR processing during image import (ISO 639-1 code).", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "useContentAsIndexableText": { + "default": "false", + "description": "Whether to use the uploaded content as indexable text.", + "location": "query", + "type": "boolean" + } + }, + "path": "files", + "request": { + "$ref": "File" + }, + "response": { + "$ref": "File" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file" + ], + "supportsMediaUpload": true + }, + "delete": { + "description": "Permanently deletes a file owned by the user without moving it to the trash. If the file belongs to a shared drive, the user must be an `organizer` on the parent folder. If the target is a folder, all descendants owned by the user are also deleted.", + "flatPath": "files/{fileId}", + "httpMethod": "DELETE", + "id": "drive.files.delete", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "enforceSingleParent": { + "default": "false", + "deprecated": true, + "description": "Deprecated: If an item is not in a shared drive and its last parent is deleted but the item itself is not, the item will be placed under its owner's root.", + "location": "query", + "type": "boolean" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}", + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file" + ] + }, + "download": { + "description": "Downloads content of a file. Operations are valid for 24 hours from the time of creation.", + "flatPath": "files/{fileId}/download", + "httpMethod": "POST", + "id": "drive.files.download", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "fileId": { + "description": "Required. The ID of the file to download.", + "location": "path", + "required": true, + "type": "string" + }, + "mimeType": { + "description": "Optional. The MIME type the file should be downloaded as. This field can only be set when downloading Google Workspace documents. See [Export MIME types for Google Workspace documents](/drive/api/guides/ref-export-formats) for the list of supported MIME types. If not set, a Google Workspace document is downloaded with a default MIME type. The default MIME type might change in the future.", + "location": "query", + "type": "string" + }, + "revisionId": { + "description": "Optional. The revision ID of the file to download. This field can only be set when downloading blob files, Google Docs, and Google Sheets. Returns `INVALID_ARGUMENT` if downloading a specific revision on the file is unsupported.", + "location": "query", + "type": "string" + } + }, + "path": "files/{fileId}/download", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "emptyTrash": { + "description": "Permanently deletes all of the user's trashed files.", + "flatPath": "files/trash", + "httpMethod": "DELETE", + "id": "drive.files.emptyTrash", + "parameterOrder": [], + "parameters": { + "driveId": { + "description": "If set, empties the trash of the provided shared drive.", + "location": "query", + "type": "string" + }, + "enforceSingleParent": { + "default": "false", + "deprecated": true, + "description": "Deprecated: If an item is not in a shared drive and its last parent is deleted but the item itself is not, the item will be placed under its owner's root.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/trash", + "scopes": [ + "https://www.googleapis.com/auth/drive" + ] + }, + "export": { + "description": "Exports a Google Workspace document to the requested MIME type and returns exported byte content. Note that the exported content is limited to 10MB.", + "flatPath": "files/{fileId}/export", + "httpMethod": "GET", + "id": "drive.files.export", + "parameterOrder": [ + "fileId", + "mimeType" + ], + "parameters": { + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "mimeType": { + "description": "Required. The MIME type of the format requested for this export.", + "location": "query", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/export", + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ], + "supportsMediaDownload": true, + "useMediaDownloadService": true + }, + "generateIds": { + "description": "Generates a set of file IDs which can be provided in create or copy requests.", + "flatPath": "files/generateIds", + "httpMethod": "GET", + "id": "drive.files.generateIds", + "parameterOrder": [], + "parameters": { + "count": { + "default": "10", + "description": "The number of IDs to return.", + "format": "int32", + "location": "query", + "maximum": "1000", + "minimum": "1", + "type": "integer" + }, + "space": { + "default": "drive", + "description": "The space in which the IDs can be used to create new files. Supported values are 'drive' and 'appDataFolder'. (Default: 'drive')", + "location": "query", + "type": "string" + }, + "type": { + "default": "files", + "description": "The type of items which the IDs can be used for. Supported values are 'files' and 'shortcuts'. Note that 'shortcuts' are only supported in the `drive` 'space'. (Default: 'files')", + "location": "query", + "type": "string" + } + }, + "path": "files/generateIds", + "response": { + "$ref": "GeneratedIds" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file" + ] + }, + "get": { + "description": " Gets a file's metadata or content by ID. If you provide the URL parameter `alt=media`, then the response includes the file contents in the response body. Downloading content with `alt=media` only works if the file is stored in Drive. To download Google Docs, Sheets, and Slides use [`files.export`](/drive/api/reference/rest/v3/files/export) instead. For more information, see [Download \u0026 export files](/drive/api/guides/manage-downloads).", + "flatPath": "files/{fileId}", + "httpMethod": "GET", + "id": "drive.files.get", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "acknowledgeAbuse": { + "default": "false", + "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when the `alt` parameter is set to `media` and the user is the owner of the file or an organizer of the shared drive in which the file resides.", + "location": "query", + "type": "boolean" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "includeLabels": { + "description": "A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.", + "location": "query", + "type": "string" + }, + "includePermissionsForView": { + "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}", + "response": { + "$ref": "File" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ], + "supportsMediaDownload": true, + "supportsSubscription": true, + "useMediaDownloadService": true + }, + "list": { + "description": " Lists the user's files. This method accepts the `q` parameter, which is a search query combining one or more search terms. For more information, see the [Search for files \u0026 folders](/drive/api/guides/search-files) guide. *Note:* This method returns *all* files by default, including trashed files. If you don't want trashed files to appear in the list, use the `trashed=false` query parameter to remove trashed files from the results.", + "flatPath": "files", + "httpMethod": "GET", + "id": "drive.files.list", + "parameterOrder": [], + "parameters": { + "corpora": { + "description": "Bodies of items (files/documents) to which the query applies. Supported bodies are 'user', 'domain', 'drive', and 'allDrives'. Prefer 'user' or 'drive' to 'allDrives' for efficiency. By default, corpora is set to 'user'. However, this can change depending on the filter set through the 'q' parameter.", + "location": "query", + "type": "string" + }, + "corpus": { + "deprecated": true, + "description": "Deprecated: The source of files to list. Use 'corpora' instead.", + "enum": [ + "domain", + "user" + ], + "enumDescriptions": [ + "Files shared to the user's domain.", + "Files owned by or shared to the user." + ], + "location": "query", + "type": "string" + }, + "driveId": { + "description": "ID of the shared drive to search.", + "location": "query", + "type": "string" + }, + "includeItemsFromAllDrives": { + "default": "false", + "description": "Whether both My Drive and shared drive items should be included in results.", + "location": "query", + "type": "boolean" + }, + "includeLabels": { + "description": "A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.", + "location": "query", + "type": "string" + }, + "includePermissionsForView": { + "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.", + "location": "query", + "type": "string" + }, + "includeTeamDriveItems": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `includeItemsFromAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "orderBy": { + "description": "A comma-separated list of sort keys. Valid keys are: * `createdTime`: When the file was created. * `folder`: The folder ID. This field is sorted using alphabetical ordering. * `modifiedByMeTime`: The last time the file was modified by the user. * `modifiedTime`: The last time the file was modified by anyone. * `name`: The name of the file. This field is sorted using alphabetical ordering, so 1, 12, 2, 22. * `name_natural`: The name of the file. This field is sorted using natural sort ordering, so 1, 2, 12, 22. * `quotaBytesUsed`: The number of storage quota bytes used by the file. * `recency`: The most recent timestamp from the file's date-time fields. * `sharedWithMeTime`: When the file was shared with the user, if applicable. * `starred`: Whether the user has starred the file. * `viewedByMeTime`: The last time the file was viewed by the user. Each key sorts ascending by default, but can be reversed with the 'desc' modifier. Example usage: `?orderBy=folder,modifiedTime desc,name`.", + "location": "query", + "type": "string" + }, + "pageSize": { + "default": "100", + "description": "The maximum number of files to return per page. Partial or empty result pages are possible even before the end of the files list has been reached.", + "format": "int32", + "location": "query", + "maximum": "1000", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", + "location": "query", + "type": "string" + }, + "q": { + "description": "A query for filtering the file results. See the \"Search for files \u0026 folders\" guide for supported syntax.", + "location": "query", + "type": "string" + }, + "spaces": { + "default": "drive", + "description": "A comma-separated list of spaces to query within the corpora. Supported values are 'drive' and 'appDataFolder'.", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "teamDriveId": { + "deprecated": true, + "description": "Deprecated: Use `driveId` instead.", + "location": "query", + "type": "string" + } + }, + "path": "files", + "response": { + "$ref": "FileList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "listLabels": { + "description": "Lists the labels on a file.", + "flatPath": "files/{fileId}/listLabels", + "httpMethod": "GET", + "id": "drive.files.listLabels", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "fileId": { + "description": "The ID for the file.", + "location": "path", + "required": true, + "type": "string" + }, + "maxResults": { + "default": "100", + "description": "The maximum number of labels to return per page. When not set, defaults to 100.", + "format": "int32", + "location": "query", + "maximum": "100", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", + "location": "query", + "type": "string" + } + }, + "path": "files/{fileId}/listLabels", + "response": { + "$ref": "LabelList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "modifyLabels": { + "description": "Modifies the set of labels applied to a file. Returns a list of the labels that were added or modified.", + "flatPath": "files/{fileId}/modifyLabels", + "httpMethod": "POST", + "id": "drive.files.modifyLabels", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file to which the labels belong.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/modifyLabels", + "request": { + "$ref": "ModifyLabelsRequest" + }, + "response": { + "$ref": "ModifyLabelsResponse" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.metadata" + ] + }, + "update": { + "description": " Updates a file's metadata and/or content. When calling this method, only populate fields in the request that you want to modify. When updating fields, some fields might be changed automatically, such as `modifiedDate`. This method supports patch semantics. This method supports an */upload* URI and accepts uploaded media with the following characteristics: - *Maximum file size:* 5,120 GB - *Accepted Media MIME types:*`*/*` Note: Specify a valid MIME type, rather than the literal `*/*` value. The literal `*/*` is only used to indicate that any valid MIME type can be uploaded. For more information on uploading files, see [Upload file data](/drive/api/guides/manage-uploads).", + "flatPath": "files/{fileId}", + "httpMethod": "PATCH", + "id": "drive.files.update", + "mediaUpload": { + "accept": [ + "*/*" + ], + "maxSize": "5497558138880", + "protocols": { + "resumable": { + "multipart": true, + "path": "/resumable/upload/drive/v3/files/{fileId}" + }, + "simple": { + "multipart": true, + "path": "/upload/drive/v3/files/{fileId}" + } + } + }, + "parameterOrder": [ + "fileId" + ], + "parameters": { + "addParents": { + "description": "A comma-separated list of parent IDs to add.", + "location": "query", + "type": "string" + }, + "enforceSingleParent": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Adding files to multiple folders is no longer supported. Use shortcuts instead.", + "location": "query", + "type": "boolean" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "includeLabels": { + "description": "A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.", + "location": "query", + "type": "string" + }, + "includePermissionsForView": { + "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.", + "location": "query", + "type": "string" + }, + "keepRevisionForever": { + "default": "false", + "description": "Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Google Drive. Only 200 revisions for the file can be kept forever. If the limit is reached, try deleting pinned revisions.", + "location": "query", + "type": "boolean" + }, + "ocrLanguage": { + "description": "A language hint for OCR processing during image import (ISO 639-1 code).", + "location": "query", + "type": "string" + }, + "removeParents": { + "description": "A comma-separated list of parent IDs to remove.", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "useContentAsIndexableText": { + "default": "false", + "description": "Whether to use the uploaded content as indexable text.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}", + "request": { + "$ref": "File" + }, + "response": { + "$ref": "File" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.scripts" + ], + "supportsMediaUpload": true + }, + "watch": { + "description": "Subscribes to changes to a file.", + "flatPath": "files/{fileId}/watch", + "httpMethod": "POST", + "id": "drive.files.watch", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "acknowledgeAbuse": { + "default": "false", + "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when the `alt` parameter is set to `media` and the user is the owner of the file or an organizer of the shared drive in which the file resides.", + "location": "query", + "type": "boolean" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "includeLabels": { + "description": "A comma-separated list of IDs of labels to include in the `labelInfo` part of the response.", + "location": "query", + "type": "string" + }, + "includePermissionsForView": { + "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}/watch", + "request": { + "$ref": "Channel", + "parameterName": "resource" + }, + "response": { + "$ref": "Channel" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ], + "supportsSubscription": true + } + } }, - "folderColorRgb": { - "type": "string", - "description": "The color for a folder as an RGB hex string. The supported colors are published in the folderColorPalette field of the About resource.\nIf an unsupported color is specified, the closest color in the palette will be used instead." + "operation": { + "methods": { + "cancel": { + "description": "Starts asynchronous cancellation on a long-running operation. The server makes a best effort to cancel the operation, but success is not guaranteed. If the server doesn't support this method, it returns `google.rpc.Code.UNIMPLEMENTED`. Clients can use Operations.GetOperation or other methods to check whether the cancellation succeeded or whether the operation completed despite cancellation. On successful cancellation, the operation is not deleted; instead, it becomes an operation with an Operation.error value with a google.rpc.Status.code of `1`, corresponding to `Code.CANCELLED`.", + "flatPath": "operation/{name}:cancel", + "httpMethod": "POST", + "id": "drive.operation.cancel", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name of the operation resource to be cancelled.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "operation/{name}:cancel" + }, + "delete": { + "description": "Deletes a long-running operation. This method indicates that the client is no longer interested in the operation result. It does not cancel the operation. If the server doesn't support this method, it returns `google.rpc.Code.UNIMPLEMENTED`.", + "flatPath": "operation/{name}", + "httpMethod": "DELETE", + "id": "drive.operation.delete", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name of the operation resource to be deleted.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "operation/{name}" + } + } }, - "fullFileExtension": { - "type": "string", - "description": "The full file extension extracted from the name field. May contain multiple concatenated extensions, such as \"tar.gz\". This is only available for files with binary content in Drive.\nThis is automatically updated when the name field changes, however it is not cleared if the new name does not contain a valid extension." + "operations": { + "methods": { + "get": { + "description": "Gets the latest state of a long-running operation. Clients can use this method to poll the operation result at intervals as recommended by the API service.", + "flatPath": "operations/{name}", + "httpMethod": "GET", + "id": "drive.operations.get", + "parameterOrder": [ + "name" + ], + "parameters": { + "name": { + "description": "The name of the operation resource.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "operations/{name}", + "response": { + "$ref": "Operation" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "list": { + "description": "Lists operations that match the specified filter in the request. If the server doesn't support this method, it returns `UNIMPLEMENTED`.", + "flatPath": "operations", + "httpMethod": "GET", + "id": "drive.operations.list", + "parameterOrder": [], + "parameters": { + "filter": { + "description": "The standard list filter.", + "location": "query", + "type": "string" + }, + "name": { + "description": "The name of the operation's parent resource.", + "location": "query", + "type": "string" + }, + "pageSize": { + "description": "The standard list page size.", + "format": "int32", + "location": "query", + "type": "integer" + }, + "pageToken": { + "description": "The standard list page token.", + "location": "query", + "type": "string" + } + }, + "path": "operations", + "response": { + "$ref": "ListOperationsResponse" + } + } + } }, - "headRevisionId": { - "type": "string", - "description": "The ID of the file's head revision. This is currently only available for files with binary content in Drive." + "permissions": { + "methods": { + "create": { + "description": "Creates a permission for a file or shared drive. **Warning:** Concurrent permissions operations on the same file are not supported; only the last update is applied.", + "flatPath": "files/{fileId}/permissions", + "httpMethod": "POST", + "id": "drive.permissions.create", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "emailMessage": { + "description": "A plain text custom message to include in the notification email.", + "location": "query", + "type": "string" + }, + "enforceSingleParent": { + "default": "false", + "deprecated": true, + "description": "Deprecated: See `moveToNewOwnersRoot` for details.", + "location": "query", + "type": "boolean" + }, + "fileId": { + "description": "The ID of the file or shared drive.", + "location": "path", + "required": true, + "type": "string" + }, + "moveToNewOwnersRoot": { + "default": "false", + "description": "This parameter will only take effect if the item is not in a shared drive and the request is attempting to transfer the ownership of the item. If set to `true`, the item will be moved to the new owner's My Drive root folder and all prior parents removed. If set to `false`, parents are not changed.", + "location": "query", + "type": "boolean" + }, + "sendNotificationEmail": { + "description": "Whether to send a notification email when sharing to users or groups. This defaults to true for users and groups, and is not allowed for other requests. It must not be disabled for ownership transfers.", + "location": "query", + "type": "boolean" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "transferOwnership": { + "default": "false", + "description": "Whether to transfer ownership to the specified user and downgrade the current owner to a writer. This parameter is required as an acknowledgement of the side effect.", + "location": "query", + "type": "boolean" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if the file ID parameter refers to a shared drive and the requester is an administrator of the domain to which the shared drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}/permissions", + "request": { + "$ref": "Permission" + }, + "response": { + "$ref": "Permission" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + }, + "delete": { + "description": "Deletes a permission. **Warning:** Concurrent permissions operations on the same file are not supported; only the last update is applied.", + "flatPath": "files/{fileId}/permissions/{permissionId}", + "httpMethod": "DELETE", + "id": "drive.permissions.delete", + "parameterOrder": [ + "fileId", + "permissionId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file or shared drive.", + "location": "path", + "required": true, + "type": "string" + }, + "permissionId": { + "description": "The ID of the permission.", + "location": "path", + "required": true, + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if the file ID parameter refers to a shared drive and the requester is an administrator of the domain to which the shared drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}/permissions/{permissionId}", + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + }, + "get": { + "description": "Gets a permission by ID.", + "flatPath": "files/{fileId}/permissions/{permissionId}", + "httpMethod": "GET", + "id": "drive.permissions.get", + "parameterOrder": [ + "fileId", + "permissionId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "permissionId": { + "description": "The ID of the permission.", + "location": "path", + "required": true, + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if the file ID parameter refers to a shared drive and the requester is an administrator of the domain to which the shared drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}/permissions/{permissionId}", + "response": { + "$ref": "Permission" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "list": { + "description": "Lists a file's or shared drive's permissions.", + "flatPath": "files/{fileId}/permissions", + "httpMethod": "GET", + "id": "drive.permissions.list", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file or shared drive.", + "location": "path", + "required": true, + "type": "string" + }, + "includePermissionsForView": { + "description": "Specifies which additional view's permissions to include in the response. Only 'published' is supported.", + "location": "query", + "type": "string" + }, + "pageSize": { + "description": "The maximum number of permissions to return per page. When not set for files in a shared drive, at most 100 results will be returned. When not set for files that are not in a shared drive, the entire list will be returned.", + "format": "int32", + "location": "query", + "maximum": "100", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", + "location": "query", + "type": "string" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if the file ID parameter refers to a shared drive and the requester is an administrator of the domain to which the shared drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}/permissions", + "response": { + "$ref": "PermissionList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "update": { + "description": "Updates a permission with patch semantics. **Warning:** Concurrent permissions operations on the same file are not supported; only the last update is applied.", + "flatPath": "files/{fileId}/permissions/{permissionId}", + "httpMethod": "PATCH", + "id": "drive.permissions.update", + "parameterOrder": [ + "fileId", + "permissionId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file or shared drive.", + "location": "path", + "required": true, + "type": "string" + }, + "permissionId": { + "description": "The ID of the permission.", + "location": "path", + "required": true, + "type": "string" + }, + "removeExpiration": { + "default": "false", + "description": "Whether to remove the expiration date.", + "location": "query", + "type": "boolean" + }, + "supportsAllDrives": { + "default": "false", + "description": "Whether the requesting application supports both My Drives and shared drives.", + "location": "query", + "type": "boolean" + }, + "supportsTeamDrives": { + "default": "false", + "deprecated": true, + "description": "Deprecated: Use `supportsAllDrives` instead.", + "location": "query", + "type": "boolean" + }, + "transferOwnership": { + "default": "false", + "description": "Whether to transfer ownership to the specified user and downgrade the current owner to a writer. This parameter is required as an acknowledgement of the side effect.", + "location": "query", + "type": "boolean" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if the file ID parameter refers to a shared drive and the requester is an administrator of the domain to which the shared drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "files/{fileId}/permissions/{permissionId}", + "request": { + "$ref": "Permission" + }, + "response": { + "$ref": "Permission" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + } + } }, - "iconLink": { - "type": "string", - "description": "A static, unauthenticated link to the file's icon." + "replies": { + "methods": { + "create": { + "description": "Creates a reply to a comment.", + "flatPath": "files/{fileId}/comments/{commentId}/replies", + "httpMethod": "POST", + "id": "drive.replies.create", + "parameterOrder": [ + "fileId", + "commentId" + ], + "parameters": { + "commentId": { + "description": "The ID of the comment.", + "location": "path", + "required": true, + "type": "string" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/comments/{commentId}/replies", + "request": { + "$ref": "Reply" + }, + "response": { + "$ref": "Reply" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + }, + "delete": { + "description": "Deletes a reply.", + "flatPath": "files/{fileId}/comments/{commentId}/replies/{replyId}", + "httpMethod": "DELETE", + "id": "drive.replies.delete", + "parameterOrder": [ + "fileId", + "commentId", + "replyId" + ], + "parameters": { + "commentId": { + "description": "The ID of the comment.", + "location": "path", + "required": true, + "type": "string" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "replyId": { + "description": "The ID of the reply.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/comments/{commentId}/replies/{replyId}", + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + }, + "get": { + "description": "Gets a reply by ID.", + "flatPath": "files/{fileId}/comments/{commentId}/replies/{replyId}", + "httpMethod": "GET", + "id": "drive.replies.get", + "parameterOrder": [ + "fileId", + "commentId", + "replyId" + ], + "parameters": { + "commentId": { + "description": "The ID of the comment.", + "location": "path", + "required": true, + "type": "string" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "includeDeleted": { + "default": "false", + "description": "Whether to return deleted replies. Deleted replies will not include their original content.", + "location": "query", + "type": "boolean" + }, + "replyId": { + "description": "The ID of the reply.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/comments/{commentId}/replies/{replyId}", + "response": { + "$ref": "Reply" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "list": { + "description": "Lists a comment's replies.", + "flatPath": "files/{fileId}/comments/{commentId}/replies", + "httpMethod": "GET", + "id": "drive.replies.list", + "parameterOrder": [ + "fileId", + "commentId" + ], + "parameters": { + "commentId": { + "description": "The ID of the comment.", + "location": "path", + "required": true, + "type": "string" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "includeDeleted": { + "default": "false", + "description": "Whether to include deleted replies. Deleted replies will not include their original content.", + "location": "query", + "type": "boolean" + }, + "pageSize": { + "default": "20", + "description": "The maximum number of replies to return per page.", + "format": "int32", + "location": "query", + "maximum": "100", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", + "location": "query", + "type": "string" + } + }, + "path": "files/{fileId}/comments/{commentId}/replies", + "response": { + "$ref": "ReplyList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "update": { + "description": "Updates a reply with patch semantics.", + "flatPath": "files/{fileId}/comments/{commentId}/replies/{replyId}", + "httpMethod": "PATCH", + "id": "drive.replies.update", + "parameterOrder": [ + "fileId", + "commentId", + "replyId" + ], + "parameters": { + "commentId": { + "description": "The ID of the comment.", + "location": "path", + "required": true, + "type": "string" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "replyId": { + "description": "The ID of the reply.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/comments/{commentId}/replies/{replyId}", + "request": { + "$ref": "Reply" + }, + "response": { + "$ref": "Reply" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.file" + ] + } + } }, - "id": { - "type": "string", - "description": "The ID of the file." + "revisions": { + "methods": { + "delete": { + "description": "Permanently deletes a file version. You can only delete revisions for files with binary content in Google Drive, like images or videos. Revisions for other files, like Google Docs or Sheets, and the last remaining file version can't be deleted.", + "flatPath": "files/{fileId}/revisions/{revisionId}", + "httpMethod": "DELETE", + "id": "drive.revisions.delete", + "parameterOrder": [ + "fileId", + "revisionId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "revisionId": { + "description": "The ID of the revision.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/revisions/{revisionId}", + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file" + ] + }, + "get": { + "description": "Gets a revision's metadata or content by ID.", + "flatPath": "files/{fileId}/revisions/{revisionId}", + "httpMethod": "GET", + "id": "drive.revisions.get", + "parameterOrder": [ + "fileId", + "revisionId" + ], + "parameters": { + "acknowledgeAbuse": { + "default": "false", + "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when the `alt` parameter is set to `media` and the user is the owner of the file or an organizer of the shared drive in which the file resides.", + "location": "query", + "type": "boolean" + }, + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "revisionId": { + "description": "The ID of the revision.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/revisions/{revisionId}", + "response": { + "$ref": "Revision" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ], + "supportsMediaDownload": true, + "useMediaDownloadService": true + }, + "list": { + "description": "Lists a file's revisions.", + "flatPath": "files/{fileId}/revisions", + "httpMethod": "GET", + "id": "drive.revisions.list", + "parameterOrder": [ + "fileId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "pageSize": { + "default": "200", + "description": "The maximum number of revisions to return per page.", + "format": "int32", + "location": "query", + "maximum": "1000", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", + "location": "query", + "type": "string" + } + }, + "path": "files/{fileId}/revisions", + "response": { + "$ref": "RevisionList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "update": { + "description": "Updates a revision with patch semantics.", + "flatPath": "files/{fileId}/revisions/{revisionId}", + "httpMethod": "PATCH", + "id": "drive.revisions.update", + "parameterOrder": [ + "fileId", + "revisionId" + ], + "parameters": { + "fileId": { + "description": "The ID of the file.", + "location": "path", + "required": true, + "type": "string" + }, + "revisionId": { + "description": "The ID of the revision.", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "files/{fileId}/revisions/{revisionId}", + "request": { + "$ref": "Revision" + }, + "response": { + "$ref": "Revision" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.file" + ] + } + } }, - "imageMediaMetadata": { - "type": "object", - "description": "Additional metadata about image media, if available.", - "properties": { - "aperture": { - "type": "number", - "description": "The aperture used to create the photo (f-number).", - "format": "float" - }, - "cameraMake": { - "type": "string", - "description": "The make of the camera used to create the photo." - }, - "cameraModel": { - "type": "string", - "description": "The model of the camera used to create the photo." - }, - "colorSpace": { - "type": "string", - "description": "The color space of the photo." + "teamdrives": { + "methods": { + "create": { + "description": "Deprecated: Use `drives.create` instead.", + "flatPath": "teamdrives", + "httpMethod": "POST", + "id": "drive.teamdrives.create", + "parameterOrder": [ + "requestId" + ], + "parameters": { + "requestId": { + "description": "Required. An ID, such as a random UUID, which uniquely identifies this user's request for idempotent creation of a Team Drive. A repeated request by the same user and with the same request ID will avoid creating duplicates by attempting to create the same Team Drive. If the Team Drive already exists a 409 error will be returned.", + "location": "query", + "required": true, + "type": "string" + } + }, + "path": "teamdrives", + "request": { + "$ref": "TeamDrive" + }, + "response": { + "$ref": "TeamDrive" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive" + ] + }, + "delete": { + "description": "Deprecated: Use `drives.delete` instead.", + "flatPath": "teamdrives/{teamDriveId}", + "httpMethod": "DELETE", + "id": "drive.teamdrives.delete", + "parameterOrder": [ + "teamDriveId" + ], + "parameters": { + "teamDriveId": { + "description": "The ID of the Team Drive", + "location": "path", + "required": true, + "type": "string" + } + }, + "path": "teamdrives/{teamDriveId}", + "scopes": [ + "https://www.googleapis.com/auth/drive" + ] + }, + "get": { + "description": "Deprecated: Use `drives.get` instead.", + "flatPath": "teamdrives/{teamDriveId}", + "httpMethod": "GET", + "id": "drive.teamdrives.get", + "parameterOrder": [ + "teamDriveId" + ], + "parameters": { + "teamDriveId": { + "description": "The ID of the Team Drive", + "location": "path", + "required": true, + "type": "string" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the Team Drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "teamdrives/{teamDriveId}", + "response": { + "$ref": "TeamDrive" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "list": { + "description": "Deprecated: Use `drives.list` instead.", + "flatPath": "teamdrives", + "httpMethod": "GET", + "id": "drive.teamdrives.list", + "parameterOrder": [], + "parameters": { + "pageSize": { + "default": "10", + "description": "Maximum number of Team Drives to return.", + "format": "int32", + "location": "query", + "maximum": "100", + "minimum": "1", + "type": "integer" + }, + "pageToken": { + "description": "Page token for Team Drives.", + "location": "query", + "type": "string" + }, + "q": { + "description": "Query string for searching Team Drives.", + "location": "query", + "type": "string" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then all Team Drives of the domain in which the requester is an administrator are returned.", + "location": "query", + "type": "boolean" + } + }, + "path": "teamdrives", + "response": { + "$ref": "TeamDriveList" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.readonly" + ] + }, + "update": { + "description": "Deprecated: Use `drives.update` instead.", + "flatPath": "teamdrives/{teamDriveId}", + "httpMethod": "PATCH", + "id": "drive.teamdrives.update", + "parameterOrder": [ + "teamDriveId" + ], + "parameters": { + "teamDriveId": { + "description": "The ID of the Team Drive", + "location": "path", + "required": true, + "type": "string" + }, + "useDomainAdminAccess": { + "default": "false", + "description": "Issue the request as a domain administrator; if set to true, then the requester will be granted access if they are an administrator of the domain to which the Team Drive belongs.", + "location": "query", + "type": "boolean" + } + }, + "path": "teamdrives/{teamDriveId}", + "request": { + "$ref": "TeamDrive" + }, + "response": { + "$ref": "TeamDrive" + }, + "scopes": [ + "https://www.googleapis.com/auth/drive" + ] + } + } + } + }, + "revision": "20241117", + "rootUrl": "https://www.googleapis.com/", + "schemas": { + "About": { + "description": "Information about the user, the user's Drive, and system capabilities.", + "id": "About", + "properties": { + "appInstalled": { + "description": "Whether the user has installed the requesting app.", + "type": "boolean" + }, + "canCreateDrives": { + "description": "Whether the user can create shared drives.", + "type": "boolean" + }, + "canCreateTeamDrives": { + "deprecated": true, + "description": "Deprecated: Use `canCreateDrives` instead.", + "type": "boolean" + }, + "driveThemes": { + "description": "A list of themes that are supported for shared drives.", + "items": { + "properties": { + "backgroundImageLink": { + "description": "A link to this theme's background image.", + "type": "string" + }, + "colorRgb": { + "description": "The color of this theme as an RGB hex string.", + "type": "string" + }, + "id": { + "description": "The ID of the theme.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "exportFormats": { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "description": "A map of source MIME type to possible targets for all supported exports.", + "type": "object" + }, + "folderColorPalette": { + "description": "The currently supported folder colors as RGB hex strings.", + "items": { + "type": "string" + }, + "type": "array" + }, + "importFormats": { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "description": "A map of source MIME type to possible targets for all supported imports.", + "type": "object" + }, + "kind": { + "default": "drive#about", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#about\"`.", + "type": "string" + }, + "maxImportSizes": { + "additionalProperties": { + "format": "int64", + "type": "string" + }, + "description": "A map of maximum import sizes by MIME type, in bytes.", + "type": "object" + }, + "maxUploadSize": { + "description": "The maximum upload size in bytes.", + "format": "int64", + "type": "string" + }, + "storageQuota": { + "description": "The user's storage quota limits and usage. For users that are part of an organization with pooled storage, information about the limit and usage across all services is for the organization, rather than the individual user. All fields are measured in bytes.", + "properties": { + "limit": { + "description": "The usage limit, if applicable. This will not be present if the user has unlimited storage. For users that are part of an organization with pooled storage, this is the limit for the organization, rather than the individual user.", + "format": "int64", + "type": "string" + }, + "usage": { + "description": "The total usage across all services. For users that are part of an organization with pooled storage, this is the usage across all services for the organization, rather than the individual user.", + "format": "int64", + "type": "string" + }, + "usageInDrive": { + "description": "The usage by all files in Google Drive.", + "format": "int64", + "type": "string" + }, + "usageInDriveTrash": { + "description": "The usage by trashed files in Google Drive.", + "format": "int64", + "type": "string" + } + }, + "type": "object" + }, + "teamDriveThemes": { + "deprecated": true, + "description": "Deprecated: Use `driveThemes` instead.", + "items": { + "properties": { + "backgroundImageLink": { + "deprecated": true, + "description": "Deprecated: Use `driveThemes/backgroundImageLink` instead.", + "type": "string" + }, + "colorRgb": { + "deprecated": true, + "description": "Deprecated: Use `driveThemes/colorRgb` instead.", + "type": "string" + }, + "id": { + "deprecated": true, + "description": "Deprecated: Use `driveThemes/id` instead.", + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + }, + "user": { + "$ref": "User", + "description": "The authenticated user." + } }, - "exposureBias": { - "type": "number", - "description": "The exposure bias of the photo (APEX value).", - "format": "float" + "type": "object" + }, + "AccessProposal": { + "description": "The Access Proposal resource for outstanding access proposals on a file", + "id": "AccessProposal", + "properties": { + "createTime": { + "description": "The creation time", + "format": "google-datetime", + "type": "string" + }, + "fileId": { + "description": "The file id that the proposal for access is on", + "type": "string" + }, + "proposalId": { + "description": "The id of the access proposal", + "type": "string" + }, + "recipientEmailAddress": { + "description": "The email address of the user that will receive permissions if accepted", + "type": "string" + }, + "requestMessage": { + "description": "The message that the requester added to the proposal", + "type": "string" + }, + "requesterEmailAddress": { + "description": "The email address of the requesting user", + "type": "string" + }, + "rolesAndViews": { + "description": "A wrapper for the role and view of an access proposal.", + "items": { + "$ref": "AccessProposalRoleAndView" + }, + "type": "array" + } }, - "exposureMode": { - "type": "string", - "description": "The exposure mode used to create the photo." + "type": "object" + }, + "AccessProposalRoleAndView": { + "description": "A wrapper for the role and view of an access proposal.", + "id": "AccessProposalRoleAndView", + "properties": { + "role": { + "description": "The role that was proposed by the requester New values may be added in the future, but the following are currently possible: * `writer` * `commenter` * `reader`", + "type": "string" + }, + "view": { + "description": "Indicates the view for this access proposal. Only populated for proposals that belong to a view. `published` is the only supported value.", + "type": "string" + } }, - "exposureTime": { - "type": "number", - "description": "The length of the exposure, in seconds.", - "format": "float" + "type": "object" + }, + "App": { + "description": "The `apps` resource provides a list of apps that a user has installed, with information about each app's supported MIME types, file extensions, and other details. Some resource methods (such as `apps.get`) require an `appId`. Use the `apps.list` method to retrieve the ID for an installed application.", + "id": "App", + "properties": { + "authorized": { + "description": "Whether the app is authorized to access data on the user's Drive.", + "type": "boolean" + }, + "createInFolderTemplate": { + "description": "The template URL to create a file with this app in a given folder. The template contains the {folderId} to be replaced by the folder ID house the new file.", + "type": "string" + }, + "createUrl": { + "description": "The URL to create a file with this app.", + "type": "string" + }, + "hasDriveWideScope": { + "description": "Whether the app has Drive-wide scope. An app with Drive-wide scope can access all files in the user's Drive.", + "type": "boolean" + }, + "icons": { + "description": "The various icons for the app.", + "items": { + "$ref": "AppIcons" + }, + "type": "array" + }, + "id": { + "description": "The ID of the app.", + "type": "string" + }, + "installed": { + "description": "Whether the app is installed.", + "type": "boolean" + }, + "kind": { + "default": "drive#app", + "description": "Output only. Identifies what kind of resource this is. Value: the fixed string \"drive#app\".", + "type": "string" + }, + "longDescription": { + "description": "A long description of the app.", + "type": "string" + }, + "name": { + "description": "The name of the app.", + "type": "string" + }, + "objectType": { + "description": "The type of object this app creates such as a Chart. If empty, the app name should be used instead.", + "type": "string" + }, + "openUrlTemplate": { + "description": "The template URL for opening files with this app. The template contains {ids} or {exportIds} to be replaced by the actual file IDs. For more information, see Open Files for the full documentation.", + "type": "string" + }, + "primaryFileExtensions": { + "description": "The list of primary file extensions.", + "items": { + "type": "string" + }, + "type": "array" + }, + "primaryMimeTypes": { + "description": "The list of primary MIME types.", + "items": { + "type": "string" + }, + "type": "array" + }, + "productId": { + "description": "The ID of the product listing for this app.", + "type": "string" + }, + "productUrl": { + "description": "A link to the product listing for this app.", + "type": "string" + }, + "secondaryFileExtensions": { + "description": "The list of secondary file extensions.", + "items": { + "type": "string" + }, + "type": "array" + }, + "secondaryMimeTypes": { + "description": "The list of secondary MIME types.", + "items": { + "type": "string" + }, + "type": "array" + }, + "shortDescription": { + "description": "A short description of the app.", + "type": "string" + }, + "supportsCreate": { + "description": "Whether this app supports creating objects.", + "type": "boolean" + }, + "supportsImport": { + "description": "Whether this app supports importing from Google Docs.", + "type": "boolean" + }, + "supportsMultiOpen": { + "description": "Whether this app supports opening more than one file.", + "type": "boolean" + }, + "supportsOfflineCreate": { + "description": "Whether this app supports creating files when offline.", + "type": "boolean" + }, + "useByDefault": { + "description": "Whether the app is selected as the default handler for the types it supports.", + "type": "boolean" + } }, - "flashUsed": { - "type": "boolean", - "description": "Whether a flash was used to create the photo." + "type": "object" + }, + "AppIcons": { + "id": "AppIcons", + "properties": { + "category": { + "description": "Category of the icon. Allowed values are: * `application` - The icon for the application. * `document` - The icon for a file associated with the app. * `documentShared` - The icon for a shared file associated with the app.", + "type": "string" + }, + "iconUrl": { + "description": "URL for the icon.", + "type": "string" + }, + "size": { + "description": "Size of the icon. Represented as the maximum of the width and height.", + "format": "int32", + "type": "integer" + } }, - "focalLength": { - "type": "number", - "description": "The focal length used to create the photo, in millimeters.", - "format": "float" + "type": "object" + }, + "AppList": { + "description": "A list of third-party applications which the user has installed or given access to Google Drive.", + "id": "AppList", + "properties": { + "defaultAppIds": { + "description": "The list of app IDs that the user has specified to use by default. The list is in reverse-priority order (lowest to highest).", + "items": { + "type": "string" + }, + "type": "array" + }, + "items": { + "description": "The list of apps.", + "items": { + "$ref": "App" + }, + "type": "array" + }, + "kind": { + "default": "drive#appList", + "description": "Output only. Identifies what kind of resource this is. Value: the fixed string \"drive#appList\".", + "type": "string" + }, + "selfLink": { + "description": "A link back to this list.", + "type": "string" + } }, - "height": { - "type": "integer", - "description": "The height of the image in pixels.", - "format": "int32" + "type": "object" + }, + "Change": { + "description": "A change to a file or shared drive.", + "id": "Change", + "properties": { + "changeType": { + "description": "The type of the change. Possible values are `file` and `drive`.", + "type": "string" + }, + "drive": { + "$ref": "Drive", + "description": "The updated state of the shared drive. Present if the changeType is drive, the user is still a member of the shared drive, and the shared drive has not been deleted." + }, + "driveId": { + "description": "The ID of the shared drive associated with this change.", + "type": "string" + }, + "file": { + "$ref": "File", + "description": "The updated state of the file. Present if the type is file and the file has not been removed from this list of changes." + }, + "fileId": { + "description": "The ID of the file which has changed.", + "type": "string" + }, + "kind": { + "default": "drive#change", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#change\"`.", + "type": "string" + }, + "removed": { + "description": "Whether the file or shared drive has been removed from this list of changes, for example by deletion or loss of access.", + "type": "boolean" + }, + "teamDrive": { + "$ref": "TeamDrive", + "deprecated": true, + "description": "Deprecated: Use `drive` instead." + }, + "teamDriveId": { + "deprecated": true, + "description": "Deprecated: Use `driveId` instead.", + "type": "string" + }, + "time": { + "description": "The time of this change (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "type": { + "deprecated": true, + "description": "Deprecated: Use `changeType` instead.", + "type": "string" + } }, - "isoSpeed": { - "type": "integer", - "description": "The ISO speed used to create the photo.", - "format": "int32" + "type": "object" + }, + "ChangeList": { + "description": "A list of changes for a user.", + "id": "ChangeList", + "properties": { + "changes": { + "description": "The list of changes. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.", + "items": { + "$ref": "Change" + }, + "type": "array" + }, + "kind": { + "default": "drive#changeList", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#changeList\"`.", + "type": "string" + }, + "newStartPageToken": { + "description": "The starting page token for future changes. This will be present only if the end of the current changes list has been reached. The page token doesn't expire.", + "type": "string" + }, + "nextPageToken": { + "description": "The page token for the next page of changes. This will be absent if the end of the changes list has been reached. The page token doesn't expire.", + "type": "string" + } }, - "lens": { - "type": "string", - "description": "The lens used to create the photo." + "type": "object" + }, + "Channel": { + "description": "A notification channel used to watch for resource changes.", + "id": "Channel", + "properties": { + "address": { + "description": "The address where notifications are delivered for this channel.", + "type": "string" + }, + "expiration": { + "description": "Date and time of notification channel expiration, expressed as a Unix timestamp, in milliseconds. Optional.", + "format": "int64", + "type": "string" + }, + "id": { + "description": "A UUID or similar unique string that identifies this channel.", + "type": "string" + }, + "kind": { + "default": "api#channel", + "description": "Identifies this as a notification channel used to watch for changes to a resource, which is `api#channel`.", + "type": "string" + }, + "params": { + "additionalProperties": { + "type": "string" + }, + "description": "Additional parameters controlling delivery channel behavior. Optional.", + "type": "object" + }, + "payload": { + "description": "A Boolean value to indicate whether payload is wanted. Optional.", + "type": "boolean" + }, + "resourceId": { + "description": "An opaque ID that identifies the resource being watched on this channel. Stable across different API versions.", + "type": "string" + }, + "resourceUri": { + "description": "A version-specific identifier for the watched resource.", + "type": "string" + }, + "token": { + "description": "An arbitrary string delivered to the target address with each notification delivered over this channel. Optional.", + "type": "string" + }, + "type": { + "description": "The type of delivery mechanism used for this channel. Valid values are \"web_hook\" or \"webhook\".", + "type": "string" + } }, - "location": { - "type": "object", - "description": "Geographic location information stored in the image.", - "properties": { - "altitude": { - "type": "number", - "description": "The altitude stored in the image.", - "format": "double" - }, - "latitude": { - "type": "number", - "description": "The latitude stored in the image.", - "format": "double" - }, - "longitude": { - "type": "number", - "description": "The longitude stored in the image.", - "format": "double" + "type": "object" + }, + "Comment": { + "description": "A comment on a file. Some resource methods (such as `comments.update`) require a `commentId`. Use the `comments.list` method to retrieve the ID for a comment in a file.", + "id": "Comment", + "properties": { + "anchor": { + "description": "A region of the document represented as a JSON string. For details on defining anchor properties, refer to [Manage comments and replies](https://developers.google.com/drive/api/v3/manage-comments).", + "type": "string" + }, + "author": { + "$ref": "User", + "description": "Output only. The author of the comment. The author's email address and permission ID will not be populated." + }, + "content": { + "annotations": { + "required": [ + "drive.comments.create", + "drive.comments.update" + ] + }, + "description": "The plain text content of the comment. This field is used for setting the content, while `htmlContent` should be displayed.", + "type": "string" + }, + "createdTime": { + "description": "The time at which the comment was created (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "deleted": { + "description": "Output only. Whether the comment has been deleted. A deleted comment has no content.", + "type": "boolean" + }, + "htmlContent": { + "description": "Output only. The content of the comment with HTML formatting.", + "type": "string" + }, + "id": { + "description": "Output only. The ID of the comment.", + "type": "string" + }, + "kind": { + "default": "drive#comment", + "description": "Output only. Identifies what kind of resource this is. Value: the fixed string `\"drive#comment\"`.", + "type": "string" + }, + "modifiedTime": { + "description": "The last time the comment or any of its replies was modified (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "quotedFileContent": { + "description": "The file content to which the comment refers, typically within the anchor region. For a text file, for example, this would be the text at the location of the comment.", + "properties": { + "mimeType": { + "description": "The MIME type of the quoted content.", + "type": "string" + }, + "value": { + "description": "The quoted content itself. This is interpreted as plain text if set through the API.", + "type": "string" + } + }, + "type": "object" + }, + "replies": { + "description": "Output only. The full list of replies to the comment in chronological order.", + "items": { + "$ref": "Reply" + }, + "type": "array" + }, + "resolved": { + "description": "Output only. Whether the comment has been resolved by one of its replies.", + "type": "boolean" } - } }, - "maxApertureValue": { - "type": "number", - "description": "The smallest f-number of the lens at the focal length used to create the photo (APEX value).", - "format": "float" + "type": "object" + }, + "CommentList": { + "description": "A list of comments on a file.", + "id": "CommentList", + "properties": { + "comments": { + "description": "The list of comments. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.", + "items": { + "$ref": "Comment" + }, + "type": "array" + }, + "kind": { + "default": "drive#commentList", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#commentList\"`.", + "type": "string" + }, + "nextPageToken": { + "description": "The page token for the next page of comments. This will be absent if the end of the comments list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.", + "type": "string" + } }, - "meteringMode": { - "type": "string", - "description": "The metering mode used to create the photo." - }, - "rotation": { - "type": "integer", - "description": "The rotation in clockwise degrees from the image's original orientation.", - "format": "int32" - }, - "sensor": { - "type": "string", - "description": "The type of sensor used to create the photo." - }, - "subjectDistance": { - "type": "integer", - "description": "The distance to the subject of the photo, in meters.", - "format": "int32" - }, - "time": { - "type": "string", - "description": "The date and time the photo was taken (EXIF DateTime)." - }, - "whiteBalance": { - "type": "string", - "description": "The white balance mode used to create the photo." - }, - "width": { - "type": "integer", - "description": "The width of the image in pixels.", - "format": "int32" - } - } - }, - "kind": { - "type": "string", - "description": "This is always drive#file.", - "default": "drive#file" - }, - "lastModifyingUser": { - "$ref": "User", - "description": "The last user to modify the file." - }, - "md5Checksum": { - "type": "string", - "description": "The MD5 checksum for the content of the file. This is only applicable to files with binary content in Drive." - }, - "mimeType": { - "type": "string", - "description": "The MIME type of the file.\nDrive will attempt to automatically detect an appropriate value from uploaded content if no value is provided. The value cannot be changed unless a new revision is uploaded.\nIf a file is created with a Google Doc MIME type, the uploaded content will be imported if possible. The supported import formats are published in the About resource." - }, - "modifiedByMeTime": { - "type": "string", - "description": "The last time the file was modified by the user (RFC 3339 date-time).", - "format": "date-time" - }, - "modifiedTime": { - "type": "string", - "description": "The last time the file was modified by anyone (RFC 3339 date-time).\nNote that setting modifiedTime will also update modifiedByMeTime for the user.", - "format": "date-time" - }, - "name": { - "type": "string", - "description": "The name of the file. This is not necessarily unique within a folder." - }, - "originalFilename": { - "type": "string", - "description": "The original filename of the uploaded content if available, or else the original value of the name field. This is only available for files with binary content in Drive." - }, - "ownedByMe": { - "type": "boolean", - "description": "Whether the user owns the file." - }, - "owners": { - "type": "array", - "description": "The owners of the file. Currently, only certain legacy files may have more than one owner.", - "items": { - "$ref": "User" - } - }, - "parents": { - "type": "array", - "description": "The IDs of the parent folders which contain the file.\nIf not specified as part of a create request, the file will be placed directly in the My Drive folder. Update requests must use the addParents and removeParents parameters to modify the values.", - "items": { - "type": "string" - } - }, - "permissions": { - "type": "array", - "description": "The full list of permissions for the file. This is only available if the requesting user can share the file.", - "items": { - "$ref": "Permission" - } - }, - "properties": { - "type": "object", - "description": "A collection of arbitrary key-value pairs which are visible to all apps.\nEntries with null values are cleared in update and copy requests.", - "additionalProperties": { - "type": "string" - } - }, - "quotaBytesUsed": { - "type": "string", - "description": "The number of storage quota bytes used by the file. This includes the head revision as well as previous revisions with keepForever enabled.", - "format": "int64" - }, - "shared": { - "type": "boolean", - "description": "Whether the file has been shared." - }, - "sharedWithMeTime": { - "type": "string", - "description": "The time at which the file was shared with the user, if applicable (RFC 3339 date-time).", - "format": "date-time" - }, - "sharingUser": { - "$ref": "User", - "description": "The user who shared the file with the requesting user, if applicable." - }, - "size": { - "type": "string", - "description": "The size of the file's content in bytes. This is only applicable to files with binary content in Drive.", - "format": "int64" - }, - "spaces": { - "type": "array", - "description": "The list of spaces which contain the file. The currently supported values are 'drive', 'appDataFolder' and 'photos'.", - "items": { - "type": "string" - } - }, - "starred": { - "type": "boolean", - "description": "Whether the user has starred the file." - }, - "thumbnailLink": { - "type": "string", - "description": "A short-lived link to the file's thumbnail, if available. Typically lasts on the order of hours." - }, - "trashed": { - "type": "boolean", - "description": "Whether the file has been trashed, either explicitly or from a trashed parent folder. Only the owner may trash a file, and other users cannot see files in the owner's trash." - }, - "version": { - "type": "string", - "description": "A monotonically increasing version number for the file. This reflects every change made to the file on the server, even those not visible to the user.", - "format": "int64" - }, - "videoMediaMetadata": { - "type": "object", - "description": "Additional metadata about video media. This may not be available immediately upon upload.", - "properties": { - "durationMillis": { - "type": "string", - "description": "The duration of the video in milliseconds.", - "format": "int64" - }, - "height": { - "type": "integer", - "description": "The height of the video in pixels.", - "format": "int32" - }, - "width": { - "type": "integer", - "description": "The width of the video in pixels.", - "format": "int32" - } - } - }, - "viewedByMe": { - "type": "boolean", - "description": "Whether the file has been viewed by this user." - }, - "viewedByMeTime": { - "type": "string", - "description": "The last time the file was viewed by the user (RFC 3339 date-time).", - "format": "date-time" - }, - "viewersCanCopyContent": { - "type": "boolean", - "description": "Whether users with only reader or commenter permission can copy the file's content. This affects copy, download, and print operations." - }, - "webContentLink": { - "type": "string", - "description": "A link for downloading the content of the file in a browser. This is only available for files with binary content in Drive." - }, - "webViewLink": { - "type": "string", - "description": "A link for opening the file in a relevant Google editor or viewer in a browser." - }, - "writersCanShare": { - "type": "boolean", - "description": "Whether users with only writer permission can modify the file's permissions." - } - } - }, - "FileList": { - "id": "FileList", - "type": "object", - "description": "A list of files.", - "properties": { - "files": { - "type": "array", - "description": "The page of files.", - "items": { - "$ref": "File" - } - }, - "kind": { - "type": "string", - "description": "This is always drive#fileList.", - "default": "drive#fileList" - }, - "nextPageToken": { - "type": "string", - "description": "The page token for the next page of files. This will be absent if the end of the files list has been reached." - } - } - }, - "GeneratedIds": { - "id": "GeneratedIds", - "type": "object", - "description": "A list of generated file IDs which can be provided in create requests.", - "properties": { - "ids": { - "type": "array", - "description": "The IDs generated for the requesting user in the specified space.", - "items": { - "type": "string" - } - }, - "kind": { - "type": "string", - "description": "This is always drive#generatedIds", - "default": "drive#generatedIds" - }, - "space": { - "type": "string", - "description": "The type of file that can be created with these IDs." - } - } - }, - "Permission": { - "id": "Permission", - "type": "object", - "description": "A permission for a file. A permission grants a user, group, domain or the world access to a file or a folder hierarchy.", - "properties": { - "allowFileDiscovery": { - "type": "boolean", - "description": "Whether the permission allows the file to be discovered through search. This is only applicable for permissions of type domain or anyone." - }, - "displayName": { - "type": "string", - "description": "A displayable name for users, groups or domains." - }, - "domain": { - "type": "string", - "description": "The domain to which this permission refers." - }, - "emailAddress": { - "type": "string", - "description": "The email address of the user or group to which this permission refers." - }, - "id": { - "type": "string", - "description": "The ID of this permission. This is a unique identifier for the grantee, and is published in User resources as permissionId." - }, - "kind": { - "type": "string", - "description": "This is always drive#permission.", - "default": "drive#permission" - }, - "photoLink": { - "type": "string", - "description": "A link to the user's profile photo, if available." - }, - "role": { - "type": "string", - "description": "The role granted by this permission. Valid values are: \n- owner \n- writer \n- commenter \n- reader", - "annotations": { - "required": [ - "drive.permissions.create" - ] - } - }, - "type": { - "type": "string", - "description": "The type of the grantee. Valid values are: \n- user \n- group \n- domain \n- anyone", - "annotations": { - "required": [ - "drive.permissions.create" - ] - } - } - } - }, - "PermissionList": { - "id": "PermissionList", - "type": "object", - "description": "A list of permissions for a file.", - "properties": { - "kind": { - "type": "string", - "description": "This is always drive#permissionList.", - "default": "drive#permissionList" - }, - "permissions": { - "type": "array", - "description": "The full list of permissions.", - "items": { - "$ref": "Permission" - } - } - } - }, - "Reply": { - "id": "Reply", - "type": "object", - "description": "A reply to a comment on a file.", - "properties": { - "action": { - "type": "string", - "description": "The action the reply performed to the parent comment. Valid values are: \n- resolve \n- reopen" - }, - "author": { - "$ref": "User", - "description": "The user who created the reply." - }, - "content": { - "type": "string", - "description": "The plain text content of the reply. This field is used for setting the content, while htmlContent should be displayed. This is required on creates if no action is specified.", - "annotations": { - "required": [ - "drive.replies.update" - ] - } - }, - "createdTime": { - "type": "string", - "description": "The time at which the reply was created (RFC 3339 date-time).", - "format": "date-time" - }, - "deleted": { - "type": "boolean", - "description": "Whether the reply has been deleted. A deleted reply has no content." - }, - "htmlContent": { - "type": "string", - "description": "The content of the reply with HTML formatting." - }, - "id": { - "type": "string", - "description": "The ID of the reply." - }, - "kind": { - "type": "string", - "description": "This is always drive#reply.", - "default": "drive#reply" - }, - "modifiedTime": { - "type": "string", - "description": "The last time the reply was modified (RFC 3339 date-time).", - "format": "date-time" - } - } - }, - "ReplyList": { - "id": "ReplyList", - "type": "object", - "description": "A list of replies to a comment on a file.", - "properties": { - "kind": { - "type": "string", - "description": "This is always drive#replyList.", - "default": "drive#replyList" - }, - "nextPageToken": { - "type": "string", - "description": "The page token for the next page of replies. This will be absent if the end of the replies list has been reached." - }, - "replies": { - "type": "array", - "description": "The page of replies.", - "items": { - "$ref": "Reply" - } - } - } - }, - "Revision": { - "id": "Revision", - "type": "object", - "description": "The metadata for a revision to a file.", - "properties": { - "id": { - "type": "string", - "description": "The ID of the revision." - }, - "keepForever": { - "type": "boolean", - "description": "Whether to keep this revision forever, even if it is no longer the head revision. If not set, the revision will be automatically purged 30 days after newer content is uploaded. This can be set on a maximum of 200 revisions for a file.\nThis field is only applicable to files with binary content in Drive." - }, - "kind": { - "type": "string", - "description": "This is always drive#revision.", - "default": "drive#revision" - }, - "lastModifyingUser": { - "$ref": "User", - "description": "The last user to modify this revision." - }, - "md5Checksum": { - "type": "string", - "description": "The MD5 checksum of the revision's content. This is only applicable to files with binary content in Drive." - }, - "mimeType": { - "type": "string", - "description": "The MIME type of the revision." - }, - "modifiedTime": { - "type": "string", - "description": "The last time the revision was modified (RFC 3339 date-time).", - "format": "date-time" - }, - "originalFilename": { - "type": "string", - "description": "The original filename used to create this revision. This is only applicable to files with binary content in Drive." - }, - "publishAuto": { - "type": "boolean", - "description": "Whether subsequent revisions will be automatically republished. This is only applicable to Google Docs." - }, - "published": { - "type": "boolean", - "description": "Whether this revision is published. This is only applicable to Google Docs." - }, - "publishedOutsideDomain": { - "type": "boolean", - "description": "Whether this revision is published outside the domain. This is only applicable to Google Docs." - }, - "size": { - "type": "string", - "description": "The size of the revision's content in bytes. This is only applicable to files with binary content in Drive.", - "format": "int64" - } - } - }, - "RevisionList": { - "id": "RevisionList", - "type": "object", - "description": "A list of revisions of a file.", - "properties": { - "kind": { - "type": "string", - "description": "This is always drive#revisionList.", - "default": "drive#revisionList" - }, - "revisions": { - "type": "array", - "description": "The full list of revisions.", - "items": { - "$ref": "Revision" - } - } - } - }, - "StartPageToken": { - "id": "StartPageToken", - "type": "object", - "properties": { - "kind": { - "type": "string", - "description": "This is always drive#startPageToken.", - "default": "drive#startPageToken" - }, - "startPageToken": { - "type": "string", - "description": "The starting page token for listing changes." - } - } - }, - "User": { - "id": "User", - "type": "object", - "description": "Information about a Drive user.", - "properties": { - "displayName": { - "type": "string", - "description": "A plain text displayable name for this user." - }, - "emailAddress": { - "type": "string", - "description": "The email address of the user. This may not be present in certain contexts if the user has not made their email address visible to the requester." - }, - "kind": { - "type": "string", - "description": "This is always drive#user.", - "default": "drive#user" - }, - "me": { - "type": "boolean", - "description": "Whether this user is the requesting user." - }, - "permissionId": { - "type": "string", - "description": "The user's ID as visible in Permission resources." - }, - "photoLink": { - "type": "string", - "description": "A link to the user's profile photo, if available." - } - } - } - }, - "resources": { - "about": { - "methods": { - "get": { - "id": "drive.about.get", - "path": "about", - "httpMethod": "GET", - "description": "Gets information about the user, the user's Drive, and system capabilities.", - "response": { - "$ref": "About" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ] - } - } - }, - "changes": { - "methods": { - "getStartPageToken": { - "id": "drive.changes.getStartPageToken", - "path": "changes/startPageToken", - "httpMethod": "GET", - "description": "Gets the starting pageToken for listing future changes.", - "response": { - "$ref": "StartPageToken" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ] - }, - "list": { - "id": "drive.changes.list", - "path": "changes", - "httpMethod": "GET", - "description": "Lists changes for a user.", - "parameters": { - "includeRemoved": { - "type": "boolean", - "description": "Whether to include changes indicating that items have left the view of the changes list, for example by deletion or lost access.", - "default": "true", - "location": "query" - }, - "pageSize": { - "type": "integer", - "description": "The maximum number of changes to return per page.", - "default": "100", - "format": "int32", - "minimum": "1", - "maximum": "1000", - "location": "query" - }, - "pageToken": { - "type": "string", - "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response or to the response from the getStartPageToken method.", - "required": true, - "location": "query" - }, - "restrictToMyDrive": { - "type": "boolean", - "description": "Whether to restrict the results to changes inside the My Drive hierarchy. This omits changes to files such as those in the Application Data folder or shared files which have not been added to My Drive.", - "default": "false", - "location": "query" - }, - "spaces": { - "type": "string", - "description": "A comma-separated list of spaces to query within the user corpus. Supported values are 'drive', 'appDataFolder' and 'photos'.", - "default": "drive", - "location": "query" - } - }, - "parameterOrder": [ - "pageToken" - ], - "response": { - "$ref": "ChangeList" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ], - "supportsSubscription": true - }, - "watch": { - "id": "drive.changes.watch", - "path": "changes/watch", - "httpMethod": "POST", - "description": "Subscribes to changes for a user.", - "parameters": { - "includeRemoved": { - "type": "boolean", - "description": "Whether to include changes indicating that items have left the view of the changes list, for example by deletion or lost access.", - "default": "true", - "location": "query" - }, - "pageSize": { - "type": "integer", - "description": "The maximum number of changes to return per page.", - "default": "100", - "format": "int32", - "minimum": "1", - "maximum": "1000", - "location": "query" - }, - "pageToken": { - "type": "string", - "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response or to the response from the getStartPageToken method.", - "required": true, - "location": "query" - }, - "restrictToMyDrive": { - "type": "boolean", - "description": "Whether to restrict the results to changes inside the My Drive hierarchy. This omits changes to files such as those in the Application Data folder or shared files which have not been added to My Drive.", - "default": "false", - "location": "query" - }, - "spaces": { - "type": "string", - "description": "A comma-separated list of spaces to query within the user corpus. Supported values are 'drive', 'appDataFolder' and 'photos'.", - "default": "drive", - "location": "query" - } - }, - "parameterOrder": [ - "pageToken" - ], - "request": { - "$ref": "Channel", - "parameterName": "resource" - }, - "response": { - "$ref": "Channel" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ], - "supportsSubscription": true - } - } - }, - "channels": { - "methods": { - "stop": { - "id": "drive.channels.stop", - "path": "channels/stop", - "httpMethod": "POST", - "description": "Stop watching resources through this channel", - "request": { - "$ref": "Channel", - "parameterName": "resource" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ] - } - } - }, - "comments": { - "methods": { - "create": { - "id": "drive.comments.create", - "path": "files/{fileId}/comments", - "httpMethod": "POST", - "description": "Creates a new comment on a file.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId" - ], - "request": { - "$ref": "Comment" - }, - "response": { - "$ref": "Comment" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file" - ] - }, - "delete": { - "id": "drive.comments.delete", - "path": "files/{fileId}/comments/{commentId}", - "httpMethod": "DELETE", - "description": "Deletes a comment.", - "parameters": { - "commentId": { - "type": "string", - "description": "The ID of the comment.", - "required": true, - "location": "path" - }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "commentId" - ], - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file" - ] - }, - "get": { - "id": "drive.comments.get", - "path": "files/{fileId}/comments/{commentId}", - "httpMethod": "GET", - "description": "Gets a comment by ID.", - "parameters": { - "commentId": { - "type": "string", - "description": "The ID of the comment.", - "required": true, - "location": "path" - }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - }, - "includeDeleted": { - "type": "boolean", - "description": "Whether to return deleted comments. Deleted comments will not include their original content.", - "default": "false", - "location": "query" - } - }, - "parameterOrder": [ - "fileId", - "commentId" - ], - "response": { - "$ref": "Comment" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.readonly" - ] - }, - "list": { - "id": "drive.comments.list", - "path": "files/{fileId}/comments", - "httpMethod": "GET", - "description": "Lists a file's comments.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - }, - "includeDeleted": { - "type": "boolean", - "description": "Whether to include deleted comments. Deleted comments will not include their original content.", - "default": "false", - "location": "query" - }, - "pageSize": { - "type": "integer", - "description": "The maximum number of comments to return per page.", - "default": "20", - "format": "int32", - "minimum": "1", - "maximum": "100", - "location": "query" - }, - "pageToken": { - "type": "string", - "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", - "location": "query" - }, - "startModifiedTime": { - "type": "string", - "description": "The minimum value of 'modifiedTime' for the result comments (RFC 3339 date-time).", - "location": "query" - } - }, - "parameterOrder": [ - "fileId" - ], - "response": { - "$ref": "CommentList" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.readonly" - ] - }, - "update": { - "id": "drive.comments.update", - "path": "files/{fileId}/comments/{commentId}", - "httpMethod": "PATCH", - "description": "Updates a comment with patch semantics.", - "parameters": { - "commentId": { - "type": "string", - "description": "The ID of the comment.", - "required": true, - "location": "path" - }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "commentId" - ], - "request": { - "$ref": "Comment" - }, - "response": { - "$ref": "Comment" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file" - ] - } - } - }, - "files": { - "methods": { - "copy": { - "id": "drive.files.copy", - "path": "files/{fileId}/copy", - "httpMethod": "POST", - "description": "Creates a copy of a file and applies any requested updates with patch semantics.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - }, - "ignoreDefaultVisibility": { - "type": "boolean", - "description": "Whether to ignore the domain's default visibility settings for the created file. Domain administrators can choose to make all uploaded files visible to the domain by default; this parameter bypasses that behavior for the request. Permissions are still inherited from parent folders.", - "default": "false", - "location": "query" - }, - "keepRevisionForever": { - "type": "boolean", - "description": "Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Drive.", - "default": "false", - "location": "query" - }, - "ocrLanguage": { - "type": "string", - "description": "A language hint for OCR processing during image import (ISO 639-1 code).", - "location": "query" - } - }, - "parameterOrder": [ - "fileId" - ], - "request": { - "$ref": "File" - }, - "response": { - "$ref": "File" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.photos.readonly" - ] - }, - "create": { - "id": "drive.files.create", - "path": "files", - "httpMethod": "POST", - "description": "Creates a new file.", - "parameters": { - "ignoreDefaultVisibility": { - "type": "boolean", - "description": "Whether to ignore the domain's default visibility settings for the created file. Domain administrators can choose to make all uploaded files visible to the domain by default; this parameter bypasses that behavior for the request. Permissions are still inherited from parent folders.", - "default": "false", - "location": "query" - }, - "keepRevisionForever": { - "type": "boolean", - "description": "Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Drive.", - "default": "false", - "location": "query" - }, - "ocrLanguage": { - "type": "string", - "description": "A language hint for OCR processing during image import (ISO 639-1 code).", - "location": "query" - }, - "useContentAsIndexableText": { - "type": "boolean", - "description": "Whether to use the uploaded content as indexable text.", - "default": "false", - "location": "query" - } - }, - "request": { - "$ref": "File" - }, - "response": { - "$ref": "File" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file" - ], - "supportsMediaUpload": true, - "mediaUpload": { - "accept": [ - "*/*" - ], - "maxSize": "5120GB", - "protocols": { - "simple": { - "multipart": true, - "path": "/upload/drive/v3/files" - }, - "resumable": { - "multipart": true, - "path": "/resumable/upload/drive/v3/files" - } - } - }, - "supportsSubscription": true - }, - "delete": { - "id": "drive.files.delete", - "path": "files/{fileId}", - "httpMethod": "DELETE", - "description": "Permanently deletes a file owned by the user without moving it to the trash. If the target is a folder, all descendants owned by the user are also deleted.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId" - ], - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file" - ] - }, - "emptyTrash": { - "id": "drive.files.emptyTrash", - "path": "files/trash", - "httpMethod": "DELETE", - "description": "Permanently deletes all of the user's trashed files.", - "scopes": [ - "https://www.googleapis.com/auth/drive" - ] - }, - "export": { - "id": "drive.files.export", - "path": "files/{fileId}/export", - "httpMethod": "GET", - "description": "Exports a Google Doc to the requested MIME type and returns the exported content.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - }, - "mimeType": { - "type": "string", - "description": "The MIME type of the format requested for this export.", - "required": true, - "location": "query" - } - }, - "parameterOrder": [ - "fileId", - "mimeType" - ], - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.readonly" - ], - "supportsMediaDownload": true - }, - "generateIds": { - "id": "drive.files.generateIds", - "path": "files/generateIds", - "httpMethod": "GET", - "description": "Generates a set of file IDs which can be provided in create requests.", - "parameters": { - "count": { - "type": "integer", - "description": "The number of IDs to return.", - "default": "10", - "format": "int32", - "minimum": "1", - "maximum": "1000", - "location": "query" - }, - "space": { - "type": "string", - "description": "The space in which the IDs can be used to create new files. Supported values are 'drive' and 'appDataFolder'.", - "default": "drive", - "location": "query" - } - }, - "response": { - "$ref": "GeneratedIds" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file" - ] - }, - "get": { - "id": "drive.files.get", - "path": "files/{fileId}", - "httpMethod": "GET", - "description": "Gets a file's metadata or content by ID.", - "parameters": { - "acknowledgeAbuse": { - "type": "boolean", - "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when alt=media.", - "default": "false", - "location": "query" - }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId" - ], - "response": { - "$ref": "File" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ], - "supportsMediaDownload": true, - "useMediaDownloadService": true, - "supportsSubscription": true - }, - "list": { - "id": "drive.files.list", - "path": "files", - "httpMethod": "GET", - "description": "Lists or searches files.", - "parameters": { - "corpus": { - "type": "string", - "description": "The source of files to list.", - "default": "user", - "enum": [ - "domain", - "user" - ], - "enumDescriptions": [ - "Files shared to the user's domain.", - "Files owned by or shared to the user." - ], - "location": "query" - }, - "orderBy": { - "type": "string", - "description": "A comma-separated list of sort keys. Valid keys are 'createdTime', 'folder', 'modifiedByMeTime', 'modifiedTime', 'name', 'quotaBytesUsed', 'recency', 'sharedWithMeTime', 'starred', and 'viewedByMeTime'. Each key sorts ascending by default, but may be reversed with the 'desc' modifier. Example usage: ?orderBy=folder,modifiedTime desc,name. Please note that there is a current limitation for users with approximately one million files in which the requested sort order is ignored.", - "location": "query" - }, - "pageSize": { - "type": "integer", - "description": "The maximum number of files to return per page.", - "default": "100", - "format": "int32", - "minimum": "1", - "maximum": "1000", - "location": "query" + "type": "object" + }, + "ContentRestriction": { + "description": "A restriction for accessing the content of the file.", + "id": "ContentRestriction", + "properties": { + "ownerRestricted": { + "description": "Whether the content restriction can only be modified or removed by a user who owns the file. For files in shared drives, any user with `organizer` capabilities can modify or remove this content restriction.", + "type": "boolean" + }, + "readOnly": { + "description": "Whether the content of the file is read-only. If a file is read-only, a new revision of the file may not be added, comments may not be added or modified, and the title of the file may not be modified.", + "type": "boolean" + }, + "reason": { + "description": "Reason for why the content of the file is restricted. This is only mutable on requests that also set `readOnly=true`.", + "type": "string" + }, + "restrictingUser": { + "$ref": "User", + "description": "Output only. The user who set the content restriction. Only populated if `readOnly` is true." + }, + "restrictionTime": { + "description": "The time at which the content restriction was set (formatted RFC 3339 timestamp). Only populated if readOnly is true.", + "format": "date-time", + "type": "string" + }, + "systemRestricted": { + "description": "Output only. Whether the content restriction was applied by the system, for example due to an esignature. Users cannot modify or remove system restricted content restrictions.", + "type": "boolean" + }, + "type": { + "description": "Output only. The type of the content restriction. Currently the only possible value is `globalContentRestriction`.", + "type": "string" + } }, - "pageToken": { - "type": "string", - "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", - "location": "query" + "type": "object" + }, + "Drive": { + "description": "Representation of a shared drive. Some resource methods (such as `drives.update`) require a `driveId`. Use the `drives.list` method to retrieve the ID for a shared drive.", + "id": "Drive", + "properties": { + "backgroundImageFile": { + "description": "An image file and cropping parameters from which a background image for this shared drive is set. This is a write only field; it can only be set on `drive.drives.update` requests that don't set `themeId`. When specified, all fields of the `backgroundImageFile` must be set.", + "properties": { + "id": { + "description": "The ID of an image file in Google Drive to use for the background image.", + "type": "string" + }, + "width": { + "description": "The width of the cropped image in the closed range of 0 to 1. This value represents the width of the cropped image divided by the width of the entire image. The height is computed by applying a width to height aspect ratio of 80 to 9. The resulting image must be at least 1280 pixels wide and 144 pixels high.", + "format": "float", + "type": "number" + }, + "xCoordinate": { + "description": "The X coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the horizontal distance from the left side of the entire image to the left side of the cropping area divided by the width of the entire image.", + "format": "float", + "type": "number" + }, + "yCoordinate": { + "description": "The Y coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the vertical distance from the top side of the entire image to the top side of the cropping area divided by the height of the entire image.", + "format": "float", + "type": "number" + } + }, + "type": "object" + }, + "backgroundImageLink": { + "description": "Output only. A short-lived link to this shared drive's background image.", + "type": "string" + }, + "capabilities": { + "description": "Output only. Capabilities the current user has on this shared drive.", + "properties": { + "canAddChildren": { + "description": "Output only. Whether the current user can add children to folders in this shared drive.", + "type": "boolean" + }, + "canChangeCopyRequiresWriterPermissionRestriction": { + "description": "Output only. Whether the current user can change the `copyRequiresWriterPermission` restriction of this shared drive.", + "type": "boolean" + }, + "canChangeDomainUsersOnlyRestriction": { + "description": "Output only. Whether the current user can change the `domainUsersOnly` restriction of this shared drive.", + "type": "boolean" + }, + "canChangeDriveBackground": { + "description": "Output only. Whether the current user can change the background of this shared drive.", + "type": "boolean" + }, + "canChangeDriveMembersOnlyRestriction": { + "description": "Output only. Whether the current user can change the `driveMembersOnly` restriction of this shared drive.", + "type": "boolean" + }, + "canChangeSharingFoldersRequiresOrganizerPermissionRestriction": { + "description": "Output only. Whether the current user can change the `sharingFoldersRequiresOrganizerPermission` restriction of this shared drive.", + "type": "boolean" + }, + "canComment": { + "description": "Output only. Whether the current user can comment on files in this shared drive.", + "type": "boolean" + }, + "canCopy": { + "description": "Output only. Whether the current user can copy files in this shared drive.", + "type": "boolean" + }, + "canDeleteChildren": { + "description": "Output only. Whether the current user can delete children from folders in this shared drive.", + "type": "boolean" + }, + "canDeleteDrive": { + "description": "Output only. Whether the current user can delete this shared drive. Attempting to delete the shared drive may still fail if there are untrashed items inside the shared drive.", + "type": "boolean" + }, + "canDownload": { + "description": "Output only. Whether the current user can download files in this shared drive.", + "type": "boolean" + }, + "canEdit": { + "description": "Output only. Whether the current user can edit files in this shared drive", + "type": "boolean" + }, + "canListChildren": { + "description": "Output only. Whether the current user can list the children of folders in this shared drive.", + "type": "boolean" + }, + "canManageMembers": { + "description": "Output only. Whether the current user can add members to this shared drive or remove them or change their role.", + "type": "boolean" + }, + "canReadRevisions": { + "description": "Output only. Whether the current user can read the revisions resource of files in this shared drive.", + "type": "boolean" + }, + "canRename": { + "description": "Output only. Whether the current user can rename files or folders in this shared drive.", + "type": "boolean" + }, + "canRenameDrive": { + "description": "Output only. Whether the current user can rename this shared drive.", + "type": "boolean" + }, + "canResetDriveRestrictions": { + "description": "Output only. Whether the current user can reset the shared drive restrictions to defaults.", + "type": "boolean" + }, + "canShare": { + "description": "Output only. Whether the current user can share files or folders in this shared drive.", + "type": "boolean" + }, + "canTrashChildren": { + "description": "Output only. Whether the current user can trash children from folders in this shared drive.", + "type": "boolean" + } + }, + "type": "object" + }, + "colorRgb": { + "description": "The color of this shared drive as an RGB hex string. It can only be set on a `drive.drives.update` request that does not set `themeId`.", + "type": "string" + }, + "createdTime": { + "description": "The time at which the shared drive was created (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "hidden": { + "description": "Whether the shared drive is hidden from default view.", + "type": "boolean" + }, + "id": { + "description": "Output only. The ID of this shared drive which is also the ID of the top level folder of this shared drive.", + "type": "string" + }, + "kind": { + "default": "drive#drive", + "description": "Output only. Identifies what kind of resource this is. Value: the fixed string `\"drive#drive\"`.", + "type": "string" + }, + "name": { + "description": "The name of this shared drive.", + "type": "string" + }, + "orgUnitId": { + "description": "Output only. The organizational unit of this shared drive. This field is only populated on `drives.list` responses when the `useDomainAdminAccess` parameter is set to `true`.", + "type": "string" + }, + "restrictions": { + "description": "A set of restrictions that apply to this shared drive or items inside this shared drive. Note that restrictions can't be set when creating a shared drive. To add a restriction, first create a shared drive and then use `drives.update` to add restrictions.", + "properties": { + "adminManagedRestrictions": { + "description": "Whether administrative privileges on this shared drive are required to modify restrictions.", + "type": "boolean" + }, + "copyRequiresWriterPermission": { + "description": "Whether the options to copy, print, or download files inside this shared drive, should be disabled for readers and commenters. When this restriction is set to `true`, it will override the similarly named field to `true` for any file inside this shared drive.", + "type": "boolean" + }, + "domainUsersOnly": { + "description": "Whether access to this shared drive and items inside this shared drive is restricted to users of the domain to which this shared drive belongs. This restriction may be overridden by other sharing policies controlled outside of this shared drive.", + "type": "boolean" + }, + "driveMembersOnly": { + "description": "Whether access to items inside this shared drive is restricted to its members.", + "type": "boolean" + }, + "sharingFoldersRequiresOrganizerPermission": { + "description": "If true, only users with the organizer role can share folders. If false, users with either the organizer role or the file organizer role can share folders.", + "type": "boolean" + } + }, + "type": "object" + }, + "themeId": { + "description": "The ID of the theme from which the background image and color will be set. The set of possible `driveThemes` can be retrieved from a `drive.about.get` response. When not specified on a `drive.drives.create` request, a random theme is chosen from which the background image and color are set. This is a write-only field; it can only be set on requests that don't set `colorRgb` or `backgroundImageFile`.", + "type": "string" + } }, - "q": { - "type": "string", - "description": "A query for filtering the file results. See the \"Search for Files\" guide for supported syntax.", - "location": "query" + "type": "object" + }, + "DriveList": { + "description": "A list of shared drives.", + "id": "DriveList", + "properties": { + "drives": { + "description": "The list of shared drives. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.", + "items": { + "$ref": "Drive" + }, + "type": "array" + }, + "kind": { + "default": "drive#driveList", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#driveList\"`.", + "type": "string" + }, + "nextPageToken": { + "description": "The page token for the next page of shared drives. This will be absent if the end of the list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.", + "type": "string" + } }, - "spaces": { - "type": "string", - "description": "A comma-separated list of spaces to query within the corpus. Supported values are 'drive', 'appDataFolder' and 'photos'.", - "default": "drive", - "location": "query" - } - }, - "response": { - "$ref": "FileList" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ] - }, - "update": { - "id": "drive.files.update", - "path": "files/{fileId}", - "httpMethod": "PATCH", - "description": "Updates a file's metadata and/or content with patch semantics.", - "parameters": { - "addParents": { - "type": "string", - "description": "A comma-separated list of parent IDs to add.", - "location": "query" + "type": "object" + }, + "File": { + "description": "The metadata for a file. Some resource methods (such as `files.update`) require a `fileId`. Use the `files.list` method to retrieve the ID for a file.", + "id": "File", + "properties": { + "appProperties": { + "additionalProperties": { + "type": "string" + }, + "description": "A collection of arbitrary key-value pairs which are private to the requesting app.\nEntries with null values are cleared in update and copy requests. These properties can only be retrieved using an authenticated request. An authenticated request uses an access token obtained with a OAuth 2 client ID. You cannot use an API key to retrieve private properties.", + "type": "object" + }, + "capabilities": { + "description": "Output only. Capabilities the current user has on this file. Each capability corresponds to a fine-grained action that a user may take.", + "properties": { + "canAcceptOwnership": { + "description": "Output only. Whether the current user is the pending owner of the file. Not populated for shared drive files.", + "type": "boolean" + }, + "canAddChildren": { + "description": "Output only. Whether the current user can add children to this folder. This is always false when the item is not a folder.", + "type": "boolean" + }, + "canAddFolderFromAnotherDrive": { + "description": "Output only. Whether the current user can add a folder from another drive (different shared drive or My Drive) to this folder. This is false when the item is not a folder. Only populated for items in shared drives.", + "type": "boolean" + }, + "canAddMyDriveParent": { + "description": "Output only. Whether the current user can add a parent for the item without removing an existing parent in the same request. Not populated for shared drive files.", + "type": "boolean" + }, + "canChangeCopyRequiresWriterPermission": { + "description": "Output only. Whether the current user can change the `copyRequiresWriterPermission` restriction of this file.", + "type": "boolean" + }, + "canChangeSecurityUpdateEnabled": { + "description": "Output only. Whether the current user can change the securityUpdateEnabled field on link share metadata.", + "type": "boolean" + }, + "canChangeViewersCanCopyContent": { + "deprecated": true, + "description": "Deprecated: Output only.", + "type": "boolean" + }, + "canComment": { + "description": "Output only. Whether the current user can comment on this file.", + "type": "boolean" + }, + "canCopy": { + "description": "Output only. Whether the current user can copy this file. For an item in a shared drive, whether the current user can copy non-folder descendants of this item, or this item itself if it is not a folder.", + "type": "boolean" + }, + "canDelete": { + "description": "Output only. Whether the current user can delete this file.", + "type": "boolean" + }, + "canDeleteChildren": { + "description": "Output only. Whether the current user can delete children of this folder. This is false when the item is not a folder. Only populated for items in shared drives.", + "type": "boolean" + }, + "canDownload": { + "description": "Output only. Whether the current user can download this file.", + "type": "boolean" + }, + "canEdit": { + "description": "Output only. Whether the current user can edit this file. Other factors may limit the type of changes a user can make to a file. For example, see `canChangeCopyRequiresWriterPermission` or `canModifyContent`.", + "type": "boolean" + }, + "canListChildren": { + "description": "Output only. Whether the current user can list the children of this folder. This is always false when the item is not a folder.", + "type": "boolean" + }, + "canModifyContent": { + "description": "Output only. Whether the current user can modify the content of this file.", + "type": "boolean" + }, + "canModifyContentRestriction": { + "deprecated": true, + "description": "Deprecated: Output only. Use one of `canModifyEditorContentRestriction`, `canModifyOwnerContentRestriction` or `canRemoveContentRestriction`.", + "type": "boolean" + }, + "canModifyEditorContentRestriction": { + "description": "Output only. Whether the current user can add or modify content restrictions on the file which are editor restricted.", + "type": "boolean" + }, + "canModifyLabels": { + "description": "Output only. Whether the current user can modify the labels on the file.", + "type": "boolean" + }, + "canModifyOwnerContentRestriction": { + "description": "Output only. Whether the current user can add or modify content restrictions which are owner restricted.", + "type": "boolean" + }, + "canMoveChildrenOutOfDrive": { + "description": "Output only. Whether the current user can move children of this folder outside of the shared drive. This is false when the item is not a folder. Only populated for items in shared drives.", + "type": "boolean" + }, + "canMoveChildrenOutOfTeamDrive": { + "deprecated": true, + "description": "Deprecated: Output only. Use `canMoveChildrenOutOfDrive` instead.", + "type": "boolean" + }, + "canMoveChildrenWithinDrive": { + "description": "Output only. Whether the current user can move children of this folder within this drive. This is false when the item is not a folder. Note that a request to move the child may still fail depending on the current user's access to the child and to the destination folder.", + "type": "boolean" + }, + "canMoveChildrenWithinTeamDrive": { + "deprecated": true, + "description": "Deprecated: Output only. Use `canMoveChildrenWithinDrive` instead.", + "type": "boolean" + }, + "canMoveItemIntoTeamDrive": { + "deprecated": true, + "description": "Deprecated: Output only. Use `canMoveItemOutOfDrive` instead.", + "type": "boolean" + }, + "canMoveItemOutOfDrive": { + "description": "Output only. Whether the current user can move this item outside of this drive by changing its parent. Note that a request to change the parent of the item may still fail depending on the new parent that is being added.", + "type": "boolean" + }, + "canMoveItemOutOfTeamDrive": { + "deprecated": true, + "description": "Deprecated: Output only. Use `canMoveItemOutOfDrive` instead.", + "type": "boolean" + }, + "canMoveItemWithinDrive": { + "description": "Output only. Whether the current user can move this item within this drive. Note that a request to change the parent of the item may still fail depending on the new parent that is being added and the parent that is being removed.", + "type": "boolean" + }, + "canMoveItemWithinTeamDrive": { + "deprecated": true, + "description": "Deprecated: Output only. Use `canMoveItemWithinDrive` instead.", + "type": "boolean" + }, + "canMoveTeamDriveItem": { + "deprecated": true, + "description": "Deprecated: Output only. Use `canMoveItemWithinDrive` or `canMoveItemOutOfDrive` instead.", + "type": "boolean" + }, + "canReadDrive": { + "description": "Output only. Whether the current user can read the shared drive to which this file belongs. Only populated for items in shared drives.", + "type": "boolean" + }, + "canReadLabels": { + "description": "Output only. Whether the current user can read the labels on the file.", + "type": "boolean" + }, + "canReadRevisions": { + "description": "Output only. Whether the current user can read the revisions resource of this file. For a shared drive item, whether revisions of non-folder descendants of this item, or this item itself if it is not a folder, can be read.", + "type": "boolean" + }, + "canReadTeamDrive": { + "deprecated": true, + "description": "Deprecated: Output only. Use `canReadDrive` instead.", + "type": "boolean" + }, + "canRemoveChildren": { + "description": "Output only. Whether the current user can remove children from this folder. This is always false when the item is not a folder. For a folder in a shared drive, use `canDeleteChildren` or `canTrashChildren` instead.", + "type": "boolean" + }, + "canRemoveContentRestriction": { + "description": "Output only. Whether there is a content restriction on the file that can be removed by the current user.", + "type": "boolean" + }, + "canRemoveMyDriveParent": { + "description": "Output only. Whether the current user can remove a parent from the item without adding another parent in the same request. Not populated for shared drive files.", + "type": "boolean" + }, + "canRename": { + "description": "Output only. Whether the current user can rename this file.", + "type": "boolean" + }, + "canShare": { + "description": "Output only. Whether the current user can modify the sharing settings for this file.", + "type": "boolean" + }, + "canTrash": { + "description": "Output only. Whether the current user can move this file to trash.", + "type": "boolean" + }, + "canTrashChildren": { + "description": "Output only. Whether the current user can trash children of this folder. This is false when the item is not a folder. Only populated for items in shared drives.", + "type": "boolean" + }, + "canUntrash": { + "description": "Output only. Whether the current user can restore this file from trash.", + "type": "boolean" + } + }, + "type": "object" + }, + "contentHints": { + "description": "Additional information about the content of the file. These fields are never populated in responses.", + "properties": { + "indexableText": { + "description": "Text to be indexed for the file to improve fullText queries. This is limited to 128KB in length and may contain HTML elements.", + "type": "string" + }, + "thumbnail": { + "description": "A thumbnail for the file. This will only be used if Google Drive cannot generate a standard thumbnail.", + "properties": { + "image": { + "description": "The thumbnail data encoded with URL-safe Base64 (RFC 4648 section 5).", + "format": "byte", + "type": "string" + }, + "mimeType": { + "description": "The MIME type of the thumbnail.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "contentRestrictions": { + "description": "Restrictions for accessing the content of the file. Only populated if such a restriction exists.", + "items": { + "$ref": "ContentRestriction" + }, + "type": "array" + }, + "copyRequiresWriterPermission": { + "description": "Whether the options to copy, print, or download this file, should be disabled for readers and commenters.", + "type": "boolean" + }, + "createdTime": { + "description": "The time at which the file was created (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "description": { + "description": "A short description of the file.", + "type": "string" + }, + "driveId": { + "description": "Output only. ID of the shared drive the file resides in. Only populated for items in shared drives.", + "type": "string" + }, + "explicitlyTrashed": { + "description": "Output only. Whether the file has been explicitly trashed, as opposed to recursively trashed from a parent folder.", + "type": "boolean" + }, + "exportLinks": { + "additionalProperties": { + "type": "string" + }, + "description": "Output only. Links for exporting Docs Editors files to specific formats.", + "readOnly": true, + "type": "object" + }, + "fileExtension": { + "description": "Output only. The final component of `fullFileExtension`. This is only available for files with binary content in Google Drive.", + "type": "string" + }, + "folderColorRgb": { + "description": "The color for a folder or a shortcut to a folder as an RGB hex string. The supported colors are published in the `folderColorPalette` field of the About resource. If an unsupported color is specified, the closest color in the palette is used instead.", + "type": "string" + }, + "fullFileExtension": { + "description": "Output only. The full file extension extracted from the `name` field. May contain multiple concatenated extensions, such as \"tar.gz\". This is only available for files with binary content in Google Drive. This is automatically updated when the `name` field changes, however it is not cleared if the new name does not contain a valid extension.", + "type": "string" + }, + "hasAugmentedPermissions": { + "description": "Output only. Whether there are permissions directly on this file. This field is only populated for items in shared drives.", + "type": "boolean" + }, + "hasThumbnail": { + "description": "Output only. Whether this file has a thumbnail. This does not indicate whether the requesting app has access to the thumbnail. To check access, look for the presence of the thumbnailLink field.", + "type": "boolean" + }, + "headRevisionId": { + "description": "Output only. The ID of the file's head revision. This is currently only available for files with binary content in Google Drive.", + "type": "string" + }, + "iconLink": { + "description": "Output only. A static, unauthenticated link to the file's icon.", + "type": "string" + }, + "id": { + "description": "The ID of the file.", + "type": "string" + }, + "imageMediaMetadata": { + "description": "Output only. Additional metadata about image media, if available.", + "properties": { + "aperture": { + "description": "Output only. The aperture used to create the photo (f-number).", + "format": "float", + "type": "number" + }, + "cameraMake": { + "description": "Output only. The make of the camera used to create the photo.", + "type": "string" + }, + "cameraModel": { + "description": "Output only. The model of the camera used to create the photo.", + "type": "string" + }, + "colorSpace": { + "description": "Output only. The color space of the photo.", + "type": "string" + }, + "exposureBias": { + "description": "Output only. The exposure bias of the photo (APEX value).", + "format": "float", + "type": "number" + }, + "exposureMode": { + "description": "Output only. The exposure mode used to create the photo.", + "type": "string" + }, + "exposureTime": { + "description": "Output only. The length of the exposure, in seconds.", + "format": "float", + "type": "number" + }, + "flashUsed": { + "description": "Output only. Whether a flash was used to create the photo.", + "type": "boolean" + }, + "focalLength": { + "description": "Output only. The focal length used to create the photo, in millimeters.", + "format": "float", + "type": "number" + }, + "height": { + "description": "Output only. The height of the image in pixels.", + "format": "int32", + "type": "integer" + }, + "isoSpeed": { + "description": "Output only. The ISO speed used to create the photo.", + "format": "int32", + "type": "integer" + }, + "lens": { + "description": "Output only. The lens used to create the photo.", + "type": "string" + }, + "location": { + "description": "Output only. Geographic location information stored in the image.", + "properties": { + "altitude": { + "description": "Output only. The altitude stored in the image.", + "format": "double", + "type": "number" + }, + "latitude": { + "description": "Output only. The latitude stored in the image.", + "format": "double", + "type": "number" + }, + "longitude": { + "description": "Output only. The longitude stored in the image.", + "format": "double", + "type": "number" + } + }, + "type": "object" + }, + "maxApertureValue": { + "description": "Output only. The smallest f-number of the lens at the focal length used to create the photo (APEX value).", + "format": "float", + "type": "number" + }, + "meteringMode": { + "description": "Output only. The metering mode used to create the photo.", + "type": "string" + }, + "rotation": { + "description": "Output only. The number of clockwise 90 degree rotations applied from the image's original orientation.", + "format": "int32", + "type": "integer" + }, + "sensor": { + "description": "Output only. The type of sensor used to create the photo.", + "type": "string" + }, + "subjectDistance": { + "description": "Output only. The distance to the subject of the photo, in meters.", + "format": "int32", + "type": "integer" + }, + "time": { + "description": "Output only. The date and time the photo was taken (EXIF DateTime).", + "type": "string" + }, + "whiteBalance": { + "description": "Output only. The white balance mode used to create the photo.", + "type": "string" + }, + "width": { + "description": "Output only. The width of the image in pixels.", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, + "isAppAuthorized": { + "description": "Output only. Whether the file was created or opened by the requesting app.", + "type": "boolean" + }, + "kind": { + "default": "drive#file", + "description": "Output only. Identifies what kind of resource this is. Value: the fixed string `\"drive#file\"`.", + "type": "string" + }, + "labelInfo": { + "description": "Output only. An overview of the labels on the file.", + "properties": { + "labels": { + "description": "Output only. The set of labels on the file as requested by the label IDs in the `includeLabels` parameter. By default, no labels are returned.", + "items": { + "$ref": "Label" + }, + "type": "array" + } + }, + "type": "object" + }, + "lastModifyingUser": { + "$ref": "User", + "description": "Output only. The last user to modify the file. This field is only populated when the last modification was performed by a signed-in user." + }, + "linkShareMetadata": { + "description": "Contains details about the link URLs that clients are using to refer to this item.", + "properties": { + "securityUpdateEligible": { + "description": "Output only. Whether the file is eligible for security update.", + "type": "boolean" + }, + "securityUpdateEnabled": { + "description": "Output only. Whether the security update is enabled for this file.", + "type": "boolean" + } + }, + "type": "object" + }, + "md5Checksum": { + "description": "Output only. The MD5 checksum for the content of the file. This is only applicable to files with binary content in Google Drive.", + "type": "string" + }, + "mimeType": { + "description": "The MIME type of the file. Google Drive attempts to automatically detect an appropriate value from uploaded content, if no value is provided. The value cannot be changed unless a new revision is uploaded. If a file is created with a Google Doc MIME type, the uploaded content is imported, if possible. The supported import formats are published in the About resource.", + "type": "string" + }, + "modifiedByMe": { + "description": "Output only. Whether the file has been modified by this user.", + "type": "boolean" + }, + "modifiedByMeTime": { + "description": "The last time the file was modified by the user (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "modifiedTime": { + "description": "he last time the file was modified by anyone (RFC 3339 date-time). Note that setting modifiedTime will also update modifiedByMeTime for the user.", + "format": "date-time", + "type": "string" + }, + "name": { + "description": "The name of the file. This is not necessarily unique within a folder. Note that for immutable items such as the top level folders of shared drives, My Drive root folder, and Application Data folder the name is constant.", + "type": "string" + }, + "originalFilename": { + "description": "The original filename of the uploaded content if available, or else the original value of the `name` field. This is only available for files with binary content in Google Drive.", + "type": "string" + }, + "ownedByMe": { + "description": "Output only. Whether the user owns the file. Not populated for items in shared drives.", + "type": "boolean" + }, + "owners": { + "description": "Output only. The owner of this file. Only certain legacy files may have more than one owner. This field isn't populated for items in shared drives.", + "items": { + "$ref": "User" + }, + "type": "array" + }, + "parents": { + "description": "The ID of the parent folder containing the file. A file can only have one parent folder; specifying multiple parents isn't supported. If not specified as part of a create request, the file is placed directly in the user's My Drive folder. If not specified as part of a copy request, the file inherits any discoverable parent of the source file. Update requests must use the `addParents` and `removeParents` parameters to modify the parents list.", + "items": { + "type": "string" + }, + "type": "array" + }, + "permissionIds": { + "description": "Output only. List of permission IDs for users with access to this file.", + "items": { + "type": "string" + }, + "type": "array" + }, + "permissions": { + "description": "Output only. The full list of permissions for the file. This is only available if the requesting user can share the file. Not populated for items in shared drives.", + "items": { + "$ref": "Permission" + }, + "type": "array" + }, + "properties": { + "additionalProperties": { + "type": "string" + }, + "description": "A collection of arbitrary key-value pairs which are visible to all apps.\nEntries with null values are cleared in update and copy requests.", + "type": "object" + }, + "quotaBytesUsed": { + "description": "Output only. The number of storage quota bytes used by the file. This includes the head revision as well as previous revisions with `keepForever` enabled.", + "format": "int64", + "type": "string" + }, + "resourceKey": { + "description": "Output only. A key needed to access the item via a shared link.", + "type": "string" + }, + "sha1Checksum": { + "description": "Output only. The SHA1 checksum associated with this file, if available. This field is only populated for files with content stored in Google Drive; it is not populated for Docs Editors or shortcut files.", + "type": "string" + }, + "sha256Checksum": { + "description": "Output only. The SHA256 checksum associated with this file, if available. This field is only populated for files with content stored in Google Drive; it is not populated for Docs Editors or shortcut files.", + "type": "string" + }, + "shared": { + "description": "Output only. Whether the file has been shared. Not populated for items in shared drives.", + "type": "boolean" + }, + "sharedWithMeTime": { + "description": "The time at which the file was shared with the user, if applicable (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "sharingUser": { + "$ref": "User", + "description": "Output only. The user who shared the file with the requesting user, if applicable." + }, + "shortcutDetails": { + "description": "Shortcut file details. Only populated for shortcut files, which have the mimeType field set to `application/vnd.google-apps.shortcut`. Can only be set on `files.create` requests.", + "properties": { + "targetId": { + "description": "The ID of the file that this shortcut points to. Can only be set on `files.create` requests.", + "type": "string" + }, + "targetMimeType": { + "description": "Output only. The MIME type of the file that this shortcut points to. The value of this field is a snapshot of the target's MIME type, captured when the shortcut is created.", + "type": "string" + }, + "targetResourceKey": { + "description": "Output only. The ResourceKey for the target file.", + "type": "string" + } + }, + "type": "object" + }, + "size": { + "description": "Output only. Size in bytes of blobs and first party editor files. Won't be populated for files that have no size, like shortcuts and folders.", + "format": "int64", + "type": "string" + }, + "spaces": { + "description": "Output only. The list of spaces which contain the file. The currently supported values are 'drive', 'appDataFolder' and 'photos'.", + "items": { + "type": "string" + }, + "type": "array" + }, + "starred": { + "description": "Whether the user has starred the file.", + "type": "boolean" + }, + "teamDriveId": { + "deprecated": true, + "description": "Deprecated: Output only. Use `driveId` instead.", + "type": "string" + }, + "thumbnailLink": { + "description": "Output only. A short-lived link to the file's thumbnail, if available. Typically lasts on the order of hours. Not intended for direct usage on web applications due to [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policies, consider using a proxy server. Only populated when the requesting app can access the file's content. If the file isn't shared publicly, the URL returned in `Files.thumbnailLink` must be fetched using a credentialed request.", + "type": "string" + }, + "thumbnailVersion": { + "description": "Output only. The thumbnail version for use in thumbnail cache invalidation.", + "format": "int64", + "type": "string" + }, + "trashed": { + "description": "Whether the file has been trashed, either explicitly or from a trashed parent folder. Only the owner may trash a file, and other users cannot see files in the owner's trash.", + "type": "boolean" + }, + "trashedTime": { + "description": "The time that the item was trashed (RFC 3339 date-time). Only populated for items in shared drives.", + "format": "date-time", + "type": "string" + }, + "trashingUser": { + "$ref": "User", + "description": "Output only. If the file has been explicitly trashed, the user who trashed it. Only populated for items in shared drives." + }, + "version": { + "description": "Output only. A monotonically increasing version number for the file. This reflects every change made to the file on the server, even those not visible to the user.", + "format": "int64", + "type": "string" + }, + "videoMediaMetadata": { + "description": "Output only. Additional metadata about video media. This may not be available immediately upon upload.", + "properties": { + "durationMillis": { + "description": "Output only. The duration of the video in milliseconds.", + "format": "int64", + "type": "string" + }, + "height": { + "description": "Output only. The height of the video in pixels.", + "format": "int32", + "type": "integer" + }, + "width": { + "description": "Output only. The width of the video in pixels.", + "format": "int32", + "type": "integer" + } + }, + "type": "object" + }, + "viewedByMe": { + "description": "Output only. Whether the file has been viewed by this user.", + "type": "boolean" + }, + "viewedByMeTime": { + "description": "The last time the file was viewed by the user (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "viewersCanCopyContent": { + "deprecated": true, + "description": "Deprecated: Use `copyRequiresWriterPermission` instead.", + "type": "boolean" + }, + "webContentLink": { + "description": "Output only. A link for downloading the content of the file in a browser. This is only available for files with binary content in Google Drive.", + "type": "string" + }, + "webViewLink": { + "description": "Output only. A link for opening the file in a relevant Google editor or viewer in a browser.", + "type": "string" + }, + "writersCanShare": { + "description": "Whether users with only `writer` permission can modify the file's permissions. Not populated for items in shared drives.", + "type": "boolean" + } }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" + "type": "object" + }, + "FileList": { + "description": "A list of files.", + "id": "FileList", + "properties": { + "files": { + "description": "The list of files. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.", + "items": { + "$ref": "File" + }, + "type": "array" + }, + "incompleteSearch": { + "description": "Whether the search process was incomplete. If true, then some search results might be missing, since all documents were not searched. This can occur when searching multiple drives with the 'allDrives' corpora, but all corpora couldn't be searched. When this happens, it's suggested that clients narrow their query by choosing a different corpus such as 'user' or 'drive'.", + "type": "boolean" + }, + "kind": { + "default": "drive#fileList", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#fileList\"`.", + "type": "string" + }, + "nextPageToken": { + "description": "The page token for the next page of files. This will be absent if the end of the files list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.", + "type": "string" + } }, - "keepRevisionForever": { - "type": "boolean", - "description": "Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Drive.", - "default": "false", - "location": "query" + "type": "object" + }, + "GeneratedIds": { + "description": "A list of generated file IDs which can be provided in create requests.", + "id": "GeneratedIds", + "properties": { + "ids": { + "description": "The IDs generated for the requesting user in the specified space.", + "items": { + "type": "string" + }, + "type": "array" + }, + "kind": { + "default": "drive#generatedIds", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#generatedIds\"`.", + "type": "string" + }, + "space": { + "description": "The type of file that can be created with these IDs.", + "type": "string" + } }, - "ocrLanguage": { - "type": "string", - "description": "A language hint for OCR processing during image import (ISO 639-1 code).", - "location": "query" + "type": "object" + }, + "Label": { + "description": "Representation of label and label fields.", + "id": "Label", + "properties": { + "fields": { + "additionalProperties": { + "$ref": "LabelField" + }, + "description": "A map of the fields on the label, keyed by the field's ID.", + "type": "object" + }, + "id": { + "description": "The ID of the label.", + "type": "string" + }, + "kind": { + "description": "This is always drive#label", + "type": "string" + }, + "revisionId": { + "description": "The revision ID of the label.", + "type": "string" + } }, - "removeParents": { - "type": "string", - "description": "A comma-separated list of parent IDs to remove.", - "location": "query" + "type": "object" + }, + "LabelField": { + "description": "Representation of field, which is a typed key-value pair.", + "id": "LabelField", + "properties": { + "dateString": { + "description": "Only present if valueType is dateString. RFC 3339 formatted date: YYYY-MM-DD.", + "items": { + "format": "date", + "type": "string" + }, + "type": "array" + }, + "id": { + "description": "The identifier of this label field.", + "type": "string" + }, + "integer": { + "description": "Only present if `valueType` is `integer`.", + "items": { + "format": "int64", + "type": "string" + }, + "type": "array" + }, + "kind": { + "description": "This is always drive#labelField.", + "type": "string" + }, + "selection": { + "description": "Only present if `valueType` is `selection`", + "items": { + "type": "string" + }, + "type": "array" + }, + "text": { + "description": "Only present if `valueType` is `text`.", + "items": { + "type": "string" + }, + "type": "array" + }, + "user": { + "description": "Only present if `valueType` is `user`.", + "items": { + "$ref": "User" + }, + "type": "array" + }, + "valueType": { + "description": "The field type. While new values may be supported in the future, the following are currently allowed: * `dateString` * `integer` * `selection` * `text` * `user`", + "type": "string" + } }, - "useContentAsIndexableText": { - "type": "boolean", - "description": "Whether to use the uploaded content as indexable text.", - "default": "false", - "location": "query" - } - }, - "parameterOrder": [ - "fileId" - ], - "request": { - "$ref": "File" - }, - "response": { - "$ref": "File" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.scripts" - ], - "supportsMediaUpload": true, - "mediaUpload": { - "accept": [ - "*/*" - ], - "maxSize": "5120GB", - "protocols": { - "simple": { - "multipart": true, - "path": "/upload/drive/v3/files/{fileId}" - }, - "resumable": { - "multipart": true, - "path": "/resumable/upload/drive/v3/files/{fileId}" - } - } - } - }, - "watch": { - "id": "drive.files.watch", - "path": "files/{fileId}/watch", - "httpMethod": "POST", - "description": "Subscribes to changes to a file", - "parameters": { - "acknowledgeAbuse": { - "type": "boolean", - "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when alt=media.", - "default": "false", - "location": "query" + "type": "object" + }, + "LabelFieldModification": { + "description": "A modification to a label's field.", + "id": "LabelFieldModification", + "properties": { + "fieldId": { + "description": "The ID of the field to be modified.", + "type": "string" + }, + "kind": { + "description": "This is always drive#labelFieldModification.", + "type": "string" + }, + "setDateValues": { + "description": "Replaces the value of a dateString Field with these new values. The string must be in the RFC 3339 full-date format: YYYY-MM-DD.", + "items": { + "format": "date", + "type": "string" + }, + "type": "array" + }, + "setIntegerValues": { + "description": "Replaces the value of an `integer` field with these new values.", + "items": { + "format": "int64", + "type": "string" + }, + "type": "array" + }, + "setSelectionValues": { + "description": "Replaces a `selection` field with these new values.", + "items": { + "type": "string" + }, + "type": "array" + }, + "setTextValues": { + "description": "Sets the value of a `text` field.", + "items": { + "type": "string" + }, + "type": "array" + }, + "setUserValues": { + "description": "Replaces a `user` field with these new values. The values must be valid email addresses.", + "items": { + "type": "string" + }, + "type": "array" + }, + "unsetValues": { + "description": "Unsets the values for this field.", + "type": "boolean" + } }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId" - ], - "request": { - "$ref": "Channel", - "parameterName": "resource" - }, - "response": { - "$ref": "Channel" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ], - "supportsMediaDownload": true, - "useMediaDownloadService": true, - "supportsSubscription": true - } - } - }, - "permissions": { - "methods": { - "create": { - "id": "drive.permissions.create", - "path": "files/{fileId}/permissions", - "httpMethod": "POST", - "description": "Creates a permission for a file.", - "parameters": { - "emailMessage": { - "type": "string", - "description": "A custom message to include in the notification email.", - "location": "query" + "type": "object" + }, + "LabelList": { + "description": "A list of labels applied to a file.", + "id": "LabelList", + "properties": { + "kind": { + "description": "This is always drive#labelList", + "type": "string" + }, + "labels": { + "description": "The list of labels.", + "items": { + "$ref": "Label" + }, + "type": "array" + }, + "nextPageToken": { + "description": "The page token for the next page of labels. This field will be absent if the end of the list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.", + "type": "string" + } }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" + "type": "object" + }, + "LabelModification": { + "description": "A modification to a label on a file. A LabelModification can be used to apply a label to a file, update an existing label on a file, or remove a label from a file.", + "id": "LabelModification", + "properties": { + "fieldModifications": { + "description": "The list of modifications to this label's fields.", + "items": { + "$ref": "LabelFieldModification" + }, + "type": "array" + }, + "kind": { + "description": "This is always drive#labelModification.", + "type": "string" + }, + "labelId": { + "annotations": { + "required": [ + "drive.files.modifyLabels" + ] + }, + "description": "The ID of the label to modify.", + "type": "string" + }, + "removeLabel": { + "description": "If true, the label will be removed from the file.", + "type": "boolean" + } }, - "sendNotificationEmail": { - "type": "boolean", - "description": "Whether to send a notification email when sharing to users or groups. This defaults to true for users and groups, and is not allowed for other requests. It must not be disabled for ownership transfers.", - "location": "query" + "type": "object" + }, + "ListAccessProposalsResponse": { + "description": "The response to an Access Proposal list request.", + "id": "ListAccessProposalsResponse", + "properties": { + "accessProposals": { + "description": "The list of Access Proposals. This field is only populated in v3 and v3beta.", + "items": { + "$ref": "AccessProposal" + }, + "type": "array" + }, + "nextPageToken": { + "description": "The continuation token for the next page of results. This will be absent if the end of the results list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results.", + "type": "string" + } }, - "transferOwnership": { - "type": "boolean", - "description": "Whether to transfer ownership to the specified user and downgrade the current owner to a writer. This parameter is required as an acknowledgement of the side effect.", - "default": "false", - "location": "query" - } - }, - "parameterOrder": [ - "fileId" - ], - "request": { - "$ref": "Permission" - }, - "response": { - "$ref": "Permission" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file" - ] - }, - "delete": { - "id": "drive.permissions.delete", - "path": "files/{fileId}/permissions/{permissionId}", - "httpMethod": "DELETE", - "description": "Deletes a permission.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" + "type": "object" + }, + "ListOperationsResponse": { + "description": "The response message for Operations.ListOperations.", + "id": "ListOperationsResponse", + "properties": { + "nextPageToken": { + "description": "The standard List next-page token.", + "type": "string" + }, + "operations": { + "description": "A list of operations that matches the specified filter in the request.", + "items": { + "$ref": "Operation" + }, + "type": "array" + } }, - "permissionId": { - "type": "string", - "description": "The ID of the permission.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "permissionId" - ], - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file" - ] - }, - "get": { - "id": "drive.permissions.get", - "path": "files/{fileId}/permissions/{permissionId}", - "httpMethod": "GET", - "description": "Gets a permission by ID.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" + "type": "object" + }, + "ModifyLabelsRequest": { + "description": "A request to modify the set of labels on a file. This request may contain many modifications that will either all succeed or all fail atomically.", + "id": "ModifyLabelsRequest", + "properties": { + "kind": { + "description": "This is always drive#modifyLabelsRequest.", + "type": "string" + }, + "labelModifications": { + "description": "The list of modifications to apply to the labels on the file.", + "items": { + "$ref": "LabelModification" + }, + "type": "array" + } }, - "permissionId": { - "type": "string", - "description": "The ID of the permission.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "permissionId" - ], - "response": { - "$ref": "Permission" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ] - }, - "list": { - "id": "drive.permissions.list", - "path": "files/{fileId}/permissions", - "httpMethod": "GET", - "description": "Lists a file's permissions.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId" - ], - "response": { - "$ref": "PermissionList" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ] - }, - "update": { - "id": "drive.permissions.update", - "path": "files/{fileId}/permissions/{permissionId}", - "httpMethod": "PATCH", - "description": "Updates a permission with patch semantics.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" + "type": "object" + }, + "ModifyLabelsResponse": { + "description": "Response to a ModifyLabels request. This contains only those labels which were added or updated by the request.", + "id": "ModifyLabelsResponse", + "properties": { + "kind": { + "description": "This is always drive#modifyLabelsResponse", + "type": "string" + }, + "modifiedLabels": { + "description": "The list of labels which were added or updated by the request.", + "items": { + "$ref": "Label" + }, + "type": "array" + } }, - "permissionId": { - "type": "string", - "description": "The ID of the permission.", - "required": true, - "location": "path" + "type": "object" + }, + "Operation": { + "description": "This resource represents a long-running operation that is the result of a network API call.", + "id": "Operation", + "properties": { + "done": { + "description": "If the value is `false`, it means the operation is still in progress. If `true`, the operation is completed, and either `error` or `response` is available.", + "type": "boolean" + }, + "error": { + "$ref": "Status", + "description": "The error result of the operation in case of failure or cancellation." + }, + "metadata": { + "additionalProperties": { + "description": "Properties of the object. Contains field @type with type URL.", + "type": "any" + }, + "description": "Service-specific metadata associated with the operation. It typically contains progress information and common metadata such as create time. Some services might not provide such metadata. Any method that returns a long-running operation should document the metadata type, if any.", + "type": "object" + }, + "name": { + "description": "The server-assigned name, which is only unique within the same service that originally returns it. If you use the default HTTP mapping, the `name` should be a resource name ending with `operations/{unique_id}`.", + "type": "string" + }, + "response": { + "additionalProperties": { + "description": "Properties of the object. Contains field @type with type URL.", + "type": "any" + }, + "description": "The normal, successful response of the operation. If the original method returns no data on success, such as `Delete`, the response is `google.protobuf.Empty`. If the original method is standard `Get`/`Create`/`Update`, the response should be the resource. For other methods, the response should have the type `XxxResponse`, where `Xxx` is the original method name. For example, if the original method name is `TakeSnapshot()`, the inferred response type is `TakeSnapshotResponse`.", + "type": "object" + } }, - "transferOwnership": { - "type": "boolean", - "description": "Whether to transfer ownership to the specified user and downgrade the current owner to a writer. This parameter is required as an acknowledgement of the side effect.", - "default": "false", - "location": "query" - } - }, - "parameterOrder": [ - "fileId", - "permissionId" - ], - "request": { - "$ref": "Permission" - }, - "response": { - "$ref": "Permission" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file" - ] - } - } - }, - "replies": { - "methods": { - "create": { - "id": "drive.replies.create", - "path": "files/{fileId}/comments/{commentId}/replies", - "httpMethod": "POST", - "description": "Creates a new reply to a comment.", - "parameters": { - "commentId": { - "type": "string", - "description": "The ID of the comment.", - "required": true, - "location": "path" + "type": "object" + }, + "Permission": { + "description": "A permission for a file. A permission grants a user, group, domain, or the world access to a file or a folder hierarchy. Some resource methods (such as `permissions.update`) require a `permissionId`. Use the `permissions.list` method to retrieve the ID for a file, folder, or shared drive.", + "id": "Permission", + "properties": { + "allowFileDiscovery": { + "description": "Whether the permission allows the file to be discovered through search. This is only applicable for permissions of type `domain` or `anyone`.", + "type": "boolean" + }, + "deleted": { + "description": "Output only. Whether the account associated with this permission has been deleted. This field only pertains to user and group permissions.", + "type": "boolean" + }, + "displayName": { + "description": "Output only. The \"pretty\" name of the value of the permission. The following is a list of examples for each type of permission: * `user` - User's full name, as defined for their Google account, such as \"Joe Smith.\" * `group` - Name of the Google Group, such as \"The Company Administrators.\" * `domain` - String domain name, such as \"thecompany.com.\" * `anyone` - No `displayName` is present.", + "type": "string" + }, + "domain": { + "description": "The domain to which this permission refers.", + "type": "string" + }, + "emailAddress": { + "description": "The email address of the user or group to which this permission refers.", + "type": "string" + }, + "expirationTime": { + "description": "The time at which this permission will expire (RFC 3339 date-time). Expiration times have the following restrictions: - They can only be set on user and group permissions - The time must be in the future - The time cannot be more than a year in the future", + "format": "date-time", + "type": "string" + }, + "id": { + "description": "Output only. The ID of this permission. This is a unique identifier for the grantee, and is published in User resources as `permissionId`. IDs should be treated as opaque values.", + "type": "string" + }, + "kind": { + "default": "drive#permission", + "description": "Output only. Identifies what kind of resource this is. Value: the fixed string `\"drive#permission\"`.", + "type": "string" + }, + "pendingOwner": { + "description": "Whether the account associated with this permission is a pending owner. Only populated for `user` type permissions for files that are not in a shared drive.", + "type": "boolean" + }, + "permissionDetails": { + "description": "Output only. Details of whether the permissions on this shared drive item are inherited or directly on this item. This is an output-only field which is present only for shared drive items.", + "items": { + "properties": { + "inherited": { + "description": "Output only. Whether this permission is inherited. This field is always populated. This is an output-only field.", + "type": "boolean" + }, + "inheritedFrom": { + "description": "Output only. The ID of the item from which this permission is inherited. This is an output-only field.", + "type": "string" + }, + "permissionType": { + "description": "Output only. The permission type for this user. While new values may be added in future, the following are currently possible: * `file` * `member`", + "type": "string" + }, + "role": { + "description": "Output only. The primary role for this user. While new values may be added in the future, the following are currently possible: * `organizer` * `fileOrganizer` * `writer` * `commenter` * `reader`", + "type": "string" + } + }, + "type": "object" + }, + "readOnly": true, + "type": "array" + }, + "photoLink": { + "description": "Output only. A link to the user's profile photo, if available.", + "type": "string" + }, + "role": { + "annotations": { + "required": [ + "drive.permissions.create" + ] + }, + "description": "The role granted by this permission. While new values may be supported in the future, the following are currently allowed: * `owner` * `organizer` * `fileOrganizer` * `writer` * `commenter` * `reader`", + "type": "string" + }, + "teamDrivePermissionDetails": { + "deprecated": true, + "description": "Output only. Deprecated: Output only. Use `permissionDetails` instead.", + "items": { + "properties": { + "inherited": { + "deprecated": true, + "description": "Deprecated: Output only. Use `permissionDetails/inherited` instead.", + "type": "boolean" + }, + "inheritedFrom": { + "deprecated": true, + "description": "Deprecated: Output only. Use `permissionDetails/inheritedFrom` instead.", + "type": "string" + }, + "role": { + "deprecated": true, + "description": "Deprecated: Output only. Use `permissionDetails/role` instead.", + "type": "string" + }, + "teamDrivePermissionType": { + "deprecated": true, + "description": "Deprecated: Output only. Use `permissionDetails/permissionType` instead.", + "type": "string" + } + }, + "type": "object" + }, + "readOnly": true, + "type": "array" + }, + "type": { + "annotations": { + "required": [ + "drive.permissions.create" + ] + }, + "description": "The type of the grantee. Valid values are: * `user` * `group` * `domain` * `anyone` When creating a permission, if `type` is `user` or `group`, you must provide an `emailAddress` for the user or group. When `type` is `domain`, you must provide a `domain`. There isn't extra information required for an `anyone` type.", + "type": "string" + }, + "view": { + "description": "Indicates the view for this permission. Only populated for permissions that belong to a view. 'published' is the only supported value.", + "type": "string" + } }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "commentId" - ], - "request": { - "$ref": "Reply" - }, - "response": { - "$ref": "Reply" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file" - ] - }, - "delete": { - "id": "drive.replies.delete", - "path": "files/{fileId}/comments/{commentId}/replies/{replyId}", - "httpMethod": "DELETE", - "description": "Deletes a reply.", - "parameters": { - "commentId": { - "type": "string", - "description": "The ID of the comment.", - "required": true, - "location": "path" + "type": "object" + }, + "PermissionList": { + "description": "A list of permissions for a file.", + "id": "PermissionList", + "properties": { + "kind": { + "default": "drive#permissionList", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#permissionList\"`.", + "type": "string" + }, + "nextPageToken": { + "description": "The page token for the next page of permissions. This field will be absent if the end of the permissions list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.", + "type": "string" + }, + "permissions": { + "description": "The list of permissions. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.", + "items": { + "$ref": "Permission" + }, + "type": "array" + } }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" + "type": "object" + }, + "Reply": { + "description": "A reply to a comment on a file. Some resource methods (such as `replies.update`) require a `replyId`. Use the `replies.list` method to retrieve the ID for a reply.", + "id": "Reply", + "properties": { + "action": { + "description": "The action the reply performed to the parent comment. Valid values are: * `resolve` * `reopen`", + "type": "string" + }, + "author": { + "$ref": "User", + "description": "Output only. The author of the reply. The author's email address and permission ID will not be populated." + }, + "content": { + "annotations": { + "required": [ + "drive.replies.update" + ] + }, + "description": "The plain text content of the reply. This field is used for setting the content, while `htmlContent` should be displayed. This is required on creates if no `action` is specified.", + "type": "string" + }, + "createdTime": { + "description": "The time at which the reply was created (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "deleted": { + "description": "Output only. Whether the reply has been deleted. A deleted reply has no content.", + "type": "boolean" + }, + "htmlContent": { + "description": "Output only. The content of the reply with HTML formatting.", + "type": "string" + }, + "id": { + "description": "Output only. The ID of the reply.", + "type": "string" + }, + "kind": { + "default": "drive#reply", + "description": "Output only. Identifies what kind of resource this is. Value: the fixed string `\"drive#reply\"`.", + "type": "string" + }, + "modifiedTime": { + "description": "The last time the reply was modified (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + } }, - "replyId": { - "type": "string", - "description": "The ID of the reply.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "commentId", - "replyId" - ], - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file" - ] - }, - "get": { - "id": "drive.replies.get", - "path": "files/{fileId}/comments/{commentId}/replies/{replyId}", - "httpMethod": "GET", - "description": "Gets a reply by ID.", - "parameters": { - "commentId": { - "type": "string", - "description": "The ID of the comment.", - "required": true, - "location": "path" + "type": "object" + }, + "ReplyList": { + "description": "A list of replies to a comment on a file.", + "id": "ReplyList", + "properties": { + "kind": { + "default": "drive#replyList", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#replyList\"`.", + "type": "string" + }, + "nextPageToken": { + "description": "The page token for the next page of replies. This will be absent if the end of the replies list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.", + "type": "string" + }, + "replies": { + "description": "The list of replies. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.", + "items": { + "$ref": "Reply" + }, + "type": "array" + } }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" + "type": "object" + }, + "ResolveAccessProposalRequest": { + "description": "Request message for resolving an AccessProposal on a file.", + "id": "ResolveAccessProposalRequest", + "properties": { + "action": { + "description": "Required. The action to take on the AccessProposal.", + "enum": [ + "ACTION_UNSPECIFIED", + "ACCEPT", + "DENY" + ], + "enumDescriptions": [ + "Unspecified action", + "The user accepts the proposal. Note: If this action is used, the `role` field must have at least one value.", + "The user denies the proposal" + ], + "type": "string" + }, + "role": { + "description": "Optional. The roles the approver has allowed, if any. Note: This field is required for the `ACCEPT` action.", + "items": { + "type": "string" + }, + "type": "array" + }, + "sendNotification": { + "description": "Optional. Whether to send an email to the requester when the AccessProposal is denied or accepted.", + "type": "boolean" + }, + "view": { + "description": "Optional. Indicates the view for this access proposal. This should only be set when the proposal belongs to a view. `published` is the only supported value.", + "type": "string" + } }, - "includeDeleted": { - "type": "boolean", - "description": "Whether to return deleted replies. Deleted replies will not include their original content.", - "default": "false", - "location": "query" + "type": "object" + }, + "Revision": { + "description": "The metadata for a revision to a file. Some resource methods (such as `revisions.update`) require a `revisionId`. Use the `revisions.list` method to retrieve the ID for a revision.", + "id": "Revision", + "properties": { + "exportLinks": { + "additionalProperties": { + "type": "string" + }, + "description": "Output only. Links for exporting Docs Editors files to specific formats.", + "type": "object" + }, + "id": { + "description": "Output only. The ID of the revision.", + "type": "string" + }, + "keepForever": { + "description": "Whether to keep this revision forever, even if it is no longer the head revision. If not set, the revision will be automatically purged 30 days after newer content is uploaded. This can be set on a maximum of 200 revisions for a file. This field is only applicable to files with binary content in Drive.", + "type": "boolean" + }, + "kind": { + "default": "drive#revision", + "description": "Output only. Identifies what kind of resource this is. Value: the fixed string `\"drive#revision\"`.", + "type": "string" + }, + "lastModifyingUser": { + "$ref": "User", + "description": "Output only. The last user to modify this revision. This field is only populated when the last modification was performed by a signed-in user." + }, + "md5Checksum": { + "description": "Output only. The MD5 checksum of the revision's content. This is only applicable to files with binary content in Drive.", + "type": "string" + }, + "mimeType": { + "description": "Output only. The MIME type of the revision.", + "type": "string" + }, + "modifiedTime": { + "description": "The last time the revision was modified (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "originalFilename": { + "description": "Output only. The original filename used to create this revision. This is only applicable to files with binary content in Drive.", + "type": "string" + }, + "publishAuto": { + "description": "Whether subsequent revisions will be automatically republished. This is only applicable to Docs Editors files.", + "type": "boolean" + }, + "published": { + "description": "Whether this revision is published. This is only applicable to Docs Editors files.", + "type": "boolean" + }, + "publishedLink": { + "description": "Output only. A link to the published revision. This is only populated for Google Sites files.", + "type": "string" + }, + "publishedOutsideDomain": { + "description": "Whether this revision is published outside the domain. This is only applicable to Docs Editors files.", + "type": "boolean" + }, + "size": { + "description": "Output only. The size of the revision's content in bytes. This is only applicable to files with binary content in Drive.", + "format": "int64", + "type": "string" + } }, - "replyId": { - "type": "string", - "description": "The ID of the reply.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "commentId", - "replyId" - ], - "response": { - "$ref": "Reply" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.readonly" - ] - }, - "list": { - "id": "drive.replies.list", - "path": "files/{fileId}/comments/{commentId}/replies", - "httpMethod": "GET", - "description": "Lists a comment's replies.", - "parameters": { - "commentId": { - "type": "string", - "description": "The ID of the comment.", - "required": true, - "location": "path" + "type": "object" + }, + "RevisionList": { + "description": "A list of revisions of a file.", + "id": "RevisionList", + "properties": { + "kind": { + "default": "drive#revisionList", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#revisionList\"`.", + "type": "string" + }, + "nextPageToken": { + "description": "The page token for the next page of revisions. This will be absent if the end of the revisions list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.", + "type": "string" + }, + "revisions": { + "description": "The list of revisions. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.", + "items": { + "$ref": "Revision" + }, + "type": "array" + } }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" + "type": "object" + }, + "StartPageToken": { + "id": "StartPageToken", + "properties": { + "kind": { + "default": "drive#startPageToken", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#startPageToken\"`.", + "type": "string" + }, + "startPageToken": { + "description": "The starting page token for listing future changes. The page token doesn't expire.", + "type": "string" + } }, - "includeDeleted": { - "type": "boolean", - "description": "Whether to include deleted replies. Deleted replies will not include their original content.", - "default": "false", - "location": "query" + "type": "object" + }, + "Status": { + "description": "The `Status` type defines a logical error model that is suitable for different programming environments, including REST APIs and RPC APIs. It is used by [gRPC](https://github.com/grpc). Each `Status` message contains three pieces of data: error code, error message, and error details. You can find out more about this error model and how to work with it in the [API Design Guide](https://cloud.google.com/apis/design/errors).", + "id": "Status", + "properties": { + "code": { + "description": "The status code, which should be an enum value of google.rpc.Code.", + "format": "int32", + "type": "integer" + }, + "details": { + "description": "A list of messages that carry the error details. There is a common set of message types for APIs to use.", + "items": { + "additionalProperties": { + "description": "Properties of the object. Contains field @type with type URL.", + "type": "any" + }, + "type": "object" + }, + "type": "array" + }, + "message": { + "description": "A developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the google.rpc.Status.details field, or localized by the client.", + "type": "string" + } }, - "pageSize": { - "type": "integer", - "description": "The maximum number of replies to return per page.", - "default": "20", - "format": "int32", - "minimum": "1", - "maximum": "100", - "location": "query" + "type": "object" + }, + "TeamDrive": { + "description": "Deprecated: use the drive collection instead.", + "id": "TeamDrive", + "properties": { + "backgroundImageFile": { + "description": "An image file and cropping parameters from which a background image for this Team Drive is set. This is a write only field; it can only be set on `drive.teamdrives.update` requests that don't set `themeId`. When specified, all fields of the `backgroundImageFile` must be set.", + "properties": { + "id": { + "description": "The ID of an image file in Drive to use for the background image.", + "type": "string" + }, + "width": { + "description": "The width of the cropped image in the closed range of 0 to 1. This value represents the width of the cropped image divided by the width of the entire image. The height is computed by applying a width to height aspect ratio of 80 to 9. The resulting image must be at least 1280 pixels wide and 144 pixels high.", + "format": "float", + "type": "number" + }, + "xCoordinate": { + "description": "The X coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the horizontal distance from the left side of the entire image to the left side of the cropping area divided by the width of the entire image.", + "format": "float", + "type": "number" + }, + "yCoordinate": { + "description": "The Y coordinate of the upper left corner of the cropping area in the background image. This is a value in the closed range of 0 to 1. This value represents the vertical distance from the top side of the entire image to the top side of the cropping area divided by the height of the entire image.", + "format": "float", + "type": "number" + } + }, + "type": "object" + }, + "backgroundImageLink": { + "description": "A short-lived link to this Team Drive's background image.", + "type": "string" + }, + "capabilities": { + "description": "Capabilities the current user has on this Team Drive.", + "properties": { + "canAddChildren": { + "description": "Whether the current user can add children to folders in this Team Drive.", + "type": "boolean" + }, + "canChangeCopyRequiresWriterPermissionRestriction": { + "description": "Whether the current user can change the `copyRequiresWriterPermission` restriction of this Team Drive.", + "type": "boolean" + }, + "canChangeDomainUsersOnlyRestriction": { + "description": "Whether the current user can change the `domainUsersOnly` restriction of this Team Drive.", + "type": "boolean" + }, + "canChangeSharingFoldersRequiresOrganizerPermissionRestriction": { + "description": "Whether the current user can change the `sharingFoldersRequiresOrganizerPermission` restriction of this Team Drive.", + "type": "boolean" + }, + "canChangeTeamDriveBackground": { + "description": "Whether the current user can change the background of this Team Drive.", + "type": "boolean" + }, + "canChangeTeamMembersOnlyRestriction": { + "description": "Whether the current user can change the `teamMembersOnly` restriction of this Team Drive.", + "type": "boolean" + }, + "canComment": { + "description": "Whether the current user can comment on files in this Team Drive.", + "type": "boolean" + }, + "canCopy": { + "description": "Whether the current user can copy files in this Team Drive.", + "type": "boolean" + }, + "canDeleteChildren": { + "description": "Whether the current user can delete children from folders in this Team Drive.", + "type": "boolean" + }, + "canDeleteTeamDrive": { + "description": "Whether the current user can delete this Team Drive. Attempting to delete the Team Drive may still fail if there are untrashed items inside the Team Drive.", + "type": "boolean" + }, + "canDownload": { + "description": "Whether the current user can download files in this Team Drive.", + "type": "boolean" + }, + "canEdit": { + "description": "Whether the current user can edit files in this Team Drive", + "type": "boolean" + }, + "canListChildren": { + "description": "Whether the current user can list the children of folders in this Team Drive.", + "type": "boolean" + }, + "canManageMembers": { + "description": "Whether the current user can add members to this Team Drive or remove them or change their role.", + "type": "boolean" + }, + "canReadRevisions": { + "description": "Whether the current user can read the revisions resource of files in this Team Drive.", + "type": "boolean" + }, + "canRemoveChildren": { + "deprecated": true, + "description": "Deprecated: Use `canDeleteChildren` or `canTrashChildren` instead.", + "type": "boolean" + }, + "canRename": { + "description": "Whether the current user can rename files or folders in this Team Drive.", + "type": "boolean" + }, + "canRenameTeamDrive": { + "description": "Whether the current user can rename this Team Drive.", + "type": "boolean" + }, + "canResetTeamDriveRestrictions": { + "description": "Whether the current user can reset the Team Drive restrictions to defaults.", + "type": "boolean" + }, + "canShare": { + "description": "Whether the current user can share files or folders in this Team Drive.", + "type": "boolean" + }, + "canTrashChildren": { + "description": "Whether the current user can trash children from folders in this Team Drive.", + "type": "boolean" + } + }, + "type": "object" + }, + "colorRgb": { + "description": "The color of this Team Drive as an RGB hex string. It can only be set on a `drive.teamdrives.update` request that does not set `themeId`.", + "type": "string" + }, + "createdTime": { + "description": "The time at which the Team Drive was created (RFC 3339 date-time).", + "format": "date-time", + "type": "string" + }, + "id": { + "description": "The ID of this Team Drive which is also the ID of the top level folder of this Team Drive.", + "type": "string" + }, + "kind": { + "default": "drive#teamDrive", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#teamDrive\"`.", + "type": "string" + }, + "name": { + "description": "The name of this Team Drive.", + "type": "string" + }, + "orgUnitId": { + "description": "The organizational unit of this shared drive. This field is only populated on `drives.list` responses when the `useDomainAdminAccess` parameter is set to `true`.", + "type": "string" + }, + "restrictions": { + "description": "A set of restrictions that apply to this Team Drive or items inside this Team Drive.", + "properties": { + "adminManagedRestrictions": { + "description": "Whether administrative privileges on this Team Drive are required to modify restrictions.", + "type": "boolean" + }, + "copyRequiresWriterPermission": { + "description": "Whether the options to copy, print, or download files inside this Team Drive, should be disabled for readers and commenters. When this restriction is set to `true`, it will override the similarly named field to `true` for any file inside this Team Drive.", + "type": "boolean" + }, + "domainUsersOnly": { + "description": "Whether access to this Team Drive and items inside this Team Drive is restricted to users of the domain to which this Team Drive belongs. This restriction may be overridden by other sharing policies controlled outside of this Team Drive.", + "type": "boolean" + }, + "sharingFoldersRequiresOrganizerPermission": { + "description": "If true, only users with the organizer role can share folders. If false, users with either the organizer role or the file organizer role can share folders.", + "type": "boolean" + }, + "teamMembersOnly": { + "description": "Whether access to items inside this Team Drive is restricted to members of this Team Drive.", + "type": "boolean" + } + }, + "type": "object" + }, + "themeId": { + "description": "The ID of the theme from which the background image and color will be set. The set of possible `teamDriveThemes` can be retrieved from a `drive.about.get` response. When not specified on a `drive.teamdrives.create` request, a random theme is chosen from which the background image and color are set. This is a write-only field; it can only be set on requests that don't set `colorRgb` or `backgroundImageFile`.", + "type": "string" + } }, - "pageToken": { - "type": "string", - "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", - "location": "query" - } - }, - "parameterOrder": [ - "fileId", - "commentId" - ], - "response": { - "$ref": "ReplyList" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.readonly" - ] - }, - "update": { - "id": "drive.replies.update", - "path": "files/{fileId}/comments/{commentId}/replies/{replyId}", - "httpMethod": "PATCH", - "description": "Updates a reply with patch semantics.", - "parameters": { - "commentId": { - "type": "string", - "description": "The ID of the comment.", - "required": true, - "location": "path" + "type": "object" + }, + "TeamDriveList": { + "description": "A list of Team Drives.", + "id": "TeamDriveList", + "properties": { + "kind": { + "default": "drive#teamDriveList", + "description": "Identifies what kind of resource this is. Value: the fixed string `\"drive#teamDriveList\"`.", + "type": "string" + }, + "nextPageToken": { + "description": "The page token for the next page of Team Drives. This will be absent if the end of the Team Drives list has been reached. If the token is rejected for any reason, it should be discarded, and pagination should be restarted from the first page of results. The page token is typically valid for several hours. However, if new items are added or removed, your expected results might differ.", + "type": "string" + }, + "teamDrives": { + "description": "The list of Team Drives. If nextPageToken is populated, then this list may be incomplete and an additional page of results should be fetched.", + "items": { + "$ref": "TeamDrive" + }, + "type": "array" + } }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" + "type": "object" + }, + "User": { + "description": "Information about a Drive user.", + "id": "User", + "properties": { + "displayName": { + "description": "Output only. A plain text displayable name for this user.", + "type": "string" + }, + "emailAddress": { + "description": "Output only. The email address of the user. This may not be present in certain contexts if the user has not made their email address visible to the requester.", + "type": "string" + }, + "kind": { + "default": "drive#user", + "description": "Output only. Identifies what kind of resource this is. Value: the fixed string `\"drive#user\"`.", + "type": "string" + }, + "me": { + "description": "Output only. Whether this user is the requesting user.", + "type": "boolean" + }, + "permissionId": { + "description": "Output only. The user's ID as visible in Permission resources.", + "type": "string" + }, + "photoLink": { + "description": "Output only. A link to the user's profile photo, if available.", + "type": "string" + } }, - "replyId": { - "type": "string", - "description": "The ID of the reply.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "commentId", - "replyId" - ], - "request": { - "$ref": "Reply" - }, - "response": { - "$ref": "Reply" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.file" - ] + "type": "object" } - } }, - "revisions": { - "methods": { - "delete": { - "id": "drive.revisions.delete", - "path": "files/{fileId}/revisions/{revisionId}", - "httpMethod": "DELETE", - "description": "Permanently deletes a revision. This method is only applicable to files with binary content in Drive.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - }, - "revisionId": { - "type": "string", - "description": "The ID of the revision.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "revisionId" - ], - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file" - ] - }, - "get": { - "id": "drive.revisions.get", - "path": "files/{fileId}/revisions/{revisionId}", - "httpMethod": "GET", - "description": "Gets a revision's metadata or content by ID.", - "parameters": { - "acknowledgeAbuse": { - "type": "boolean", - "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when alt=media.", - "default": "false", - "location": "query" - }, - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - }, - "revisionId": { - "type": "string", - "description": "The ID of the revision.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "revisionId" - ], - "response": { - "$ref": "Revision" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ], - "supportsMediaDownload": true, - "useMediaDownloadService": true - }, - "list": { - "id": "drive.revisions.list", - "path": "files/{fileId}/revisions", - "httpMethod": "GET", - "description": "Lists a file's revisions.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId" - ], - "response": { - "$ref": "RevisionList" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file", - "https://www.googleapis.com/auth/drive.metadata", - "https://www.googleapis.com/auth/drive.metadata.readonly", - "https://www.googleapis.com/auth/drive.photos.readonly", - "https://www.googleapis.com/auth/drive.readonly" - ] - }, - "update": { - "id": "drive.revisions.update", - "path": "files/{fileId}/revisions/{revisionId}", - "httpMethod": "PATCH", - "description": "Updates a revision with patch semantics.", - "parameters": { - "fileId": { - "type": "string", - "description": "The ID of the file.", - "required": true, - "location": "path" - }, - "revisionId": { - "type": "string", - "description": "The ID of the revision.", - "required": true, - "location": "path" - } - }, - "parameterOrder": [ - "fileId", - "revisionId" - ], - "request": { - "$ref": "Revision" - }, - "response": { - "$ref": "Revision" - }, - "scopes": [ - "https://www.googleapis.com/auth/drive", - "https://www.googleapis.com/auth/drive.appdata", - "https://www.googleapis.com/auth/drive.file" - ] - } - } - } - } -} + "servicePath": "drive/v3/", + "title": "Google Drive API", + "version": "v3" +} \ No newline at end of file diff --git a/vendor/google.golang.org/api/drive/v3/drive-gen.go b/vendor/google.golang.org/api/drive/v3/drive-gen.go index 9e6e0874..924c63bf 100644 --- a/vendor/google.golang.org/api/drive/v3/drive-gen.go +++ b/vendor/google.golang.org/api/drive/v3/drive-gen.go @@ -1,28 +1,78 @@ -// Package drive provides access to the Drive API. +// Copyright 2024 Google LLC. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + +// Package drive provides access to the Google Drive API. +// +// For product documentation, see: https://developers.google.com/drive/ +// +// # Library status // -// See https://developers.google.com/drive/ +// These client libraries are officially supported by Google. However, this +// library is considered complete and is in maintenance mode. This means +// that we will address critical bugs and security issues but will not add +// any new features. +// +// When possible, we recommend using our newer +// [Cloud Client Libraries for Go](https://pkg.go.dev/cloud.google.com/go) +// that are still actively being worked and iterated on. +// +// # Creating a client // // Usage example: // -// import "google.golang.org/api/drive/v3" -// ... -// driveService, err := drive.New(oauthHttpClient) -package drive +// import "google.golang.org/api/drive/v3" +// ... +// ctx := context.Background() +// driveService, err := drive.NewService(ctx) +// +// In this example, Google Application Default Credentials are used for +// authentication. For information on how to create and obtain Application +// Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials. +// +// # Other authentication options +// +// By default, all available scopes (see "Constants") are used to authenticate. +// To restrict scopes, use [google.golang.org/api/option.WithScopes]: +// +// driveService, err := drive.NewService(ctx, option.WithScopes(drive.DriveScriptsScope)) +// +// To use an API key for authentication (note: some APIs do not support API +// keys), use [google.golang.org/api/option.WithAPIKey]: +// +// driveService, err := drive.NewService(ctx, option.WithAPIKey("AIza...")) +// +// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth +// flow, use [google.golang.org/api/option.WithTokenSource]: +// +// config := &oauth2.Config{...} +// // ... +// token, err := config.Exchange(ctx, ...) +// driveService, err := drive.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token))) +// +// See [google.golang.org/api/option.ClientOption] for details on options. +package drive // import "google.golang.org/api/drive/v3" import ( "bytes" + "context" "encoding/json" "errors" "fmt" - context "golang.org/x/net/context" - ctxhttp "golang.org/x/net/context/ctxhttp" - gensupport "google.golang.org/api/gensupport" - googleapi "google.golang.org/api/googleapi" "io" "net/http" "net/url" "strconv" "strings" + + googleapi "google.golang.org/api/googleapi" + internal "google.golang.org/api/internal" + gensupport "google.golang.org/api/internal/gensupport" + option "google.golang.org/api/option" + internaloption "google.golang.org/api/option/internaloption" + htransport "google.golang.org/api/transport/http" ) // Always reference these packages, just in case the auto-generated code @@ -38,54 +88,109 @@ var _ = googleapi.Version var _ = errors.New var _ = strings.Replace var _ = context.Canceled -var _ = ctxhttp.Do +var _ = internaloption.WithDefaultEndpoint +var _ = internal.Version const apiId = "drive:v3" const apiName = "drive" const apiVersion = "v3" const basePath = "https://www.googleapis.com/drive/v3/" +const basePathTemplate = "https://www.UNIVERSE_DOMAIN/drive/v3/" +const mtlsBasePath = "https://www.mtls.googleapis.com/drive/v3/" // OAuth2 scopes used by this API. const ( - // View and manage the files in your Google Drive + // See, edit, create, and delete all of your Google Drive files DriveScope = "https://www.googleapis.com/auth/drive" - // View and manage its own configuration data in your Google Drive + // See, create, and delete its own configuration data in your Google Drive DriveAppdataScope = "https://www.googleapis.com/auth/drive.appdata" - // View and manage Google Drive files and folders that you have opened - // or created with this app + // View your Google Drive apps + DriveAppsReadonlyScope = "https://www.googleapis.com/auth/drive.apps.readonly" + + // See, edit, create, and delete only the specific Google Drive files you use + // with this app DriveFileScope = "https://www.googleapis.com/auth/drive.file" + // See and download your Google Drive files that were created or edited by + // Google Meet. + DriveMeetReadonlyScope = "https://www.googleapis.com/auth/drive.meet.readonly" + // View and manage metadata of files in your Google Drive DriveMetadataScope = "https://www.googleapis.com/auth/drive.metadata" - // View metadata for files in your Google Drive + // See information about your Google Drive files DriveMetadataReadonlyScope = "https://www.googleapis.com/auth/drive.metadata.readonly" // View the photos, videos and albums in your Google Photos DrivePhotosReadonlyScope = "https://www.googleapis.com/auth/drive.photos.readonly" - // View the files in your Google Drive + // See and download all your Google Drive files DriveReadonlyScope = "https://www.googleapis.com/auth/drive.readonly" // Modify your Google Apps Script scripts' behavior DriveScriptsScope = "https://www.googleapis.com/auth/drive.scripts" ) +// NewService creates a new Service. +func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) { + scopesOption := internaloption.WithDefaultScopes( + "https://www.googleapis.com/auth/drive", + "https://www.googleapis.com/auth/drive.appdata", + "https://www.googleapis.com/auth/drive.apps.readonly", + "https://www.googleapis.com/auth/drive.file", + "https://www.googleapis.com/auth/drive.meet.readonly", + "https://www.googleapis.com/auth/drive.metadata", + "https://www.googleapis.com/auth/drive.metadata.readonly", + "https://www.googleapis.com/auth/drive.photos.readonly", + "https://www.googleapis.com/auth/drive.readonly", + "https://www.googleapis.com/auth/drive.scripts", + ) + // NOTE: prepend, so we don't override user-specified scopes. + opts = append([]option.ClientOption{scopesOption}, opts...) + opts = append(opts, internaloption.WithDefaultEndpoint(basePath)) + opts = append(opts, internaloption.WithDefaultEndpointTemplate(basePathTemplate)) + opts = append(opts, internaloption.WithDefaultMTLSEndpoint(mtlsBasePath)) + opts = append(opts, internaloption.EnableNewAuthLibrary()) + client, endpoint, err := htransport.NewClient(ctx, opts...) + if err != nil { + return nil, err + } + s, err := New(client) + if err != nil { + return nil, err + } + if endpoint != "" { + s.BasePath = endpoint + } + return s, nil +} + +// New creates a new Service. It uses the provided http.Client for requests. +// +// Deprecated: please use NewService instead. +// To provide a custom HTTP client, use option.WithHTTPClient. +// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead. func New(client *http.Client) (*Service, error) { if client == nil { return nil, errors.New("client is nil") } s := &Service{client: client, BasePath: basePath} s.About = NewAboutService(s) + s.Accessproposals = NewAccessproposalsService(s) + s.Apps = NewAppsService(s) s.Changes = NewChangesService(s) s.Channels = NewChannelsService(s) s.Comments = NewCommentsService(s) + s.Drives = NewDrivesService(s) s.Files = NewFilesService(s) + s.Operation = NewOperationService(s) + s.Operations = NewOperationsService(s) s.Permissions = NewPermissionsService(s) s.Replies = NewRepliesService(s) s.Revisions = NewRevisionsService(s) + s.Teamdrives = NewTeamdrivesService(s) return s, nil } @@ -96,19 +201,31 @@ type Service struct { About *AboutService + Accessproposals *AccessproposalsService + + Apps *AppsService + Changes *ChangesService Channels *ChannelsService Comments *CommentsService + Drives *DrivesService + Files *FilesService + Operation *OperationService + + Operations *OperationsService + Permissions *PermissionsService Replies *RepliesService Revisions *RevisionsService + + Teamdrives *TeamdrivesService } func (s *Service) userAgent() string { @@ -127,6 +244,24 @@ type AboutService struct { s *Service } +func NewAccessproposalsService(s *Service) *AccessproposalsService { + rs := &AccessproposalsService{s: s} + return rs +} + +type AccessproposalsService struct { + s *Service +} + +func NewAppsService(s *Service) *AppsService { + rs := &AppsService{s: s} + return rs +} + +type AppsService struct { + s *Service +} + func NewChangesService(s *Service) *ChangesService { rs := &ChangesService{s: s} return rs @@ -154,6 +289,15 @@ type CommentsService struct { s *Service } +func NewDrivesService(s *Service) *DrivesService { + rs := &DrivesService{s: s} + return rs +} + +type DrivesService struct { + s *Service +} + func NewFilesService(s *Service) *FilesService { rs := &FilesService{s: s} return rs @@ -163,6 +307,24 @@ type FilesService struct { s *Service } +func NewOperationService(s *Service) *OperationService { + rs := &OperationService{s: s} + return rs +} + +type OperationService struct { + s *Service +} + +func NewOperationsService(s *Service) *OperationsService { + rs := &OperationsService{s: s} + return rs +} + +type OperationsService struct { + s *Service +} + func NewPermissionsService(s *Service) *PermissionsService { rs := &PermissionsService{s: s} return rs @@ -190,1176 +352,2866 @@ type RevisionsService struct { s *Service } +func NewTeamdrivesService(s *Service) *TeamdrivesService { + rs := &TeamdrivesService{s: s} + return rs +} + +type TeamdrivesService struct { + s *Service +} + // About: Information about the user, the user's Drive, and system // capabilities. type About struct { // AppInstalled: Whether the user has installed the requesting app. AppInstalled bool `json:"appInstalled,omitempty"` - + // CanCreateDrives: Whether the user can create shared drives. + CanCreateDrives bool `json:"canCreateDrives,omitempty"` + // CanCreateTeamDrives: Deprecated: Use `canCreateDrives` instead. + CanCreateTeamDrives bool `json:"canCreateTeamDrives,omitempty"` + // DriveThemes: A list of themes that are supported for shared drives. + DriveThemes []*AboutDriveThemes `json:"driveThemes,omitempty"` // ExportFormats: A map of source MIME type to possible targets for all // supported exports. ExportFormats map[string][]string `json:"exportFormats,omitempty"` - // FolderColorPalette: The currently supported folder colors as RGB hex // strings. FolderColorPalette []string `json:"folderColorPalette,omitempty"` - // ImportFormats: A map of source MIME type to possible targets for all // supported imports. ImportFormats map[string][]string `json:"importFormats,omitempty"` - - // Kind: This is always drive#about. + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#about". Kind string `json:"kind,omitempty"` - // MaxImportSizes: A map of maximum import sizes by MIME type, in bytes. MaxImportSizes map[string]string `json:"maxImportSizes,omitempty"` - // MaxUploadSize: The maximum upload size in bytes. MaxUploadSize int64 `json:"maxUploadSize,omitempty,string"` - - // StorageQuota: The user's storage quota limits and usage. All fields - // are measured in bytes. + // StorageQuota: The user's storage quota limits and usage. For users that are + // part of an organization with pooled storage, information about the limit and + // usage across all services is for the organization, rather than the + // individual user. All fields are measured in bytes. StorageQuota *AboutStorageQuota `json:"storageQuota,omitempty"` - + // TeamDriveThemes: Deprecated: Use `driveThemes` instead. + TeamDriveThemes []*AboutTeamDriveThemes `json:"teamDriveThemes,omitempty"` // User: The authenticated user. User *User `json:"user,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "AppInstalled") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "AppInstalled") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s About) MarshalJSON() ([]byte, error) { + type NoMethod About + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +type AboutDriveThemes struct { + // BackgroundImageLink: A link to this theme's background image. + BackgroundImageLink string `json:"backgroundImageLink,omitempty"` + // ColorRgb: The color of this theme as an RGB hex string. + ColorRgb string `json:"colorRgb,omitempty"` + // Id: The ID of the theme. + Id string `json:"id,omitempty"` + // ForceSendFields is a list of field names (e.g. "BackgroundImageLink") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "BackgroundImageLink") to include + // in API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *About) MarshalJSON() ([]byte, error) { - type noMethod About - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s AboutDriveThemes) MarshalJSON() ([]byte, error) { + type NoMethod AboutDriveThemes + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// AboutStorageQuota: The user's storage quota limits and usage. All -// fields are measured in bytes. +// AboutStorageQuota: The user's storage quota limits and usage. For users that +// are part of an organization with pooled storage, information about the limit +// and usage across all services is for the organization, rather than the +// individual user. All fields are measured in bytes. type AboutStorageQuota struct { - // Limit: The usage limit, if applicable. This will not be present if - // the user has unlimited storage. + // Limit: The usage limit, if applicable. This will not be present if the user + // has unlimited storage. For users that are part of an organization with + // pooled storage, this is the limit for the organization, rather than the + // individual user. Limit int64 `json:"limit,omitempty,string"` - - // Usage: The total usage across all services. + // Usage: The total usage across all services. For users that are part of an + // organization with pooled storage, this is the usage across all services for + // the organization, rather than the individual user. Usage int64 `json:"usage,omitempty,string"` - // UsageInDrive: The usage by all files in Google Drive. UsageInDrive int64 `json:"usageInDrive,omitempty,string"` - // UsageInDriveTrash: The usage by trashed files in Google Drive. UsageInDriveTrash int64 `json:"usageInDriveTrash,omitempty,string"` + // ForceSendFields is a list of field names (e.g. "Limit") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Limit") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s AboutStorageQuota) MarshalJSON() ([]byte, error) { + type NoMethod AboutStorageQuota + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +type AboutTeamDriveThemes struct { + // BackgroundImageLink: Deprecated: Use `driveThemes/backgroundImageLink` + // instead. + BackgroundImageLink string `json:"backgroundImageLink,omitempty"` + // ColorRgb: Deprecated: Use `driveThemes/colorRgb` instead. + ColorRgb string `json:"colorRgb,omitempty"` + // Id: Deprecated: Use `driveThemes/id` instead. + Id string `json:"id,omitempty"` + // ForceSendFields is a list of field names (e.g. "BackgroundImageLink") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "BackgroundImageLink") to include + // in API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s AboutTeamDriveThemes) MarshalJSON() ([]byte, error) { + type NoMethod AboutTeamDriveThemes + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// AccessProposal: The Access Proposal resource for outstanding access +// proposals on a file +type AccessProposal struct { + // CreateTime: The creation time + CreateTime string `json:"createTime,omitempty"` + // FileId: The file id that the proposal for access is on + FileId string `json:"fileId,omitempty"` + // ProposalId: The id of the access proposal + ProposalId string `json:"proposalId,omitempty"` + // RecipientEmailAddress: The email address of the user that will receive + // permissions if accepted + RecipientEmailAddress string `json:"recipientEmailAddress,omitempty"` + // RequestMessage: The message that the requester added to the proposal + RequestMessage string `json:"requestMessage,omitempty"` + // RequesterEmailAddress: The email address of the requesting user + RequesterEmailAddress string `json:"requesterEmailAddress,omitempty"` + // RolesAndViews: A wrapper for the role and view of an access proposal. + RolesAndViews []*AccessProposalRoleAndView `json:"rolesAndViews,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "CreateTime") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "CreateTime") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s AccessProposal) MarshalJSON() ([]byte, error) { + type NoMethod AccessProposal + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// AccessProposalRoleAndView: A wrapper for the role and view of an access +// proposal. +type AccessProposalRoleAndView struct { + // Role: The role that was proposed by the requester New values may be added in + // the future, but the following are currently possible: * `writer` * + // `commenter` * `reader` + Role string `json:"role,omitempty"` + // View: Indicates the view for this access proposal. Only populated for + // proposals that belong to a view. `published` is the only supported value. + View string `json:"view,omitempty"` + // ForceSendFields is a list of field names (e.g. "Role") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Role") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} - // ForceSendFields is a list of field names (e.g. "Limit") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. +func (s AccessProposalRoleAndView) MarshalJSON() ([]byte, error) { + type NoMethod AccessProposalRoleAndView + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// App: The `apps` resource provides a list of apps that a user has installed, +// with information about each app's supported MIME types, file extensions, and +// other details. Some resource methods (such as `apps.get`) require an +// `appId`. Use the `apps.list` method to retrieve the ID for an installed +// application. +type App struct { + // Authorized: Whether the app is authorized to access data on the user's + // Drive. + Authorized bool `json:"authorized,omitempty"` + // CreateInFolderTemplate: The template URL to create a file with this app in a + // given folder. The template contains the {folderId} to be replaced by the + // folder ID house the new file. + CreateInFolderTemplate string `json:"createInFolderTemplate,omitempty"` + // CreateUrl: The URL to create a file with this app. + CreateUrl string `json:"createUrl,omitempty"` + // HasDriveWideScope: Whether the app has Drive-wide scope. An app with + // Drive-wide scope can access all files in the user's Drive. + HasDriveWideScope bool `json:"hasDriveWideScope,omitempty"` + // Icons: The various icons for the app. + Icons []*AppIcons `json:"icons,omitempty"` + // Id: The ID of the app. + Id string `json:"id,omitempty"` + // Installed: Whether the app is installed. + Installed bool `json:"installed,omitempty"` + // Kind: Output only. Identifies what kind of resource this is. Value: the + // fixed string "drive#app". + Kind string `json:"kind,omitempty"` + // LongDescription: A long description of the app. + LongDescription string `json:"longDescription,omitempty"` + // Name: The name of the app. + Name string `json:"name,omitempty"` + // ObjectType: The type of object this app creates such as a Chart. If empty, + // the app name should be used instead. + ObjectType string `json:"objectType,omitempty"` + // OpenUrlTemplate: The template URL for opening files with this app. The + // template contains {ids} or {exportIds} to be replaced by the actual file + // IDs. For more information, see Open Files for the full documentation. + OpenUrlTemplate string `json:"openUrlTemplate,omitempty"` + // PrimaryFileExtensions: The list of primary file extensions. + PrimaryFileExtensions []string `json:"primaryFileExtensions,omitempty"` + // PrimaryMimeTypes: The list of primary MIME types. + PrimaryMimeTypes []string `json:"primaryMimeTypes,omitempty"` + // ProductId: The ID of the product listing for this app. + ProductId string `json:"productId,omitempty"` + // ProductUrl: A link to the product listing for this app. + ProductUrl string `json:"productUrl,omitempty"` + // SecondaryFileExtensions: The list of secondary file extensions. + SecondaryFileExtensions []string `json:"secondaryFileExtensions,omitempty"` + // SecondaryMimeTypes: The list of secondary MIME types. + SecondaryMimeTypes []string `json:"secondaryMimeTypes,omitempty"` + // ShortDescription: A short description of the app. + ShortDescription string `json:"shortDescription,omitempty"` + // SupportsCreate: Whether this app supports creating objects. + SupportsCreate bool `json:"supportsCreate,omitempty"` + // SupportsImport: Whether this app supports importing from Google Docs. + SupportsImport bool `json:"supportsImport,omitempty"` + // SupportsMultiOpen: Whether this app supports opening more than one file. + SupportsMultiOpen bool `json:"supportsMultiOpen,omitempty"` + // SupportsOfflineCreate: Whether this app supports creating files when + // offline. + SupportsOfflineCreate bool `json:"supportsOfflineCreate,omitempty"` + // UseByDefault: Whether the app is selected as the default handler for the + // types it supports. + UseByDefault bool `json:"useByDefault,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "Authorized") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Authorized") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s App) MarshalJSON() ([]byte, error) { + type NoMethod App + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +type AppIcons struct { + // Category: Category of the icon. Allowed values are: * `application` - The + // icon for the application. * `document` - The icon for a file associated with + // the app. * `documentShared` - The icon for a shared file associated with the + // app. + Category string `json:"category,omitempty"` + // IconUrl: URL for the icon. + IconUrl string `json:"iconUrl,omitempty"` + // Size: Size of the icon. Represented as the maximum of the width and height. + Size int64 `json:"size,omitempty"` + // ForceSendFields is a list of field names (e.g. "Category") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Category") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s AppIcons) MarshalJSON() ([]byte, error) { + type NoMethod AppIcons + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// AppList: A list of third-party applications which the user has installed or +// given access to Google Drive. +type AppList struct { + // DefaultAppIds: The list of app IDs that the user has specified to use by + // default. The list is in reverse-priority order (lowest to highest). + DefaultAppIds []string `json:"defaultAppIds,omitempty"` + // Items: The list of apps. + Items []*App `json:"items,omitempty"` + // Kind: Output only. Identifies what kind of resource this is. Value: the + // fixed string "drive#appList". + Kind string `json:"kind,omitempty"` + // SelfLink: A link back to this list. + SelfLink string `json:"selfLink,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "DefaultAppIds") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "DefaultAppIds") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *AboutStorageQuota) MarshalJSON() ([]byte, error) { - type noMethod AboutStorageQuota - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s AppList) MarshalJSON() ([]byte, error) { + type NoMethod AppList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// Change: A change to a file. +// Change: A change to a file or shared drive. type Change struct { - // File: The updated state of the file. Present if the file has not been - // removed. + // ChangeType: The type of the change. Possible values are `file` and `drive`. + ChangeType string `json:"changeType,omitempty"` + // Drive: The updated state of the shared drive. Present if the changeType is + // drive, the user is still a member of the shared drive, and the shared drive + // has not been deleted. + Drive *Drive `json:"drive,omitempty"` + // DriveId: The ID of the shared drive associated with this change. + DriveId string `json:"driveId,omitempty"` + // File: The updated state of the file. Present if the type is file and the + // file has not been removed from this list of changes. File *File `json:"file,omitempty"` - // FileId: The ID of the file which has changed. FileId string `json:"fileId,omitempty"` - - // Kind: This is always drive#change. + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#change". Kind string `json:"kind,omitempty"` - - // Removed: Whether the file has been removed from the view of the - // changes list, for example by deletion or lost access. + // Removed: Whether the file or shared drive has been removed from this list of + // changes, for example by deletion or loss of access. Removed bool `json:"removed,omitempty"` - + // TeamDrive: Deprecated: Use `drive` instead. + TeamDrive *TeamDrive `json:"teamDrive,omitempty"` + // TeamDriveId: Deprecated: Use `driveId` instead. + TeamDriveId string `json:"teamDriveId,omitempty"` // Time: The time of this change (RFC 3339 date-time). Time string `json:"time,omitempty"` - - // ForceSendFields is a list of field names (e.g. "File") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // Type: Deprecated: Use `changeType` instead. + Type string `json:"type,omitempty"` + // ForceSendFields is a list of field names (e.g. "ChangeType") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "ChangeType") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *Change) MarshalJSON() ([]byte, error) { - type noMethod Change - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s Change) MarshalJSON() ([]byte, error) { + type NoMethod Change + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } // ChangeList: A list of changes for a user. type ChangeList struct { - // Changes: The page of changes. + // Changes: The list of changes. If nextPageToken is populated, then this list + // may be incomplete and an additional page of results should be fetched. Changes []*Change `json:"changes,omitempty"` - - // Kind: This is always drive#changeList. + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#changeList". Kind string `json:"kind,omitempty"` - - // NewStartPageToken: The starting page token for future changes. This - // will be present only if the end of the current changes list has been - // reached. + // NewStartPageToken: The starting page token for future changes. This will be + // present only if the end of the current changes list has been reached. The + // page token doesn't expire. NewStartPageToken string `json:"newStartPageToken,omitempty"` - - // NextPageToken: The page token for the next page of changes. This will - // be absent if the end of the current changes list has been reached. + // NextPageToken: The page token for the next page of changes. This will be + // absent if the end of the changes list has been reached. The page token + // doesn't expire. NextPageToken string `json:"nextPageToken,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Changes") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "Changes") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Changes") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *ChangeList) MarshalJSON() ([]byte, error) { - type noMethod ChangeList - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s ChangeList) MarshalJSON() ([]byte, error) { + type NoMethod ChangeList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// Channel: An notification channel used to watch for resource changes. +// Channel: A notification channel used to watch for resource changes. type Channel struct { - // Address: The address where notifications are delivered for this - // channel. + // Address: The address where notifications are delivered for this channel. Address string `json:"address,omitempty"` - - // Expiration: Date and time of notification channel expiration, - // expressed as a Unix timestamp, in milliseconds. Optional. + // Expiration: Date and time of notification channel expiration, expressed as a + // Unix timestamp, in milliseconds. Optional. Expiration int64 `json:"expiration,omitempty,string"` - // Id: A UUID or similar unique string that identifies this channel. Id string `json:"id,omitempty"` - - // Kind: Identifies this as a notification channel used to watch for - // changes to a resource. Value: the fixed string "api#channel". + // Kind: Identifies this as a notification channel used to watch for changes to + // a resource, which is `api#channel`. Kind string `json:"kind,omitempty"` - // Params: Additional parameters controlling delivery channel behavior. // Optional. Params map[string]string `json:"params,omitempty"` - - // Payload: A Boolean value to indicate whether payload is wanted. - // Optional. + // Payload: A Boolean value to indicate whether payload is wanted. Optional. Payload bool `json:"payload,omitempty"` - - // ResourceId: An opaque ID that identifies the resource being watched - // on this channel. Stable across different API versions. + // ResourceId: An opaque ID that identifies the resource being watched on this + // channel. Stable across different API versions. ResourceId string `json:"resourceId,omitempty"` - // ResourceUri: A version-specific identifier for the watched resource. ResourceUri string `json:"resourceUri,omitempty"` - // Token: An arbitrary string delivered to the target address with each // notification delivered over this channel. Optional. Token string `json:"token,omitempty"` - - // Type: The type of delivery mechanism used for this channel. + // Type: The type of delivery mechanism used for this channel. Valid values are + // "web_hook" or "webhook". Type string `json:"type,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Address") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "Address") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Address") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *Channel) MarshalJSON() ([]byte, error) { - type noMethod Channel - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s Channel) MarshalJSON() ([]byte, error) { + type NoMethod Channel + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// Comment: A comment on a file. +// Comment: A comment on a file. Some resource methods (such as +// `comments.update`) require a `commentId`. Use the `comments.list` method to +// retrieve the ID for a comment in a file. type Comment struct { - // Anchor: A region of the document represented as a JSON string. See - // anchor documentation for details on how to define and interpret - // anchor properties. + // Anchor: A region of the document represented as a JSON string. For details + // on defining anchor properties, refer to Manage comments and replies + // (https://developers.google.com/drive/api/v3/manage-comments). Anchor string `json:"anchor,omitempty"` - - // Author: The user who created the comment. + // Author: Output only. The author of the comment. The author's email address + // and permission ID will not be populated. Author *User `json:"author,omitempty"` - - // Content: The plain text content of the comment. This field is used - // for setting the content, while htmlContent should be displayed. + // Content: The plain text content of the comment. This field is used for + // setting the content, while `htmlContent` should be displayed. Content string `json:"content,omitempty"` - - // CreatedTime: The time at which the comment was created (RFC 3339 - // date-time). + // CreatedTime: The time at which the comment was created (RFC 3339 date-time). CreatedTime string `json:"createdTime,omitempty"` - - // Deleted: Whether the comment has been deleted. A deleted comment has - // no content. + // Deleted: Output only. Whether the comment has been deleted. A deleted + // comment has no content. Deleted bool `json:"deleted,omitempty"` - - // HtmlContent: The content of the comment with HTML formatting. + // HtmlContent: Output only. The content of the comment with HTML formatting. HtmlContent string `json:"htmlContent,omitempty"` - - // Id: The ID of the comment. + // Id: Output only. The ID of the comment. Id string `json:"id,omitempty"` - - // Kind: This is always drive#comment. + // Kind: Output only. Identifies what kind of resource this is. Value: the + // fixed string "drive#comment". Kind string `json:"kind,omitempty"` - - // ModifiedTime: The last time the comment or any of its replies was - // modified (RFC 3339 date-time). + // ModifiedTime: The last time the comment or any of its replies was modified + // (RFC 3339 date-time). ModifiedTime string `json:"modifiedTime,omitempty"` - - // QuotedFileContent: The file content to which the comment refers, - // typically within the anchor region. For a text file, for example, - // this would be the text at the location of the comment. + // QuotedFileContent: The file content to which the comment refers, typically + // within the anchor region. For a text file, for example, this would be the + // text at the location of the comment. QuotedFileContent *CommentQuotedFileContent `json:"quotedFileContent,omitempty"` - - // Replies: The full list of replies to the comment in chronological - // order. + // Replies: Output only. The full list of replies to the comment in + // chronological order. Replies []*Reply `json:"replies,omitempty"` - - // Resolved: Whether the comment has been resolved by one of its + // Resolved: Output only. Whether the comment has been resolved by one of its // replies. Resolved bool `json:"resolved,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Anchor") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "Anchor") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Anchor") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *Comment) MarshalJSON() ([]byte, error) { - type noMethod Comment - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s Comment) MarshalJSON() ([]byte, error) { + type NoMethod Comment + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// CommentQuotedFileContent: The file content to which the comment -// refers, typically within the anchor region. For a text file, for -// example, this would be the text at the location of the comment. +// CommentQuotedFileContent: The file content to which the comment refers, +// typically within the anchor region. For a text file, for example, this would +// be the text at the location of the comment. type CommentQuotedFileContent struct { // MimeType: The MIME type of the quoted content. MimeType string `json:"mimeType,omitempty"` - - // Value: The quoted content itself. This is interpreted as plain text - // if set through the API. + // Value: The quoted content itself. This is interpreted as plain text if set + // through the API. Value string `json:"value,omitempty"` - // ForceSendFields is a list of field names (e.g. "MimeType") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "MimeType") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *CommentQuotedFileContent) MarshalJSON() ([]byte, error) { - type noMethod CommentQuotedFileContent - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s CommentQuotedFileContent) MarshalJSON() ([]byte, error) { + type NoMethod CommentQuotedFileContent + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } // CommentList: A list of comments on a file. type CommentList struct { - // Comments: The page of comments. + // Comments: The list of comments. If nextPageToken is populated, then this + // list may be incomplete and an additional page of results should be fetched. Comments []*Comment `json:"comments,omitempty"` + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#commentList". + Kind string `json:"kind,omitempty"` + // NextPageToken: The page token for the next page of comments. This will be + // absent if the end of the comments list has been reached. If the token is + // rejected for any reason, it should be discarded, and pagination should be + // restarted from the first page of results. The page token is typically valid + // for several hours. However, if new items are added or removed, your expected + // results might differ. + NextPageToken string `json:"nextPageToken,omitempty"` - // Kind: This is always drive#commentList. + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "Comments") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Comments") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s CommentList) MarshalJSON() ([]byte, error) { + type NoMethod CommentList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// ContentRestriction: A restriction for accessing the content of the file. +type ContentRestriction struct { + // OwnerRestricted: Whether the content restriction can only be modified or + // removed by a user who owns the file. For files in shared drives, any user + // with `organizer` capabilities can modify or remove this content restriction. + OwnerRestricted bool `json:"ownerRestricted,omitempty"` + // ReadOnly: Whether the content of the file is read-only. If a file is + // read-only, a new revision of the file may not be added, comments may not be + // added or modified, and the title of the file may not be modified. + ReadOnly bool `json:"readOnly,omitempty"` + // Reason: Reason for why the content of the file is restricted. This is only + // mutable on requests that also set `readOnly=true`. + Reason string `json:"reason,omitempty"` + // RestrictingUser: Output only. The user who set the content restriction. Only + // populated if `readOnly` is true. + RestrictingUser *User `json:"restrictingUser,omitempty"` + // RestrictionTime: The time at which the content restriction was set + // (formatted RFC 3339 timestamp). Only populated if readOnly is true. + RestrictionTime string `json:"restrictionTime,omitempty"` + // SystemRestricted: Output only. Whether the content restriction was applied + // by the system, for example due to an esignature. Users cannot modify or + // remove system restricted content restrictions. + SystemRestricted bool `json:"systemRestricted,omitempty"` + // Type: Output only. The type of the content restriction. Currently the only + // possible value is `globalContentRestriction`. + Type string `json:"type,omitempty"` + // ForceSendFields is a list of field names (e.g. "OwnerRestricted") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "OwnerRestricted") to include in + // API requests with the JSON null value. By default, fields with empty values + // are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s ContentRestriction) MarshalJSON() ([]byte, error) { + type NoMethod ContentRestriction + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// Drive: Representation of a shared drive. Some resource methods (such as +// `drives.update`) require a `driveId`. Use the `drives.list` method to +// retrieve the ID for a shared drive. +type Drive struct { + // BackgroundImageFile: An image file and cropping parameters from which a + // background image for this shared drive is set. This is a write only field; + // it can only be set on `drive.drives.update` requests that don't set + // `themeId`. When specified, all fields of the `backgroundImageFile` must be + // set. + BackgroundImageFile *DriveBackgroundImageFile `json:"backgroundImageFile,omitempty"` + // BackgroundImageLink: Output only. A short-lived link to this shared drive's + // background image. + BackgroundImageLink string `json:"backgroundImageLink,omitempty"` + // Capabilities: Output only. Capabilities the current user has on this shared + // drive. + Capabilities *DriveCapabilities `json:"capabilities,omitempty"` + // ColorRgb: The color of this shared drive as an RGB hex string. It can only + // be set on a `drive.drives.update` request that does not set `themeId`. + ColorRgb string `json:"colorRgb,omitempty"` + // CreatedTime: The time at which the shared drive was created (RFC 3339 + // date-time). + CreatedTime string `json:"createdTime,omitempty"` + // Hidden: Whether the shared drive is hidden from default view. + Hidden bool `json:"hidden,omitempty"` + // Id: Output only. The ID of this shared drive which is also the ID of the top + // level folder of this shared drive. + Id string `json:"id,omitempty"` + // Kind: Output only. Identifies what kind of resource this is. Value: the + // fixed string "drive#drive". Kind string `json:"kind,omitempty"` + // Name: The name of this shared drive. + Name string `json:"name,omitempty"` + // OrgUnitId: Output only. The organizational unit of this shared drive. This + // field is only populated on `drives.list` responses when the + // `useDomainAdminAccess` parameter is set to `true`. + OrgUnitId string `json:"orgUnitId,omitempty"` + // Restrictions: A set of restrictions that apply to this shared drive or items + // inside this shared drive. Note that restrictions can't be set when creating + // a shared drive. To add a restriction, first create a shared drive and then + // use `drives.update` to add restrictions. + Restrictions *DriveRestrictions `json:"restrictions,omitempty"` + // ThemeId: The ID of the theme from which the background image and color will + // be set. The set of possible `driveThemes` can be retrieved from a + // `drive.about.get` response. When not specified on a `drive.drives.create` + // request, a random theme is chosen from which the background image and color + // are set. This is a write-only field; it can only be set on requests that + // don't set `colorRgb` or `backgroundImageFile`. + ThemeId string `json:"themeId,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "BackgroundImageFile") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "BackgroundImageFile") to include + // in API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s Drive) MarshalJSON() ([]byte, error) { + type NoMethod Drive + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// DriveBackgroundImageFile: An image file and cropping parameters from which a +// background image for this shared drive is set. This is a write only field; +// it can only be set on `drive.drives.update` requests that don't set +// `themeId`. When specified, all fields of the `backgroundImageFile` must be +// set. +type DriveBackgroundImageFile struct { + // Id: The ID of an image file in Google Drive to use for the background image. + Id string `json:"id,omitempty"` + // Width: The width of the cropped image in the closed range of 0 to 1. This + // value represents the width of the cropped image divided by the width of the + // entire image. The height is computed by applying a width to height aspect + // ratio of 80 to 9. The resulting image must be at least 1280 pixels wide and + // 144 pixels high. + Width float64 `json:"width,omitempty"` + // XCoordinate: The X coordinate of the upper left corner of the cropping area + // in the background image. This is a value in the closed range of 0 to 1. This + // value represents the horizontal distance from the left side of the entire + // image to the left side of the cropping area divided by the width of the + // entire image. + XCoordinate float64 `json:"xCoordinate,omitempty"` + // YCoordinate: The Y coordinate of the upper left corner of the cropping area + // in the background image. This is a value in the closed range of 0 to 1. This + // value represents the vertical distance from the top side of the entire image + // to the top side of the cropping area divided by the height of the entire + // image. + YCoordinate float64 `json:"yCoordinate,omitempty"` + // ForceSendFields is a list of field names (e.g. "Id") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Id") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s DriveBackgroundImageFile) MarshalJSON() ([]byte, error) { + type NoMethod DriveBackgroundImageFile + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +func (s *DriveBackgroundImageFile) UnmarshalJSON(data []byte) error { + type NoMethod DriveBackgroundImageFile + var s1 struct { + Width gensupport.JSONFloat64 `json:"width"` + XCoordinate gensupport.JSONFloat64 `json:"xCoordinate"` + YCoordinate gensupport.JSONFloat64 `json:"yCoordinate"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.Width = float64(s1.Width) + s.XCoordinate = float64(s1.XCoordinate) + s.YCoordinate = float64(s1.YCoordinate) + return nil +} + +// DriveCapabilities: Output only. Capabilities the current user has on this +// shared drive. +type DriveCapabilities struct { + // CanAddChildren: Output only. Whether the current user can add children to + // folders in this shared drive. + CanAddChildren bool `json:"canAddChildren,omitempty"` + // CanChangeCopyRequiresWriterPermissionRestriction: Output only. Whether the + // current user can change the `copyRequiresWriterPermission` restriction of + // this shared drive. + CanChangeCopyRequiresWriterPermissionRestriction bool `json:"canChangeCopyRequiresWriterPermissionRestriction,omitempty"` + // CanChangeDomainUsersOnlyRestriction: Output only. Whether the current user + // can change the `domainUsersOnly` restriction of this shared drive. + CanChangeDomainUsersOnlyRestriction bool `json:"canChangeDomainUsersOnlyRestriction,omitempty"` + // CanChangeDriveBackground: Output only. Whether the current user can change + // the background of this shared drive. + CanChangeDriveBackground bool `json:"canChangeDriveBackground,omitempty"` + // CanChangeDriveMembersOnlyRestriction: Output only. Whether the current user + // can change the `driveMembersOnly` restriction of this shared drive. + CanChangeDriveMembersOnlyRestriction bool `json:"canChangeDriveMembersOnlyRestriction,omitempty"` + // CanChangeSharingFoldersRequiresOrganizerPermissionRestriction: Output only. + // Whether the current user can change the + // `sharingFoldersRequiresOrganizerPermission` restriction of this shared + // drive. + CanChangeSharingFoldersRequiresOrganizerPermissionRestriction bool `json:"canChangeSharingFoldersRequiresOrganizerPermissionRestriction,omitempty"` + // CanComment: Output only. Whether the current user can comment on files in + // this shared drive. + CanComment bool `json:"canComment,omitempty"` + // CanCopy: Output only. Whether the current user can copy files in this shared + // drive. + CanCopy bool `json:"canCopy,omitempty"` + // CanDeleteChildren: Output only. Whether the current user can delete children + // from folders in this shared drive. + CanDeleteChildren bool `json:"canDeleteChildren,omitempty"` + // CanDeleteDrive: Output only. Whether the current user can delete this shared + // drive. Attempting to delete the shared drive may still fail if there are + // untrashed items inside the shared drive. + CanDeleteDrive bool `json:"canDeleteDrive,omitempty"` + // CanDownload: Output only. Whether the current user can download files in + // this shared drive. + CanDownload bool `json:"canDownload,omitempty"` + // CanEdit: Output only. Whether the current user can edit files in this shared + // drive + CanEdit bool `json:"canEdit,omitempty"` + // CanListChildren: Output only. Whether the current user can list the children + // of folders in this shared drive. + CanListChildren bool `json:"canListChildren,omitempty"` + // CanManageMembers: Output only. Whether the current user can add members to + // this shared drive or remove them or change their role. + CanManageMembers bool `json:"canManageMembers,omitempty"` + // CanReadRevisions: Output only. Whether the current user can read the + // revisions resource of files in this shared drive. + CanReadRevisions bool `json:"canReadRevisions,omitempty"` + // CanRename: Output only. Whether the current user can rename files or folders + // in this shared drive. + CanRename bool `json:"canRename,omitempty"` + // CanRenameDrive: Output only. Whether the current user can rename this shared + // drive. + CanRenameDrive bool `json:"canRenameDrive,omitempty"` + // CanResetDriveRestrictions: Output only. Whether the current user can reset + // the shared drive restrictions to defaults. + CanResetDriveRestrictions bool `json:"canResetDriveRestrictions,omitempty"` + // CanShare: Output only. Whether the current user can share files or folders + // in this shared drive. + CanShare bool `json:"canShare,omitempty"` + // CanTrashChildren: Output only. Whether the current user can trash children + // from folders in this shared drive. + CanTrashChildren bool `json:"canTrashChildren,omitempty"` + // ForceSendFields is a list of field names (e.g. "CanAddChildren") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "CanAddChildren") to include in + // API requests with the JSON null value. By default, fields with empty values + // are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s DriveCapabilities) MarshalJSON() ([]byte, error) { + type NoMethod DriveCapabilities + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// DriveRestrictions: A set of restrictions that apply to this shared drive or +// items inside this shared drive. Note that restrictions can't be set when +// creating a shared drive. To add a restriction, first create a shared drive +// and then use `drives.update` to add restrictions. +type DriveRestrictions struct { + // AdminManagedRestrictions: Whether administrative privileges on this shared + // drive are required to modify restrictions. + AdminManagedRestrictions bool `json:"adminManagedRestrictions,omitempty"` + // CopyRequiresWriterPermission: Whether the options to copy, print, or + // download files inside this shared drive, should be disabled for readers and + // commenters. When this restriction is set to `true`, it will override the + // similarly named field to `true` for any file inside this shared drive. + CopyRequiresWriterPermission bool `json:"copyRequiresWriterPermission,omitempty"` + // DomainUsersOnly: Whether access to this shared drive and items inside this + // shared drive is restricted to users of the domain to which this shared drive + // belongs. This restriction may be overridden by other sharing policies + // controlled outside of this shared drive. + DomainUsersOnly bool `json:"domainUsersOnly,omitempty"` + // DriveMembersOnly: Whether access to items inside this shared drive is + // restricted to its members. + DriveMembersOnly bool `json:"driveMembersOnly,omitempty"` + // SharingFoldersRequiresOrganizerPermission: If true, only users with the + // organizer role can share folders. If false, users with either the organizer + // role or the file organizer role can share folders. + SharingFoldersRequiresOrganizerPermission bool `json:"sharingFoldersRequiresOrganizerPermission,omitempty"` + // ForceSendFields is a list of field names (e.g. "AdminManagedRestrictions") + // to unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "AdminManagedRestrictions") to + // include in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s DriveRestrictions) MarshalJSON() ([]byte, error) { + type NoMethod DriveRestrictions + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} - // NextPageToken: The page token for the next page of comments. This - // will be absent if the end of the comments list has been reached. +// DriveList: A list of shared drives. +type DriveList struct { + // Drives: The list of shared drives. If nextPageToken is populated, then this + // list may be incomplete and an additional page of results should be fetched. + Drives []*Drive `json:"drives,omitempty"` + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#driveList". + Kind string `json:"kind,omitempty"` + // NextPageToken: The page token for the next page of shared drives. This will + // be absent if the end of the list has been reached. If the token is rejected + // for any reason, it should be discarded, and pagination should be restarted + // from the first page of results. The page token is typically valid for + // several hours. However, if new items are added or removed, your expected + // results might differ. NextPageToken string `json:"nextPageToken,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Comments") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "Drives") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Drives") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *CommentList) MarshalJSON() ([]byte, error) { - type noMethod CommentList - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s DriveList) MarshalJSON() ([]byte, error) { + type NoMethod DriveList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// File: The metadata for a file. +// File: The metadata for a file. Some resource methods (such as +// `files.update`) require a `fileId`. Use the `files.list` method to retrieve +// the ID for a file. type File struct { - // AppProperties: A collection of arbitrary key-value pairs which are - // private to the requesting app. - // Entries with null values are cleared in update and copy requests. + // AppProperties: A collection of arbitrary key-value pairs which are private + // to the requesting app. + // Entries with null values are cleared in update and copy requests. These + // properties can only be retrieved using an authenticated request. An + // authenticated request uses an access token obtained with a OAuth 2 client + // ID. You cannot use an API key to retrieve private properties. AppProperties map[string]string `json:"appProperties,omitempty"` - - // Capabilities: Capabilities the current user has on the file. + // Capabilities: Output only. Capabilities the current user has on this file. + // Each capability corresponds to a fine-grained action that a user may take. Capabilities *FileCapabilities `json:"capabilities,omitempty"` - - // ContentHints: Additional information about the content of the file. - // These fields are never populated in responses. + // ContentHints: Additional information about the content of the file. These + // fields are never populated in responses. ContentHints *FileContentHints `json:"contentHints,omitempty"` - - // CreatedTime: The time at which the file was created (RFC 3339 - // date-time). + // ContentRestrictions: Restrictions for accessing the content of the file. + // Only populated if such a restriction exists. + ContentRestrictions []*ContentRestriction `json:"contentRestrictions,omitempty"` + // CopyRequiresWriterPermission: Whether the options to copy, print, or + // download this file, should be disabled for readers and commenters. + CopyRequiresWriterPermission bool `json:"copyRequiresWriterPermission,omitempty"` + // CreatedTime: The time at which the file was created (RFC 3339 date-time). CreatedTime string `json:"createdTime,omitempty"` - // Description: A short description of the file. Description string `json:"description,omitempty"` - - // ExplicitlyTrashed: Whether the file has been explicitly trashed, as - // opposed to recursively trashed from a parent folder. + // DriveId: Output only. ID of the shared drive the file resides in. Only + // populated for items in shared drives. + DriveId string `json:"driveId,omitempty"` + // ExplicitlyTrashed: Output only. Whether the file has been explicitly + // trashed, as opposed to recursively trashed from a parent folder. ExplicitlyTrashed bool `json:"explicitlyTrashed,omitempty"` - - // FileExtension: The final component of fullFileExtension. This is only - // available for files with binary content in Drive. + // ExportLinks: Output only. Links for exporting Docs Editors files to specific + // formats. + ExportLinks map[string]string `json:"exportLinks,omitempty"` + // FileExtension: Output only. The final component of `fullFileExtension`. This + // is only available for files with binary content in Google Drive. FileExtension string `json:"fileExtension,omitempty"` - - // FolderColorRgb: The color for a folder as an RGB hex string. The - // supported colors are published in the folderColorPalette field of the - // About resource. - // If an unsupported color is specified, the closest color in the - // palette will be used instead. + // FolderColorRgb: The color for a folder or a shortcut to a folder as an RGB + // hex string. The supported colors are published in the `folderColorPalette` + // field of the About resource. If an unsupported color is specified, the + // closest color in the palette is used instead. FolderColorRgb string `json:"folderColorRgb,omitempty"` - - // FullFileExtension: The full file extension extracted from the name - // field. May contain multiple concatenated extensions, such as - // "tar.gz". This is only available for files with binary content in - // Drive. - // This is automatically updated when the name field changes, however it - // is not cleared if the new name does not contain a valid extension. + // FullFileExtension: Output only. The full file extension extracted from the + // `name` field. May contain multiple concatenated extensions, such as + // "tar.gz". This is only available for files with binary content in Google + // Drive. This is automatically updated when the `name` field changes, however + // it is not cleared if the new name does not contain a valid extension. FullFileExtension string `json:"fullFileExtension,omitempty"` - - // HeadRevisionId: The ID of the file's head revision. This is currently - // only available for files with binary content in Drive. + // HasAugmentedPermissions: Output only. Whether there are permissions directly + // on this file. This field is only populated for items in shared drives. + HasAugmentedPermissions bool `json:"hasAugmentedPermissions,omitempty"` + // HasThumbnail: Output only. Whether this file has a thumbnail. This does not + // indicate whether the requesting app has access to the thumbnail. To check + // access, look for the presence of the thumbnailLink field. + HasThumbnail bool `json:"hasThumbnail,omitempty"` + // HeadRevisionId: Output only. The ID of the file's head revision. This is + // currently only available for files with binary content in Google Drive. HeadRevisionId string `json:"headRevisionId,omitempty"` - - // IconLink: A static, unauthenticated link to the file's icon. + // IconLink: Output only. A static, unauthenticated link to the file's icon. IconLink string `json:"iconLink,omitempty"` - // Id: The ID of the file. Id string `json:"id,omitempty"` - - // ImageMediaMetadata: Additional metadata about image media, if + // ImageMediaMetadata: Output only. Additional metadata about image media, if // available. ImageMediaMetadata *FileImageMediaMetadata `json:"imageMediaMetadata,omitempty"` - - // Kind: This is always drive#file. + // IsAppAuthorized: Output only. Whether the file was created or opened by the + // requesting app. + IsAppAuthorized bool `json:"isAppAuthorized,omitempty"` + // Kind: Output only. Identifies what kind of resource this is. Value: the + // fixed string "drive#file". Kind string `json:"kind,omitempty"` - - // LastModifyingUser: The last user to modify the file. + // LabelInfo: Output only. An overview of the labels on the file. + LabelInfo *FileLabelInfo `json:"labelInfo,omitempty"` + // LastModifyingUser: Output only. The last user to modify the file. This field + // is only populated when the last modification was performed by a signed-in + // user. LastModifyingUser *User `json:"lastModifyingUser,omitempty"` - - // Md5Checksum: The MD5 checksum for the content of the file. This is - // only applicable to files with binary content in Drive. + // LinkShareMetadata: Contains details about the link URLs that clients are + // using to refer to this item. + LinkShareMetadata *FileLinkShareMetadata `json:"linkShareMetadata,omitempty"` + // Md5Checksum: Output only. The MD5 checksum for the content of the file. This + // is only applicable to files with binary content in Google Drive. Md5Checksum string `json:"md5Checksum,omitempty"` - - // MimeType: The MIME type of the file. - // Drive will attempt to automatically detect an appropriate value from - // uploaded content if no value is provided. The value cannot be changed - // unless a new revision is uploaded. - // If a file is created with a Google Doc MIME type, the uploaded - // content will be imported if possible. The supported import formats - // are published in the About resource. + // MimeType: The MIME type of the file. Google Drive attempts to automatically + // detect an appropriate value from uploaded content, if no value is provided. + // The value cannot be changed unless a new revision is uploaded. If a file is + // created with a Google Doc MIME type, the uploaded content is imported, if + // possible. The supported import formats are published in the About resource. MimeType string `json:"mimeType,omitempty"` - - // ModifiedByMeTime: The last time the file was modified by the user - // (RFC 3339 date-time). - ModifiedByMeTime string `json:"modifiedByMeTime,omitempty"` - - // ModifiedTime: The last time the file was modified by anyone (RFC 3339 + // ModifiedByMe: Output only. Whether the file has been modified by this user. + ModifiedByMe bool `json:"modifiedByMe,omitempty"` + // ModifiedByMeTime: The last time the file was modified by the user (RFC 3339 // date-time). - // Note that setting modifiedTime will also update modifiedByMeTime for - // the user. + ModifiedByMeTime string `json:"modifiedByMeTime,omitempty"` + // ModifiedTime: he last time the file was modified by anyone (RFC 3339 + // date-time). Note that setting modifiedTime will also update modifiedByMeTime + // for the user. ModifiedTime string `json:"modifiedTime,omitempty"` - - // Name: The name of the file. This is not necessarily unique within a - // folder. + // Name: The name of the file. This is not necessarily unique within a folder. + // Note that for immutable items such as the top level folders of shared + // drives, My Drive root folder, and Application Data folder the name is + // constant. Name string `json:"name,omitempty"` - // OriginalFilename: The original filename of the uploaded content if - // available, or else the original value of the name field. This is only - // available for files with binary content in Drive. + // available, or else the original value of the `name` field. This is only + // available for files with binary content in Google Drive. OriginalFilename string `json:"originalFilename,omitempty"` - - // OwnedByMe: Whether the user owns the file. + // OwnedByMe: Output only. Whether the user owns the file. Not populated for + // items in shared drives. OwnedByMe bool `json:"ownedByMe,omitempty"` - - // Owners: The owners of the file. Currently, only certain legacy files - // may have more than one owner. + // Owners: Output only. The owner of this file. Only certain legacy files may + // have more than one owner. This field isn't populated for items in shared + // drives. Owners []*User `json:"owners,omitempty"` - - // Parents: The IDs of the parent folders which contain the file. - // If not specified as part of a create request, the file will be placed - // directly in the My Drive folder. Update requests must use the - // addParents and removeParents parameters to modify the values. + // Parents: The ID of the parent folder containing the file. A file can only + // have one parent folder; specifying multiple parents isn't supported. If not + // specified as part of a create request, the file is placed directly in the + // user's My Drive folder. If not specified as part of a copy request, the file + // inherits any discoverable parent of the source file. Update requests must + // use the `addParents` and `removeParents` parameters to modify the parents + // list. Parents []string `json:"parents,omitempty"` - - // Permissions: The full list of permissions for the file. This is only - // available if the requesting user can share the file. + // PermissionIds: Output only. List of permission IDs for users with access to + // this file. + PermissionIds []string `json:"permissionIds,omitempty"` + // Permissions: Output only. The full list of permissions for the file. This is + // only available if the requesting user can share the file. Not populated for + // items in shared drives. Permissions []*Permission `json:"permissions,omitempty"` - - // Properties: A collection of arbitrary key-value pairs which are - // visible to all apps. + // Properties: A collection of arbitrary key-value pairs which are visible to + // all apps. // Entries with null values are cleared in update and copy requests. Properties map[string]string `json:"properties,omitempty"` - - // QuotaBytesUsed: The number of storage quota bytes used by the file. - // This includes the head revision as well as previous revisions with - // keepForever enabled. + // QuotaBytesUsed: Output only. The number of storage quota bytes used by the + // file. This includes the head revision as well as previous revisions with + // `keepForever` enabled. QuotaBytesUsed int64 `json:"quotaBytesUsed,omitempty,string"` - - // Shared: Whether the file has been shared. + // ResourceKey: Output only. A key needed to access the item via a shared link. + ResourceKey string `json:"resourceKey,omitempty"` + // Sha1Checksum: Output only. The SHA1 checksum associated with this file, if + // available. This field is only populated for files with content stored in + // Google Drive; it is not populated for Docs Editors or shortcut files. + Sha1Checksum string `json:"sha1Checksum,omitempty"` + // Sha256Checksum: Output only. The SHA256 checksum associated with this file, + // if available. This field is only populated for files with content stored in + // Google Drive; it is not populated for Docs Editors or shortcut files. + Sha256Checksum string `json:"sha256Checksum,omitempty"` + // Shared: Output only. Whether the file has been shared. Not populated for + // items in shared drives. Shared bool `json:"shared,omitempty"` - - // SharedWithMeTime: The time at which the file was shared with the - // user, if applicable (RFC 3339 date-time). + // SharedWithMeTime: The time at which the file was shared with the user, if + // applicable (RFC 3339 date-time). SharedWithMeTime string `json:"sharedWithMeTime,omitempty"` - - // SharingUser: The user who shared the file with the requesting user, - // if applicable. + // SharingUser: Output only. The user who shared the file with the requesting + // user, if applicable. SharingUser *User `json:"sharingUser,omitempty"` - - // Size: The size of the file's content in bytes. This is only - // applicable to files with binary content in Drive. + // ShortcutDetails: Shortcut file details. Only populated for shortcut files, + // which have the mimeType field set to `application/vnd.google-apps.shortcut`. + // Can only be set on `files.create` requests. + ShortcutDetails *FileShortcutDetails `json:"shortcutDetails,omitempty"` + // Size: Output only. Size in bytes of blobs and first party editor files. + // Won't be populated for files that have no size, like shortcuts and folders. Size int64 `json:"size,omitempty,string"` - - // Spaces: The list of spaces which contain the file. The currently - // supported values are 'drive', 'appDataFolder' and 'photos'. + // Spaces: Output only. The list of spaces which contain the file. The + // currently supported values are 'drive', 'appDataFolder' and 'photos'. Spaces []string `json:"spaces,omitempty"` - // Starred: Whether the user has starred the file. Starred bool `json:"starred,omitempty"` - - // ThumbnailLink: A short-lived link to the file's thumbnail, if - // available. Typically lasts on the order of hours. + // TeamDriveId: Deprecated: Output only. Use `driveId` instead. + TeamDriveId string `json:"teamDriveId,omitempty"` + // ThumbnailLink: Output only. A short-lived link to the file's thumbnail, if + // available. Typically lasts on the order of hours. Not intended for direct + // usage on web applications due to Cross-Origin Resource Sharing (CORS) + // (https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) policies, consider + // using a proxy server. Only populated when the requesting app can access the + // file's content. If the file isn't shared publicly, the URL returned in + // `Files.thumbnailLink` must be fetched using a credentialed request. ThumbnailLink string `json:"thumbnailLink,omitempty"` - - // Trashed: Whether the file has been trashed, either explicitly or from - // a trashed parent folder. Only the owner may trash a file, and other - // users cannot see files in the owner's trash. + // ThumbnailVersion: Output only. The thumbnail version for use in thumbnail + // cache invalidation. + ThumbnailVersion int64 `json:"thumbnailVersion,omitempty,string"` + // Trashed: Whether the file has been trashed, either explicitly or from a + // trashed parent folder. Only the owner may trash a file, and other users + // cannot see files in the owner's trash. Trashed bool `json:"trashed,omitempty"` - - // Version: A monotonically increasing version number for the file. This - // reflects every change made to the file on the server, even those not - // visible to the user. + // TrashedTime: The time that the item was trashed (RFC 3339 date-time). Only + // populated for items in shared drives. + TrashedTime string `json:"trashedTime,omitempty"` + // TrashingUser: Output only. If the file has been explicitly trashed, the user + // who trashed it. Only populated for items in shared drives. + TrashingUser *User `json:"trashingUser,omitempty"` + // Version: Output only. A monotonically increasing version number for the + // file. This reflects every change made to the file on the server, even those + // not visible to the user. Version int64 `json:"version,omitempty,string"` - - // VideoMediaMetadata: Additional metadata about video media. This may - // not be available immediately upon upload. + // VideoMediaMetadata: Output only. Additional metadata about video media. This + // may not be available immediately upon upload. VideoMediaMetadata *FileVideoMediaMetadata `json:"videoMediaMetadata,omitempty"` - - // ViewedByMe: Whether the file has been viewed by this user. + // ViewedByMe: Output only. Whether the file has been viewed by this user. ViewedByMe bool `json:"viewedByMe,omitempty"` - - // ViewedByMeTime: The last time the file was viewed by the user (RFC - // 3339 date-time). + // ViewedByMeTime: The last time the file was viewed by the user (RFC 3339 + // date-time). ViewedByMeTime string `json:"viewedByMeTime,omitempty"` - - // ViewersCanCopyContent: Whether users with only reader or commenter - // permission can copy the file's content. This affects copy, download, - // and print operations. + // ViewersCanCopyContent: Deprecated: Use `copyRequiresWriterPermission` + // instead. ViewersCanCopyContent bool `json:"viewersCanCopyContent,omitempty"` - - // WebContentLink: A link for downloading the content of the file in a - // browser. This is only available for files with binary content in + // WebContentLink: Output only. A link for downloading the content of the file + // in a browser. This is only available for files with binary content in Google // Drive. WebContentLink string `json:"webContentLink,omitempty"` - - // WebViewLink: A link for opening the file in a relevant Google editor - // or viewer in a browser. + // WebViewLink: Output only. A link for opening the file in a relevant Google + // editor or viewer in a browser. WebViewLink string `json:"webViewLink,omitempty"` - - // WritersCanShare: Whether users with only writer permission can modify - // the file's permissions. + // WritersCanShare: Whether users with only `writer` permission can modify the + // file's permissions. Not populated for items in shared drives. WritersCanShare bool `json:"writersCanShare,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - // ForceSendFields is a list of field names (e.g. "AppProperties") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "AppProperties") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *File) MarshalJSON() ([]byte, error) { - type noMethod File - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s File) MarshalJSON() ([]byte, error) { + type NoMethod File + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// FileCapabilities: Capabilities the current user has on the file. +// FileCapabilities: Output only. Capabilities the current user has on this +// file. Each capability corresponds to a fine-grained action that a user may +// take. type FileCapabilities struct { - // CanComment: Whether the user can comment on the file. + // CanAcceptOwnership: Output only. Whether the current user is the pending + // owner of the file. Not populated for shared drive files. + CanAcceptOwnership bool `json:"canAcceptOwnership,omitempty"` + // CanAddChildren: Output only. Whether the current user can add children to + // this folder. This is always false when the item is not a folder. + CanAddChildren bool `json:"canAddChildren,omitempty"` + // CanAddFolderFromAnotherDrive: Output only. Whether the current user can add + // a folder from another drive (different shared drive or My Drive) to this + // folder. This is false when the item is not a folder. Only populated for + // items in shared drives. + CanAddFolderFromAnotherDrive bool `json:"canAddFolderFromAnotherDrive,omitempty"` + // CanAddMyDriveParent: Output only. Whether the current user can add a parent + // for the item without removing an existing parent in the same request. Not + // populated for shared drive files. + CanAddMyDriveParent bool `json:"canAddMyDriveParent,omitempty"` + // CanChangeCopyRequiresWriterPermission: Output only. Whether the current user + // can change the `copyRequiresWriterPermission` restriction of this file. + CanChangeCopyRequiresWriterPermission bool `json:"canChangeCopyRequiresWriterPermission,omitempty"` + // CanChangeSecurityUpdateEnabled: Output only. Whether the current user can + // change the securityUpdateEnabled field on link share metadata. + CanChangeSecurityUpdateEnabled bool `json:"canChangeSecurityUpdateEnabled,omitempty"` + // CanChangeViewersCanCopyContent: Deprecated: Output only. + CanChangeViewersCanCopyContent bool `json:"canChangeViewersCanCopyContent,omitempty"` + // CanComment: Output only. Whether the current user can comment on this file. CanComment bool `json:"canComment,omitempty"` - - // CanCopy: Whether the user can copy the file. + // CanCopy: Output only. Whether the current user can copy this file. For an + // item in a shared drive, whether the current user can copy non-folder + // descendants of this item, or this item itself if it is not a folder. CanCopy bool `json:"canCopy,omitempty"` - - // CanEdit: Whether the user can edit the file's content. + // CanDelete: Output only. Whether the current user can delete this file. + CanDelete bool `json:"canDelete,omitempty"` + // CanDeleteChildren: Output only. Whether the current user can delete children + // of this folder. This is false when the item is not a folder. Only populated + // for items in shared drives. + CanDeleteChildren bool `json:"canDeleteChildren,omitempty"` + // CanDownload: Output only. Whether the current user can download this file. + CanDownload bool `json:"canDownload,omitempty"` + // CanEdit: Output only. Whether the current user can edit this file. Other + // factors may limit the type of changes a user can make to a file. For + // example, see `canChangeCopyRequiresWriterPermission` or `canModifyContent`. CanEdit bool `json:"canEdit,omitempty"` - - // CanReadRevisions: Whether the current user has read access to the - // Revisions resource of the file. + // CanListChildren: Output only. Whether the current user can list the children + // of this folder. This is always false when the item is not a folder. + CanListChildren bool `json:"canListChildren,omitempty"` + // CanModifyContent: Output only. Whether the current user can modify the + // content of this file. + CanModifyContent bool `json:"canModifyContent,omitempty"` + // CanModifyContentRestriction: Deprecated: Output only. Use one of + // `canModifyEditorContentRestriction`, `canModifyOwnerContentRestriction` or + // `canRemoveContentRestriction`. + CanModifyContentRestriction bool `json:"canModifyContentRestriction,omitempty"` + // CanModifyEditorContentRestriction: Output only. Whether the current user can + // add or modify content restrictions on the file which are editor restricted. + CanModifyEditorContentRestriction bool `json:"canModifyEditorContentRestriction,omitempty"` + // CanModifyLabels: Output only. Whether the current user can modify the labels + // on the file. + CanModifyLabels bool `json:"canModifyLabels,omitempty"` + // CanModifyOwnerContentRestriction: Output only. Whether the current user can + // add or modify content restrictions which are owner restricted. + CanModifyOwnerContentRestriction bool `json:"canModifyOwnerContentRestriction,omitempty"` + // CanMoveChildrenOutOfDrive: Output only. Whether the current user can move + // children of this folder outside of the shared drive. This is false when the + // item is not a folder. Only populated for items in shared drives. + CanMoveChildrenOutOfDrive bool `json:"canMoveChildrenOutOfDrive,omitempty"` + // CanMoveChildrenOutOfTeamDrive: Deprecated: Output only. Use + // `canMoveChildrenOutOfDrive` instead. + CanMoveChildrenOutOfTeamDrive bool `json:"canMoveChildrenOutOfTeamDrive,omitempty"` + // CanMoveChildrenWithinDrive: Output only. Whether the current user can move + // children of this folder within this drive. This is false when the item is + // not a folder. Note that a request to move the child may still fail depending + // on the current user's access to the child and to the destination folder. + CanMoveChildrenWithinDrive bool `json:"canMoveChildrenWithinDrive,omitempty"` + // CanMoveChildrenWithinTeamDrive: Deprecated: Output only. Use + // `canMoveChildrenWithinDrive` instead. + CanMoveChildrenWithinTeamDrive bool `json:"canMoveChildrenWithinTeamDrive,omitempty"` + // CanMoveItemIntoTeamDrive: Deprecated: Output only. Use + // `canMoveItemOutOfDrive` instead. + CanMoveItemIntoTeamDrive bool `json:"canMoveItemIntoTeamDrive,omitempty"` + // CanMoveItemOutOfDrive: Output only. Whether the current user can move this + // item outside of this drive by changing its parent. Note that a request to + // change the parent of the item may still fail depending on the new parent + // that is being added. + CanMoveItemOutOfDrive bool `json:"canMoveItemOutOfDrive,omitempty"` + // CanMoveItemOutOfTeamDrive: Deprecated: Output only. Use + // `canMoveItemOutOfDrive` instead. + CanMoveItemOutOfTeamDrive bool `json:"canMoveItemOutOfTeamDrive,omitempty"` + // CanMoveItemWithinDrive: Output only. Whether the current user can move this + // item within this drive. Note that a request to change the parent of the item + // may still fail depending on the new parent that is being added and the + // parent that is being removed. + CanMoveItemWithinDrive bool `json:"canMoveItemWithinDrive,omitempty"` + // CanMoveItemWithinTeamDrive: Deprecated: Output only. Use + // `canMoveItemWithinDrive` instead. + CanMoveItemWithinTeamDrive bool `json:"canMoveItemWithinTeamDrive,omitempty"` + // CanMoveTeamDriveItem: Deprecated: Output only. Use `canMoveItemWithinDrive` + // or `canMoveItemOutOfDrive` instead. + CanMoveTeamDriveItem bool `json:"canMoveTeamDriveItem,omitempty"` + // CanReadDrive: Output only. Whether the current user can read the shared + // drive to which this file belongs. Only populated for items in shared drives. + CanReadDrive bool `json:"canReadDrive,omitempty"` + // CanReadLabels: Output only. Whether the current user can read the labels on + // the file. + CanReadLabels bool `json:"canReadLabels,omitempty"` + // CanReadRevisions: Output only. Whether the current user can read the + // revisions resource of this file. For a shared drive item, whether revisions + // of non-folder descendants of this item, or this item itself if it is not a + // folder, can be read. CanReadRevisions bool `json:"canReadRevisions,omitempty"` - - // CanShare: Whether the user can modify the file's permissions and - // sharing settings. + // CanReadTeamDrive: Deprecated: Output only. Use `canReadDrive` instead. + CanReadTeamDrive bool `json:"canReadTeamDrive,omitempty"` + // CanRemoveChildren: Output only. Whether the current user can remove children + // from this folder. This is always false when the item is not a folder. For a + // folder in a shared drive, use `canDeleteChildren` or `canTrashChildren` + // instead. + CanRemoveChildren bool `json:"canRemoveChildren,omitempty"` + // CanRemoveContentRestriction: Output only. Whether there is a content + // restriction on the file that can be removed by the current user. + CanRemoveContentRestriction bool `json:"canRemoveContentRestriction,omitempty"` + // CanRemoveMyDriveParent: Output only. Whether the current user can remove a + // parent from the item without adding another parent in the same request. Not + // populated for shared drive files. + CanRemoveMyDriveParent bool `json:"canRemoveMyDriveParent,omitempty"` + // CanRename: Output only. Whether the current user can rename this file. + CanRename bool `json:"canRename,omitempty"` + // CanShare: Output only. Whether the current user can modify the sharing + // settings for this file. CanShare bool `json:"canShare,omitempty"` - - // ForceSendFields is a list of field names (e.g. "CanComment") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // CanTrash: Output only. Whether the current user can move this file to trash. + CanTrash bool `json:"canTrash,omitempty"` + // CanTrashChildren: Output only. Whether the current user can trash children + // of this folder. This is false when the item is not a folder. Only populated + // for items in shared drives. + CanTrashChildren bool `json:"canTrashChildren,omitempty"` + // CanUntrash: Output only. Whether the current user can restore this file from + // trash. + CanUntrash bool `json:"canUntrash,omitempty"` + // ForceSendFields is a list of field names (e.g. "CanAcceptOwnership") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "CanAcceptOwnership") to include + // in API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *FileCapabilities) MarshalJSON() ([]byte, error) { - type noMethod FileCapabilities - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s FileCapabilities) MarshalJSON() ([]byte, error) { + type NoMethod FileCapabilities + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// FileContentHints: Additional information about the content of the -// file. These fields are never populated in responses. +// FileContentHints: Additional information about the content of the file. +// These fields are never populated in responses. type FileContentHints struct { - // IndexableText: Text to be indexed for the file to improve fullText - // queries. This is limited to 128KB in length and may contain HTML - // elements. + // IndexableText: Text to be indexed for the file to improve fullText queries. + // This is limited to 128KB in length and may contain HTML elements. IndexableText string `json:"indexableText,omitempty"` - - // Thumbnail: A thumbnail for the file. This will only be used if Drive + // Thumbnail: A thumbnail for the file. This will only be used if Google Drive // cannot generate a standard thumbnail. Thumbnail *FileContentHintsThumbnail `json:"thumbnail,omitempty"` - // ForceSendFields is a list of field names (e.g. "IndexableText") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "IndexableText") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *FileContentHints) MarshalJSON() ([]byte, error) { - type noMethod FileContentHints - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s FileContentHints) MarshalJSON() ([]byte, error) { + type NoMethod FileContentHints + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// FileContentHintsThumbnail: A thumbnail for the file. This will only -// be used if Drive cannot generate a standard thumbnail. +// FileContentHintsThumbnail: A thumbnail for the file. This will only be used +// if Google Drive cannot generate a standard thumbnail. type FileContentHintsThumbnail struct { - // Image: The thumbnail data encoded with URL-safe Base64 (RFC 4648 - // section 5). + // Image: The thumbnail data encoded with URL-safe Base64 (RFC 4648 section 5). Image string `json:"image,omitempty"` - // MimeType: The MIME type of the thumbnail. MimeType string `json:"mimeType,omitempty"` - - // ForceSendFields is a list of field names (e.g. "Image") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "Image") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Image") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *FileContentHintsThumbnail) MarshalJSON() ([]byte, error) { - type noMethod FileContentHintsThumbnail - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s FileContentHintsThumbnail) MarshalJSON() ([]byte, error) { + type NoMethod FileContentHintsThumbnail + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// FileImageMediaMetadata: Additional metadata about image media, if -// available. +// FileImageMediaMetadata: Output only. Additional metadata about image media, +// if available. type FileImageMediaMetadata struct { - // Aperture: The aperture used to create the photo (f-number). + // Aperture: Output only. The aperture used to create the photo (f-number). Aperture float64 `json:"aperture,omitempty"` - - // CameraMake: The make of the camera used to create the photo. + // CameraMake: Output only. The make of the camera used to create the photo. CameraMake string `json:"cameraMake,omitempty"` - - // CameraModel: The model of the camera used to create the photo. + // CameraModel: Output only. The model of the camera used to create the photo. CameraModel string `json:"cameraModel,omitempty"` - - // ColorSpace: The color space of the photo. + // ColorSpace: Output only. The color space of the photo. ColorSpace string `json:"colorSpace,omitempty"` - - // ExposureBias: The exposure bias of the photo (APEX value). + // ExposureBias: Output only. The exposure bias of the photo (APEX value). ExposureBias float64 `json:"exposureBias,omitempty"` - - // ExposureMode: The exposure mode used to create the photo. + // ExposureMode: Output only. The exposure mode used to create the photo. ExposureMode string `json:"exposureMode,omitempty"` - - // ExposureTime: The length of the exposure, in seconds. + // ExposureTime: Output only. The length of the exposure, in seconds. ExposureTime float64 `json:"exposureTime,omitempty"` - - // FlashUsed: Whether a flash was used to create the photo. + // FlashUsed: Output only. Whether a flash was used to create the photo. FlashUsed bool `json:"flashUsed,omitempty"` - - // FocalLength: The focal length used to create the photo, in + // FocalLength: Output only. The focal length used to create the photo, in // millimeters. FocalLength float64 `json:"focalLength,omitempty"` - - // Height: The height of the image in pixels. + // Height: Output only. The height of the image in pixels. Height int64 `json:"height,omitempty"` - - // IsoSpeed: The ISO speed used to create the photo. + // IsoSpeed: Output only. The ISO speed used to create the photo. IsoSpeed int64 `json:"isoSpeed,omitempty"` - - // Lens: The lens used to create the photo. + // Lens: Output only. The lens used to create the photo. Lens string `json:"lens,omitempty"` - - // Location: Geographic location information stored in the image. + // Location: Output only. Geographic location information stored in the image. Location *FileImageMediaMetadataLocation `json:"location,omitempty"` - - // MaxApertureValue: The smallest f-number of the lens at the focal - // length used to create the photo (APEX value). + // MaxApertureValue: Output only. The smallest f-number of the lens at the + // focal length used to create the photo (APEX value). MaxApertureValue float64 `json:"maxApertureValue,omitempty"` - - // MeteringMode: The metering mode used to create the photo. + // MeteringMode: Output only. The metering mode used to create the photo. MeteringMode string `json:"meteringMode,omitempty"` - - // Rotation: The rotation in clockwise degrees from the image's original - // orientation. + // Rotation: Output only. The number of clockwise 90 degree rotations applied + // from the image's original orientation. Rotation int64 `json:"rotation,omitempty"` - - // Sensor: The type of sensor used to create the photo. + // Sensor: Output only. The type of sensor used to create the photo. Sensor string `json:"sensor,omitempty"` - - // SubjectDistance: The distance to the subject of the photo, in meters. + // SubjectDistance: Output only. The distance to the subject of the photo, in + // meters. SubjectDistance int64 `json:"subjectDistance,omitempty"` - - // Time: The date and time the photo was taken (EXIF DateTime). + // Time: Output only. The date and time the photo was taken (EXIF DateTime). Time string `json:"time,omitempty"` - - // WhiteBalance: The white balance mode used to create the photo. + // WhiteBalance: Output only. The white balance mode used to create the photo. WhiteBalance string `json:"whiteBalance,omitempty"` - - // Width: The width of the image in pixels. + // Width: Output only. The width of the image in pixels. Width int64 `json:"width,omitempty"` - // ForceSendFields is a list of field names (e.g. "Aperture") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Aperture") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s FileImageMediaMetadata) MarshalJSON() ([]byte, error) { + type NoMethod FileImageMediaMetadata + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +func (s *FileImageMediaMetadata) UnmarshalJSON(data []byte) error { + type NoMethod FileImageMediaMetadata + var s1 struct { + Aperture gensupport.JSONFloat64 `json:"aperture"` + ExposureBias gensupport.JSONFloat64 `json:"exposureBias"` + ExposureTime gensupport.JSONFloat64 `json:"exposureTime"` + FocalLength gensupport.JSONFloat64 `json:"focalLength"` + MaxApertureValue gensupport.JSONFloat64 `json:"maxApertureValue"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.Aperture = float64(s1.Aperture) + s.ExposureBias = float64(s1.ExposureBias) + s.ExposureTime = float64(s1.ExposureTime) + s.FocalLength = float64(s1.FocalLength) + s.MaxApertureValue = float64(s1.MaxApertureValue) + return nil } -func (s *FileImageMediaMetadata) MarshalJSON() ([]byte, error) { - type noMethod FileImageMediaMetadata - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) -} - -// FileImageMediaMetadataLocation: Geographic location information +// FileImageMediaMetadataLocation: Output only. Geographic location information // stored in the image. type FileImageMediaMetadataLocation struct { - // Altitude: The altitude stored in the image. + // Altitude: Output only. The altitude stored in the image. Altitude float64 `json:"altitude,omitempty"` - - // Latitude: The latitude stored in the image. + // Latitude: Output only. The latitude stored in the image. Latitude float64 `json:"latitude,omitempty"` - - // Longitude: The longitude stored in the image. + // Longitude: Output only. The longitude stored in the image. Longitude float64 `json:"longitude,omitempty"` - // ForceSendFields is a list of field names (e.g. "Altitude") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Altitude") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s FileImageMediaMetadataLocation) MarshalJSON() ([]byte, error) { + type NoMethod FileImageMediaMetadataLocation + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +func (s *FileImageMediaMetadataLocation) UnmarshalJSON(data []byte) error { + type NoMethod FileImageMediaMetadataLocation + var s1 struct { + Altitude gensupport.JSONFloat64 `json:"altitude"` + Latitude gensupport.JSONFloat64 `json:"latitude"` + Longitude gensupport.JSONFloat64 `json:"longitude"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.Altitude = float64(s1.Altitude) + s.Latitude = float64(s1.Latitude) + s.Longitude = float64(s1.Longitude) + return nil +} + +// FileLabelInfo: Output only. An overview of the labels on the file. +type FileLabelInfo struct { + // Labels: Output only. The set of labels on the file as requested by the label + // IDs in the `includeLabels` parameter. By default, no labels are returned. + Labels []*Label `json:"labels,omitempty"` + // ForceSendFields is a list of field names (e.g. "Labels") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Labels") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s FileLabelInfo) MarshalJSON() ([]byte, error) { + type NoMethod FileLabelInfo + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// FileLinkShareMetadata: Contains details about the link URLs that clients are +// using to refer to this item. +type FileLinkShareMetadata struct { + // SecurityUpdateEligible: Output only. Whether the file is eligible for + // security update. + SecurityUpdateEligible bool `json:"securityUpdateEligible,omitempty"` + // SecurityUpdateEnabled: Output only. Whether the security update is enabled + // for this file. + SecurityUpdateEnabled bool `json:"securityUpdateEnabled,omitempty"` + // ForceSendFields is a list of field names (e.g. "SecurityUpdateEligible") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "SecurityUpdateEligible") to + // include in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s FileLinkShareMetadata) MarshalJSON() ([]byte, error) { + type NoMethod FileLinkShareMetadata + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// FileShortcutDetails: Shortcut file details. Only populated for shortcut +// files, which have the mimeType field set to +// `application/vnd.google-apps.shortcut`. Can only be set on `files.create` +// requests. +type FileShortcutDetails struct { + // TargetId: The ID of the file that this shortcut points to. Can only be set + // on `files.create` requests. + TargetId string `json:"targetId,omitempty"` + // TargetMimeType: Output only. The MIME type of the file that this shortcut + // points to. The value of this field is a snapshot of the target's MIME type, + // captured when the shortcut is created. + TargetMimeType string `json:"targetMimeType,omitempty"` + // TargetResourceKey: Output only. The ResourceKey for the target file. + TargetResourceKey string `json:"targetResourceKey,omitempty"` + // ForceSendFields is a list of field names (e.g. "TargetId") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "TargetId") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *FileImageMediaMetadataLocation) MarshalJSON() ([]byte, error) { - type noMethod FileImageMediaMetadataLocation - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s FileShortcutDetails) MarshalJSON() ([]byte, error) { + type NoMethod FileShortcutDetails + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// FileVideoMediaMetadata: Additional metadata about video media. This -// may not be available immediately upon upload. +// FileVideoMediaMetadata: Output only. Additional metadata about video media. +// This may not be available immediately upon upload. type FileVideoMediaMetadata struct { - // DurationMillis: The duration of the video in milliseconds. + // DurationMillis: Output only. The duration of the video in milliseconds. DurationMillis int64 `json:"durationMillis,omitempty,string"` - - // Height: The height of the video in pixels. + // Height: Output only. The height of the video in pixels. Height int64 `json:"height,omitempty"` - - // Width: The width of the video in pixels. + // Width: Output only. The width of the video in pixels. Width int64 `json:"width,omitempty"` - // ForceSendFields is a list of field names (e.g. "DurationMillis") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "DurationMillis") to include in + // API requests with the JSON null value. By default, fields with empty values + // are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *FileVideoMediaMetadata) MarshalJSON() ([]byte, error) { - type noMethod FileVideoMediaMetadata - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s FileVideoMediaMetadata) MarshalJSON() ([]byte, error) { + type NoMethod FileVideoMediaMetadata + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } // FileList: A list of files. type FileList struct { - // Files: The page of files. + // Files: The list of files. If nextPageToken is populated, then this list may + // be incomplete and an additional page of results should be fetched. Files []*File `json:"files,omitempty"` + // IncompleteSearch: Whether the search process was incomplete. If true, then + // some search results might be missing, since all documents were not searched. + // This can occur when searching multiple drives with the 'allDrives' corpora, + // but all corpora couldn't be searched. When this happens, it's suggested that + // clients narrow their query by choosing a different corpus such as 'user' or + // 'drive'. + IncompleteSearch bool `json:"incompleteSearch,omitempty"` + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#fileList". + Kind string `json:"kind,omitempty"` + // NextPageToken: The page token for the next page of files. This will be + // absent if the end of the files list has been reached. If the token is + // rejected for any reason, it should be discarded, and pagination should be + // restarted from the first page of results. The page token is typically valid + // for several hours. However, if new items are added or removed, your expected + // results might differ. + NextPageToken string `json:"nextPageToken,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "Files") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Files") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s FileList) MarshalJSON() ([]byte, error) { + type NoMethod FileList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// GeneratedIds: A list of generated file IDs which can be provided in create +// requests. +type GeneratedIds struct { + // Ids: The IDs generated for the requesting user in the specified space. + Ids []string `json:"ids,omitempty"` + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#generatedIds". + Kind string `json:"kind,omitempty"` + // Space: The type of file that can be created with these IDs. + Space string `json:"space,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "Ids") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Ids") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s GeneratedIds) MarshalJSON() ([]byte, error) { + type NoMethod GeneratedIds + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// Label: Representation of label and label fields. +type Label struct { + // Fields: A map of the fields on the label, keyed by the field's ID. + Fields map[string]LabelField `json:"fields,omitempty"` + // Id: The ID of the label. + Id string `json:"id,omitempty"` + // Kind: This is always drive#label + Kind string `json:"kind,omitempty"` + // RevisionId: The revision ID of the label. + RevisionId string `json:"revisionId,omitempty"` + // ForceSendFields is a list of field names (e.g. "Fields") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Fields") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s Label) MarshalJSON() ([]byte, error) { + type NoMethod Label + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// LabelField: Representation of field, which is a typed key-value pair. +type LabelField struct { + // DateString: Only present if valueType is dateString. RFC 3339 formatted + // date: YYYY-MM-DD. + DateString []string `json:"dateString,omitempty"` + // Id: The identifier of this label field. + Id string `json:"id,omitempty"` + // Integer: Only present if `valueType` is `integer`. + Integer googleapi.Int64s `json:"integer,omitempty"` + // Kind: This is always drive#labelField. + Kind string `json:"kind,omitempty"` + // Selection: Only present if `valueType` is `selection` + Selection []string `json:"selection,omitempty"` + // Text: Only present if `valueType` is `text`. + Text []string `json:"text,omitempty"` + // User: Only present if `valueType` is `user`. + User []*User `json:"user,omitempty"` + // ValueType: The field type. While new values may be supported in the future, + // the following are currently allowed: * `dateString` * `integer` * + // `selection` * `text` * `user` + ValueType string `json:"valueType,omitempty"` + // ForceSendFields is a list of field names (e.g. "DateString") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "DateString") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} - // Kind: This is always drive#fileList. +func (s LabelField) MarshalJSON() ([]byte, error) { + type NoMethod LabelField + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// LabelFieldModification: A modification to a label's field. +type LabelFieldModification struct { + // FieldId: The ID of the field to be modified. + FieldId string `json:"fieldId,omitempty"` + // Kind: This is always drive#labelFieldModification. Kind string `json:"kind,omitempty"` + // SetDateValues: Replaces the value of a dateString Field with these new + // values. The string must be in the RFC 3339 full-date format: YYYY-MM-DD. + SetDateValues []string `json:"setDateValues,omitempty"` + // SetIntegerValues: Replaces the value of an `integer` field with these new + // values. + SetIntegerValues googleapi.Int64s `json:"setIntegerValues,omitempty"` + // SetSelectionValues: Replaces a `selection` field with these new values. + SetSelectionValues []string `json:"setSelectionValues,omitempty"` + // SetTextValues: Sets the value of a `text` field. + SetTextValues []string `json:"setTextValues,omitempty"` + // SetUserValues: Replaces a `user` field with these new values. The values + // must be valid email addresses. + SetUserValues []string `json:"setUserValues,omitempty"` + // UnsetValues: Unsets the values for this field. + UnsetValues bool `json:"unsetValues,omitempty"` + // ForceSendFields is a list of field names (e.g. "FieldId") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "FieldId") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} - // NextPageToken: The page token for the next page of files. This will - // be absent if the end of the files list has been reached. +func (s LabelFieldModification) MarshalJSON() ([]byte, error) { + type NoMethod LabelFieldModification + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// LabelList: A list of labels applied to a file. +type LabelList struct { + // Kind: This is always drive#labelList + Kind string `json:"kind,omitempty"` + // Labels: The list of labels. + Labels []*Label `json:"labels,omitempty"` + // NextPageToken: The page token for the next page of labels. This field will + // be absent if the end of the list has been reached. If the token is rejected + // for any reason, it should be discarded, and pagination should be restarted + // from the first page of results. The page token is typically valid for + // several hours. However, if new items are added or removed, your expected + // results might differ. NextPageToken string `json:"nextPageToken,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "Kind") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Kind") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s LabelList) MarshalJSON() ([]byte, error) { + type NoMethod LabelList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// LabelModification: A modification to a label on a file. A LabelModification +// can be used to apply a label to a file, update an existing label on a file, +// or remove a label from a file. +type LabelModification struct { + // FieldModifications: The list of modifications to this label's fields. + FieldModifications []*LabelFieldModification `json:"fieldModifications,omitempty"` + // Kind: This is always drive#labelModification. + Kind string `json:"kind,omitempty"` + // LabelId: The ID of the label to modify. + LabelId string `json:"labelId,omitempty"` + // RemoveLabel: If true, the label will be removed from the file. + RemoveLabel bool `json:"removeLabel,omitempty"` + // ForceSendFields is a list of field names (e.g. "FieldModifications") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "FieldModifications") to include + // in API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s LabelModification) MarshalJSON() ([]byte, error) { + type NoMethod LabelModification + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// ListAccessProposalsResponse: The response to an Access Proposal list +// request. +type ListAccessProposalsResponse struct { + // AccessProposals: The list of Access Proposals. This field is only populated + // in v3 and v3beta. + AccessProposals []*AccessProposal `json:"accessProposals,omitempty"` + // NextPageToken: The continuation token for the next page of results. This + // will be absent if the end of the results list has been reached. If the token + // is rejected for any reason, it should be discarded, and pagination should be + // restarted from the first page of results. + NextPageToken string `json:"nextPageToken,omitempty"` - // ForceSendFields is a list of field names (e.g. "Files") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "AccessProposals") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "AccessProposals") to include in + // API requests with the JSON null value. By default, fields with empty values + // are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *FileList) MarshalJSON() ([]byte, error) { - type noMethod FileList - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s ListAccessProposalsResponse) MarshalJSON() ([]byte, error) { + type NoMethod ListAccessProposalsResponse + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// GeneratedIds: A list of generated file IDs which can be provided in -// create requests. -type GeneratedIds struct { - // Ids: The IDs generated for the requesting user in the specified - // space. - Ids []string `json:"ids,omitempty"` +// ListOperationsResponse: The response message for Operations.ListOperations. +type ListOperationsResponse struct { + // NextPageToken: The standard List next-page token. + NextPageToken string `json:"nextPageToken,omitempty"` + // Operations: A list of operations that matches the specified filter in the + // request. + Operations []*Operation `json:"operations,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "NextPageToken") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "NextPageToken") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s ListOperationsResponse) MarshalJSON() ([]byte, error) { + type NoMethod ListOperationsResponse + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} - // Kind: This is always drive#generatedIds +// ModifyLabelsRequest: A request to modify the set of labels on a file. This +// request may contain many modifications that will either all succeed or all +// fail atomically. +type ModifyLabelsRequest struct { + // Kind: This is always drive#modifyLabelsRequest. Kind string `json:"kind,omitempty"` + // LabelModifications: The list of modifications to apply to the labels on the + // file. + LabelModifications []*LabelModification `json:"labelModifications,omitempty"` + // ForceSendFields is a list of field names (e.g. "Kind") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Kind") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} - // Space: The type of file that can be created with these IDs. - Space string `json:"space,omitempty"` +func (s ModifyLabelsRequest) MarshalJSON() ([]byte, error) { + type NoMethod ModifyLabelsRequest + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// ModifyLabelsResponse: Response to a ModifyLabels request. This contains only +// those labels which were added or updated by the request. +type ModifyLabelsResponse struct { + // Kind: This is always drive#modifyLabelsResponse + Kind string `json:"kind,omitempty"` + // ModifiedLabels: The list of labels which were added or updated by the + // request. + ModifiedLabels []*Label `json:"modifiedLabels,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "Kind") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Kind") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s ModifyLabelsResponse) MarshalJSON() ([]byte, error) { + type NoMethod ModifyLabelsResponse + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} - // ForceSendFields is a list of field names (e.g. "Ids") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. +// Operation: This resource represents a long-running operation that is the +// result of a network API call. +type Operation struct { + // Done: If the value is `false`, it means the operation is still in progress. + // If `true`, the operation is completed, and either `error` or `response` is + // available. + Done bool `json:"done,omitempty"` + // Error: The error result of the operation in case of failure or cancellation. + Error *Status `json:"error,omitempty"` + // Metadata: Service-specific metadata associated with the operation. It + // typically contains progress information and common metadata such as create + // time. Some services might not provide such metadata. Any method that returns + // a long-running operation should document the metadata type, if any. + Metadata googleapi.RawMessage `json:"metadata,omitempty"` + // Name: The server-assigned name, which is only unique within the same service + // that originally returns it. If you use the default HTTP mapping, the `name` + // should be a resource name ending with `operations/{unique_id}`. + Name string `json:"name,omitempty"` + // Response: The normal, successful response of the operation. If the original + // method returns no data on success, such as `Delete`, the response is + // `google.protobuf.Empty`. If the original method is standard + // `Get`/`Create`/`Update`, the response should be the resource. For other + // methods, the response should have the type `XxxResponse`, where `Xxx` is the + // original method name. For example, if the original method name is + // `TakeSnapshot()`, the inferred response type is `TakeSnapshotResponse`. + Response googleapi.RawMessage `json:"response,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "Done") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Done") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *GeneratedIds) MarshalJSON() ([]byte, error) { - type noMethod GeneratedIds - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s Operation) MarshalJSON() ([]byte, error) { + type NoMethod Operation + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// Permission: A permission for a file. A permission grants a user, -// group, domain or the world access to a file or a folder hierarchy. +// Permission: A permission for a file. A permission grants a user, group, +// domain, or the world access to a file or a folder hierarchy. Some resource +// methods (such as `permissions.update`) require a `permissionId`. Use the +// `permissions.list` method to retrieve the ID for a file, folder, or shared +// drive. type Permission struct { - // AllowFileDiscovery: Whether the permission allows the file to be - // discovered through search. This is only applicable for permissions of - // type domain or anyone. + // AllowFileDiscovery: Whether the permission allows the file to be discovered + // through search. This is only applicable for permissions of type `domain` or + // `anyone`. AllowFileDiscovery bool `json:"allowFileDiscovery,omitempty"` - - // DisplayName: A displayable name for users, groups or domains. + // Deleted: Output only. Whether the account associated with this permission + // has been deleted. This field only pertains to user and group permissions. + Deleted bool `json:"deleted,omitempty"` + // DisplayName: Output only. The "pretty" name of the value of the permission. + // The following is a list of examples for each type of permission: * `user` - + // User's full name, as defined for their Google account, such as "Joe Smith." + // * `group` - Name of the Google Group, such as "The Company Administrators." + // * `domain` - String domain name, such as "thecompany.com." * `anyone` - No + // `displayName` is present. DisplayName string `json:"displayName,omitempty"` - // Domain: The domain to which this permission refers. Domain string `json:"domain,omitempty"` - // EmailAddress: The email address of the user or group to which this // permission refers. EmailAddress string `json:"emailAddress,omitempty"` - - // Id: The ID of this permission. This is a unique identifier for the - // grantee, and is published in User resources as permissionId. + // ExpirationTime: The time at which this permission will expire (RFC 3339 + // date-time). Expiration times have the following restrictions: - They can + // only be set on user and group permissions - The time must be in the future - + // The time cannot be more than a year in the future + ExpirationTime string `json:"expirationTime,omitempty"` + // Id: Output only. The ID of this permission. This is a unique identifier for + // the grantee, and is published in User resources as `permissionId`. IDs + // should be treated as opaque values. Id string `json:"id,omitempty"` - - // Kind: This is always drive#permission. + // Kind: Output only. Identifies what kind of resource this is. Value: the + // fixed string "drive#permission". Kind string `json:"kind,omitempty"` - - // PhotoLink: A link to the user's profile photo, if available. + // PendingOwner: Whether the account associated with this permission is a + // pending owner. Only populated for `user` type permissions for files that are + // not in a shared drive. + PendingOwner bool `json:"pendingOwner,omitempty"` + // PermissionDetails: Output only. Details of whether the permissions on this + // shared drive item are inherited or directly on this item. This is an + // output-only field which is present only for shared drive items. + PermissionDetails []*PermissionPermissionDetails `json:"permissionDetails,omitempty"` + // PhotoLink: Output only. A link to the user's profile photo, if available. PhotoLink string `json:"photoLink,omitempty"` - - // Role: The role granted by this permission. Valid values are: - // - owner - // - writer - // - commenter - // - reader + // Role: The role granted by this permission. While new values may be supported + // in the future, the following are currently allowed: * `owner` * `organizer` + // * `fileOrganizer` * `writer` * `commenter` * `reader` Role string `json:"role,omitempty"` - - // Type: The type of the grantee. Valid values are: - // - user - // - group - // - domain - // - anyone + // TeamDrivePermissionDetails: Output only. Deprecated: Output only. Use + // `permissionDetails` instead. + TeamDrivePermissionDetails []*PermissionTeamDrivePermissionDetails `json:"teamDrivePermissionDetails,omitempty"` + // Type: The type of the grantee. Valid values are: * `user` * `group` * + // `domain` * `anyone` When creating a permission, if `type` is `user` or + // `group`, you must provide an `emailAddress` for the user or group. When + // `type` is `domain`, you must provide a `domain`. There isn't extra + // information required for an `anyone` type. Type string `json:"type,omitempty"` + // View: Indicates the view for this permission. Only populated for permissions + // that belong to a view. 'published' is the only supported value. + View string `json:"view,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "AllowFileDiscovery") - // to unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "AllowFileDiscovery") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "AllowFileDiscovery") to include + // in API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s Permission) MarshalJSON() ([]byte, error) { + type NoMethod Permission + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +type PermissionPermissionDetails struct { + // Inherited: Output only. Whether this permission is inherited. This field is + // always populated. This is an output-only field. + Inherited bool `json:"inherited,omitempty"` + // InheritedFrom: Output only. The ID of the item from which this permission is + // inherited. This is an output-only field. + InheritedFrom string `json:"inheritedFrom,omitempty"` + // PermissionType: Output only. The permission type for this user. While new + // values may be added in future, the following are currently possible: * + // `file` * `member` + PermissionType string `json:"permissionType,omitempty"` + // Role: Output only. The primary role for this user. While new values may be + // added in the future, the following are currently possible: * `organizer` * + // `fileOrganizer` * `writer` * `commenter` * `reader` + Role string `json:"role,omitempty"` + // ForceSendFields is a list of field names (e.g. "Inherited") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Inherited") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s PermissionPermissionDetails) MarshalJSON() ([]byte, error) { + type NoMethod PermissionPermissionDetails + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +type PermissionTeamDrivePermissionDetails struct { + // Inherited: Deprecated: Output only. Use `permissionDetails/inherited` + // instead. + Inherited bool `json:"inherited,omitempty"` + // InheritedFrom: Deprecated: Output only. Use + // `permissionDetails/inheritedFrom` instead. + InheritedFrom string `json:"inheritedFrom,omitempty"` + // Role: Deprecated: Output only. Use `permissionDetails/role` instead. + Role string `json:"role,omitempty"` + // TeamDrivePermissionType: Deprecated: Output only. Use + // `permissionDetails/permissionType` instead. + TeamDrivePermissionType string `json:"teamDrivePermissionType,omitempty"` + // ForceSendFields is a list of field names (e.g. "Inherited") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Inherited") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *Permission) MarshalJSON() ([]byte, error) { - type noMethod Permission - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s PermissionTeamDrivePermissionDetails) MarshalJSON() ([]byte, error) { + type NoMethod PermissionTeamDrivePermissionDetails + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } // PermissionList: A list of permissions for a file. type PermissionList struct { - // Kind: This is always drive#permissionList. + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#permissionList". Kind string `json:"kind,omitempty"` - - // Permissions: The full list of permissions. + // NextPageToken: The page token for the next page of permissions. This field + // will be absent if the end of the permissions list has been reached. If the + // token is rejected for any reason, it should be discarded, and pagination + // should be restarted from the first page of results. The page token is + // typically valid for several hours. However, if new items are added or + // removed, your expected results might differ. + NextPageToken string `json:"nextPageToken,omitempty"` + // Permissions: The list of permissions. If nextPageToken is populated, then + // this list may be incomplete and an additional page of results should be + // fetched. Permissions []*Permission `json:"permissions,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Kind") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "Kind") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Kind") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *PermissionList) MarshalJSON() ([]byte, error) { - type noMethod PermissionList - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s PermissionList) MarshalJSON() ([]byte, error) { + type NoMethod PermissionList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// Reply: A reply to a comment on a file. +// Reply: A reply to a comment on a file. Some resource methods (such as +// `replies.update`) require a `replyId`. Use the `replies.list` method to +// retrieve the ID for a reply. type Reply struct { - // Action: The action the reply performed to the parent comment. Valid - // values are: - // - resolve - // - reopen + // Action: The action the reply performed to the parent comment. Valid values + // are: * `resolve` * `reopen` Action string `json:"action,omitempty"` - - // Author: The user who created the reply. + // Author: Output only. The author of the reply. The author's email address and + // permission ID will not be populated. Author *User `json:"author,omitempty"` - - // Content: The plain text content of the reply. This field is used for - // setting the content, while htmlContent should be displayed. This is - // required on creates if no action is specified. + // Content: The plain text content of the reply. This field is used for setting + // the content, while `htmlContent` should be displayed. This is required on + // creates if no `action` is specified. Content string `json:"content,omitempty"` - - // CreatedTime: The time at which the reply was created (RFC 3339 - // date-time). + // CreatedTime: The time at which the reply was created (RFC 3339 date-time). CreatedTime string `json:"createdTime,omitempty"` - - // Deleted: Whether the reply has been deleted. A deleted reply has no - // content. + // Deleted: Output only. Whether the reply has been deleted. A deleted reply + // has no content. Deleted bool `json:"deleted,omitempty"` - - // HtmlContent: The content of the reply with HTML formatting. + // HtmlContent: Output only. The content of the reply with HTML formatting. HtmlContent string `json:"htmlContent,omitempty"` - - // Id: The ID of the reply. + // Id: Output only. The ID of the reply. Id string `json:"id,omitempty"` - - // Kind: This is always drive#reply. + // Kind: Output only. Identifies what kind of resource this is. Value: the + // fixed string "drive#reply". Kind string `json:"kind,omitempty"` - - // ModifiedTime: The last time the reply was modified (RFC 3339 - // date-time). + // ModifiedTime: The last time the reply was modified (RFC 3339 date-time). ModifiedTime string `json:"modifiedTime,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Action") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "Action") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Action") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *Reply) MarshalJSON() ([]byte, error) { - type noMethod Reply - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s Reply) MarshalJSON() ([]byte, error) { + type NoMethod Reply + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } // ReplyList: A list of replies to a comment on a file. type ReplyList struct { - // Kind: This is always drive#replyList. + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#replyList". Kind string `json:"kind,omitempty"` - - // NextPageToken: The page token for the next page of replies. This will - // be absent if the end of the replies list has been reached. + // NextPageToken: The page token for the next page of replies. This will be + // absent if the end of the replies list has been reached. If the token is + // rejected for any reason, it should be discarded, and pagination should be + // restarted from the first page of results. The page token is typically valid + // for several hours. However, if new items are added or removed, your expected + // results might differ. NextPageToken string `json:"nextPageToken,omitempty"` - - // Replies: The page of replies. + // Replies: The list of replies. If nextPageToken is populated, then this list + // may be incomplete and an additional page of results should be fetched. Replies []*Reply `json:"replies,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Kind") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "Kind") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Kind") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s ReplyList) MarshalJSON() ([]byte, error) { + type NoMethod ReplyList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// ResolveAccessProposalRequest: Request message for resolving an +// AccessProposal on a file. +type ResolveAccessProposalRequest struct { + // Action: Required. The action to take on the AccessProposal. + // + // Possible values: + // "ACTION_UNSPECIFIED" - Unspecified action + // "ACCEPT" - The user accepts the proposal. Note: If this action is used, + // the `role` field must have at least one value. + // "DENY" - The user denies the proposal + Action string `json:"action,omitempty"` + // Role: Optional. The roles the approver has allowed, if any. Note: This field + // is required for the `ACCEPT` action. + Role []string `json:"role,omitempty"` + // SendNotification: Optional. Whether to send an email to the requester when + // the AccessProposal is denied or accepted. + SendNotification bool `json:"sendNotification,omitempty"` + // View: Optional. Indicates the view for this access proposal. This should + // only be set when the proposal belongs to a view. `published` is the only + // supported value. + View string `json:"view,omitempty"` + // ForceSendFields is a list of field names (e.g. "Action") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Action") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *ReplyList) MarshalJSON() ([]byte, error) { - type noMethod ReplyList - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s ResolveAccessProposalRequest) MarshalJSON() ([]byte, error) { + type NoMethod ResolveAccessProposalRequest + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// Revision: The metadata for a revision to a file. +// Revision: The metadata for a revision to a file. Some resource methods (such +// as `revisions.update`) require a `revisionId`. Use the `revisions.list` +// method to retrieve the ID for a revision. type Revision struct { - // Id: The ID of the revision. + // ExportLinks: Output only. Links for exporting Docs Editors files to specific + // formats. + ExportLinks map[string]string `json:"exportLinks,omitempty"` + // Id: Output only. The ID of the revision. Id string `json:"id,omitempty"` - - // KeepForever: Whether to keep this revision forever, even if it is no - // longer the head revision. If not set, the revision will be - // automatically purged 30 days after newer content is uploaded. This - // can be set on a maximum of 200 revisions for a file. - // This field is only applicable to files with binary content in Drive. + // KeepForever: Whether to keep this revision forever, even if it is no longer + // the head revision. If not set, the revision will be automatically purged 30 + // days after newer content is uploaded. This can be set on a maximum of 200 + // revisions for a file. This field is only applicable to files with binary + // content in Drive. KeepForever bool `json:"keepForever,omitempty"` - - // Kind: This is always drive#revision. + // Kind: Output only. Identifies what kind of resource this is. Value: the + // fixed string "drive#revision". Kind string `json:"kind,omitempty"` - - // LastModifyingUser: The last user to modify this revision. + // LastModifyingUser: Output only. The last user to modify this revision. This + // field is only populated when the last modification was performed by a + // signed-in user. LastModifyingUser *User `json:"lastModifyingUser,omitempty"` - - // Md5Checksum: The MD5 checksum of the revision's content. This is only - // applicable to files with binary content in Drive. + // Md5Checksum: Output only. The MD5 checksum of the revision's content. This + // is only applicable to files with binary content in Drive. Md5Checksum string `json:"md5Checksum,omitempty"` - - // MimeType: The MIME type of the revision. + // MimeType: Output only. The MIME type of the revision. MimeType string `json:"mimeType,omitempty"` - - // ModifiedTime: The last time the revision was modified (RFC 3339 - // date-time). + // ModifiedTime: The last time the revision was modified (RFC 3339 date-time). ModifiedTime string `json:"modifiedTime,omitempty"` - - // OriginalFilename: The original filename used to create this revision. - // This is only applicable to files with binary content in Drive. + // OriginalFilename: Output only. The original filename used to create this + // revision. This is only applicable to files with binary content in Drive. OriginalFilename string `json:"originalFilename,omitempty"` - - // PublishAuto: Whether subsequent revisions will be automatically - // republished. This is only applicable to Google Docs. + // PublishAuto: Whether subsequent revisions will be automatically republished. + // This is only applicable to Docs Editors files. PublishAuto bool `json:"publishAuto,omitempty"` - - // Published: Whether this revision is published. This is only - // applicable to Google Docs. + // Published: Whether this revision is published. This is only applicable to + // Docs Editors files. Published bool `json:"published,omitempty"` - - // PublishedOutsideDomain: Whether this revision is published outside - // the domain. This is only applicable to Google Docs. + // PublishedLink: Output only. A link to the published revision. This is only + // populated for Google Sites files. + PublishedLink string `json:"publishedLink,omitempty"` + // PublishedOutsideDomain: Whether this revision is published outside the + // domain. This is only applicable to Docs Editors files. PublishedOutsideDomain bool `json:"publishedOutsideDomain,omitempty"` - - // Size: The size of the revision's content in bytes. This is only + // Size: Output only. The size of the revision's content in bytes. This is only // applicable to files with binary content in Drive. Size int64 `json:"size,omitempty,string"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Id") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "ExportLinks") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "ExportLinks") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *Revision) MarshalJSON() ([]byte, error) { - type noMethod Revision - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s Revision) MarshalJSON() ([]byte, error) { + type NoMethod Revision + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } // RevisionList: A list of revisions of a file. type RevisionList struct { - // Kind: This is always drive#revisionList. + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#revisionList". Kind string `json:"kind,omitempty"` - - // Revisions: The full list of revisions. + // NextPageToken: The page token for the next page of revisions. This will be + // absent if the end of the revisions list has been reached. If the token is + // rejected for any reason, it should be discarded, and pagination should be + // restarted from the first page of results. The page token is typically valid + // for several hours. However, if new items are added or removed, your expected + // results might differ. + NextPageToken string `json:"nextPageToken,omitempty"` + // Revisions: The list of revisions. If nextPageToken is populated, then this + // list may be incomplete and an additional page of results should be fetched. Revisions []*Revision `json:"revisions,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` - - // ForceSendFields is a list of field names (e.g. "Kind") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // ForceSendFields is a list of field names (e.g. "Kind") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Kind") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *RevisionList) MarshalJSON() ([]byte, error) { - type noMethod RevisionList - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s RevisionList) MarshalJSON() ([]byte, error) { + type NoMethod RevisionList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } type StartPageToken struct { - // Kind: This is always drive#startPageToken. + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#startPageToken". Kind string `json:"kind,omitempty"` - - // StartPageToken: The starting page token for listing changes. + // StartPageToken: The starting page token for listing future changes. The page + // token doesn't expire. StartPageToken string `json:"startPageToken,omitempty"` - // ServerResponse contains the HTTP response code and headers from the - // server. + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "Kind") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Kind") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s StartPageToken) MarshalJSON() ([]byte, error) { + type NoMethod StartPageToken + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// Status: The `Status` type defines a logical error model that is suitable for +// different programming environments, including REST APIs and RPC APIs. It is +// used by gRPC (https://github.com/grpc). Each `Status` message contains three +// pieces of data: error code, error message, and error details. You can find +// out more about this error model and how to work with it in the API Design +// Guide (https://cloud.google.com/apis/design/errors). +type Status struct { + // Code: The status code, which should be an enum value of google.rpc.Code. + Code int64 `json:"code,omitempty"` + // Details: A list of messages that carry the error details. There is a common + // set of message types for APIs to use. + Details []googleapi.RawMessage `json:"details,omitempty"` + // Message: A developer-facing error message, which should be in English. Any + // user-facing error message should be localized and sent in the + // google.rpc.Status.details field, or localized by the client. + Message string `json:"message,omitempty"` + // ForceSendFields is a list of field names (e.g. "Code") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Code") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s Status) MarshalJSON() ([]byte, error) { + type NoMethod Status + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// TeamDrive: Deprecated: use the drive collection instead. +type TeamDrive struct { + // BackgroundImageFile: An image file and cropping parameters from which a + // background image for this Team Drive is set. This is a write only field; it + // can only be set on `drive.teamdrives.update` requests that don't set + // `themeId`. When specified, all fields of the `backgroundImageFile` must be + // set. + BackgroundImageFile *TeamDriveBackgroundImageFile `json:"backgroundImageFile,omitempty"` + // BackgroundImageLink: A short-lived link to this Team Drive's background + // image. + BackgroundImageLink string `json:"backgroundImageLink,omitempty"` + // Capabilities: Capabilities the current user has on this Team Drive. + Capabilities *TeamDriveCapabilities `json:"capabilities,omitempty"` + // ColorRgb: The color of this Team Drive as an RGB hex string. It can only be + // set on a `drive.teamdrives.update` request that does not set `themeId`. + ColorRgb string `json:"colorRgb,omitempty"` + // CreatedTime: The time at which the Team Drive was created (RFC 3339 + // date-time). + CreatedTime string `json:"createdTime,omitempty"` + // Id: The ID of this Team Drive which is also the ID of the top level folder + // of this Team Drive. + Id string `json:"id,omitempty"` + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#teamDrive". + Kind string `json:"kind,omitempty"` + // Name: The name of this Team Drive. + Name string `json:"name,omitempty"` + // OrgUnitId: The organizational unit of this shared drive. This field is only + // populated on `drives.list` responses when the `useDomainAdminAccess` + // parameter is set to `true`. + OrgUnitId string `json:"orgUnitId,omitempty"` + // Restrictions: A set of restrictions that apply to this Team Drive or items + // inside this Team Drive. + Restrictions *TeamDriveRestrictions `json:"restrictions,omitempty"` + // ThemeId: The ID of the theme from which the background image and color will + // be set. The set of possible `teamDriveThemes` can be retrieved from a + // `drive.about.get` response. When not specified on a + // `drive.teamdrives.create` request, a random theme is chosen from which the + // background image and color are set. This is a write-only field; it can only + // be set on requests that don't set `colorRgb` or `backgroundImageFile`. + ThemeId string `json:"themeId,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "BackgroundImageFile") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "BackgroundImageFile") to include + // in API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s TeamDrive) MarshalJSON() ([]byte, error) { + type NoMethod TeamDrive + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// TeamDriveBackgroundImageFile: An image file and cropping parameters from +// which a background image for this Team Drive is set. This is a write only +// field; it can only be set on `drive.teamdrives.update` requests that don't +// set `themeId`. When specified, all fields of the `backgroundImageFile` must +// be set. +type TeamDriveBackgroundImageFile struct { + // Id: The ID of an image file in Drive to use for the background image. + Id string `json:"id,omitempty"` + // Width: The width of the cropped image in the closed range of 0 to 1. This + // value represents the width of the cropped image divided by the width of the + // entire image. The height is computed by applying a width to height aspect + // ratio of 80 to 9. The resulting image must be at least 1280 pixels wide and + // 144 pixels high. + Width float64 `json:"width,omitempty"` + // XCoordinate: The X coordinate of the upper left corner of the cropping area + // in the background image. This is a value in the closed range of 0 to 1. This + // value represents the horizontal distance from the left side of the entire + // image to the left side of the cropping area divided by the width of the + // entire image. + XCoordinate float64 `json:"xCoordinate,omitempty"` + // YCoordinate: The Y coordinate of the upper left corner of the cropping area + // in the background image. This is a value in the closed range of 0 to 1. This + // value represents the vertical distance from the top side of the entire image + // to the top side of the cropping area divided by the height of the entire + // image. + YCoordinate float64 `json:"yCoordinate,omitempty"` + // ForceSendFields is a list of field names (e.g. "Id") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Id") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s TeamDriveBackgroundImageFile) MarshalJSON() ([]byte, error) { + type NoMethod TeamDriveBackgroundImageFile + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} - // ForceSendFields is a list of field names (e.g. "Kind") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. +func (s *TeamDriveBackgroundImageFile) UnmarshalJSON(data []byte) error { + type NoMethod TeamDriveBackgroundImageFile + var s1 struct { + Width gensupport.JSONFloat64 `json:"width"` + XCoordinate gensupport.JSONFloat64 `json:"xCoordinate"` + YCoordinate gensupport.JSONFloat64 `json:"yCoordinate"` + *NoMethod + } + s1.NoMethod = (*NoMethod)(s) + if err := json.Unmarshal(data, &s1); err != nil { + return err + } + s.Width = float64(s1.Width) + s.XCoordinate = float64(s1.XCoordinate) + s.YCoordinate = float64(s1.YCoordinate) + return nil +} + +// TeamDriveCapabilities: Capabilities the current user has on this Team Drive. +type TeamDriveCapabilities struct { + // CanAddChildren: Whether the current user can add children to folders in this + // Team Drive. + CanAddChildren bool `json:"canAddChildren,omitempty"` + // CanChangeCopyRequiresWriterPermissionRestriction: Whether the current user + // can change the `copyRequiresWriterPermission` restriction of this Team + // Drive. + CanChangeCopyRequiresWriterPermissionRestriction bool `json:"canChangeCopyRequiresWriterPermissionRestriction,omitempty"` + // CanChangeDomainUsersOnlyRestriction: Whether the current user can change the + // `domainUsersOnly` restriction of this Team Drive. + CanChangeDomainUsersOnlyRestriction bool `json:"canChangeDomainUsersOnlyRestriction,omitempty"` + // CanChangeSharingFoldersRequiresOrganizerPermissionRestriction: Whether the + // current user can change the `sharingFoldersRequiresOrganizerPermission` + // restriction of this Team Drive. + CanChangeSharingFoldersRequiresOrganizerPermissionRestriction bool `json:"canChangeSharingFoldersRequiresOrganizerPermissionRestriction,omitempty"` + // CanChangeTeamDriveBackground: Whether the current user can change the + // background of this Team Drive. + CanChangeTeamDriveBackground bool `json:"canChangeTeamDriveBackground,omitempty"` + // CanChangeTeamMembersOnlyRestriction: Whether the current user can change the + // `teamMembersOnly` restriction of this Team Drive. + CanChangeTeamMembersOnlyRestriction bool `json:"canChangeTeamMembersOnlyRestriction,omitempty"` + // CanComment: Whether the current user can comment on files in this Team + // Drive. + CanComment bool `json:"canComment,omitempty"` + // CanCopy: Whether the current user can copy files in this Team Drive. + CanCopy bool `json:"canCopy,omitempty"` + // CanDeleteChildren: Whether the current user can delete children from folders + // in this Team Drive. + CanDeleteChildren bool `json:"canDeleteChildren,omitempty"` + // CanDeleteTeamDrive: Whether the current user can delete this Team Drive. + // Attempting to delete the Team Drive may still fail if there are untrashed + // items inside the Team Drive. + CanDeleteTeamDrive bool `json:"canDeleteTeamDrive,omitempty"` + // CanDownload: Whether the current user can download files in this Team Drive. + CanDownload bool `json:"canDownload,omitempty"` + // CanEdit: Whether the current user can edit files in this Team Drive + CanEdit bool `json:"canEdit,omitempty"` + // CanListChildren: Whether the current user can list the children of folders + // in this Team Drive. + CanListChildren bool `json:"canListChildren,omitempty"` + // CanManageMembers: Whether the current user can add members to this Team + // Drive or remove them or change their role. + CanManageMembers bool `json:"canManageMembers,omitempty"` + // CanReadRevisions: Whether the current user can read the revisions resource + // of files in this Team Drive. + CanReadRevisions bool `json:"canReadRevisions,omitempty"` + // CanRemoveChildren: Deprecated: Use `canDeleteChildren` or `canTrashChildren` + // instead. + CanRemoveChildren bool `json:"canRemoveChildren,omitempty"` + // CanRename: Whether the current user can rename files or folders in this Team + // Drive. + CanRename bool `json:"canRename,omitempty"` + // CanRenameTeamDrive: Whether the current user can rename this Team Drive. + CanRenameTeamDrive bool `json:"canRenameTeamDrive,omitempty"` + // CanResetTeamDriveRestrictions: Whether the current user can reset the Team + // Drive restrictions to defaults. + CanResetTeamDriveRestrictions bool `json:"canResetTeamDriveRestrictions,omitempty"` + // CanShare: Whether the current user can share files or folders in this Team + // Drive. + CanShare bool `json:"canShare,omitempty"` + // CanTrashChildren: Whether the current user can trash children from folders + // in this Team Drive. + CanTrashChildren bool `json:"canTrashChildren,omitempty"` + // ForceSendFields is a list of field names (e.g. "CanAddChildren") to + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "CanAddChildren") to include in + // API requests with the JSON null value. By default, fields with empty values + // are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s TeamDriveCapabilities) MarshalJSON() ([]byte, error) { + type NoMethod TeamDriveCapabilities + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// TeamDriveRestrictions: A set of restrictions that apply to this Team Drive +// or items inside this Team Drive. +type TeamDriveRestrictions struct { + // AdminManagedRestrictions: Whether administrative privileges on this Team + // Drive are required to modify restrictions. + AdminManagedRestrictions bool `json:"adminManagedRestrictions,omitempty"` + // CopyRequiresWriterPermission: Whether the options to copy, print, or + // download files inside this Team Drive, should be disabled for readers and + // commenters. When this restriction is set to `true`, it will override the + // similarly named field to `true` for any file inside this Team Drive. + CopyRequiresWriterPermission bool `json:"copyRequiresWriterPermission,omitempty"` + // DomainUsersOnly: Whether access to this Team Drive and items inside this + // Team Drive is restricted to users of the domain to which this Team Drive + // belongs. This restriction may be overridden by other sharing policies + // controlled outside of this Team Drive. + DomainUsersOnly bool `json:"domainUsersOnly,omitempty"` + // SharingFoldersRequiresOrganizerPermission: If true, only users with the + // organizer role can share folders. If false, users with either the organizer + // role or the file organizer role can share folders. + SharingFoldersRequiresOrganizerPermission bool `json:"sharingFoldersRequiresOrganizerPermission,omitempty"` + // TeamMembersOnly: Whether access to items inside this Team Drive is + // restricted to members of this Team Drive. + TeamMembersOnly bool `json:"teamMembersOnly,omitempty"` + // ForceSendFields is a list of field names (e.g. "AdminManagedRestrictions") + // to unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "AdminManagedRestrictions") to + // include in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *StartPageToken) MarshalJSON() ([]byte, error) { - type noMethod StartPageToken - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s TeamDriveRestrictions) MarshalJSON() ([]byte, error) { + type NoMethod TeamDriveRestrictions + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) +} + +// TeamDriveList: A list of Team Drives. +type TeamDriveList struct { + // Kind: Identifies what kind of resource this is. Value: the fixed string + // "drive#teamDriveList". + Kind string `json:"kind,omitempty"` + // NextPageToken: The page token for the next page of Team Drives. This will be + // absent if the end of the Team Drives list has been reached. If the token is + // rejected for any reason, it should be discarded, and pagination should be + // restarted from the first page of results. The page token is typically valid + // for several hours. However, if new items are added or removed, your expected + // results might differ. + NextPageToken string `json:"nextPageToken,omitempty"` + // TeamDrives: The list of Team Drives. If nextPageToken is populated, then + // this list may be incomplete and an additional page of results should be + // fetched. + TeamDrives []*TeamDrive `json:"teamDrives,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the server. + googleapi.ServerResponse `json:"-"` + // ForceSendFields is a list of field names (e.g. "Kind") to unconditionally + // include in API requests. By default, fields with empty or default values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. + ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "Kind") to include in API requests + // with the JSON null value. By default, fields with empty values are omitted + // from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` +} + +func (s TeamDriveList) MarshalJSON() ([]byte, error) { + type NoMethod TeamDriveList + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } // User: Information about a Drive user. type User struct { - // DisplayName: A plain text displayable name for this user. + // DisplayName: Output only. A plain text displayable name for this user. DisplayName string `json:"displayName,omitempty"` - - // EmailAddress: The email address of the user. This may not be present - // in certain contexts if the user has not made their email address + // EmailAddress: Output only. The email address of the user. This may not be + // present in certain contexts if the user has not made their email address // visible to the requester. EmailAddress string `json:"emailAddress,omitempty"` - - // Kind: This is always drive#user. + // Kind: Output only. Identifies what kind of resource this is. Value: the + // fixed string "drive#user". Kind string `json:"kind,omitempty"` - - // Me: Whether this user is the requesting user. + // Me: Output only. Whether this user is the requesting user. Me bool `json:"me,omitempty"` - - // PermissionId: The user's ID as visible in Permission resources. + // PermissionId: Output only. The user's ID as visible in Permission resources. PermissionId string `json:"permissionId,omitempty"` - - // PhotoLink: A link to the user's profile photo, if available. + // PhotoLink: Output only. A link to the user's profile photo, if available. PhotoLink string `json:"photoLink,omitempty"` - // ForceSendFields is a list of field names (e.g. "DisplayName") to - // unconditionally include in API requests. By default, fields with - // empty values are omitted from API requests. However, any non-pointer, - // non-interface field appearing in ForceSendFields will be sent to the - // server regardless of whether the field is empty or not. This may be - // used to include empty fields in Patch requests. + // unconditionally include in API requests. By default, fields with empty or + // default values are omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-ForceSendFields for more + // details. ForceSendFields []string `json:"-"` + // NullFields is a list of field names (e.g. "DisplayName") to include in API + // requests with the JSON null value. By default, fields with empty values are + // omitted from API requests. See + // https://pkg.go.dev/google.golang.org/api#hdr-NullFields for more details. + NullFields []string `json:"-"` } -func (s *User) MarshalJSON() ([]byte, error) { - type noMethod User - raw := noMethod(*s) - return gensupport.MarshalJSON(raw, s.ForceSendFields) +func (s User) MarshalJSON() ([]byte, error) { + type NoMethod User + return gensupport.MarshalJSON(NoMethod(s), s.ForceSendFields, s.NullFields) } -// method id "drive.about.get": - type AboutGetCall struct { s *Service urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } // Get: Gets information about the user, the user's Drive, and system @@ -1370,55 +3222,59 @@ func (r *AboutService) Get() *AboutGetCall { } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. func (c *AboutGetCall) Fields(s ...googleapi.Field) *AboutGetCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. func (c *AboutGetCall) IfNoneMatch(entityTag string) *AboutGetCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. +// Context sets the context to be used in this call's Do method. func (c *AboutGetCall) Context(ctx context.Context) *AboutGetCall { c.ctx_ = ctx return c } +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *AboutGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + func (c *AboutGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") urls := googleapi.ResolveRelative(c.s.BasePath, "about") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - googleapi.SetOpaque(req.URL) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) - } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) } // Do executes the "drive.about.get" call. -// Exactly one of *About or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *About.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. +// Any non-2xx status code is an error. Response headers are in either +// *About.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. func (c *AboutGetCall) Do(opts ...googleapi.CallOption) (*About, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") @@ -1426,17 +3282,17 @@ func (c *AboutGetCall) Do(opts ...googleapi.CallOption) (*About, error) { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } ret := &About{ ServerResponse: googleapi.ServerResponse{ @@ -1444,1161 +3300,4004 @@ func (c *AboutGetCall) Do(opts ...googleapi.CallOption) (*About, error) { HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Gets information about the user, the user's Drive, and system capabilities.", - // "httpMethod": "GET", - // "id": "drive.about.get", - // "path": "about", - // "response": { - // "$ref": "About" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// method id "drive.changes.getStartPageToken": +} -type ChangesGetStartPageTokenCall struct { +type AccessproposalsGetCall struct { s *Service + fileId string + proposalId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// GetStartPageToken: Gets the starting pageToken for listing future -// changes. -func (r *ChangesService) GetStartPageToken() *ChangesGetStartPageTokenCall { - c := &ChangesGetStartPageTokenCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Get: Retrieves an AccessProposal by ID. +// +// - fileId: The id of the item the request is on. +// - proposalId: The id of the access proposal to resolve. +func (r *AccessproposalsService) Get(fileId string, proposalId string) *AccessproposalsGetCall { + c := &AccessproposalsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.proposalId = proposalId return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *ChangesGetStartPageTokenCall) Fields(s ...googleapi.Field) *ChangesGetStartPageTokenCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *AccessproposalsGetCall) Fields(s ...googleapi.Field) *AccessproposalsGetCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *ChangesGetStartPageTokenCall) IfNoneMatch(entityTag string) *ChangesGetStartPageTokenCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *AccessproposalsGetCall) IfNoneMatch(entityTag string) *AccessproposalsGetCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *ChangesGetStartPageTokenCall) Context(ctx context.Context) *ChangesGetStartPageTokenCall { +// Context sets the context to be used in this call's Do method. +func (c *AccessproposalsGetCall) Context(ctx context.Context) *AccessproposalsGetCall { c.ctx_ = ctx return c } -func (c *ChangesGetStartPageTokenCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *AccessproposalsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AccessproposalsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "changes/startPageToken") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/accessproposals/{proposalId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - googleapi.SetOpaque(req.URL) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + "proposalId": c.proposalId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.changes.getStartPageToken" call. -// Exactly one of *StartPageToken or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *StartPageToken.ServerResponse.Header or (if a response was returned -// at all) in error.(*googleapi.Error).Header. Use -// googleapi.IsNotModified to check whether the returned error was -// because http.StatusNotModified was returned. -func (c *ChangesGetStartPageTokenCall) Do(opts ...googleapi.CallOption) (*StartPageToken, error) { +// Do executes the "drive.accessproposals.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *AccessProposal.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *AccessproposalsGetCall) Do(opts ...googleapi.CallOption) (*AccessProposal, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &StartPageToken{ + ret := &AccessProposal{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Gets the starting pageToken for listing future changes.", - // "httpMethod": "GET", - // "id": "drive.changes.getStartPageToken", - // "path": "changes/startPageToken", - // "response": { - // "$ref": "StartPageToken" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// method id "drive.changes.list": +} -type ChangesListCall struct { +type AccessproposalsListCall struct { s *Service + fileId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// List: Lists changes for a user. -func (r *ChangesService) List(pageToken string) *ChangesListCall { - c := &ChangesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.urlParams_.Set("pageToken", pageToken) - return c -} - -// IncludeRemoved sets the optional parameter "includeRemoved": Whether -// to include changes indicating that items have left the view of the -// changes list, for example by deletion or lost access. -func (c *ChangesListCall) IncludeRemoved(includeRemoved bool) *ChangesListCall { - c.urlParams_.Set("includeRemoved", fmt.Sprint(includeRemoved)) +// List: List the AccessProposals on a file. Note: Only approvers are able to +// list AccessProposals on a file. If the user is not an approver, returns a +// 403. +// +// - fileId: The id of the item the request is on. +func (r *AccessproposalsService) List(fileId string) *AccessproposalsListCall { + c := &AccessproposalsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId return c } -// PageSize sets the optional parameter "pageSize": The maximum number -// of changes to return per page. -func (c *ChangesListCall) PageSize(pageSize int64) *ChangesListCall { +// PageSize sets the optional parameter "pageSize": The number of results per +// page +func (c *AccessproposalsListCall) PageSize(pageSize int64) *AccessproposalsListCall { c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) return c } -// RestrictToMyDrive sets the optional parameter "restrictToMyDrive": -// Whether to restrict the results to changes inside the My Drive -// hierarchy. This omits changes to files such as those in the -// Application Data folder or shared files which have not been added to -// My Drive. -func (c *ChangesListCall) RestrictToMyDrive(restrictToMyDrive bool) *ChangesListCall { - c.urlParams_.Set("restrictToMyDrive", fmt.Sprint(restrictToMyDrive)) - return c -} - -// Spaces sets the optional parameter "spaces": A comma-separated list -// of spaces to query within the user corpus. Supported values are -// 'drive', 'appDataFolder' and 'photos'. -func (c *ChangesListCall) Spaces(spaces string) *ChangesListCall { - c.urlParams_.Set("spaces", spaces) +// PageToken sets the optional parameter "pageToken": The continuation token on +// the list of access requests. +func (c *AccessproposalsListCall) PageToken(pageToken string) *AccessproposalsListCall { + c.urlParams_.Set("pageToken", pageToken) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *ChangesListCall) Fields(s ...googleapi.Field) *ChangesListCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *AccessproposalsListCall) Fields(s ...googleapi.Field) *AccessproposalsListCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *ChangesListCall) IfNoneMatch(entityTag string) *ChangesListCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *AccessproposalsListCall) IfNoneMatch(entityTag string) *AccessproposalsListCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *ChangesListCall) Context(ctx context.Context) *ChangesListCall { +// Context sets the context to be used in this call's Do method. +func (c *AccessproposalsListCall) Context(ctx context.Context) *AccessproposalsListCall { c.ctx_ = ctx return c } -func (c *ChangesListCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *AccessproposalsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AccessproposalsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "changes") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/accessproposals") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - googleapi.SetOpaque(req.URL) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) - } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.changes.list" call. -// Exactly one of *ChangeList or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *ChangeList.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because +// Do executes the "drive.accessproposals.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *ListAccessProposalsResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was because // http.StatusNotModified was returned. -func (c *ChangesListCall) Do(opts ...googleapi.CallOption) (*ChangeList, error) { +func (c *AccessproposalsListCall) Do(opts ...googleapi.CallOption) (*ListAccessProposalsResponse, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &ChangeList{ + ret := &ListAccessProposalsResponse{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Lists changes for a user.", - // "httpMethod": "GET", - // "id": "drive.changes.list", - // "parameterOrder": [ - // "pageToken" - // ], - // "parameters": { - // "includeRemoved": { - // "default": "true", - // "description": "Whether to include changes indicating that items have left the view of the changes list, for example by deletion or lost access.", - // "location": "query", - // "type": "boolean" - // }, - // "pageSize": { - // "default": "100", - // "description": "The maximum number of changes to return per page.", - // "format": "int32", - // "location": "query", - // "maximum": "1000", - // "minimum": "1", - // "type": "integer" - // }, - // "pageToken": { - // "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response or to the response from the getStartPageToken method.", - // "location": "query", - // "required": true, - // "type": "string" - // }, - // "restrictToMyDrive": { - // "default": "false", - // "description": "Whether to restrict the results to changes inside the My Drive hierarchy. This omits changes to files such as those in the Application Data folder or shared files which have not been added to My Drive.", - // "location": "query", - // "type": "boolean" - // }, - // "spaces": { - // "default": "drive", - // "description": "A comma-separated list of spaces to query within the user corpus. Supported values are 'drive', 'appDataFolder' and 'photos'.", - // "location": "query", - // "type": "string" - // } - // }, - // "path": "changes", - // "response": { - // "$ref": "ChangeList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ], - // "supportsSubscription": true - // } - -} - -// method id "drive.changes.watch": +} -type ChangesWatchCall struct { - s *Service - channel *Channel - urlParams_ gensupport.URLParams - ctx_ context.Context +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *AccessproposalsListCall) Pages(ctx context.Context, f func(*ListAccessProposalsResponse) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } } -// Watch: Subscribes to changes for a user. -func (r *ChangesService) Watch(pageToken string, channel *Channel) *ChangesWatchCall { - c := &ChangesWatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.urlParams_.Set("pageToken", pageToken) - c.channel = channel - return c +type AccessproposalsResolveCall struct { + s *Service + fileId string + proposalId string + resolveaccessproposalrequest *ResolveAccessProposalRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header } -// IncludeRemoved sets the optional parameter "includeRemoved": Whether -// to include changes indicating that items have left the view of the -// changes list, for example by deletion or lost access. -func (c *ChangesWatchCall) IncludeRemoved(includeRemoved bool) *ChangesWatchCall { - c.urlParams_.Set("includeRemoved", fmt.Sprint(includeRemoved)) +// Resolve: Used to approve or deny an Access Proposal. +// +// - fileId: The id of the item the request is on. +// - proposalId: The id of the access proposal to resolve. +func (r *AccessproposalsService) Resolve(fileId string, proposalId string, resolveaccessproposalrequest *ResolveAccessProposalRequest) *AccessproposalsResolveCall { + c := &AccessproposalsResolveCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.proposalId = proposalId + c.resolveaccessproposalrequest = resolveaccessproposalrequest return c } -// PageSize sets the optional parameter "pageSize": The maximum number -// of changes to return per page. -func (c *ChangesWatchCall) PageSize(pageSize int64) *ChangesWatchCall { - c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *AccessproposalsResolveCall) Fields(s ...googleapi.Field) *AccessproposalsResolveCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// RestrictToMyDrive sets the optional parameter "restrictToMyDrive": -// Whether to restrict the results to changes inside the My Drive -// hierarchy. This omits changes to files such as those in the -// Application Data folder or shared files which have not been added to -// My Drive. -func (c *ChangesWatchCall) RestrictToMyDrive(restrictToMyDrive bool) *ChangesWatchCall { - c.urlParams_.Set("restrictToMyDrive", fmt.Sprint(restrictToMyDrive)) +// Context sets the context to be used in this call's Do method. +func (c *AccessproposalsResolveCall) Context(ctx context.Context) *AccessproposalsResolveCall { + c.ctx_ = ctx return c } -// Spaces sets the optional parameter "spaces": A comma-separated list -// of spaces to query within the user corpus. Supported values are -// 'drive', 'appDataFolder' and 'photos'. -func (c *ChangesWatchCall) Spaces(spaces string) *ChangesWatchCall { - c.urlParams_.Set("spaces", spaces) +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *AccessproposalsResolveCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AccessproposalsResolveCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.resolveaccessproposalrequest) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/accessproposals/{proposalId}:resolve") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + "proposalId": c.proposalId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.accessproposals.resolve" call. +func (c *AccessproposalsResolveCall) Do(opts ...googleapi.CallOption) error { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if err != nil { + return err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return gensupport.WrapError(err) + } + return nil +} + +type AppsGetCall struct { + s *Service + appId string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Gets a specific app. +// +// - appId: The ID of the app. +func (r *AppsService) Get(appId string) *AppsGetCall { + c := &AppsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.appId = appId return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *ChangesWatchCall) Fields(s ...googleapi.Field) *ChangesWatchCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *AppsGetCall) Fields(s ...googleapi.Field) *AppsGetCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *ChangesWatchCall) Context(ctx context.Context) *ChangesWatchCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *AppsGetCall) IfNoneMatch(entityTag string) *AppsGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *AppsGetCall) Context(ctx context.Context) *AppsGetCall { c.ctx_ = ctx return c } -func (c *ChangesWatchCall) doRequest(alt string) (*http.Response, error) { - var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.channel) - if err != nil { - return nil, err +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *AppsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AppsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) } - ctype := "application/json" + var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "changes/watch") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "apps/{appId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) - googleapi.SetOpaque(req.URL) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "appId": c.appId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.changes.watch" call. -// Exactly one of *Channel or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Channel.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *ChangesWatchCall) Do(opts ...googleapi.CallOption) (*Channel, error) { +// Do executes the "drive.apps.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *App.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *AppsGetCall) Do(opts ...googleapi.CallOption) (*App, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Channel{ + ret := &App{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Subscribes to changes for a user.", - // "httpMethod": "POST", - // "id": "drive.changes.watch", - // "parameterOrder": [ - // "pageToken" - // ], - // "parameters": { - // "includeRemoved": { - // "default": "true", - // "description": "Whether to include changes indicating that items have left the view of the changes list, for example by deletion or lost access.", - // "location": "query", - // "type": "boolean" - // }, - // "pageSize": { - // "default": "100", - // "description": "The maximum number of changes to return per page.", - // "format": "int32", - // "location": "query", - // "maximum": "1000", - // "minimum": "1", - // "type": "integer" - // }, - // "pageToken": { - // "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response or to the response from the getStartPageToken method.", - // "location": "query", - // "required": true, - // "type": "string" - // }, - // "restrictToMyDrive": { - // "default": "false", - // "description": "Whether to restrict the results to changes inside the My Drive hierarchy. This omits changes to files such as those in the Application Data folder or shared files which have not been added to My Drive.", - // "location": "query", - // "type": "boolean" - // }, - // "spaces": { - // "default": "drive", - // "description": "A comma-separated list of spaces to query within the user corpus. Supported values are 'drive', 'appDataFolder' and 'photos'.", - // "location": "query", - // "type": "string" - // } - // }, - // "path": "changes/watch", - // "request": { - // "$ref": "Channel", - // "parameterName": "resource" - // }, - // "response": { - // "$ref": "Channel" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ], - // "supportsSubscription": true - // } - -} - -// method id "drive.channels.stop": - -type ChannelsStopCall struct { - s *Service - channel *Channel - urlParams_ gensupport.URLParams - ctx_ context.Context } -// Stop: Stop watching resources through this channel -func (r *ChannelsService) Stop(channel *Channel) *ChannelsStopCall { - c := &ChannelsStopCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.channel = channel - return c +type AppsListCall struct { + s *Service + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header } -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *ChannelsStopCall) Fields(s ...googleapi.Field) *ChannelsStopCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) +// List: Lists a user's installed apps. +func (r *AppsService) List() *AppsListCall { + c := &AppsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *ChannelsStopCall) Context(ctx context.Context) *ChannelsStopCall { - c.ctx_ = ctx +// AppFilterExtensions sets the optional parameter "appFilterExtensions": A +// comma-separated list of file extensions to limit returned results. All +// results within the given app query scope which can open any of the given +// file extensions are included in the response. If `appFilterMimeTypes` are +// provided as well, the result is a union of the two resulting app lists. +func (c *AppsListCall) AppFilterExtensions(appFilterExtensions string) *AppsListCall { + c.urlParams_.Set("appFilterExtensions", appFilterExtensions) return c } -func (c *ChannelsStopCall) doRequest(alt string) (*http.Response, error) { - var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.channel) - if err != nil { - return nil, err - } - ctype := "application/json" - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "channels/stop") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) - googleapi.SetOpaque(req.URL) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) -} - -// Do executes the "drive.channels.stop" call. -func (c *ChannelsStopCall) Do(opts ...googleapi.CallOption) error { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if err != nil { - return err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return err - } - return nil - // { - // "description": "Stop watching resources through this channel", - // "httpMethod": "POST", - // "id": "drive.channels.stop", - // "path": "channels/stop", - // "request": { - // "$ref": "Channel", - // "parameterName": "resource" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// method id "drive.comments.create": - -type CommentsCreateCall struct { - s *Service - fileId string - comment *Comment - urlParams_ gensupport.URLParams - ctx_ context.Context +// AppFilterMimeTypes sets the optional parameter "appFilterMimeTypes": A +// comma-separated list of file extensions to limit returned results. All +// results within the given app query scope which can open any of the given +// MIME types will be included in the response. If `appFilterExtensions` are +// provided as well, the result is a union of the two resulting app lists. +func (c *AppsListCall) AppFilterMimeTypes(appFilterMimeTypes string) *AppsListCall { + c.urlParams_.Set("appFilterMimeTypes", appFilterMimeTypes) + return c } -// Create: Creates a new comment on a file. -func (r *CommentsService) Create(fileId string, comment *Comment) *CommentsCreateCall { - c := &CommentsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId - c.comment = comment +// LanguageCode sets the optional parameter "languageCode": A language or +// locale code, as defined by BCP 47, with some extensions from Unicode's LDML +// format (http://www.unicode.org/reports/tr35/). +func (c *AppsListCall) LanguageCode(languageCode string) *AppsListCall { + c.urlParams_.Set("languageCode", languageCode) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *CommentsCreateCall) Fields(s ...googleapi.Field) *CommentsCreateCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *AppsListCall) Fields(s ...googleapi.Field) *AppsListCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *CommentsCreateCall) Context(ctx context.Context) *CommentsCreateCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *AppsListCall) IfNoneMatch(entityTag string) *AppsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *AppsListCall) Context(ctx context.Context) *AppsListCall { c.ctx_ = ctx return c } -func (c *CommentsCreateCall) doRequest(alt string) (*http.Response, error) { - var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.comment) - if err != nil { - return nil, err +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *AppsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *AppsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) } - ctype := "application/json" + var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "apps") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) - googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - }) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.comments.create" call. -// Exactly one of *Comment or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Comment.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *CommentsCreateCall) Do(opts ...googleapi.CallOption) (*Comment, error) { +// Do executes the "drive.apps.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *AppList.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *AppsListCall) Do(opts ...googleapi.CallOption) (*AppList, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Comment{ + ret := &AppList{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Creates a new comment on a file.", - // "httpMethod": "POST", - // "id": "drive.comments.create", - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/comments", - // "request": { - // "$ref": "Comment" - // }, - // "response": { - // "$ref": "Comment" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.comments.delete": +} -type CommentsDeleteCall struct { - s *Service - fileId string - commentId string - urlParams_ gensupport.URLParams - ctx_ context.Context +type ChangesGetStartPageTokenCall struct { + s *Service + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header } -// Delete: Deletes a comment. -func (r *CommentsService) Delete(fileId string, commentId string) *CommentsDeleteCall { - c := &CommentsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId +// GetStartPageToken: Gets the starting pageToken for listing future changes. +func (r *ChangesService) GetStartPageToken() *ChangesGetStartPageTokenCall { + c := &ChangesGetStartPageTokenCall{s: r.s, urlParams_: make(gensupport.URLParams)} + return c +} + +// DriveId sets the optional parameter "driveId": The ID of the shared drive +// for which the starting pageToken for listing future changes from that shared +// drive will be returned. +func (c *ChangesGetStartPageTokenCall) DriveId(driveId string) *ChangesGetStartPageTokenCall { + c.urlParams_.Set("driveId", driveId) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *ChangesGetStartPageTokenCall) SupportsAllDrives(supportsAllDrives bool) *ChangesGetStartPageTokenCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *ChangesGetStartPageTokenCall) SupportsTeamDrives(supportsTeamDrives bool) *ChangesGetStartPageTokenCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) + return c +} + +// TeamDriveId sets the optional parameter "teamDriveId": Deprecated: Use +// `driveId` instead. +func (c *ChangesGetStartPageTokenCall) TeamDriveId(teamDriveId string) *ChangesGetStartPageTokenCall { + c.urlParams_.Set("teamDriveId", teamDriveId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *ChangesGetStartPageTokenCall) Fields(s ...googleapi.Field) *ChangesGetStartPageTokenCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *ChangesGetStartPageTokenCall) IfNoneMatch(entityTag string) *ChangesGetStartPageTokenCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *ChangesGetStartPageTokenCall) Context(ctx context.Context) *ChangesGetStartPageTokenCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *ChangesGetStartPageTokenCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ChangesGetStartPageTokenCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "changes/startPageToken") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.changes.getStartPageToken" call. +// Any non-2xx status code is an error. Response headers are in either +// *StartPageToken.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *ChangesGetStartPageTokenCall) Do(opts ...googleapi.CallOption) (*StartPageToken, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &StartPageToken{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type ChangesListCall struct { + s *Service + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists the changes for a user or shared drive. +// +// - pageToken: The token for continuing a previous list request on the next +// page. This should be set to the value of 'nextPageToken' from the previous +// response or to the response from the getStartPageToken method. +func (r *ChangesService) List(pageToken string) *ChangesListCall { + c := &ChangesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// DriveId sets the optional parameter "driveId": The shared drive from which +// changes will be returned. If specified the change IDs will be reflective of +// the shared drive; use the combined drive ID and change ID as an identifier. +func (c *ChangesListCall) DriveId(driveId string) *ChangesListCall { + c.urlParams_.Set("driveId", driveId) + return c +} + +// IncludeCorpusRemovals sets the optional parameter "includeCorpusRemovals": +// Whether changes should include the file resource if the file is still +// accessible by the user at the time of the request, even when a file was +// removed from the list of changes and there will be no further change entries +// for this file. +func (c *ChangesListCall) IncludeCorpusRemovals(includeCorpusRemovals bool) *ChangesListCall { + c.urlParams_.Set("includeCorpusRemovals", fmt.Sprint(includeCorpusRemovals)) + return c +} + +// IncludeItemsFromAllDrives sets the optional parameter +// "includeItemsFromAllDrives": Whether both My Drive and shared drive items +// should be included in results. +func (c *ChangesListCall) IncludeItemsFromAllDrives(includeItemsFromAllDrives bool) *ChangesListCall { + c.urlParams_.Set("includeItemsFromAllDrives", fmt.Sprint(includeItemsFromAllDrives)) + return c +} + +// IncludeLabels sets the optional parameter "includeLabels": A comma-separated +// list of IDs of labels to include in the `labelInfo` part of the response. +func (c *ChangesListCall) IncludeLabels(includeLabels string) *ChangesListCall { + c.urlParams_.Set("includeLabels", includeLabels) + return c +} + +// IncludePermissionsForView sets the optional parameter +// "includePermissionsForView": Specifies which additional view's permissions +// to include in the response. Only 'published' is supported. +func (c *ChangesListCall) IncludePermissionsForView(includePermissionsForView string) *ChangesListCall { + c.urlParams_.Set("includePermissionsForView", includePermissionsForView) + return c +} + +// IncludeRemoved sets the optional parameter "includeRemoved": Whether to +// include changes indicating that items have been removed from the list of +// changes, for example by deletion or loss of access. +func (c *ChangesListCall) IncludeRemoved(includeRemoved bool) *ChangesListCall { + c.urlParams_.Set("includeRemoved", fmt.Sprint(includeRemoved)) + return c +} + +// IncludeTeamDriveItems sets the optional parameter "includeTeamDriveItems": +// Deprecated: Use `includeItemsFromAllDrives` instead. +func (c *ChangesListCall) IncludeTeamDriveItems(includeTeamDriveItems bool) *ChangesListCall { + c.urlParams_.Set("includeTeamDriveItems", fmt.Sprint(includeTeamDriveItems)) + return c +} + +// PageSize sets the optional parameter "pageSize": The maximum number of +// changes to return per page. +func (c *ChangesListCall) PageSize(pageSize int64) *ChangesListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// RestrictToMyDrive sets the optional parameter "restrictToMyDrive": Whether +// to restrict the results to changes inside the My Drive hierarchy. This omits +// changes to files such as those in the Application Data folder or shared +// files which have not been added to My Drive. +func (c *ChangesListCall) RestrictToMyDrive(restrictToMyDrive bool) *ChangesListCall { + c.urlParams_.Set("restrictToMyDrive", fmt.Sprint(restrictToMyDrive)) + return c +} + +// Spaces sets the optional parameter "spaces": A comma-separated list of +// spaces to query within the corpora. Supported values are 'drive' and +// 'appDataFolder'. +func (c *ChangesListCall) Spaces(spaces string) *ChangesListCall { + c.urlParams_.Set("spaces", spaces) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *ChangesListCall) SupportsAllDrives(supportsAllDrives bool) *ChangesListCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *ChangesListCall) SupportsTeamDrives(supportsTeamDrives bool) *ChangesListCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) + return c +} + +// TeamDriveId sets the optional parameter "teamDriveId": Deprecated: Use +// `driveId` instead. +func (c *ChangesListCall) TeamDriveId(teamDriveId string) *ChangesListCall { + c.urlParams_.Set("teamDriveId", teamDriveId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *ChangesListCall) Fields(s ...googleapi.Field) *ChangesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *ChangesListCall) IfNoneMatch(entityTag string) *ChangesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *ChangesListCall) Context(ctx context.Context) *ChangesListCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *ChangesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ChangesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "changes") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.changes.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *ChangeList.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *ChangesListCall) Do(opts ...googleapi.CallOption) (*ChangeList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &ChangeList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type ChangesWatchCall struct { + s *Service + channel *Channel + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Watch: Subscribes to changes for a user. +// +// - pageToken: The token for continuing a previous list request on the next +// page. This should be set to the value of 'nextPageToken' from the previous +// response or to the response from the getStartPageToken method. +func (r *ChangesService) Watch(pageToken string, channel *Channel) *ChangesWatchCall { + c := &ChangesWatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.urlParams_.Set("pageToken", pageToken) + c.channel = channel + return c +} + +// DriveId sets the optional parameter "driveId": The shared drive from which +// changes will be returned. If specified the change IDs will be reflective of +// the shared drive; use the combined drive ID and change ID as an identifier. +func (c *ChangesWatchCall) DriveId(driveId string) *ChangesWatchCall { + c.urlParams_.Set("driveId", driveId) + return c +} + +// IncludeCorpusRemovals sets the optional parameter "includeCorpusRemovals": +// Whether changes should include the file resource if the file is still +// accessible by the user at the time of the request, even when a file was +// removed from the list of changes and there will be no further change entries +// for this file. +func (c *ChangesWatchCall) IncludeCorpusRemovals(includeCorpusRemovals bool) *ChangesWatchCall { + c.urlParams_.Set("includeCorpusRemovals", fmt.Sprint(includeCorpusRemovals)) + return c +} + +// IncludeItemsFromAllDrives sets the optional parameter +// "includeItemsFromAllDrives": Whether both My Drive and shared drive items +// should be included in results. +func (c *ChangesWatchCall) IncludeItemsFromAllDrives(includeItemsFromAllDrives bool) *ChangesWatchCall { + c.urlParams_.Set("includeItemsFromAllDrives", fmt.Sprint(includeItemsFromAllDrives)) + return c +} + +// IncludeLabels sets the optional parameter "includeLabels": A comma-separated +// list of IDs of labels to include in the `labelInfo` part of the response. +func (c *ChangesWatchCall) IncludeLabels(includeLabels string) *ChangesWatchCall { + c.urlParams_.Set("includeLabels", includeLabels) + return c +} + +// IncludePermissionsForView sets the optional parameter +// "includePermissionsForView": Specifies which additional view's permissions +// to include in the response. Only 'published' is supported. +func (c *ChangesWatchCall) IncludePermissionsForView(includePermissionsForView string) *ChangesWatchCall { + c.urlParams_.Set("includePermissionsForView", includePermissionsForView) + return c +} + +// IncludeRemoved sets the optional parameter "includeRemoved": Whether to +// include changes indicating that items have been removed from the list of +// changes, for example by deletion or loss of access. +func (c *ChangesWatchCall) IncludeRemoved(includeRemoved bool) *ChangesWatchCall { + c.urlParams_.Set("includeRemoved", fmt.Sprint(includeRemoved)) + return c +} + +// IncludeTeamDriveItems sets the optional parameter "includeTeamDriveItems": +// Deprecated: Use `includeItemsFromAllDrives` instead. +func (c *ChangesWatchCall) IncludeTeamDriveItems(includeTeamDriveItems bool) *ChangesWatchCall { + c.urlParams_.Set("includeTeamDriveItems", fmt.Sprint(includeTeamDriveItems)) + return c +} + +// PageSize sets the optional parameter "pageSize": The maximum number of +// changes to return per page. +func (c *ChangesWatchCall) PageSize(pageSize int64) *ChangesWatchCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// RestrictToMyDrive sets the optional parameter "restrictToMyDrive": Whether +// to restrict the results to changes inside the My Drive hierarchy. This omits +// changes to files such as those in the Application Data folder or shared +// files which have not been added to My Drive. +func (c *ChangesWatchCall) RestrictToMyDrive(restrictToMyDrive bool) *ChangesWatchCall { + c.urlParams_.Set("restrictToMyDrive", fmt.Sprint(restrictToMyDrive)) + return c +} + +// Spaces sets the optional parameter "spaces": A comma-separated list of +// spaces to query within the corpora. Supported values are 'drive' and +// 'appDataFolder'. +func (c *ChangesWatchCall) Spaces(spaces string) *ChangesWatchCall { + c.urlParams_.Set("spaces", spaces) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *ChangesWatchCall) SupportsAllDrives(supportsAllDrives bool) *ChangesWatchCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *ChangesWatchCall) SupportsTeamDrives(supportsTeamDrives bool) *ChangesWatchCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) + return c +} + +// TeamDriveId sets the optional parameter "teamDriveId": Deprecated: Use +// `driveId` instead. +func (c *ChangesWatchCall) TeamDriveId(teamDriveId string) *ChangesWatchCall { + c.urlParams_.Set("teamDriveId", teamDriveId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *ChangesWatchCall) Fields(s ...googleapi.Field) *ChangesWatchCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *ChangesWatchCall) Context(ctx context.Context) *ChangesWatchCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *ChangesWatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ChangesWatchCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.channel) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "changes/watch") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.changes.watch" call. +// Any non-2xx status code is an error. Response headers are in either +// *Channel.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *ChangesWatchCall) Do(opts ...googleapi.CallOption) (*Channel, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Channel{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type ChannelsStopCall struct { + s *Service + channel *Channel + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Stop: Stops watching resources through this channel. +func (r *ChannelsService) Stop(channel *Channel) *ChannelsStopCall { + c := &ChannelsStopCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.channel = channel + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *ChannelsStopCall) Fields(s ...googleapi.Field) *ChannelsStopCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *ChannelsStopCall) Context(ctx context.Context) *ChannelsStopCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *ChannelsStopCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ChannelsStopCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.channel) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "channels/stop") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.channels.stop" call. +func (c *ChannelsStopCall) Do(opts ...googleapi.CallOption) error { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if err != nil { + return err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return gensupport.WrapError(err) + } + return nil +} + +type CommentsCreateCall struct { + s *Service + fileId string + comment *Comment + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Creates a comment on a file. +// +// - fileId: The ID of the file. +func (r *CommentsService) Create(fileId string, comment *Comment) *CommentsCreateCall { + c := &CommentsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.comment = comment + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *CommentsCreateCall) Fields(s ...googleapi.Field) *CommentsCreateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *CommentsCreateCall) Context(ctx context.Context) *CommentsCreateCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *CommentsCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *CommentsCreateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.comment) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.comments.create" call. +// Any non-2xx status code is an error. Response headers are in either +// *Comment.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *CommentsCreateCall) Do(opts ...googleapi.CallOption) (*Comment, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Comment{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type CommentsDeleteCall struct { + s *Service + fileId string + commentId string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Deletes a comment. +// +// - commentId: The ID of the comment. +// - fileId: The ID of the file. +func (r *CommentsService) Delete(fileId string, commentId string) *CommentsDeleteCall { + c := &CommentsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.commentId = commentId + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *CommentsDeleteCall) Fields(s ...googleapi.Field) *CommentsDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *CommentsDeleteCall) Context(ctx context.Context) *CommentsDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *CommentsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *CommentsDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + "commentId": c.commentId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.comments.delete" call. +func (c *CommentsDeleteCall) Do(opts ...googleapi.CallOption) error { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if err != nil { + return err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return gensupport.WrapError(err) + } + return nil +} + +type CommentsGetCall struct { + s *Service + fileId string + commentId string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Gets a comment by ID. +// +// - commentId: The ID of the comment. +// - fileId: The ID of the file. +func (r *CommentsService) Get(fileId string, commentId string) *CommentsGetCall { + c := &CommentsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.commentId = commentId + return c +} + +// IncludeDeleted sets the optional parameter "includeDeleted": Whether to +// return deleted comments. Deleted comments will not include their original +// content. +func (c *CommentsGetCall) IncludeDeleted(includeDeleted bool) *CommentsGetCall { + c.urlParams_.Set("includeDeleted", fmt.Sprint(includeDeleted)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *CommentsGetCall) Fields(s ...googleapi.Field) *CommentsGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *CommentsGetCall) IfNoneMatch(entityTag string) *CommentsGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *CommentsGetCall) Context(ctx context.Context) *CommentsGetCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *CommentsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *CommentsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + "commentId": c.commentId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.comments.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *Comment.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *CommentsGetCall) Do(opts ...googleapi.CallOption) (*Comment, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Comment{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type CommentsListCall struct { + s *Service + fileId string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists a file's comments. +// +// - fileId: The ID of the file. +func (r *CommentsService) List(fileId string) *CommentsListCall { + c := &CommentsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + return c +} + +// IncludeDeleted sets the optional parameter "includeDeleted": Whether to +// include deleted comments. Deleted comments will not include their original +// content. +func (c *CommentsListCall) IncludeDeleted(includeDeleted bool) *CommentsListCall { + c.urlParams_.Set("includeDeleted", fmt.Sprint(includeDeleted)) + return c +} + +// PageSize sets the optional parameter "pageSize": The maximum number of +// comments to return per page. +func (c *CommentsListCall) PageSize(pageSize int64) *CommentsListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": The token for continuing +// a previous list request on the next page. This should be set to the value of +// 'nextPageToken' from the previous response. +func (c *CommentsListCall) PageToken(pageToken string) *CommentsListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// StartModifiedTime sets the optional parameter "startModifiedTime": The +// minimum value of 'modifiedTime' for the result comments (RFC 3339 +// date-time). +func (c *CommentsListCall) StartModifiedTime(startModifiedTime string) *CommentsListCall { + c.urlParams_.Set("startModifiedTime", startModifiedTime) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *CommentsListCall) Fields(s ...googleapi.Field) *CommentsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *CommentsListCall) IfNoneMatch(entityTag string) *CommentsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *CommentsListCall) Context(ctx context.Context) *CommentsListCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *CommentsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *CommentsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.comments.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *CommentList.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *CommentsListCall) Do(opts ...googleapi.CallOption) (*CommentList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &CommentList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *CommentsListCall) Pages(ctx context.Context, f func(*CommentList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +type CommentsUpdateCall struct { + s *Service + fileId string + commentId string + comment *Comment + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Update: Updates a comment with patch semantics. +// +// - commentId: The ID of the comment. +// - fileId: The ID of the file. +func (r *CommentsService) Update(fileId string, commentId string, comment *Comment) *CommentsUpdateCall { + c := &CommentsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId c.commentId = commentId + c.comment = comment + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *CommentsUpdateCall) Fields(s ...googleapi.Field) *CommentsUpdateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *CommentsUpdateCall) Context(ctx context.Context) *CommentsUpdateCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *CommentsUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *CommentsUpdateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.comment) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + "commentId": c.commentId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.comments.update" call. +// Any non-2xx status code is an error. Response headers are in either +// *Comment.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *CommentsUpdateCall) Do(opts ...googleapi.CallOption) (*Comment, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Comment{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type DrivesCreateCall struct { + s *Service + drive *Drive + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Creates a shared drive. +// +// - requestId: An ID, such as a random UUID, which uniquely identifies this +// user's request for idempotent creation of a shared drive. A repeated +// request by the same user and with the same request ID will avoid creating +// duplicates by attempting to create the same shared drive. If the shared +// drive already exists a 409 error will be returned. +func (r *DrivesService) Create(requestId string, drive *Drive) *DrivesCreateCall { + c := &DrivesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.urlParams_.Set("requestId", requestId) + c.drive = drive + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *DrivesCreateCall) Fields(s ...googleapi.Field) *DrivesCreateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *DrivesCreateCall) Context(ctx context.Context) *DrivesCreateCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *DrivesCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DrivesCreateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.drive) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "drives") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.drives.create" call. +// Any non-2xx status code is an error. Response headers are in either +// *Drive.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *DrivesCreateCall) Do(opts ...googleapi.CallOption) (*Drive, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Drive{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type DrivesDeleteCall struct { + s *Service + driveId string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Permanently deletes a shared drive for which the user is an +// `organizer`. The shared drive cannot contain any untrashed items. +// +// - driveId: The ID of the shared drive. +func (r *DrivesService) Delete(driveId string) *DrivesDeleteCall { + c := &DrivesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.driveId = driveId + return c +} + +// AllowItemDeletion sets the optional parameter "allowItemDeletion": Whether +// any items inside the shared drive should also be deleted. This option is +// only supported when `useDomainAdminAccess` is also set to `true`. +func (c *DrivesDeleteCall) AllowItemDeletion(allowItemDeletion bool) *DrivesDeleteCall { + c.urlParams_.Set("allowItemDeletion", fmt.Sprint(allowItemDeletion)) + return c +} + +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if they are an administrator of the domain +// to which the shared drive belongs. +func (c *DrivesDeleteCall) UseDomainAdminAccess(useDomainAdminAccess bool) *DrivesDeleteCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *DrivesDeleteCall) Fields(s ...googleapi.Field) *DrivesDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *DrivesDeleteCall) Context(ctx context.Context) *DrivesDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *DrivesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DrivesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "drives/{driveId}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "driveId": c.driveId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.drives.delete" call. +func (c *DrivesDeleteCall) Do(opts ...googleapi.CallOption) error { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if err != nil { + return err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return gensupport.WrapError(err) + } + return nil +} + +type DrivesGetCall struct { + s *Service + driveId string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Get: Gets a shared drive's metadata by ID. +// +// - driveId: The ID of the shared drive. +func (r *DrivesService) Get(driveId string) *DrivesGetCall { + c := &DrivesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.driveId = driveId + return c +} + +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if they are an administrator of the domain +// to which the shared drive belongs. +func (c *DrivesGetCall) UseDomainAdminAccess(useDomainAdminAccess bool) *DrivesGetCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *DrivesGetCall) Fields(s ...googleapi.Field) *DrivesGetCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *DrivesGetCall) IfNoneMatch(entityTag string) *DrivesGetCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *DrivesGetCall) Context(ctx context.Context) *DrivesGetCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *DrivesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DrivesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "drives/{driveId}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "driveId": c.driveId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.drives.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *Drive.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *DrivesGetCall) Do(opts ...googleapi.CallOption) (*Drive, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Drive{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type DrivesHideCall struct { + s *Service + driveId string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Hide: Hides a shared drive from the default view. +// +// - driveId: The ID of the shared drive. +func (r *DrivesService) Hide(driveId string) *DrivesHideCall { + c := &DrivesHideCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.driveId = driveId + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *DrivesHideCall) Fields(s ...googleapi.Field) *DrivesHideCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *DrivesHideCall) Context(ctx context.Context) *DrivesHideCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *DrivesHideCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DrivesHideCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "drives/{driveId}/hide") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "driveId": c.driveId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.drives.hide" call. +// Any non-2xx status code is an error. Response headers are in either +// *Drive.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *DrivesHideCall) Do(opts ...googleapi.CallOption) (*Drive, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Drive{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type DrivesListCall struct { + s *Service + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists the user's shared drives. This method accepts the `q` +// parameter, which is a search query combining one or more search terms. For +// more information, see the Search for shared drives +// (/drive/api/guides/search-shareddrives) guide. +func (r *DrivesService) List() *DrivesListCall { + c := &DrivesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + return c +} + +// PageSize sets the optional parameter "pageSize": Maximum number of shared +// drives to return per page. +func (c *DrivesListCall) PageSize(pageSize int64) *DrivesListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": Page token for shared +// drives. +func (c *DrivesListCall) PageToken(pageToken string) *DrivesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Q sets the optional parameter "q": Query string for searching shared drives. +func (c *DrivesListCall) Q(q string) *DrivesListCall { + c.urlParams_.Set("q", q) + return c +} + +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then all shared +// drives of the domain in which the requester is an administrator are +// returned. +func (c *DrivesListCall) UseDomainAdminAccess(useDomainAdminAccess bool) *DrivesListCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *DrivesListCall) Fields(s ...googleapi.Field) *DrivesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *DrivesListCall) IfNoneMatch(entityTag string) *DrivesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *DrivesListCall) Context(ctx context.Context) *DrivesListCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *DrivesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DrivesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "drives") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.drives.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *DriveList.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *DrivesListCall) Do(opts ...googleapi.CallOption) (*DriveList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &DriveList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *DrivesListCall) Pages(ctx context.Context, f func(*DriveList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +type DrivesUnhideCall struct { + s *Service + driveId string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Unhide: Restores a shared drive to the default view. +// +// - driveId: The ID of the shared drive. +func (r *DrivesService) Unhide(driveId string) *DrivesUnhideCall { + c := &DrivesUnhideCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.driveId = driveId + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *DrivesUnhideCall) Fields(s ...googleapi.Field) *DrivesUnhideCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *DrivesUnhideCall) Context(ctx context.Context) *DrivesUnhideCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *DrivesUnhideCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DrivesUnhideCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "drives/{driveId}/unhide") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "driveId": c.driveId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.drives.unhide" call. +// Any non-2xx status code is an error. Response headers are in either +// *Drive.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *DrivesUnhideCall) Do(opts ...googleapi.CallOption) (*Drive, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Drive{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type DrivesUpdateCall struct { + s *Service + driveId string + drive *Drive + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Update: Updates the metadata for a shared drive. +// +// - driveId: The ID of the shared drive. +func (r *DrivesService) Update(driveId string, drive *Drive) *DrivesUpdateCall { + c := &DrivesUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.driveId = driveId + c.drive = drive + return c +} + +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if they are an administrator of the domain +// to which the shared drive belongs. +func (c *DrivesUpdateCall) UseDomainAdminAccess(useDomainAdminAccess bool) *DrivesUpdateCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *DrivesUpdateCall) Fields(s ...googleapi.Field) *DrivesUpdateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *DrivesUpdateCall) Context(ctx context.Context) *DrivesUpdateCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *DrivesUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *DrivesUpdateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.drive) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "drives/{driveId}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "driveId": c.driveId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.drives.update" call. +// Any non-2xx status code is an error. Response headers are in either +// *Drive.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *DrivesUpdateCall) Do(opts ...googleapi.CallOption) (*Drive, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Drive{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type FilesCopyCall struct { + s *Service + fileId string + file *File + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Copy: Creates a copy of a file and applies any requested updates with patch +// semantics. +// +// - fileId: The ID of the file. +func (r *FilesService) Copy(fileId string, file *File) *FilesCopyCall { + c := &FilesCopyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.file = file + return c +} + +// EnforceSingleParent sets the optional parameter "enforceSingleParent": +// Deprecated. Copying files into multiple folders is no longer supported. Use +// shortcuts instead. +func (c *FilesCopyCall) EnforceSingleParent(enforceSingleParent bool) *FilesCopyCall { + c.urlParams_.Set("enforceSingleParent", fmt.Sprint(enforceSingleParent)) + return c +} + +// IgnoreDefaultVisibility sets the optional parameter +// "ignoreDefaultVisibility": Whether to ignore the domain's default visibility +// settings for the created file. Domain administrators can choose to make all +// uploaded files visible to the domain by default; this parameter bypasses +// that behavior for the request. Permissions are still inherited from parent +// folders. +func (c *FilesCopyCall) IgnoreDefaultVisibility(ignoreDefaultVisibility bool) *FilesCopyCall { + c.urlParams_.Set("ignoreDefaultVisibility", fmt.Sprint(ignoreDefaultVisibility)) + return c +} + +// IncludeLabels sets the optional parameter "includeLabels": A comma-separated +// list of IDs of labels to include in the `labelInfo` part of the response. +func (c *FilesCopyCall) IncludeLabels(includeLabels string) *FilesCopyCall { + c.urlParams_.Set("includeLabels", includeLabels) + return c +} + +// IncludePermissionsForView sets the optional parameter +// "includePermissionsForView": Specifies which additional view's permissions +// to include in the response. Only 'published' is supported. +func (c *FilesCopyCall) IncludePermissionsForView(includePermissionsForView string) *FilesCopyCall { + c.urlParams_.Set("includePermissionsForView", includePermissionsForView) + return c +} + +// KeepRevisionForever sets the optional parameter "keepRevisionForever": +// Whether to set the 'keepForever' field in the new head revision. This is +// only applicable to files with binary content in Google Drive. Only 200 +// revisions for the file can be kept forever. If the limit is reached, try +// deleting pinned revisions. +func (c *FilesCopyCall) KeepRevisionForever(keepRevisionForever bool) *FilesCopyCall { + c.urlParams_.Set("keepRevisionForever", fmt.Sprint(keepRevisionForever)) + return c +} + +// OcrLanguage sets the optional parameter "ocrLanguage": A language hint for +// OCR processing during image import (ISO 639-1 code). +func (c *FilesCopyCall) OcrLanguage(ocrLanguage string) *FilesCopyCall { + c.urlParams_.Set("ocrLanguage", ocrLanguage) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *FilesCopyCall) SupportsAllDrives(supportsAllDrives bool) *FilesCopyCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *FilesCopyCall) SupportsTeamDrives(supportsTeamDrives bool) *FilesCopyCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesCopyCall) Fields(s ...googleapi.Field) *FilesCopyCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *FilesCopyCall) Context(ctx context.Context) *FilesCopyCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesCopyCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesCopyCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.file) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/copy") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.files.copy" call. +// Any non-2xx status code is an error. Response headers are in either +// *File.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *FilesCopyCall) Do(opts ...googleapi.CallOption) (*File, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &File{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type FilesCreateCall struct { + s *Service + file *File + urlParams_ gensupport.URLParams + mediaInfo_ *gensupport.MediaInfo + ctx_ context.Context + header_ http.Header +} + +// Create: Creates a new file. This method supports an */upload* URI and +// accepts uploaded media with the following characteristics: - *Maximum file +// size:* 5,120 GB - *Accepted Media MIME types:*`*/*` Note: Specify a valid +// MIME type, rather than the literal `*/*` value. The literal `*/*` is only +// used to indicate that any valid MIME type can be uploaded. For more +// information on uploading files, see Upload file data +// (/drive/api/guides/manage-uploads). Apps creating shortcuts with +// `files.create` must specify the MIME type +// `application/vnd.google-apps.shortcut`. Apps should specify a file extension +// in the `name` property when inserting files with the API. For example, an +// operation to insert a JPEG file should specify something like "name": +// "cat.jpg" in the metadata. Subsequent `GET` requests include the read-only +// `fileExtension` property populated with the extension originally specified +// in the `title` property. When a Google Drive user requests to download a +// file, or when the file is downloaded through the sync client, Drive builds a +// full filename (with extension) based on the title. In cases where the +// extension is missing, Drive attempts to determine the extension based on the +// file's MIME type. +func (r *FilesService) Create(file *File) *FilesCreateCall { + c := &FilesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.file = file + return c +} + +// EnforceSingleParent sets the optional parameter "enforceSingleParent": +// Deprecated. Creating files in multiple folders is no longer supported. +func (c *FilesCreateCall) EnforceSingleParent(enforceSingleParent bool) *FilesCreateCall { + c.urlParams_.Set("enforceSingleParent", fmt.Sprint(enforceSingleParent)) + return c +} + +// IgnoreDefaultVisibility sets the optional parameter +// "ignoreDefaultVisibility": Whether to ignore the domain's default visibility +// settings for the created file. Domain administrators can choose to make all +// uploaded files visible to the domain by default; this parameter bypasses +// that behavior for the request. Permissions are still inherited from parent +// folders. +func (c *FilesCreateCall) IgnoreDefaultVisibility(ignoreDefaultVisibility bool) *FilesCreateCall { + c.urlParams_.Set("ignoreDefaultVisibility", fmt.Sprint(ignoreDefaultVisibility)) + return c +} + +// IncludeLabels sets the optional parameter "includeLabels": A comma-separated +// list of IDs of labels to include in the `labelInfo` part of the response. +func (c *FilesCreateCall) IncludeLabels(includeLabels string) *FilesCreateCall { + c.urlParams_.Set("includeLabels", includeLabels) + return c +} + +// IncludePermissionsForView sets the optional parameter +// "includePermissionsForView": Specifies which additional view's permissions +// to include in the response. Only 'published' is supported. +func (c *FilesCreateCall) IncludePermissionsForView(includePermissionsForView string) *FilesCreateCall { + c.urlParams_.Set("includePermissionsForView", includePermissionsForView) + return c +} + +// KeepRevisionForever sets the optional parameter "keepRevisionForever": +// Whether to set the 'keepForever' field in the new head revision. This is +// only applicable to files with binary content in Google Drive. Only 200 +// revisions for the file can be kept forever. If the limit is reached, try +// deleting pinned revisions. +func (c *FilesCreateCall) KeepRevisionForever(keepRevisionForever bool) *FilesCreateCall { + c.urlParams_.Set("keepRevisionForever", fmt.Sprint(keepRevisionForever)) + return c +} + +// OcrLanguage sets the optional parameter "ocrLanguage": A language hint for +// OCR processing during image import (ISO 639-1 code). +func (c *FilesCreateCall) OcrLanguage(ocrLanguage string) *FilesCreateCall { + c.urlParams_.Set("ocrLanguage", ocrLanguage) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *FilesCreateCall) SupportsAllDrives(supportsAllDrives bool) *FilesCreateCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *FilesCreateCall) SupportsTeamDrives(supportsTeamDrives bool) *FilesCreateCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) + return c +} + +// UseContentAsIndexableText sets the optional parameter +// "useContentAsIndexableText": Whether to use the uploaded content as +// indexable text. +func (c *FilesCreateCall) UseContentAsIndexableText(useContentAsIndexableText bool) *FilesCreateCall { + c.urlParams_.Set("useContentAsIndexableText", fmt.Sprint(useContentAsIndexableText)) + return c +} + +// Media specifies the media to upload in one or more chunks. The chunk size +// may be controlled by supplying a MediaOption generated by +// googleapi.ChunkSize. The chunk size defaults to +// googleapi.DefaultUploadChunkSize.The Content-Type header used in the upload +// request will be determined by sniffing the contents of r, unless a +// MediaOption generated by googleapi.ContentType is supplied. +// At most one of Media and ResumableMedia may be set. +func (c *FilesCreateCall) Media(r io.Reader, options ...googleapi.MediaOption) *FilesCreateCall { + c.mediaInfo_ = gensupport.NewInfoFromMedia(r, options) + return c +} + +// ResumableMedia specifies the media to upload in chunks and can be canceled +// with ctx. +// +// Deprecated: use Media instead. +// +// At most one of Media and ResumableMedia may be set. mediaType identifies the +// MIME media type of the upload, such as "image/png". If mediaType is "", it +// will be auto-detected. The provided ctx will supersede any context +// previously provided to the Context method. +func (c *FilesCreateCall) ResumableMedia(ctx context.Context, r io.ReaderAt, size int64, mediaType string) *FilesCreateCall { + c.ctx_ = ctx + c.mediaInfo_ = gensupport.NewInfoFromResumableMedia(r, size, mediaType) + return c +} + +// ProgressUpdater provides a callback function that will be called after every +// chunk. It should be a low-latency function in order to not slow down the +// upload operation. This should only be called when using ResumableMedia (as +// opposed to Media). +func (c *FilesCreateCall) ProgressUpdater(pu googleapi.ProgressUpdater) *FilesCreateCall { + c.mediaInfo_.SetProgressUpdater(pu) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesCreateCall) Fields(s ...googleapi.Field) *FilesCreateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +// This context will supersede any context previously provided to the +// ResumableMedia method. +func (c *FilesCreateCall) Context(ctx context.Context) *FilesCreateCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesCreateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.file) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files") + if c.mediaInfo_ != nil { + urls = googleapi.ResolveRelative(c.s.BasePath, "/upload/drive/v3/files") + c.urlParams_.Set("uploadType", c.mediaInfo_.UploadType()) + } + if body == nil { + body = new(bytes.Buffer) + reqHeaders.Set("Content-Type", "application/json") + } + body, getBody, cleanup := c.mediaInfo_.UploadRequest(reqHeaders, body) + defer cleanup() + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + req.GetBody = getBody + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.files.create" call. +// Any non-2xx status code is an error. Response headers are in either +// *File.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *FilesCreateCall) Do(opts ...googleapi.CallOption) (*File, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + rx := c.mediaInfo_.ResumableUpload(res.Header.Get("Location")) + if rx != nil { + rx.Client = c.s.client + rx.UserAgent = c.s.userAgent() + ctx := c.ctx_ + if ctx == nil { + ctx = context.TODO() + } + res, err = rx.Upload(ctx) + if err != nil { + return nil, err + } + defer res.Body.Close() + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + } + ret := &File{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type FilesDeleteCall struct { + s *Service + fileId string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Delete: Permanently deletes a file owned by the user without moving it to +// the trash. If the file belongs to a shared drive, the user must be an +// `organizer` on the parent folder. If the target is a folder, all descendants +// owned by the user are also deleted. +// +// - fileId: The ID of the file. +func (r *FilesService) Delete(fileId string) *FilesDeleteCall { + c := &FilesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + return c +} + +// EnforceSingleParent sets the optional parameter "enforceSingleParent": +// Deprecated: If an item is not in a shared drive and its last parent is +// deleted but the item itself is not, the item will be placed under its +// owner's root. +func (c *FilesDeleteCall) EnforceSingleParent(enforceSingleParent bool) *FilesDeleteCall { + c.urlParams_.Set("enforceSingleParent", fmt.Sprint(enforceSingleParent)) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *FilesDeleteCall) SupportsAllDrives(supportsAllDrives bool) *FilesDeleteCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *FilesDeleteCall) SupportsTeamDrives(supportsTeamDrives bool) *FilesDeleteCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesDeleteCall) Fields(s ...googleapi.Field) *FilesDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *FilesDeleteCall) Context(ctx context.Context) *FilesDeleteCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.files.delete" call. +func (c *FilesDeleteCall) Do(opts ...googleapi.CallOption) error { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if err != nil { + return err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return gensupport.WrapError(err) + } + return nil +} + +type FilesDownloadCall struct { + s *Service + fileId string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Download: Downloads content of a file. Operations are valid for 24 hours +// from the time of creation. +// +// - fileId: The ID of the file to download. +func (r *FilesService) Download(fileId string) *FilesDownloadCall { + c := &FilesDownloadCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + return c +} + +// MimeType sets the optional parameter "mimeType": The MIME type the file +// should be downloaded as. This field can only be set when downloading Google +// Workspace documents. See Export MIME types for Google Workspace documents +// (/drive/api/guides/ref-export-formats) for the list of supported MIME types. +// If not set, a Google Workspace document is downloaded with a default MIME +// type. The default MIME type might change in the future. +func (c *FilesDownloadCall) MimeType(mimeType string) *FilesDownloadCall { + c.urlParams_.Set("mimeType", mimeType) + return c +} + +// RevisionId sets the optional parameter "revisionId": The revision ID of the +// file to download. This field can only be set when downloading blob files, +// Google Docs, and Google Sheets. Returns `INVALID_ARGUMENT` if downloading a +// specific revision on the file is unsupported. +func (c *FilesDownloadCall) RevisionId(revisionId string) *FilesDownloadCall { + c.urlParams_.Set("revisionId", revisionId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesDownloadCall) Fields(s ...googleapi.Field) *FilesDownloadCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *FilesDownloadCall) Context(ctx context.Context) *FilesDownloadCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesDownloadCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesDownloadCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/download") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.files.download" call. +// Any non-2xx status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *FilesDownloadCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type FilesEmptyTrashCall struct { + s *Service + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// EmptyTrash: Permanently deletes all of the user's trashed files. +func (r *FilesService) EmptyTrash() *FilesEmptyTrashCall { + c := &FilesEmptyTrashCall{s: r.s, urlParams_: make(gensupport.URLParams)} + return c +} + +// DriveId sets the optional parameter "driveId": If set, empties the trash of +// the provided shared drive. +func (c *FilesEmptyTrashCall) DriveId(driveId string) *FilesEmptyTrashCall { + c.urlParams_.Set("driveId", driveId) + return c +} + +// EnforceSingleParent sets the optional parameter "enforceSingleParent": +// Deprecated: If an item is not in a shared drive and its last parent is +// deleted but the item itself is not, the item will be placed under its +// owner's root. +func (c *FilesEmptyTrashCall) EnforceSingleParent(enforceSingleParent bool) *FilesEmptyTrashCall { + c.urlParams_.Set("enforceSingleParent", fmt.Sprint(enforceSingleParent)) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesEmptyTrashCall) Fields(s ...googleapi.Field) *FilesEmptyTrashCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *FilesEmptyTrashCall) Context(ctx context.Context) *FilesEmptyTrashCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesEmptyTrashCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesEmptyTrashCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/trash") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.files.emptyTrash" call. +func (c *FilesEmptyTrashCall) Do(opts ...googleapi.CallOption) error { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if err != nil { + return err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return gensupport.WrapError(err) + } + return nil +} + +type FilesExportCall struct { + s *Service + fileId string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// Export: Exports a Google Workspace document to the requested MIME type and +// returns exported byte content. Note that the exported content is limited to +// 10MB. +// +// - fileId: The ID of the file. +// - mimeType: The MIME type of the format requested for this export. +func (r *FilesService) Export(fileId string, mimeType string) *FilesExportCall { + c := &FilesExportCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.urlParams_.Set("mimeType", mimeType) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesExportCall) Fields(s ...googleapi.Field) *FilesExportCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *FilesExportCall) IfNoneMatch(entityTag string) *FilesExportCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do and Download methods. +func (c *FilesExportCall) Context(ctx context.Context) *FilesExportCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesExportCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesExportCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/export") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Download fetches the API endpoint's "media" value, instead of the normal +// API response value. If the returned error is nil, the Response is guaranteed to +// have a 2xx status code. Callers must close the Response.Body as usual. +func (c *FilesExportCall) Download(opts ...googleapi.CallOption) (*http.Response, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("media") + if err != nil { + return nil, err + } + if err := googleapi.CheckResponse(res); err != nil { + res.Body.Close() + return nil, gensupport.WrapError(err) + } + return res, nil +} + +// Do executes the "drive.files.export" call. +func (c *FilesExportCall) Do(opts ...googleapi.CallOption) error { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if err != nil { + return err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return gensupport.WrapError(err) + } + return nil +} + +type FilesGenerateIdsCall struct { + s *Service + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// GenerateIds: Generates a set of file IDs which can be provided in create or +// copy requests. +func (r *FilesService) GenerateIds() *FilesGenerateIdsCall { + c := &FilesGenerateIdsCall{s: r.s, urlParams_: make(gensupport.URLParams)} + return c +} + +// Count sets the optional parameter "count": The number of IDs to return. +func (c *FilesGenerateIdsCall) Count(count int64) *FilesGenerateIdsCall { + c.urlParams_.Set("count", fmt.Sprint(count)) + return c +} + +// Space sets the optional parameter "space": The space in which the IDs can be +// used to create new files. Supported values are 'drive' and 'appDataFolder'. +// (Default: 'drive') +func (c *FilesGenerateIdsCall) Space(space string) *FilesGenerateIdsCall { + c.urlParams_.Set("space", space) + return c +} + +// Type sets the optional parameter "type": The type of items which the IDs can +// be used for. Supported values are 'files' and 'shortcuts'. Note that +// 'shortcuts' are only supported in the `drive` 'space'. (Default: 'files') +func (c *FilesGenerateIdsCall) Type(type_ string) *FilesGenerateIdsCall { + c.urlParams_.Set("type", type_) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *CommentsDeleteCall) Fields(s ...googleapi.Field) *CommentsDeleteCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesGenerateIdsCall) Fields(s ...googleapi.Field) *FilesGenerateIdsCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *CommentsDeleteCall) Context(ctx context.Context) *CommentsDeleteCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *FilesGenerateIdsCall) IfNoneMatch(entityTag string) *FilesGenerateIdsCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *FilesGenerateIdsCall) Context(ctx context.Context) *FilesGenerateIdsCall { c.ctx_ = ctx return c } -func (c *CommentsDeleteCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesGenerateIdsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesGenerateIdsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/generateIds") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) - googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "commentId": c.commentId, - }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.comments.delete" call. -func (c *CommentsDeleteCall) Do(opts ...googleapi.CallOption) error { +// Do executes the "drive.files.generateIds" call. +// Any non-2xx status code is an error. Response headers are in either +// *GeneratedIds.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *FilesGenerateIdsCall) Do(opts ...googleapi.CallOption) (*GeneratedIds, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } if err != nil { - return err + return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return err + return nil, gensupport.WrapError(err) } - return nil - // { - // "description": "Deletes a comment.", - // "httpMethod": "DELETE", - // "id": "drive.comments.delete", - // "parameterOrder": [ - // "fileId", - // "commentId" - // ], - // "parameters": { - // "commentId": { - // "description": "The ID of the comment.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/comments/{commentId}", - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.comments.get": + ret := &GeneratedIds{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} -type CommentsGetCall struct { +type FilesGetCall struct { s *Service fileId string - commentId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// Get: Gets a comment by ID. -func (r *CommentsService) Get(fileId string, commentId string) *CommentsGetCall { - c := &CommentsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Get: Gets a file's metadata or content by ID. If you provide the URL +// parameter `alt=media`, then the response includes the file contents in the +// response body. Downloading content with `alt=media` only works if the file +// is stored in Drive. To download Google Docs, Sheets, and Slides use +// `files.export` (/drive/api/reference/rest/v3/files/export) instead. For more +// information, see Download & export files +// (/drive/api/guides/manage-downloads). +// +// - fileId: The ID of the file. +func (r *FilesService) Get(fileId string) *FilesGetCall { + c := &FilesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId - c.commentId = commentId return c } -// IncludeDeleted sets the optional parameter "includeDeleted": Whether -// to return deleted comments. Deleted comments will not include their -// original content. -func (c *CommentsGetCall) IncludeDeleted(includeDeleted bool) *CommentsGetCall { - c.urlParams_.Set("includeDeleted", fmt.Sprint(includeDeleted)) +// AcknowledgeAbuse sets the optional parameter "acknowledgeAbuse": Whether the +// user is acknowledging the risk of downloading known malware or other abusive +// files. This is only applicable when the `alt` parameter is set to `media` +// and the user is the owner of the file or an organizer of the shared drive in +// which the file resides. +func (c *FilesGetCall) AcknowledgeAbuse(acknowledgeAbuse bool) *FilesGetCall { + c.urlParams_.Set("acknowledgeAbuse", fmt.Sprint(acknowledgeAbuse)) + return c +} + +// IncludeLabels sets the optional parameter "includeLabels": A comma-separated +// list of IDs of labels to include in the `labelInfo` part of the response. +func (c *FilesGetCall) IncludeLabels(includeLabels string) *FilesGetCall { + c.urlParams_.Set("includeLabels", includeLabels) + return c +} + +// IncludePermissionsForView sets the optional parameter +// "includePermissionsForView": Specifies which additional view's permissions +// to include in the response. Only 'published' is supported. +func (c *FilesGetCall) IncludePermissionsForView(includePermissionsForView string) *FilesGetCall { + c.urlParams_.Set("includePermissionsForView", includePermissionsForView) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *FilesGetCall) SupportsAllDrives(supportsAllDrives bool) *FilesGetCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *FilesGetCall) SupportsTeamDrives(supportsTeamDrives bool) *FilesGetCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *CommentsGetCall) Fields(s ...googleapi.Field) *CommentsGetCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesGetCall) Fields(s ...googleapi.Field) *FilesGetCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *CommentsGetCall) IfNoneMatch(entityTag string) *CommentsGetCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *FilesGetCall) IfNoneMatch(entityTag string) *FilesGetCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *CommentsGetCall) Context(ctx context.Context) *CommentsGetCall { +// Context sets the context to be used in this call's Do and Download methods. +func (c *FilesGetCall) Context(ctx context.Context) *FilesGetCall { c.ctx_ = ctx return c } -func (c *CommentsGetCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "commentId": c.commentId, + "fileId": c.fileId, }) - req.Header.Set("User-Agent", c.s.userAgent()) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Download fetches the API endpoint's "media" value, instead of the normal +// API response value. If the returned error is nil, the Response is guaranteed to +// have a 2xx status code. Callers must close the Response.Body as usual. +func (c *FilesGetCall) Download(opts ...googleapi.CallOption) (*http.Response, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("media") + if err != nil { + return nil, err + } + if err := googleapi.CheckResponse(res); err != nil { + res.Body.Close() + return nil, gensupport.WrapError(err) + } + return res, nil +} + +// Do executes the "drive.files.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *File.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *FilesGetCall) Do(opts ...googleapi.CallOption) (*File, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &File{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type FilesListCall struct { + s *Service + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists the user's files. This method accepts the `q` parameter, which +// is a search query combining one or more search terms. For more information, +// see the Search for files & folders (/drive/api/guides/search-files) guide. +// *Note:* This method returns *all* files by default, including trashed files. +// If you don't want trashed files to appear in the list, use the +// `trashed=false` query parameter to remove trashed files from the results. +func (r *FilesService) List() *FilesListCall { + c := &FilesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + return c +} + +// Corpora sets the optional parameter "corpora": Bodies of items +// (files/documents) to which the query applies. Supported bodies are 'user', +// 'domain', 'drive', and 'allDrives'. Prefer 'user' or 'drive' to 'allDrives' +// for efficiency. By default, corpora is set to 'user'. However, this can +// change depending on the filter set through the 'q' parameter. +func (c *FilesListCall) Corpora(corpora string) *FilesListCall { + c.urlParams_.Set("corpora", corpora) + return c +} + +// Corpus sets the optional parameter "corpus": Deprecated: The source of files +// to list. Use 'corpora' instead. +// +// Possible values: +// +// "domain" - Files shared to the user's domain. +// "user" - Files owned by or shared to the user. +func (c *FilesListCall) Corpus(corpus string) *FilesListCall { + c.urlParams_.Set("corpus", corpus) + return c +} + +// DriveId sets the optional parameter "driveId": ID of the shared drive to +// search. +func (c *FilesListCall) DriveId(driveId string) *FilesListCall { + c.urlParams_.Set("driveId", driveId) + return c +} + +// IncludeItemsFromAllDrives sets the optional parameter +// "includeItemsFromAllDrives": Whether both My Drive and shared drive items +// should be included in results. +func (c *FilesListCall) IncludeItemsFromAllDrives(includeItemsFromAllDrives bool) *FilesListCall { + c.urlParams_.Set("includeItemsFromAllDrives", fmt.Sprint(includeItemsFromAllDrives)) + return c +} + +// IncludeLabels sets the optional parameter "includeLabels": A comma-separated +// list of IDs of labels to include in the `labelInfo` part of the response. +func (c *FilesListCall) IncludeLabels(includeLabels string) *FilesListCall { + c.urlParams_.Set("includeLabels", includeLabels) + return c +} + +// IncludePermissionsForView sets the optional parameter +// "includePermissionsForView": Specifies which additional view's permissions +// to include in the response. Only 'published' is supported. +func (c *FilesListCall) IncludePermissionsForView(includePermissionsForView string) *FilesListCall { + c.urlParams_.Set("includePermissionsForView", includePermissionsForView) + return c +} + +// IncludeTeamDriveItems sets the optional parameter "includeTeamDriveItems": +// Deprecated: Use `includeItemsFromAllDrives` instead. +func (c *FilesListCall) IncludeTeamDriveItems(includeTeamDriveItems bool) *FilesListCall { + c.urlParams_.Set("includeTeamDriveItems", fmt.Sprint(includeTeamDriveItems)) + return c +} + +// OrderBy sets the optional parameter "orderBy": A comma-separated list of +// sort keys. Valid keys are: * `createdTime`: When the file was created. * +// `folder`: The folder ID. This field is sorted using alphabetical ordering. * +// `modifiedByMeTime`: The last time the file was modified by the user. * +// `modifiedTime`: The last time the file was modified by anyone. * `name`: The +// name of the file. This field is sorted using alphabetical ordering, so 1, +// 12, 2, 22. * `name_natural`: The name of the file. This field is sorted +// using natural sort ordering, so 1, 2, 12, 22. * `quotaBytesUsed`: The number +// of storage quota bytes used by the file. * `recency`: The most recent +// timestamp from the file's date-time fields. * `sharedWithMeTime`: When the +// file was shared with the user, if applicable. * `starred`: Whether the user +// has starred the file. * `viewedByMeTime`: The last time the file was viewed +// by the user. Each key sorts ascending by default, but can be reversed with +// the 'desc' modifier. Example usage: `?orderBy=folder,modifiedTime +// desc,name`. +func (c *FilesListCall) OrderBy(orderBy string) *FilesListCall { + c.urlParams_.Set("orderBy", orderBy) + return c +} + +// PageSize sets the optional parameter "pageSize": The maximum number of files +// to return per page. Partial or empty result pages are possible even before +// the end of the files list has been reached. +func (c *FilesListCall) PageSize(pageSize int64) *FilesListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": The token for continuing +// a previous list request on the next page. This should be set to the value of +// 'nextPageToken' from the previous response. +func (c *FilesListCall) PageToken(pageToken string) *FilesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Q sets the optional parameter "q": A query for filtering the file results. +// See the "Search for files & folders" guide for supported syntax. +func (c *FilesListCall) Q(q string) *FilesListCall { + c.urlParams_.Set("q", q) + return c +} + +// Spaces sets the optional parameter "spaces": A comma-separated list of +// spaces to query within the corpora. Supported values are 'drive' and +// 'appDataFolder'. +func (c *FilesListCall) Spaces(spaces string) *FilesListCall { + c.urlParams_.Set("spaces", spaces) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *FilesListCall) SupportsAllDrives(supportsAllDrives bool) *FilesListCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *FilesListCall) SupportsTeamDrives(supportsTeamDrives bool) *FilesListCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) + return c +} + +// TeamDriveId sets the optional parameter "teamDriveId": Deprecated: Use +// `driveId` instead. +func (c *FilesListCall) TeamDriveId(teamDriveId string) *FilesListCall { + c.urlParams_.Set("teamDriveId", teamDriveId) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesListCall) Fields(s ...googleapi.Field) *FilesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *FilesListCall) IfNoneMatch(entityTag string) *FilesListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *FilesListCall) Context(ctx context.Context) *FilesListCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.comments.get" call. -// Exactly one of *Comment or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Comment.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *CommentsGetCall) Do(opts ...googleapi.CallOption) (*Comment, error) { +// Do executes the "drive.files.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *FileList.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *FilesListCall) Do(opts ...googleapi.CallOption) (*FileList, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Comment{ + ret := &FileList{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Gets a comment by ID.", - // "httpMethod": "GET", - // "id": "drive.comments.get", - // "parameterOrder": [ - // "fileId", - // "commentId" - // ], - // "parameters": { - // "commentId": { - // "description": "The ID of the comment.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "includeDeleted": { - // "default": "false", - // "description": "Whether to return deleted comments. Deleted comments will not include their original content.", - // "location": "query", - // "type": "boolean" - // } - // }, - // "path": "files/{fileId}/comments/{commentId}", - // "response": { - // "$ref": "Comment" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// method id "drive.comments.list": +} -type CommentsListCall struct { +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *FilesListCall) Pages(ctx context.Context, f func(*FileList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +type FilesListLabelsCall struct { s *Service fileId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// List: Lists a file's comments. -func (r *CommentsService) List(fileId string) *CommentsListCall { - c := &CommentsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// ListLabels: Lists the labels on a file. +// +// - fileId: The ID for the file. +func (r *FilesService) ListLabels(fileId string) *FilesListLabelsCall { + c := &FilesListLabelsCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId return c } -// IncludeDeleted sets the optional parameter "includeDeleted": Whether -// to include deleted comments. Deleted comments will not include their -// original content. -func (c *CommentsListCall) IncludeDeleted(includeDeleted bool) *CommentsListCall { - c.urlParams_.Set("includeDeleted", fmt.Sprint(includeDeleted)) - return c -} - -// PageSize sets the optional parameter "pageSize": The maximum number -// of comments to return per page. -func (c *CommentsListCall) PageSize(pageSize int64) *CommentsListCall { - c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) +// MaxResults sets the optional parameter "maxResults": The maximum number of +// labels to return per page. When not set, defaults to 100. +func (c *FilesListLabelsCall) MaxResults(maxResults int64) *FilesListLabelsCall { + c.urlParams_.Set("maxResults", fmt.Sprint(maxResults)) return c } -// PageToken sets the optional parameter "pageToken": The token for -// continuing a previous list request on the next page. This should be -// set to the value of 'nextPageToken' from the previous response. -func (c *CommentsListCall) PageToken(pageToken string) *CommentsListCall { +// PageToken sets the optional parameter "pageToken": The token for continuing +// a previous list request on the next page. This should be set to the value of +// 'nextPageToken' from the previous response. +func (c *FilesListLabelsCall) PageToken(pageToken string) *FilesListLabelsCall { c.urlParams_.Set("pageToken", pageToken) return c } -// StartModifiedTime sets the optional parameter "startModifiedTime": -// The minimum value of 'modifiedTime' for the result comments (RFC 3339 -// date-time). -func (c *CommentsListCall) StartModifiedTime(startModifiedTime string) *CommentsListCall { - c.urlParams_.Set("startModifiedTime", startModifiedTime) - return c -} - // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *CommentsListCall) Fields(s ...googleapi.Field) *CommentsListCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesListLabelsCall) Fields(s ...googleapi.Field) *FilesListLabelsCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *CommentsListCall) IfNoneMatch(entityTag string) *CommentsListCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *FilesListLabelsCall) IfNoneMatch(entityTag string) *FilesListLabelsCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *CommentsListCall) Context(ctx context.Context) *CommentsListCall { +// Context sets the context to be used in this call's Do method. +func (c *FilesListLabelsCall) Context(ctx context.Context) *FilesListLabelsCall { c.ctx_ = ctx return c } -func (c *CommentsListCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesListLabelsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesListLabelsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/listLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "fileId": c.fileId, }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) - } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.comments.list" call. -// Exactly one of *CommentList or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *CommentList.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *CommentsListCall) Do(opts ...googleapi.CallOption) (*CommentList, error) { +// Do executes the "drive.files.listLabels" call. +// Any non-2xx status code is an error. Response headers are in either +// *LabelList.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *FilesListLabelsCall) Do(opts ...googleapi.CallOption) (*LabelList, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &CommentList{ + ret := &LabelList{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Lists a file's comments.", - // "httpMethod": "GET", - // "id": "drive.comments.list", - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "includeDeleted": { - // "default": "false", - // "description": "Whether to include deleted comments. Deleted comments will not include their original content.", - // "location": "query", - // "type": "boolean" - // }, - // "pageSize": { - // "default": "20", - // "description": "The maximum number of comments to return per page.", - // "format": "int32", - // "location": "query", - // "maximum": "100", - // "minimum": "1", - // "type": "integer" - // }, - // "pageToken": { - // "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", - // "location": "query", - // "type": "string" - // }, - // "startModifiedTime": { - // "description": "The minimum value of 'modifiedTime' for the result comments (RFC 3339 date-time).", - // "location": "query", - // "type": "string" - // } - // }, - // "path": "files/{fileId}/comments", - // "response": { - // "$ref": "CommentList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - } // Pages invokes f for each page of results. // A non-nil error returned from f will halt the iteration. // The provided context supersedes any context provided to the Context method. -func (c *CommentsListCall) Pages(ctx context.Context, f func(*CommentList) error) error { +func (c *FilesListLabelsCall) Pages(ctx context.Context, f func(*LabelList) error) error { c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point + defer c.PageToken(c.urlParams_.Get("pageToken")) for { x, err := c.Do() if err != nil { @@ -2614,247 +7313,348 @@ func (c *CommentsListCall) Pages(ctx context.Context, f func(*CommentList) error } } -// method id "drive.comments.update": - -type CommentsUpdateCall struct { - s *Service - fileId string - commentId string - comment *Comment - urlParams_ gensupport.URLParams - ctx_ context.Context +type FilesModifyLabelsCall struct { + s *Service + fileId string + modifylabelsrequest *ModifyLabelsRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header } -// Update: Updates a comment with patch semantics. -func (r *CommentsService) Update(fileId string, commentId string, comment *Comment) *CommentsUpdateCall { - c := &CommentsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// ModifyLabels: Modifies the set of labels applied to a file. Returns a list +// of the labels that were added or modified. +// +// - fileId: The ID of the file to which the labels belong. +func (r *FilesService) ModifyLabels(fileId string, modifylabelsrequest *ModifyLabelsRequest) *FilesModifyLabelsCall { + c := &FilesModifyLabelsCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId - c.commentId = commentId - c.comment = comment + c.modifylabelsrequest = modifylabelsrequest return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *CommentsUpdateCall) Fields(s ...googleapi.Field) *CommentsUpdateCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesModifyLabelsCall) Fields(s ...googleapi.Field) *FilesModifyLabelsCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *CommentsUpdateCall) Context(ctx context.Context) *CommentsUpdateCall { +// Context sets the context to be used in this call's Do method. +func (c *FilesModifyLabelsCall) Context(ctx context.Context) *FilesModifyLabelsCall { c.ctx_ = ctx return c } -func (c *CommentsUpdateCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesModifyLabelsCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesModifyLabelsCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.comment) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.modifylabelsrequest) if err != nil { return nil, err } - ctype := "application/json" c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/modifyLabels") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "commentId": c.commentId, + "fileId": c.fileId, }) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.comments.update" call. -// Exactly one of *Comment or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Comment.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *CommentsUpdateCall) Do(opts ...googleapi.CallOption) (*Comment, error) { +// Do executes the "drive.files.modifyLabels" call. +// Any non-2xx status code is an error. Response headers are in either +// *ModifyLabelsResponse.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified was +// returned. +func (c *FilesModifyLabelsCall) Do(opts ...googleapi.CallOption) (*ModifyLabelsResponse, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Comment{ + ret := &ModifyLabelsResponse{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Updates a comment with patch semantics.", - // "httpMethod": "PATCH", - // "id": "drive.comments.update", - // "parameterOrder": [ - // "fileId", - // "commentId" - // ], - // "parameters": { - // "commentId": { - // "description": "The ID of the comment.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/comments/{commentId}", - // "request": { - // "$ref": "Comment" - // }, - // "response": { - // "$ref": "Comment" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.files.copy": +} -type FilesCopyCall struct { +type FilesUpdateCall struct { s *Service fileId string file *File urlParams_ gensupport.URLParams + mediaInfo_ *gensupport.MediaInfo ctx_ context.Context -} - -// Copy: Creates a copy of a file and applies any requested updates with -// patch semantics. -func (r *FilesService) Copy(fileId string, file *File) *FilesCopyCall { - c := &FilesCopyCall{s: r.s, urlParams_: make(gensupport.URLParams)} + header_ http.Header +} + +// Update: Updates a file's metadata and/or content. When calling this method, +// only populate fields in the request that you want to modify. When updating +// fields, some fields might be changed automatically, such as `modifiedDate`. +// This method supports patch semantics. This method supports an */upload* URI +// and accepts uploaded media with the following characteristics: - *Maximum +// file size:* 5,120 GB - *Accepted Media MIME types:*`*/*` Note: Specify a +// valid MIME type, rather than the literal `*/*` value. The literal `*/*` is +// only used to indicate that any valid MIME type can be uploaded. For more +// information on uploading files, see Upload file data +// (/drive/api/guides/manage-uploads). +// +// - fileId: The ID of the file. +func (r *FilesService) Update(fileId string, file *File) *FilesUpdateCall { + c := &FilesUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId c.file = file return c } -// IgnoreDefaultVisibility sets the optional parameter -// "ignoreDefaultVisibility": Whether to ignore the domain's default -// visibility settings for the created file. Domain administrators can -// choose to make all uploaded files visible to the domain by default; -// this parameter bypasses that behavior for the request. Permissions -// are still inherited from parent folders. -func (c *FilesCopyCall) IgnoreDefaultVisibility(ignoreDefaultVisibility bool) *FilesCopyCall { - c.urlParams_.Set("ignoreDefaultVisibility", fmt.Sprint(ignoreDefaultVisibility)) +// AddParents sets the optional parameter "addParents": A comma-separated list +// of parent IDs to add. +func (c *FilesUpdateCall) AddParents(addParents string) *FilesUpdateCall { + c.urlParams_.Set("addParents", addParents) return c } -// KeepRevisionForever sets the optional parameter -// "keepRevisionForever": Whether to set the 'keepForever' field in the -// new head revision. This is only applicable to files with binary -// content in Drive. -func (c *FilesCopyCall) KeepRevisionForever(keepRevisionForever bool) *FilesCopyCall { +// EnforceSingleParent sets the optional parameter "enforceSingleParent": +// Deprecated: Adding files to multiple folders is no longer supported. Use +// shortcuts instead. +func (c *FilesUpdateCall) EnforceSingleParent(enforceSingleParent bool) *FilesUpdateCall { + c.urlParams_.Set("enforceSingleParent", fmt.Sprint(enforceSingleParent)) + return c +} + +// IncludeLabels sets the optional parameter "includeLabels": A comma-separated +// list of IDs of labels to include in the `labelInfo` part of the response. +func (c *FilesUpdateCall) IncludeLabels(includeLabels string) *FilesUpdateCall { + c.urlParams_.Set("includeLabels", includeLabels) + return c +} + +// IncludePermissionsForView sets the optional parameter +// "includePermissionsForView": Specifies which additional view's permissions +// to include in the response. Only 'published' is supported. +func (c *FilesUpdateCall) IncludePermissionsForView(includePermissionsForView string) *FilesUpdateCall { + c.urlParams_.Set("includePermissionsForView", includePermissionsForView) + return c +} + +// KeepRevisionForever sets the optional parameter "keepRevisionForever": +// Whether to set the 'keepForever' field in the new head revision. This is +// only applicable to files with binary content in Google Drive. Only 200 +// revisions for the file can be kept forever. If the limit is reached, try +// deleting pinned revisions. +func (c *FilesUpdateCall) KeepRevisionForever(keepRevisionForever bool) *FilesUpdateCall { c.urlParams_.Set("keepRevisionForever", fmt.Sprint(keepRevisionForever)) return c } -// OcrLanguage sets the optional parameter "ocrLanguage": A language -// hint for OCR processing during image import (ISO 639-1 code). -func (c *FilesCopyCall) OcrLanguage(ocrLanguage string) *FilesCopyCall { +// OcrLanguage sets the optional parameter "ocrLanguage": A language hint for +// OCR processing during image import (ISO 639-1 code). +func (c *FilesUpdateCall) OcrLanguage(ocrLanguage string) *FilesUpdateCall { c.urlParams_.Set("ocrLanguage", ocrLanguage) return c } +// RemoveParents sets the optional parameter "removeParents": A comma-separated +// list of parent IDs to remove. +func (c *FilesUpdateCall) RemoveParents(removeParents string) *FilesUpdateCall { + c.urlParams_.Set("removeParents", removeParents) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *FilesUpdateCall) SupportsAllDrives(supportsAllDrives bool) *FilesUpdateCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *FilesUpdateCall) SupportsTeamDrives(supportsTeamDrives bool) *FilesUpdateCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) + return c +} + +// UseContentAsIndexableText sets the optional parameter +// "useContentAsIndexableText": Whether to use the uploaded content as +// indexable text. +func (c *FilesUpdateCall) UseContentAsIndexableText(useContentAsIndexableText bool) *FilesUpdateCall { + c.urlParams_.Set("useContentAsIndexableText", fmt.Sprint(useContentAsIndexableText)) + return c +} + +// Media specifies the media to upload in one or more chunks. The chunk size +// may be controlled by supplying a MediaOption generated by +// googleapi.ChunkSize. The chunk size defaults to +// googleapi.DefaultUploadChunkSize.The Content-Type header used in the upload +// request will be determined by sniffing the contents of r, unless a +// MediaOption generated by googleapi.ContentType is supplied. +// At most one of Media and ResumableMedia may be set. +func (c *FilesUpdateCall) Media(r io.Reader, options ...googleapi.MediaOption) *FilesUpdateCall { + c.mediaInfo_ = gensupport.NewInfoFromMedia(r, options) + return c +} + +// ResumableMedia specifies the media to upload in chunks and can be canceled +// with ctx. +// +// Deprecated: use Media instead. +// +// At most one of Media and ResumableMedia may be set. mediaType identifies the +// MIME media type of the upload, such as "image/png". If mediaType is "", it +// will be auto-detected. The provided ctx will supersede any context +// previously provided to the Context method. +func (c *FilesUpdateCall) ResumableMedia(ctx context.Context, r io.ReaderAt, size int64, mediaType string) *FilesUpdateCall { + c.ctx_ = ctx + c.mediaInfo_ = gensupport.NewInfoFromResumableMedia(r, size, mediaType) + return c +} + +// ProgressUpdater provides a callback function that will be called after every +// chunk. It should be a low-latency function in order to not slow down the +// upload operation. This should only be called when using ResumableMedia (as +// opposed to Media). +func (c *FilesUpdateCall) ProgressUpdater(pu googleapi.ProgressUpdater) *FilesUpdateCall { + c.mediaInfo_.SetProgressUpdater(pu) + return c +} + // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesCopyCall) Fields(s ...googleapi.Field) *FilesCopyCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesUpdateCall) Fields(s ...googleapi.Field) *FilesUpdateCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *FilesCopyCall) Context(ctx context.Context) *FilesCopyCall { +// Context sets the context to be used in this call's Do method. +// This context will supersede any context previously provided to the +// ResumableMedia method. +func (c *FilesUpdateCall) Context(ctx context.Context) *FilesUpdateCall { c.ctx_ = ctx return c } -func (c *FilesCopyCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesUpdateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) var body io.Reader = nil body, err := googleapi.WithoutDataWrapper.JSONReader(c.file) if err != nil { return nil, err } - ctype := "application/json" c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/copy") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}") + if c.mediaInfo_ != nil { + urls = googleapi.ResolveRelative(c.s.BasePath, "/upload/drive/v3/files/{fileId}") + c.urlParams_.Set("uploadType", c.mediaInfo_.UploadType()) + } + if body == nil { + body = new(bytes.Buffer) + reqHeaders.Set("Content-Type", "application/json") + } + body, getBody, cleanup := c.mediaInfo_.UploadRequest(reqHeaders, body) + defer cleanup() urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + req.GetBody = getBody googleapi.Expand(req.URL, map[string]string{ "fileId": c.fileId, }) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.files.copy" call. -// Exactly one of *File or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either +// Do executes the "drive.files.update" call. +// Any non-2xx status code is an error. Response headers are in either // *File.ServerResponse.Header or (if a response was returned at all) in // error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check -// whether the returned error was because http.StatusNotModified was -// returned. -func (c *FilesCopyCall) Do(opts ...googleapi.CallOption) (*File, error) { +// whether the returned error was because http.StatusNotModified was returned. +func (c *FilesUpdateCall) Do(opts ...googleapi.CallOption) (*File, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) + } + rx := c.mediaInfo_.ResumableUpload(res.Header.Get("Location")) + if rx != nil { + rx.Client = c.s.client + rx.UserAgent = c.s.userAgent() + ctx := c.ctx_ + if ctx == nil { + ctx = context.TODO() + } + res, err = rx.Upload(ctx) + if err != nil { + return nil, err + } + defer res.Body.Close() + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } } ret := &File{ ServerResponse: googleapi.ServerResponse{ @@ -2862,394 +7662,221 @@ func (c *FilesCopyCall) Do(opts ...googleapi.CallOption) (*File, error) { HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Creates a copy of a file and applies any requested updates with patch semantics.", - // "httpMethod": "POST", - // "id": "drive.files.copy", - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "ignoreDefaultVisibility": { - // "default": "false", - // "description": "Whether to ignore the domain's default visibility settings for the created file. Domain administrators can choose to make all uploaded files visible to the domain by default; this parameter bypasses that behavior for the request. Permissions are still inherited from parent folders.", - // "location": "query", - // "type": "boolean" - // }, - // "keepRevisionForever": { - // "default": "false", - // "description": "Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Drive.", - // "location": "query", - // "type": "boolean" - // }, - // "ocrLanguage": { - // "description": "A language hint for OCR processing during image import (ISO 639-1 code).", - // "location": "query", - // "type": "string" - // } - // }, - // "path": "files/{fileId}/copy", - // "request": { - // "$ref": "File" - // }, - // "response": { - // "$ref": "File" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.photos.readonly" - // ] - // } - -} - -// method id "drive.files.create": - -type FilesCreateCall struct { - s *Service - file *File - urlParams_ gensupport.URLParams - media_ io.Reader - resumableBuffer_ *gensupport.ResumableBuffer - mediaType_ string - mediaSize_ int64 // mediaSize, if known. Used only for calls to progressUpdater_. - progressUpdater_ googleapi.ProgressUpdater - ctx_ context.Context -} - -// Create: Creates a new file. -func (r *FilesService) Create(file *File) *FilesCreateCall { - c := &FilesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.file = file - return c } -// IgnoreDefaultVisibility sets the optional parameter -// "ignoreDefaultVisibility": Whether to ignore the domain's default -// visibility settings for the created file. Domain administrators can -// choose to make all uploaded files visible to the domain by default; -// this parameter bypasses that behavior for the request. Permissions -// are still inherited from parent folders. -func (c *FilesCreateCall) IgnoreDefaultVisibility(ignoreDefaultVisibility bool) *FilesCreateCall { - c.urlParams_.Set("ignoreDefaultVisibility", fmt.Sprint(ignoreDefaultVisibility)) - return c +type FilesWatchCall struct { + s *Service + fileId string + channel *Channel + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header } -// KeepRevisionForever sets the optional parameter -// "keepRevisionForever": Whether to set the 'keepForever' field in the -// new head revision. This is only applicable to files with binary -// content in Drive. -func (c *FilesCreateCall) KeepRevisionForever(keepRevisionForever bool) *FilesCreateCall { - c.urlParams_.Set("keepRevisionForever", fmt.Sprint(keepRevisionForever)) +// Watch: Subscribes to changes to a file. +// +// - fileId: The ID of the file. +func (r *FilesService) Watch(fileId string, channel *Channel) *FilesWatchCall { + c := &FilesWatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.channel = channel return c } -// OcrLanguage sets the optional parameter "ocrLanguage": A language -// hint for OCR processing during image import (ISO 639-1 code). -func (c *FilesCreateCall) OcrLanguage(ocrLanguage string) *FilesCreateCall { - c.urlParams_.Set("ocrLanguage", ocrLanguage) +// AcknowledgeAbuse sets the optional parameter "acknowledgeAbuse": Whether the +// user is acknowledging the risk of downloading known malware or other abusive +// files. This is only applicable when the `alt` parameter is set to `media` +// and the user is the owner of the file or an organizer of the shared drive in +// which the file resides. +func (c *FilesWatchCall) AcknowledgeAbuse(acknowledgeAbuse bool) *FilesWatchCall { + c.urlParams_.Set("acknowledgeAbuse", fmt.Sprint(acknowledgeAbuse)) return c } -// UseContentAsIndexableText sets the optional parameter -// "useContentAsIndexableText": Whether to use the uploaded content as -// indexable text. -func (c *FilesCreateCall) UseContentAsIndexableText(useContentAsIndexableText bool) *FilesCreateCall { - c.urlParams_.Set("useContentAsIndexableText", fmt.Sprint(useContentAsIndexableText)) +// IncludeLabels sets the optional parameter "includeLabels": A comma-separated +// list of IDs of labels to include in the `labelInfo` part of the response. +func (c *FilesWatchCall) IncludeLabels(includeLabels string) *FilesWatchCall { + c.urlParams_.Set("includeLabels", includeLabels) return c } -// Media specifies the media to upload in one or more chunks. The chunk -// size may be controlled by supplying a MediaOption generated by -// googleapi.ChunkSize. The chunk size defaults to -// googleapi.DefaultUploadChunkSize.The Content-Type header used in the -// upload request will be determined by sniffing the contents of r, -// unless a MediaOption generated by googleapi.ContentType is -// supplied. -// At most one of Media and ResumableMedia may be set. -func (c *FilesCreateCall) Media(r io.Reader, options ...googleapi.MediaOption) *FilesCreateCall { - opts := googleapi.ProcessMediaOptions(options) - chunkSize := opts.ChunkSize - if !opts.ForceEmptyContentType { - r, c.mediaType_ = gensupport.DetermineContentType(r, opts.ContentType) - } - c.media_, c.resumableBuffer_ = gensupport.PrepareUpload(r, chunkSize) +// IncludePermissionsForView sets the optional parameter +// "includePermissionsForView": Specifies which additional view's permissions +// to include in the response. Only 'published' is supported. +func (c *FilesWatchCall) IncludePermissionsForView(includePermissionsForView string) *FilesWatchCall { + c.urlParams_.Set("includePermissionsForView", includePermissionsForView) return c } -// ResumableMedia specifies the media to upload in chunks and can be -// canceled with ctx. -// -// Deprecated: use Media instead. -// -// At most one of Media and ResumableMedia may be set. mediaType -// identifies the MIME media type of the upload, such as "image/png". If -// mediaType is "", it will be auto-detected. The provided ctx will -// supersede any context previously provided to the Context method. -func (c *FilesCreateCall) ResumableMedia(ctx context.Context, r io.ReaderAt, size int64, mediaType string) *FilesCreateCall { - c.ctx_ = ctx - rdr := gensupport.ReaderAtToReader(r, size) - rdr, c.mediaType_ = gensupport.DetermineContentType(rdr, mediaType) - c.resumableBuffer_ = gensupport.NewResumableBuffer(rdr, googleapi.DefaultUploadChunkSize) - c.media_ = nil - c.mediaSize_ = size +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *FilesWatchCall) SupportsAllDrives(supportsAllDrives bool) *FilesWatchCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) return c } -// ProgressUpdater provides a callback function that will be called -// after every chunk. It should be a low-latency function in order to -// not slow down the upload operation. This should only be called when -// using ResumableMedia (as opposed to Media). -func (c *FilesCreateCall) ProgressUpdater(pu googleapi.ProgressUpdater) *FilesCreateCall { - c.progressUpdater_ = pu +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *FilesWatchCall) SupportsTeamDrives(supportsTeamDrives bool) *FilesWatchCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesCreateCall) Fields(s ...googleapi.Field) *FilesCreateCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *FilesWatchCall) Fields(s ...googleapi.Field) *FilesWatchCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -// This context will supersede any context previously provided to the -// ResumableMedia method. -func (c *FilesCreateCall) Context(ctx context.Context) *FilesCreateCall { +// Context sets the context to be used in this call's Do method. +func (c *FilesWatchCall) Context(ctx context.Context) *FilesWatchCall { c.ctx_ = ctx return c } -func (c *FilesCreateCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *FilesWatchCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *FilesWatchCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.file) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.channel) if err != nil { return nil, err } - ctype := "application/json" c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files") - if c.media_ != nil || c.resumableBuffer_ != nil { - urls = strings.Replace(urls, "https://www.googleapis.com/", "https://www.googleapis.com/upload/", 1) - protocol := "multipart" - if c.resumableBuffer_ != nil { - protocol = "resumable" - } - c.urlParams_.Set("uploadType", protocol) - } + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/watch") urls += "?" + c.urlParams_.Encode() - if c.media_ != nil { - var combined io.ReadCloser - combined, ctype = gensupport.CombineBodyMedia(body, ctype, c.media_, c.mediaType_) - defer combined.Close() - body = combined - } - req, _ := http.NewRequest("POST", urls, body) - googleapi.SetOpaque(req.URL) - if c.resumableBuffer_ != nil && c.mediaType_ != "" { - req.Header.Set("X-Upload-Content-Type", c.mediaType_) - } - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.files.create" call. -// Exactly one of *File or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *File.ServerResponse.Header or (if a response was returned at all) in +// Do executes the "drive.files.watch" call. +// Any non-2xx status code is an error. Response headers are in either +// *Channel.ServerResponse.Header or (if a response was returned at all) in // error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check -// whether the returned error was because http.StatusNotModified was -// returned. -func (c *FilesCreateCall) Do(opts ...googleapi.CallOption) (*File, error) { +// whether the returned error was because http.StatusNotModified was returned. +func (c *FilesWatchCall) Do(opts ...googleapi.CallOption) (*Channel, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - if c.resumableBuffer_ != nil { - loc := res.Header.Get("Location") - rx := &gensupport.ResumableUpload{ - Client: c.s.client, - UserAgent: c.s.userAgent(), - URI: loc, - Media: c.resumableBuffer_, - MediaType: c.mediaType_, - Callback: func(curr int64) { - if c.progressUpdater_ != nil { - c.progressUpdater_(curr, c.mediaSize_) - } - }, - } - ctx := c.ctx_ - if ctx == nil { - ctx = context.TODO() - } - res, err = rx.Upload(ctx) - if err != nil { - return nil, err - } - defer res.Body.Close() - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } + return nil, gensupport.WrapError(err) } - ret := &File{ + ret := &Channel{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Creates a new file.", - // "httpMethod": "POST", - // "id": "drive.files.create", - // "mediaUpload": { - // "accept": [ - // "*/*" - // ], - // "maxSize": "5120GB", - // "protocols": { - // "resumable": { - // "multipart": true, - // "path": "/resumable/upload/drive/v3/files" - // }, - // "simple": { - // "multipart": true, - // "path": "/upload/drive/v3/files" - // } - // } - // }, - // "parameters": { - // "ignoreDefaultVisibility": { - // "default": "false", - // "description": "Whether to ignore the domain's default visibility settings for the created file. Domain administrators can choose to make all uploaded files visible to the domain by default; this parameter bypasses that behavior for the request. Permissions are still inherited from parent folders.", - // "location": "query", - // "type": "boolean" - // }, - // "keepRevisionForever": { - // "default": "false", - // "description": "Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Drive.", - // "location": "query", - // "type": "boolean" - // }, - // "ocrLanguage": { - // "description": "A language hint for OCR processing during image import (ISO 639-1 code).", - // "location": "query", - // "type": "string" - // }, - // "useContentAsIndexableText": { - // "default": "false", - // "description": "Whether to use the uploaded content as indexable text.", - // "location": "query", - // "type": "boolean" - // } - // }, - // "path": "files", - // "request": { - // "$ref": "File" - // }, - // "response": { - // "$ref": "File" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file" - // ], - // "supportsMediaUpload": true, - // "supportsSubscription": true - // } - -} - -// method id "drive.files.delete": +} -type FilesDeleteCall struct { +type OperationCancelCall struct { s *Service - fileId string + name string urlParams_ gensupport.URLParams ctx_ context.Context -} - -// Delete: Permanently deletes a file owned by the user without moving -// it to the trash. If the target is a folder, all descendants owned by -// the user are also deleted. -func (r *FilesService) Delete(fileId string) *FilesDeleteCall { - c := &FilesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId + header_ http.Header +} + +// Cancel: Starts asynchronous cancellation on a long-running operation. The +// server makes a best effort to cancel the operation, but success is not +// guaranteed. If the server doesn't support this method, it returns +// `google.rpc.Code.UNIMPLEMENTED`. Clients can use Operations.GetOperation or +// other methods to check whether the cancellation succeeded or whether the +// operation completed despite cancellation. On successful cancellation, the +// operation is not deleted; instead, it becomes an operation with an +// Operation.error value with a google.rpc.Status.code of `1`, corresponding to +// `Code.CANCELLED`. +// +// - name: The name of the operation resource to be cancelled. +func (r *OperationService) Cancel(name string) *OperationCancelCall { + c := &OperationCancelCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesDeleteCall) Fields(s ...googleapi.Field) *FilesDeleteCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *OperationCancelCall) Fields(s ...googleapi.Field) *OperationCancelCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *FilesDeleteCall) Context(ctx context.Context) *FilesDeleteCall { +// Context sets the context to be used in this call's Do method. +func (c *OperationCancelCall) Context(ctx context.Context) *OperationCancelCall { c.ctx_ = ctx return c } -func (c *FilesDeleteCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *OperationCancelCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OperationCancelCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "operation/{name}:cancel") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, + "name": c.name, }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.files.delete" call. -func (c *FilesDeleteCall) Do(opts ...googleapi.CallOption) error { +// Do executes the "drive.operation.cancel" call. +func (c *OperationCancelCall) Do(opts ...googleapi.CallOption) error { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if err != nil { @@ -3257,80 +7884,74 @@ func (c *FilesDeleteCall) Do(opts ...googleapi.CallOption) error { } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return err + return gensupport.WrapError(err) } return nil - // { - // "description": "Permanently deletes a file owned by the user without moving it to the trash. If the target is a folder, all descendants owned by the user are also deleted.", - // "httpMethod": "DELETE", - // "id": "drive.files.delete", - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}", - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.files.emptyTrash": +} -type FilesEmptyTrashCall struct { +type OperationDeleteCall struct { s *Service + name string urlParams_ gensupport.URLParams ctx_ context.Context + header_ http.Header } -// EmptyTrash: Permanently deletes all of the user's trashed files. -func (r *FilesService) EmptyTrash() *FilesEmptyTrashCall { - c := &FilesEmptyTrashCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Delete: Deletes a long-running operation. This method indicates that the +// client is no longer interested in the operation result. It does not cancel +// the operation. If the server doesn't support this method, it returns +// `google.rpc.Code.UNIMPLEMENTED`. +// +// - name: The name of the operation resource to be deleted. +func (r *OperationService) Delete(name string) *OperationDeleteCall { + c := &OperationDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesEmptyTrashCall) Fields(s ...googleapi.Field) *FilesEmptyTrashCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *OperationDeleteCall) Fields(s ...googleapi.Field) *OperationDeleteCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *FilesEmptyTrashCall) Context(ctx context.Context) *FilesEmptyTrashCall { +// Context sets the context to be used in this call's Do method. +func (c *OperationDeleteCall) Context(ctx context.Context) *OperationDeleteCall { c.ctx_ = ctx return c } -func (c *FilesEmptyTrashCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *OperationDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OperationDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/trash") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "operation/{name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) - googleapi.SetOpaque(req.URL) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.files.emptyTrash" call. -func (c *FilesEmptyTrashCall) Do(opts ...googleapi.CallOption) error { +// Do executes the "drive.operation.delete" call. +func (c *OperationDeleteCall) Do(opts ...googleapi.CallOption) error { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if err != nil { @@ -3338,1375 +7959,1172 @@ func (c *FilesEmptyTrashCall) Do(opts ...googleapi.CallOption) error { } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return err + return gensupport.WrapError(err) } return nil - // { - // "description": "Permanently deletes all of the user's trashed files.", - // "httpMethod": "DELETE", - // "id": "drive.files.emptyTrash", - // "path": "files/trash", - // "scopes": [ - // "https://www.googleapis.com/auth/drive" - // ] - // } - } -// method id "drive.files.export": - -type FilesExportCall struct { +type OperationsGetCall struct { s *Service - fileId string + name string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// Export: Exports a Google Doc to the requested MIME type and returns -// the exported content. -func (r *FilesService) Export(fileId string, mimeType string) *FilesExportCall { - c := &FilesExportCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId - c.urlParams_.Set("mimeType", mimeType) +// Get: Gets the latest state of a long-running operation. Clients can use this +// method to poll the operation result at intervals as recommended by the API +// service. +// +// - name: The name of the operation resource. +func (r *OperationsService) Get(name string) *OperationsGetCall { + c := &OperationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesExportCall) Fields(s ...googleapi.Field) *FilesExportCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *OperationsGetCall) Fields(s ...googleapi.Field) *OperationsGetCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *FilesExportCall) IfNoneMatch(entityTag string) *FilesExportCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *OperationsGetCall) IfNoneMatch(entityTag string) *OperationsGetCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do and Download -// methods. Any pending HTTP request will be aborted if the provided -// context is canceled. -func (c *FilesExportCall) Context(ctx context.Context) *FilesExportCall { +// Context sets the context to be used in this call's Do method. +func (c *OperationsGetCall) Context(ctx context.Context) *OperationsGetCall { c.ctx_ = ctx return c } -func (c *FilesExportCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *OperationsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OperationsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/export") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "operations/{name}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, + "name": c.name, }) - req.Header.Set("User-Agent", c.s.userAgent()) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.operations.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *Operation.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *OperationsGetCall) Do(opts ...googleapi.CallOption) (*Operation, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &Operation{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +type OperationsListCall struct { + s *Service + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header +} + +// List: Lists operations that match the specified filter in the request. If +// the server doesn't support this method, it returns `UNIMPLEMENTED`. +func (r *OperationsService) List() *OperationsListCall { + c := &OperationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + return c +} + +// Filter sets the optional parameter "filter": The standard list filter. +func (c *OperationsListCall) Filter(filter string) *OperationsListCall { + c.urlParams_.Set("filter", filter) + return c +} + +// Name sets the optional parameter "name": The name of the operation's parent +// resource. +func (c *OperationsListCall) Name(name string) *OperationsListCall { + c.urlParams_.Set("name", name) + return c +} + +// PageSize sets the optional parameter "pageSize": The standard list page +// size. +func (c *OperationsListCall) PageSize(pageSize int64) *OperationsListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": The standard list page +// token. +func (c *OperationsListCall) PageToken(pageToken string) *OperationsListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *OperationsListCall) Fields(s ...googleapi.Field) *OperationsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *OperationsListCall) IfNoneMatch(entityTag string) *OperationsListCall { + c.ifNoneMatch_ = entityTag + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *OperationsListCall) Context(ctx context.Context) *OperationsListCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *OperationsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *OperationsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "operations") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Download fetches the API endpoint's "media" value, instead of the normal -// API response value. If the returned error is nil, the Response is guaranteed to -// have a 2xx status code. Callers must close the Response.Body as usual. -func (c *FilesExportCall) Download(opts ...googleapi.CallOption) (*http.Response, error) { +// Do executes the "drive.operations.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *ListOperationsResponse.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to +// check whether the returned error was because http.StatusNotModified was +// returned. +func (c *OperationsListCall) Do(opts ...googleapi.CallOption) (*ListOperationsResponse, error) { gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("media") + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } if err != nil { return nil, err } - if err := googleapi.CheckMediaResponse(res); err != nil { - res.Body.Close() + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &ListOperationsResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } - return res, nil + return ret, nil +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *OperationsListCall) Pages(ctx context.Context, f func(*ListOperationsResponse) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +type PermissionsCreateCall struct { + s *Service + fileId string + permission *Permission + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Create: Creates a permission for a file or shared drive. **Warning:** +// Concurrent permissions operations on the same file are not supported; only +// the last update is applied. +// +// - fileId: The ID of the file or shared drive. +func (r *PermissionsService) Create(fileId string, permission *Permission) *PermissionsCreateCall { + c := &PermissionsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.permission = permission + return c +} + +// EmailMessage sets the optional parameter "emailMessage": A plain text custom +// message to include in the notification email. +func (c *PermissionsCreateCall) EmailMessage(emailMessage string) *PermissionsCreateCall { + c.urlParams_.Set("emailMessage", emailMessage) + return c } -// Do executes the "drive.files.export" call. -func (c *FilesExportCall) Do(opts ...googleapi.CallOption) error { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if err != nil { - return err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return err - } - return nil - // { - // "description": "Exports a Google Doc to the requested MIME type and returns the exported content.", - // "httpMethod": "GET", - // "id": "drive.files.export", - // "parameterOrder": [ - // "fileId", - // "mimeType" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "mimeType": { - // "description": "The MIME type of the format requested for this export.", - // "location": "query", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/export", - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.readonly" - // ], - // "supportsMediaDownload": true - // } - -} - -// method id "drive.files.generateIds": +// EnforceSingleParent sets the optional parameter "enforceSingleParent": +// Deprecated: See `moveToNewOwnersRoot` for details. +func (c *PermissionsCreateCall) EnforceSingleParent(enforceSingleParent bool) *PermissionsCreateCall { + c.urlParams_.Set("enforceSingleParent", fmt.Sprint(enforceSingleParent)) + return c +} -type FilesGenerateIdsCall struct { - s *Service - urlParams_ gensupport.URLParams - ifNoneMatch_ string - ctx_ context.Context +// MoveToNewOwnersRoot sets the optional parameter "moveToNewOwnersRoot": This +// parameter will only take effect if the item is not in a shared drive and the +// request is attempting to transfer the ownership of the item. If set to +// `true`, the item will be moved to the new owner's My Drive root folder and +// all prior parents removed. If set to `false`, parents are not changed. +func (c *PermissionsCreateCall) MoveToNewOwnersRoot(moveToNewOwnersRoot bool) *PermissionsCreateCall { + c.urlParams_.Set("moveToNewOwnersRoot", fmt.Sprint(moveToNewOwnersRoot)) + return c } -// GenerateIds: Generates a set of file IDs which can be provided in -// create requests. -func (r *FilesService) GenerateIds() *FilesGenerateIdsCall { - c := &FilesGenerateIdsCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// SendNotificationEmail sets the optional parameter "sendNotificationEmail": +// Whether to send a notification email when sharing to users or groups. This +// defaults to true for users and groups, and is not allowed for other +// requests. It must not be disabled for ownership transfers. +func (c *PermissionsCreateCall) SendNotificationEmail(sendNotificationEmail bool) *PermissionsCreateCall { + c.urlParams_.Set("sendNotificationEmail", fmt.Sprint(sendNotificationEmail)) return c } -// Count sets the optional parameter "count": The number of IDs to -// return. -func (c *FilesGenerateIdsCall) Count(count int64) *FilesGenerateIdsCall { - c.urlParams_.Set("count", fmt.Sprint(count)) +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *PermissionsCreateCall) SupportsAllDrives(supportsAllDrives bool) *PermissionsCreateCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) return c } -// Space sets the optional parameter "space": The space in which the IDs -// can be used to create new files. Supported values are 'drive' and -// 'appDataFolder'. -func (c *FilesGenerateIdsCall) Space(space string) *FilesGenerateIdsCall { - c.urlParams_.Set("space", space) +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *PermissionsCreateCall) SupportsTeamDrives(supportsTeamDrives bool) *PermissionsCreateCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) return c } -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesGenerateIdsCall) Fields(s ...googleapi.Field) *FilesGenerateIdsCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) +// TransferOwnership sets the optional parameter "transferOwnership": Whether +// to transfer ownership to the specified user and downgrade the current owner +// to a writer. This parameter is required as an acknowledgement of the side +// effect. +func (c *PermissionsCreateCall) TransferOwnership(transferOwnership bool) *PermissionsCreateCall { + c.urlParams_.Set("transferOwnership", fmt.Sprint(transferOwnership)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *FilesGenerateIdsCall) IfNoneMatch(entityTag string) *FilesGenerateIdsCall { - c.ifNoneMatch_ = entityTag +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if the file ID parameter refers to a shared +// drive and the requester is an administrator of the domain to which the +// shared drive belongs. +func (c *PermissionsCreateCall) UseDomainAdminAccess(useDomainAdminAccess bool) *PermissionsCreateCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *FilesGenerateIdsCall) Context(ctx context.Context) *FilesGenerateIdsCall { +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *PermissionsCreateCall) Fields(s ...googleapi.Field) *PermissionsCreateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *PermissionsCreateCall) Context(ctx context.Context) *PermissionsCreateCall { c.ctx_ = ctx return c } -func (c *FilesGenerateIdsCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *PermissionsCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *PermissionsCreateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.permission) + if err != nil { + return nil, err + } c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/generateIds") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - googleapi.SetOpaque(req.URL) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) - } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.files.generateIds" call. -// Exactly one of *GeneratedIds or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *GeneratedIds.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *FilesGenerateIdsCall) Do(opts ...googleapi.CallOption) (*GeneratedIds, error) { +// Do executes the "drive.permissions.create" call. +// Any non-2xx status code is an error. Response headers are in either +// *Permission.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *PermissionsCreateCall) Do(opts ...googleapi.CallOption) (*Permission, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &GeneratedIds{ + ret := &Permission{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Generates a set of file IDs which can be provided in create requests.", - // "httpMethod": "GET", - // "id": "drive.files.generateIds", - // "parameters": { - // "count": { - // "default": "10", - // "description": "The number of IDs to return.", - // "format": "int32", - // "location": "query", - // "maximum": "1000", - // "minimum": "1", - // "type": "integer" - // }, - // "space": { - // "default": "drive", - // "description": "The space in which the IDs can be used to create new files. Supported values are 'drive' and 'appDataFolder'.", - // "location": "query", - // "type": "string" - // } - // }, - // "path": "files/generateIds", - // "response": { - // "$ref": "GeneratedIds" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.files.get": +} -type FilesGetCall struct { +type PermissionsDeleteCall struct { s *Service fileId string + permissionId string urlParams_ gensupport.URLParams - ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// Get: Gets a file's metadata or content by ID. -func (r *FilesService) Get(fileId string) *FilesGetCall { - c := &FilesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Delete: Deletes a permission. **Warning:** Concurrent permissions operations +// on the same file are not supported; only the last update is applied. +// +// - fileId: The ID of the file or shared drive. +// - permissionId: The ID of the permission. +func (r *PermissionsService) Delete(fileId string, permissionId string) *PermissionsDeleteCall { + c := &PermissionsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId + c.permissionId = permissionId return c } -// AcknowledgeAbuse sets the optional parameter "acknowledgeAbuse": -// Whether the user is acknowledging the risk of downloading known -// malware or other abusive files. This is only applicable when -// alt=media. -func (c *FilesGetCall) AcknowledgeAbuse(acknowledgeAbuse bool) *FilesGetCall { - c.urlParams_.Set("acknowledgeAbuse", fmt.Sprint(acknowledgeAbuse)) +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *PermissionsDeleteCall) SupportsAllDrives(supportsAllDrives bool) *PermissionsDeleteCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) return c } -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesGetCall) Fields(s ...googleapi.Field) *FilesGetCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *PermissionsDeleteCall) SupportsTeamDrives(supportsTeamDrives bool) *PermissionsDeleteCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *FilesGetCall) IfNoneMatch(entityTag string) *FilesGetCall { - c.ifNoneMatch_ = entityTag +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if the file ID parameter refers to a shared +// drive and the requester is an administrator of the domain to which the +// shared drive belongs. +func (c *PermissionsDeleteCall) UseDomainAdminAccess(useDomainAdminAccess bool) *PermissionsDeleteCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) return c } -// Context sets the context to be used in this call's Do and Download -// methods. Any pending HTTP request will be aborted if the provided -// context is canceled. -func (c *FilesGetCall) Context(ctx context.Context) *FilesGetCall { +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *PermissionsDeleteCall) Fields(s ...googleapi.Field) *PermissionsDeleteCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *PermissionsDeleteCall) Context(ctx context.Context) *PermissionsDeleteCall { c.ctx_ = ctx return c } -func (c *FilesGetCall) doRequest(alt string) (*http.Response, error) { - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *PermissionsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return c.header_ } -// Download fetches the API endpoint's "media" value, instead of the normal -// API response value. If the returned error is nil, the Response is guaranteed to -// have a 2xx status code. Callers must close the Response.Body as usual. -func (c *FilesGetCall) Download(opts ...googleapi.CallOption) (*http.Response, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("media") +func (c *PermissionsDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions/{permissionId}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("DELETE", urls, body) if err != nil { return nil, err } - if err := googleapi.CheckMediaResponse(res); err != nil { - res.Body.Close() - return nil, err - } - return res, nil + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + "permissionId": c.permissionId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.files.get" call. -// Exactly one of *File or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *File.ServerResponse.Header or (if a response was returned at all) in -// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check -// whether the returned error was because http.StatusNotModified was -// returned. -func (c *FilesGetCall) Do(opts ...googleapi.CallOption) (*File, error) { +// Do executes the "drive.permissions.delete" call. +func (c *PermissionsDeleteCall) Do(opts ...googleapi.CallOption) error { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } if err != nil { - return nil, err + return err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &File{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { - return nil, err + return gensupport.WrapError(err) } - return ret, nil - // { - // "description": "Gets a file's metadata or content by ID.", - // "httpMethod": "GET", - // "id": "drive.files.get", - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "acknowledgeAbuse": { - // "default": "false", - // "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when alt=media.", - // "location": "query", - // "type": "boolean" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}", - // "response": { - // "$ref": "File" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ], - // "supportsMediaDownload": true, - // "supportsSubscription": true, - // "useMediaDownloadService": true - // } - -} - -// method id "drive.files.list": + return nil +} -type FilesListCall struct { +type PermissionsGetCall struct { s *Service + fileId string + permissionId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// List: Lists or searches files. -func (r *FilesService) List() *FilesListCall { - c := &FilesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - return c -} - -// Corpus sets the optional parameter "corpus": The source of files to -// list. +// Get: Gets a permission by ID. // -// Possible values: -// "domain" - Files shared to the user's domain. -// "user" (default) - Files owned by or shared to the user. -func (c *FilesListCall) Corpus(corpus string) *FilesListCall { - c.urlParams_.Set("corpus", corpus) - return c -} - -// OrderBy sets the optional parameter "orderBy": A comma-separated list -// of sort keys. Valid keys are 'createdTime', 'folder', -// 'modifiedByMeTime', 'modifiedTime', 'name', 'quotaBytesUsed', -// 'recency', 'sharedWithMeTime', 'starred', and 'viewedByMeTime'. Each -// key sorts ascending by default, but may be reversed with the 'desc' -// modifier. Example usage: ?orderBy=folder,modifiedTime desc,name. -// Please note that there is a current limitation for users with -// approximately one million files in which the requested sort order is -// ignored. -func (c *FilesListCall) OrderBy(orderBy string) *FilesListCall { - c.urlParams_.Set("orderBy", orderBy) - return c -} - -// PageSize sets the optional parameter "pageSize": The maximum number -// of files to return per page. -func (c *FilesListCall) PageSize(pageSize int64) *FilesListCall { - c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) +// - fileId: The ID of the file. +// - permissionId: The ID of the permission. +func (r *PermissionsService) Get(fileId string, permissionId string) *PermissionsGetCall { + c := &PermissionsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.permissionId = permissionId return c } -// PageToken sets the optional parameter "pageToken": The token for -// continuing a previous list request on the next page. This should be -// set to the value of 'nextPageToken' from the previous response. -func (c *FilesListCall) PageToken(pageToken string) *FilesListCall { - c.urlParams_.Set("pageToken", pageToken) +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *PermissionsGetCall) SupportsAllDrives(supportsAllDrives bool) *PermissionsGetCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) return c } -// Q sets the optional parameter "q": A query for filtering the file -// results. See the "Search for Files" guide for supported syntax. -func (c *FilesListCall) Q(q string) *FilesListCall { - c.urlParams_.Set("q", q) +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *PermissionsGetCall) SupportsTeamDrives(supportsTeamDrives bool) *PermissionsGetCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) return c } -// Spaces sets the optional parameter "spaces": A comma-separated list -// of spaces to query within the corpus. Supported values are 'drive', -// 'appDataFolder' and 'photos'. -func (c *FilesListCall) Spaces(spaces string) *FilesListCall { - c.urlParams_.Set("spaces", spaces) +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if the file ID parameter refers to a shared +// drive and the requester is an administrator of the domain to which the +// shared drive belongs. +func (c *PermissionsGetCall) UseDomainAdminAccess(useDomainAdminAccess bool) *PermissionsGetCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesListCall) Fields(s ...googleapi.Field) *FilesListCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *PermissionsGetCall) Fields(s ...googleapi.Field) *PermissionsGetCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *FilesListCall) IfNoneMatch(entityTag string) *FilesListCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *PermissionsGetCall) IfNoneMatch(entityTag string) *PermissionsGetCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *FilesListCall) Context(ctx context.Context) *FilesListCall { +// Context sets the context to be used in this call's Do method. +func (c *PermissionsGetCall) Context(ctx context.Context) *PermissionsGetCall { c.ctx_ = ctx return c } -func (c *FilesListCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *PermissionsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *PermissionsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions/{permissionId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - googleapi.SetOpaque(req.URL) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) - } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + "permissionId": c.permissionId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.files.list" call. -// Exactly one of *FileList or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *FileList.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *FilesListCall) Do(opts ...googleapi.CallOption) (*FileList, error) { +// Do executes the "drive.permissions.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *Permission.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *PermissionsGetCall) Do(opts ...googleapi.CallOption) (*Permission, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &FileList{ + ret := &Permission{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Lists or searches files.", - // "httpMethod": "GET", - // "id": "drive.files.list", - // "parameters": { - // "corpus": { - // "default": "user", - // "description": "The source of files to list.", - // "enum": [ - // "domain", - // "user" - // ], - // "enumDescriptions": [ - // "Files shared to the user's domain.", - // "Files owned by or shared to the user." - // ], - // "location": "query", - // "type": "string" - // }, - // "orderBy": { - // "description": "A comma-separated list of sort keys. Valid keys are 'createdTime', 'folder', 'modifiedByMeTime', 'modifiedTime', 'name', 'quotaBytesUsed', 'recency', 'sharedWithMeTime', 'starred', and 'viewedByMeTime'. Each key sorts ascending by default, but may be reversed with the 'desc' modifier. Example usage: ?orderBy=folder,modifiedTime desc,name. Please note that there is a current limitation for users with approximately one million files in which the requested sort order is ignored.", - // "location": "query", - // "type": "string" - // }, - // "pageSize": { - // "default": "100", - // "description": "The maximum number of files to return per page.", - // "format": "int32", - // "location": "query", - // "maximum": "1000", - // "minimum": "1", - // "type": "integer" - // }, - // "pageToken": { - // "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", - // "location": "query", - // "type": "string" - // }, - // "q": { - // "description": "A query for filtering the file results. See the \"Search for Files\" guide for supported syntax.", - // "location": "query", - // "type": "string" - // }, - // "spaces": { - // "default": "drive", - // "description": "A comma-separated list of spaces to query within the corpus. Supported values are 'drive', 'appDataFolder' and 'photos'.", - // "location": "query", - // "type": "string" - // } - // }, - // "path": "files", - // "response": { - // "$ref": "FileList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// Pages invokes f for each page of results. -// A non-nil error returned from f will halt the iteration. -// The provided context supersedes any context provided to the Context method. -func (c *FilesListCall) Pages(ctx context.Context, f func(*FileList) error) error { - c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point - for { - x, err := c.Do() - if err != nil { - return err - } - if err := f(x); err != nil { - return err - } - if x.NextPageToken == "" { - return nil - } - c.PageToken(x.NextPageToken) - } } -// method id "drive.files.update": - -type FilesUpdateCall struct { - s *Service - fileId string - file *File - urlParams_ gensupport.URLParams - media_ io.Reader - resumableBuffer_ *gensupport.ResumableBuffer - mediaType_ string - mediaSize_ int64 // mediaSize, if known. Used only for calls to progressUpdater_. - progressUpdater_ googleapi.ProgressUpdater - ctx_ context.Context -} - -// Update: Updates a file's metadata and/or content with patch -// semantics. -func (r *FilesService) Update(fileId string, file *File) *FilesUpdateCall { - c := &FilesUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId - c.file = file - return c +type PermissionsListCall struct { + s *Service + fileId string + urlParams_ gensupport.URLParams + ifNoneMatch_ string + ctx_ context.Context + header_ http.Header } -// AddParents sets the optional parameter "addParents": A -// comma-separated list of parent IDs to add. -func (c *FilesUpdateCall) AddParents(addParents string) *FilesUpdateCall { - c.urlParams_.Set("addParents", addParents) +// List: Lists a file's or shared drive's permissions. +// +// - fileId: The ID of the file or shared drive. +func (r *PermissionsService) List(fileId string) *PermissionsListCall { + c := &PermissionsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId return c } -// KeepRevisionForever sets the optional parameter -// "keepRevisionForever": Whether to set the 'keepForever' field in the -// new head revision. This is only applicable to files with binary -// content in Drive. -func (c *FilesUpdateCall) KeepRevisionForever(keepRevisionForever bool) *FilesUpdateCall { - c.urlParams_.Set("keepRevisionForever", fmt.Sprint(keepRevisionForever)) +// IncludePermissionsForView sets the optional parameter +// "includePermissionsForView": Specifies which additional view's permissions +// to include in the response. Only 'published' is supported. +func (c *PermissionsListCall) IncludePermissionsForView(includePermissionsForView string) *PermissionsListCall { + c.urlParams_.Set("includePermissionsForView", includePermissionsForView) return c } -// OcrLanguage sets the optional parameter "ocrLanguage": A language -// hint for OCR processing during image import (ISO 639-1 code). -func (c *FilesUpdateCall) OcrLanguage(ocrLanguage string) *FilesUpdateCall { - c.urlParams_.Set("ocrLanguage", ocrLanguage) +// PageSize sets the optional parameter "pageSize": The maximum number of +// permissions to return per page. When not set for files in a shared drive, at +// most 100 results will be returned. When not set for files that are not in a +// shared drive, the entire list will be returned. +func (c *PermissionsListCall) PageSize(pageSize int64) *PermissionsListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) return c } -// RemoveParents sets the optional parameter "removeParents": A -// comma-separated list of parent IDs to remove. -func (c *FilesUpdateCall) RemoveParents(removeParents string) *FilesUpdateCall { - c.urlParams_.Set("removeParents", removeParents) +// PageToken sets the optional parameter "pageToken": The token for continuing +// a previous list request on the next page. This should be set to the value of +// 'nextPageToken' from the previous response. +func (c *PermissionsListCall) PageToken(pageToken string) *PermissionsListCall { + c.urlParams_.Set("pageToken", pageToken) return c } -// UseContentAsIndexableText sets the optional parameter -// "useContentAsIndexableText": Whether to use the uploaded content as -// indexable text. -func (c *FilesUpdateCall) UseContentAsIndexableText(useContentAsIndexableText bool) *FilesUpdateCall { - c.urlParams_.Set("useContentAsIndexableText", fmt.Sprint(useContentAsIndexableText)) +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *PermissionsListCall) SupportsAllDrives(supportsAllDrives bool) *PermissionsListCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) return c } -// Media specifies the media to upload in one or more chunks. The chunk -// size may be controlled by supplying a MediaOption generated by -// googleapi.ChunkSize. The chunk size defaults to -// googleapi.DefaultUploadChunkSize.The Content-Type header used in the -// upload request will be determined by sniffing the contents of r, -// unless a MediaOption generated by googleapi.ContentType is -// supplied. -// At most one of Media and ResumableMedia may be set. -func (c *FilesUpdateCall) Media(r io.Reader, options ...googleapi.MediaOption) *FilesUpdateCall { - opts := googleapi.ProcessMediaOptions(options) - chunkSize := opts.ChunkSize - if !opts.ForceEmptyContentType { - r, c.mediaType_ = gensupport.DetermineContentType(r, opts.ContentType) - } - c.media_, c.resumableBuffer_ = gensupport.PrepareUpload(r, chunkSize) +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *PermissionsListCall) SupportsTeamDrives(supportsTeamDrives bool) *PermissionsListCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) return c } -// ResumableMedia specifies the media to upload in chunks and can be -// canceled with ctx. -// -// Deprecated: use Media instead. -// -// At most one of Media and ResumableMedia may be set. mediaType -// identifies the MIME media type of the upload, such as "image/png". If -// mediaType is "", it will be auto-detected. The provided ctx will -// supersede any context previously provided to the Context method. -func (c *FilesUpdateCall) ResumableMedia(ctx context.Context, r io.ReaderAt, size int64, mediaType string) *FilesUpdateCall { - c.ctx_ = ctx - rdr := gensupport.ReaderAtToReader(r, size) - rdr, c.mediaType_ = gensupport.DetermineContentType(rdr, mediaType) - c.resumableBuffer_ = gensupport.NewResumableBuffer(rdr, googleapi.DefaultUploadChunkSize) - c.media_ = nil - c.mediaSize_ = size +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if the file ID parameter refers to a shared +// drive and the requester is an administrator of the domain to which the +// shared drive belongs. +func (c *PermissionsListCall) UseDomainAdminAccess(useDomainAdminAccess bool) *PermissionsListCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) return c } -// ProgressUpdater provides a callback function that will be called -// after every chunk. It should be a low-latency function in order to -// not slow down the upload operation. This should only be called when -// using ResumableMedia (as opposed to Media). -func (c *FilesUpdateCall) ProgressUpdater(pu googleapi.ProgressUpdater) *FilesUpdateCall { - c.progressUpdater_ = pu +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *PermissionsListCall) Fields(s ...googleapi.Field) *PermissionsListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesUpdateCall) Fields(s ...googleapi.Field) *FilesUpdateCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *PermissionsListCall) IfNoneMatch(entityTag string) *PermissionsListCall { + c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -// This context will supersede any context previously provided to the -// ResumableMedia method. -func (c *FilesUpdateCall) Context(ctx context.Context) *FilesUpdateCall { +// Context sets the context to be used in this call's Do method. +func (c *PermissionsListCall) Context(ctx context.Context) *PermissionsListCall { c.ctx_ = ctx return c } -func (c *FilesUpdateCall) doRequest(alt string) (*http.Response, error) { - var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.file) - if err != nil { - return nil, err +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *PermissionsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) } - ctype := "application/json" - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}") - if c.media_ != nil || c.resumableBuffer_ != nil { - urls = strings.Replace(urls, "https://www.googleapis.com/", "https://www.googleapis.com/upload/", 1) - protocol := "multipart" - if c.resumableBuffer_ != nil { - protocol = "resumable" - } - c.urlParams_.Set("uploadType", protocol) + return c.header_ +} + +func (c *PermissionsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) } + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions") urls += "?" + c.urlParams_.Encode() - if c.media_ != nil { - var combined io.ReadCloser - combined, ctype = gensupport.CombineBodyMedia(body, ctype, c.media_, c.mediaType_) - defer combined.Close() - body = combined + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - req, _ := http.NewRequest("PATCH", urls, body) + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "fileId": c.fileId, }) - if c.resumableBuffer_ != nil && c.mediaType_ != "" { - req.Header.Set("X-Upload-Content-Type", c.mediaType_) - } - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.files.update" call. -// Exactly one of *File or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *File.ServerResponse.Header or (if a response was returned at all) in -// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check -// whether the returned error was because http.StatusNotModified was -// returned. -func (c *FilesUpdateCall) Do(opts ...googleapi.CallOption) (*File, error) { +// Do executes the "drive.permissions.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *PermissionList.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *PermissionsListCall) Do(opts ...googleapi.CallOption) (*PermissionList, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - if c.resumableBuffer_ != nil { - loc := res.Header.Get("Location") - rx := &gensupport.ResumableUpload{ - Client: c.s.client, - UserAgent: c.s.userAgent(), - URI: loc, - Media: c.resumableBuffer_, - MediaType: c.mediaType_, - Callback: func(curr int64) { - if c.progressUpdater_ != nil { - c.progressUpdater_(curr, c.mediaSize_) - } - }, - } - ctx := c.ctx_ - if ctx == nil { - ctx = context.TODO() - } - res, err = rx.Upload(ctx) - if err != nil { - return nil, err - } - defer res.Body.Close() - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } + return nil, gensupport.WrapError(err) } - ret := &File{ + ret := &PermissionList{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Updates a file's metadata and/or content with patch semantics.", - // "httpMethod": "PATCH", - // "id": "drive.files.update", - // "mediaUpload": { - // "accept": [ - // "*/*" - // ], - // "maxSize": "5120GB", - // "protocols": { - // "resumable": { - // "multipart": true, - // "path": "/resumable/upload/drive/v3/files/{fileId}" - // }, - // "simple": { - // "multipart": true, - // "path": "/upload/drive/v3/files/{fileId}" - // } - // } - // }, - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "addParents": { - // "description": "A comma-separated list of parent IDs to add.", - // "location": "query", - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "keepRevisionForever": { - // "default": "false", - // "description": "Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Drive.", - // "location": "query", - // "type": "boolean" - // }, - // "ocrLanguage": { - // "description": "A language hint for OCR processing during image import (ISO 639-1 code).", - // "location": "query", - // "type": "string" - // }, - // "removeParents": { - // "description": "A comma-separated list of parent IDs to remove.", - // "location": "query", - // "type": "string" - // }, - // "useContentAsIndexableText": { - // "default": "false", - // "description": "Whether to use the uploaded content as indexable text.", - // "location": "query", - // "type": "boolean" - // } - // }, - // "path": "files/{fileId}", - // "request": { - // "$ref": "File" - // }, - // "response": { - // "$ref": "File" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.scripts" - // ], - // "supportsMediaUpload": true - // } - -} - -// method id "drive.files.watch": +} -type FilesWatchCall struct { - s *Service - fileId string - channel *Channel - urlParams_ gensupport.URLParams - ctx_ context.Context +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *PermissionsListCall) Pages(ctx context.Context, f func(*PermissionList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } } -// Watch: Subscribes to changes to a file -func (r *FilesService) Watch(fileId string, channel *Channel) *FilesWatchCall { - c := &FilesWatchCall{s: r.s, urlParams_: make(gensupport.URLParams)} +type PermissionsUpdateCall struct { + s *Service + fileId string + permissionId string + permission *Permission + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Update: Updates a permission with patch semantics. **Warning:** Concurrent +// permissions operations on the same file are not supported; only the last +// update is applied. +// +// - fileId: The ID of the file or shared drive. +// - permissionId: The ID of the permission. +func (r *PermissionsService) Update(fileId string, permissionId string, permission *Permission) *PermissionsUpdateCall { + c := &PermissionsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId - c.channel = channel + c.permissionId = permissionId + c.permission = permission return c } -// AcknowledgeAbuse sets the optional parameter "acknowledgeAbuse": -// Whether the user is acknowledging the risk of downloading known -// malware or other abusive files. This is only applicable when -// alt=media. -func (c *FilesWatchCall) AcknowledgeAbuse(acknowledgeAbuse bool) *FilesWatchCall { - c.urlParams_.Set("acknowledgeAbuse", fmt.Sprint(acknowledgeAbuse)) +// RemoveExpiration sets the optional parameter "removeExpiration": Whether to +// remove the expiration date. +func (c *PermissionsUpdateCall) RemoveExpiration(removeExpiration bool) *PermissionsUpdateCall { + c.urlParams_.Set("removeExpiration", fmt.Sprint(removeExpiration)) + return c +} + +// SupportsAllDrives sets the optional parameter "supportsAllDrives": Whether +// the requesting application supports both My Drives and shared drives. +func (c *PermissionsUpdateCall) SupportsAllDrives(supportsAllDrives bool) *PermissionsUpdateCall { + c.urlParams_.Set("supportsAllDrives", fmt.Sprint(supportsAllDrives)) + return c +} + +// SupportsTeamDrives sets the optional parameter "supportsTeamDrives": +// Deprecated: Use `supportsAllDrives` instead. +func (c *PermissionsUpdateCall) SupportsTeamDrives(supportsTeamDrives bool) *PermissionsUpdateCall { + c.urlParams_.Set("supportsTeamDrives", fmt.Sprint(supportsTeamDrives)) + return c +} + +// TransferOwnership sets the optional parameter "transferOwnership": Whether +// to transfer ownership to the specified user and downgrade the current owner +// to a writer. This parameter is required as an acknowledgement of the side +// effect. +func (c *PermissionsUpdateCall) TransferOwnership(transferOwnership bool) *PermissionsUpdateCall { + c.urlParams_.Set("transferOwnership", fmt.Sprint(transferOwnership)) + return c +} + +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if the file ID parameter refers to a shared +// drive and the requester is an administrator of the domain to which the +// shared drive belongs. +func (c *PermissionsUpdateCall) UseDomainAdminAccess(useDomainAdminAccess bool) *PermissionsUpdateCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *FilesWatchCall) Fields(s ...googleapi.Field) *FilesWatchCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *PermissionsUpdateCall) Fields(s ...googleapi.Field) *PermissionsUpdateCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do and Download -// methods. Any pending HTTP request will be aborted if the provided -// context is canceled. -func (c *FilesWatchCall) Context(ctx context.Context) *FilesWatchCall { +// Context sets the context to be used in this call's Do method. +func (c *PermissionsUpdateCall) Context(ctx context.Context) *PermissionsUpdateCall { c.ctx_ = ctx return c } -func (c *FilesWatchCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *PermissionsUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *PermissionsUpdateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.channel) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.permission) if err != nil { return nil, err } - ctype := "application/json" c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/watch") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions/{permissionId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) - googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - }) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) -} - -// Download fetches the API endpoint's "media" value, instead of the normal -// API response value. If the returned error is nil, the Response is guaranteed to -// have a 2xx status code. Callers must close the Response.Body as usual. -func (c *FilesWatchCall) Download(opts ...googleapi.CallOption) (*http.Response, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("media") + req, err := http.NewRequest("PATCH", urls, body) if err != nil { return nil, err } - if err := googleapi.CheckMediaResponse(res); err != nil { - res.Body.Close() - return nil, err - } - return res, nil + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + "permissionId": c.permissionId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.files.watch" call. -// Exactly one of *Channel or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Channel.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *FilesWatchCall) Do(opts ...googleapi.CallOption) (*Channel, error) { +// Do executes the "drive.permissions.update" call. +// Any non-2xx status code is an error. Response headers are in either +// *Permission.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *PermissionsUpdateCall) Do(opts ...googleapi.CallOption) (*Permission, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Channel{ + ret := &Permission{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Subscribes to changes to a file", - // "httpMethod": "POST", - // "id": "drive.files.watch", - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "acknowledgeAbuse": { - // "default": "false", - // "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when alt=media.", - // "location": "query", - // "type": "boolean" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/watch", - // "request": { - // "$ref": "Channel", - // "parameterName": "resource" - // }, - // "response": { - // "$ref": "Channel" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ], - // "supportsMediaDownload": true, - // "supportsSubscription": true, - // "useMediaDownloadService": true - // } - -} - -// method id "drive.permissions.create": +} -type PermissionsCreateCall struct { +type RepliesCreateCall struct { s *Service fileId string - permission *Permission + commentId string + reply *Reply urlParams_ gensupport.URLParams ctx_ context.Context + header_ http.Header } -// Create: Creates a permission for a file. -func (r *PermissionsService) Create(fileId string, permission *Permission) *PermissionsCreateCall { - c := &PermissionsCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Create: Creates a reply to a comment. +// +// - commentId: The ID of the comment. +// - fileId: The ID of the file. +func (r *RepliesService) Create(fileId string, commentId string, reply *Reply) *RepliesCreateCall { + c := &RepliesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId - c.permission = permission - return c -} - -// EmailMessage sets the optional parameter "emailMessage": A custom -// message to include in the notification email. -func (c *PermissionsCreateCall) EmailMessage(emailMessage string) *PermissionsCreateCall { - c.urlParams_.Set("emailMessage", emailMessage) - return c -} - -// SendNotificationEmail sets the optional parameter -// "sendNotificationEmail": Whether to send a notification email when -// sharing to users or groups. This defaults to true for users and -// groups, and is not allowed for other requests. It must not be -// disabled for ownership transfers. -func (c *PermissionsCreateCall) SendNotificationEmail(sendNotificationEmail bool) *PermissionsCreateCall { - c.urlParams_.Set("sendNotificationEmail", fmt.Sprint(sendNotificationEmail)) - return c -} - -// TransferOwnership sets the optional parameter "transferOwnership": -// Whether to transfer ownership to the specified user and downgrade the -// current owner to a writer. This parameter is required as an -// acknowledgement of the side effect. -func (c *PermissionsCreateCall) TransferOwnership(transferOwnership bool) *PermissionsCreateCall { - c.urlParams_.Set("transferOwnership", fmt.Sprint(transferOwnership)) + c.commentId = commentId + c.reply = reply return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *PermissionsCreateCall) Fields(s ...googleapi.Field) *PermissionsCreateCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *RepliesCreateCall) Fields(s ...googleapi.Field) *RepliesCreateCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *PermissionsCreateCall) Context(ctx context.Context) *PermissionsCreateCall { +// Context sets the context to be used in this call's Do method. +func (c *RepliesCreateCall) Context(ctx context.Context) *RepliesCreateCall { c.ctx_ = ctx return c } -func (c *PermissionsCreateCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *RepliesCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RepliesCreateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.permission) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.reply) if err != nil { return nil, err } - ctype := "application/json" c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, + "fileId": c.fileId, + "commentId": c.commentId, }) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.permissions.create" call. -// Exactly one of *Permission or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *Permission.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *PermissionsCreateCall) Do(opts ...googleapi.CallOption) (*Permission, error) { +// Do executes the "drive.replies.create" call. +// Any non-2xx status code is an error. Response headers are in either +// *Reply.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *RepliesCreateCall) Do(opts ...googleapi.CallOption) (*Reply, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Permission{ + ret := &Reply{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Creates a permission for a file.", - // "httpMethod": "POST", - // "id": "drive.permissions.create", - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "emailMessage": { - // "description": "A custom message to include in the notification email.", - // "location": "query", - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "sendNotificationEmail": { - // "description": "Whether to send a notification email when sharing to users or groups. This defaults to true for users and groups, and is not allowed for other requests. It must not be disabled for ownership transfers.", - // "location": "query", - // "type": "boolean" - // }, - // "transferOwnership": { - // "default": "false", - // "description": "Whether to transfer ownership to the specified user and downgrade the current owner to a writer. This parameter is required as an acknowledgement of the side effect.", - // "location": "query", - // "type": "boolean" - // } - // }, - // "path": "files/{fileId}/permissions", - // "request": { - // "$ref": "Permission" - // }, - // "response": { - // "$ref": "Permission" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.permissions.delete": +} -type PermissionsDeleteCall struct { - s *Service - fileId string - permissionId string - urlParams_ gensupport.URLParams - ctx_ context.Context +type RepliesDeleteCall struct { + s *Service + fileId string + commentId string + replyId string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header } -// Delete: Deletes a permission. -func (r *PermissionsService) Delete(fileId string, permissionId string) *PermissionsDeleteCall { - c := &PermissionsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Delete: Deletes a reply. +// +// - commentId: The ID of the comment. +// - fileId: The ID of the file. +// - replyId: The ID of the reply. +func (r *RepliesService) Delete(fileId string, commentId string, replyId string) *RepliesDeleteCall { + c := &RepliesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId - c.permissionId = permissionId + c.commentId = commentId + c.replyId = replyId return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *PermissionsDeleteCall) Fields(s ...googleapi.Field) *PermissionsDeleteCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *RepliesDeleteCall) Fields(s ...googleapi.Field) *RepliesDeleteCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *PermissionsDeleteCall) Context(ctx context.Context) *PermissionsDeleteCall { +// Context sets the context to be used in this call's Do method. +func (c *RepliesDeleteCall) Context(ctx context.Context) *RepliesDeleteCall { c.ctx_ = ctx return c } -func (c *PermissionsDeleteCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *RepliesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RepliesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions/{permissionId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies/{replyId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "permissionId": c.permissionId, + "fileId": c.fileId, + "commentId": c.commentId, + "replyId": c.replyId, }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.permissions.delete" call. -func (c *PermissionsDeleteCall) Do(opts ...googleapi.CallOption) error { +// Do executes the "drive.replies.delete" call. +func (c *RepliesDeleteCall) Do(opts ...googleapi.CallOption) error { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if err != nil { @@ -4714,539 +9132,384 @@ func (c *PermissionsDeleteCall) Do(opts ...googleapi.CallOption) error { } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return err + return gensupport.WrapError(err) } return nil - // { - // "description": "Deletes a permission.", - // "httpMethod": "DELETE", - // "id": "drive.permissions.delete", - // "parameterOrder": [ - // "fileId", - // "permissionId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "permissionId": { - // "description": "The ID of the permission.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/permissions/{permissionId}", - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.permissions.get": +} -type PermissionsGetCall struct { +type RepliesGetCall struct { s *Service fileId string - permissionId string + commentId string + replyId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// Get: Gets a permission by ID. -func (r *PermissionsService) Get(fileId string, permissionId string) *PermissionsGetCall { - c := &PermissionsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Get: Gets a reply by ID. +// +// - commentId: The ID of the comment. +// - fileId: The ID of the file. +// - replyId: The ID of the reply. +func (r *RepliesService) Get(fileId string, commentId string, replyId string) *RepliesGetCall { + c := &RepliesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId - c.permissionId = permissionId + c.commentId = commentId + c.replyId = replyId + return c +} + +// IncludeDeleted sets the optional parameter "includeDeleted": Whether to +// return deleted replies. Deleted replies will not include their original +// content. +func (c *RepliesGetCall) IncludeDeleted(includeDeleted bool) *RepliesGetCall { + c.urlParams_.Set("includeDeleted", fmt.Sprint(includeDeleted)) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *PermissionsGetCall) Fields(s ...googleapi.Field) *PermissionsGetCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *RepliesGetCall) Fields(s ...googleapi.Field) *RepliesGetCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *PermissionsGetCall) IfNoneMatch(entityTag string) *PermissionsGetCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *RepliesGetCall) IfNoneMatch(entityTag string) *RepliesGetCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *PermissionsGetCall) Context(ctx context.Context) *PermissionsGetCall { +// Context sets the context to be used in this call's Do method. +func (c *RepliesGetCall) Context(ctx context.Context) *RepliesGetCall { c.ctx_ = ctx return c } -func (c *PermissionsGetCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *RepliesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RepliesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions/{permissionId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies/{replyId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "permissionId": c.permissionId, + "fileId": c.fileId, + "commentId": c.commentId, + "replyId": c.replyId, }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) - } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.permissions.get" call. -// Exactly one of *Permission or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *Permission.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *PermissionsGetCall) Do(opts ...googleapi.CallOption) (*Permission, error) { +// Do executes the "drive.replies.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *Reply.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *RepliesGetCall) Do(opts ...googleapi.CallOption) (*Reply, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Permission{ + ret := &Reply{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Gets a permission by ID.", - // "httpMethod": "GET", - // "id": "drive.permissions.get", - // "parameterOrder": [ - // "fileId", - // "permissionId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "permissionId": { - // "description": "The ID of the permission.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/permissions/{permissionId}", - // "response": { - // "$ref": "Permission" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// method id "drive.permissions.list": +} -type PermissionsListCall struct { +type RepliesListCall struct { s *Service fileId string + commentId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// List: Lists a file's permissions. -func (r *PermissionsService) List(fileId string) *PermissionsListCall { - c := &PermissionsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// List: Lists a comment's replies. +// +// - commentId: The ID of the comment. +// - fileId: The ID of the file. +func (r *RepliesService) List(fileId string, commentId string) *RepliesListCall { + c := &RepliesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId + c.commentId = commentId return c } -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *PermissionsListCall) Fields(s ...googleapi.Field) *PermissionsListCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) +// IncludeDeleted sets the optional parameter "includeDeleted": Whether to +// include deleted replies. Deleted replies will not include their original +// content. +func (c *RepliesListCall) IncludeDeleted(includeDeleted bool) *RepliesListCall { + c.urlParams_.Set("includeDeleted", fmt.Sprint(includeDeleted)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *PermissionsListCall) IfNoneMatch(entityTag string) *PermissionsListCall { - c.ifNoneMatch_ = entityTag +// PageSize sets the optional parameter "pageSize": The maximum number of +// replies to return per page. +func (c *RepliesListCall) PageSize(pageSize int64) *RepliesListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *PermissionsListCall) Context(ctx context.Context) *PermissionsListCall { - c.ctx_ = ctx +// PageToken sets the optional parameter "pageToken": The token for continuing +// a previous list request on the next page. This should be set to the value of +// 'nextPageToken' from the previous response. +func (c *RepliesListCall) PageToken(pageToken string) *RepliesListCall { + c.urlParams_.Set("pageToken", pageToken) return c } -func (c *PermissionsListCall) doRequest(alt string) (*http.Response, error) { - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) - } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) -} - -// Do executes the "drive.permissions.list" call. -// Exactly one of *PermissionList or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *PermissionList.ServerResponse.Header or (if a response was returned -// at all) in error.(*googleapi.Error).Header. Use -// googleapi.IsNotModified to check whether the returned error was -// because http.StatusNotModified was returned. -func (c *PermissionsListCall) Do(opts ...googleapi.CallOption) (*PermissionList, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("json") - if res != nil && res.StatusCode == http.StatusNotModified { - if res.Body != nil { - res.Body.Close() - } - return nil, &googleapi.Error{ - Code: res.StatusCode, - Header: res.Header, - } - } - if err != nil { - return nil, err - } - defer googleapi.CloseBody(res) - if err := googleapi.CheckResponse(res); err != nil { - return nil, err - } - ret := &PermissionList{ - ServerResponse: googleapi.ServerResponse{ - Header: res.Header, - HTTPStatusCode: res.StatusCode, - }, - } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { - return nil, err - } - return ret, nil - // { - // "description": "Lists a file's permissions.", - // "httpMethod": "GET", - // "id": "drive.permissions.list", - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/permissions", - // "response": { - // "$ref": "PermissionList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// method id "drive.permissions.update": - -type PermissionsUpdateCall struct { - s *Service - fileId string - permissionId string - permission *Permission - urlParams_ gensupport.URLParams - ctx_ context.Context -} - -// Update: Updates a permission with patch semantics. -func (r *PermissionsService) Update(fileId string, permissionId string, permission *Permission) *PermissionsUpdateCall { - c := &PermissionsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId - c.permissionId = permissionId - c.permission = permission +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *RepliesListCall) Fields(s ...googleapi.Field) *RepliesListCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// TransferOwnership sets the optional parameter "transferOwnership": -// Whether to transfer ownership to the specified user and downgrade the -// current owner to a writer. This parameter is required as an -// acknowledgement of the side effect. -func (c *PermissionsUpdateCall) TransferOwnership(transferOwnership bool) *PermissionsUpdateCall { - c.urlParams_.Set("transferOwnership", fmt.Sprint(transferOwnership)) +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *RepliesListCall) IfNoneMatch(entityTag string) *RepliesListCall { + c.ifNoneMatch_ = entityTag return c } -// Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *PermissionsUpdateCall) Fields(s ...googleapi.Field) *PermissionsUpdateCall { - c.urlParams_.Set("fields", googleapi.CombineFields(s)) +// Context sets the context to be used in this call's Do method. +func (c *RepliesListCall) Context(ctx context.Context) *RepliesListCall { + c.ctx_ = ctx return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *PermissionsUpdateCall) Context(ctx context.Context) *PermissionsUpdateCall { - c.ctx_ = ctx - return c +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *RepliesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ } -func (c *PermissionsUpdateCall) doRequest(alt string) (*http.Response, error) { +func (c *RepliesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.permission) + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) if err != nil { return nil, err } - ctype := "application/json" - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/permissions/{permissionId}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "permissionId": c.permissionId, + "fileId": c.fileId, + "commentId": c.commentId, }) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.permissions.update" call. -// Exactly one of *Permission or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *Permission.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *PermissionsUpdateCall) Do(opts ...googleapi.CallOption) (*Permission, error) { +// Do executes the "drive.replies.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *ReplyList.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *RepliesListCall) Do(opts ...googleapi.CallOption) (*ReplyList, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Permission{ + ret := &ReplyList{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Updates a permission with patch semantics.", - // "httpMethod": "PATCH", - // "id": "drive.permissions.update", - // "parameterOrder": [ - // "fileId", - // "permissionId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "permissionId": { - // "description": "The ID of the permission.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "transferOwnership": { - // "default": "false", - // "description": "Whether to transfer ownership to the specified user and downgrade the current owner to a writer. This parameter is required as an acknowledgement of the side effect.", - // "location": "query", - // "type": "boolean" - // } - // }, - // "path": "files/{fileId}/permissions/{permissionId}", - // "request": { - // "$ref": "Permission" - // }, - // "response": { - // "$ref": "Permission" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.replies.create": +} -type RepliesCreateCall struct { +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *RepliesListCall) Pages(ctx context.Context, f func(*ReplyList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +type RepliesUpdateCall struct { s *Service fileId string commentId string + replyId string reply *Reply urlParams_ gensupport.URLParams ctx_ context.Context + header_ http.Header } -// Create: Creates a new reply to a comment. -func (r *RepliesService) Create(fileId string, commentId string, reply *Reply) *RepliesCreateCall { - c := &RepliesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Update: Updates a reply with patch semantics. +// +// - commentId: The ID of the comment. +// - fileId: The ID of the file. +// - replyId: The ID of the reply. +func (r *RepliesService) Update(fileId string, commentId string, replyId string, reply *Reply) *RepliesUpdateCall { + c := &RepliesUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId c.commentId = commentId + c.replyId = replyId c.reply = reply return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *RepliesCreateCall) Fields(s ...googleapi.Field) *RepliesCreateCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *RepliesUpdateCall) Fields(s ...googleapi.Field) *RepliesUpdateCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *RepliesCreateCall) Context(ctx context.Context) *RepliesCreateCall { +// Context sets the context to be used in this call's Do method. +func (c *RepliesUpdateCall) Context(ctx context.Context) *RepliesUpdateCall { c.ctx_ = ctx return c } -func (c *RepliesCreateCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *RepliesUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RepliesUpdateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) var body io.Reader = nil body, err := googleapi.WithoutDataWrapper.JSONReader(c.reply) if err != nil { return nil, err } - ctype := "application/json" c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies/{replyId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("POST", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ "fileId": c.fileId, "commentId": c.commentId, + "replyId": c.replyId, }) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.replies.create" call. -// Exactly one of *Reply or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Reply.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *RepliesCreateCall) Do(opts ...googleapi.CallOption) (*Reply, error) { +// Do executes the "drive.replies.update" call. +// Any non-2xx status code is an error. Response headers are in either +// *Reply.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *RepliesUpdateCall) Do(opts ...googleapi.CallOption) (*Reply, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } ret := &Reply{ ServerResponse: googleapi.ServerResponse{ @@ -5254,103 +9517,80 @@ func (c *RepliesCreateCall) Do(opts ...googleapi.CallOption) (*Reply, error) { HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Creates a new reply to a comment.", - // "httpMethod": "POST", - // "id": "drive.replies.create", - // "parameterOrder": [ - // "fileId", - // "commentId" - // ], - // "parameters": { - // "commentId": { - // "description": "The ID of the comment.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/comments/{commentId}/replies", - // "request": { - // "$ref": "Reply" - // }, - // "response": { - // "$ref": "Reply" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.replies.delete": +} -type RepliesDeleteCall struct { +type RevisionsDeleteCall struct { s *Service fileId string - commentId string - replyId string + revisionId string urlParams_ gensupport.URLParams ctx_ context.Context + header_ http.Header } -// Delete: Deletes a reply. -func (r *RepliesService) Delete(fileId string, commentId string, replyId string) *RepliesDeleteCall { - c := &RepliesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Delete: Permanently deletes a file version. You can only delete revisions +// for files with binary content in Google Drive, like images or videos. +// Revisions for other files, like Google Docs or Sheets, and the last +// remaining file version can't be deleted. +// +// - fileId: The ID of the file. +// - revisionId: The ID of the revision. +func (r *RevisionsService) Delete(fileId string, revisionId string) *RevisionsDeleteCall { + c := &RevisionsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId - c.commentId = commentId - c.replyId = replyId + c.revisionId = revisionId return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *RepliesDeleteCall) Fields(s ...googleapi.Field) *RepliesDeleteCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *RevisionsDeleteCall) Fields(s ...googleapi.Field) *RevisionsDeleteCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *RepliesDeleteCall) Context(ctx context.Context) *RepliesDeleteCall { +// Context sets the context to be used in this call's Do method. +func (c *RevisionsDeleteCall) Context(ctx context.Context) *RevisionsDeleteCall { c.ctx_ = ctx return c } -func (c *RepliesDeleteCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *RevisionsDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RevisionsDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies/{replyId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/revisions/{revisionId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "commentId": c.commentId, - "replyId": c.replyId, + "fileId": c.fileId, + "revisionId": c.revisionId, }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.replies.delete" call. -func (c *RepliesDeleteCall) Do(opts ...googleapi.CallOption) error { +// Do executes the "drive.revisions.delete" call. +func (c *RevisionsDeleteCall) Do(opts ...googleapi.CallOption) error { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if err != nil { @@ -5358,603 +9598,557 @@ func (c *RepliesDeleteCall) Do(opts ...googleapi.CallOption) error { } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return err + return gensupport.WrapError(err) } return nil - // { - // "description": "Deletes a reply.", - // "httpMethod": "DELETE", - // "id": "drive.replies.delete", - // "parameterOrder": [ - // "fileId", - // "commentId", - // "replyId" - // ], - // "parameters": { - // "commentId": { - // "description": "The ID of the comment.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "replyId": { - // "description": "The ID of the reply.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/comments/{commentId}/replies/{replyId}", - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.replies.get": +} -type RepliesGetCall struct { +type RevisionsGetCall struct { s *Service fileId string - commentId string - replyId string + revisionId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// Get: Gets a reply by ID. -func (r *RepliesService) Get(fileId string, commentId string, replyId string) *RepliesGetCall { - c := &RepliesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// Get: Gets a revision's metadata or content by ID. +// +// - fileId: The ID of the file. +// - revisionId: The ID of the revision. +func (r *RevisionsService) Get(fileId string, revisionId string) *RevisionsGetCall { + c := &RevisionsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId - c.commentId = commentId - c.replyId = replyId + c.revisionId = revisionId return c } -// IncludeDeleted sets the optional parameter "includeDeleted": Whether -// to return deleted replies. Deleted replies will not include their -// original content. -func (c *RepliesGetCall) IncludeDeleted(includeDeleted bool) *RepliesGetCall { - c.urlParams_.Set("includeDeleted", fmt.Sprint(includeDeleted)) +// AcknowledgeAbuse sets the optional parameter "acknowledgeAbuse": Whether the +// user is acknowledging the risk of downloading known malware or other abusive +// files. This is only applicable when the `alt` parameter is set to `media` +// and the user is the owner of the file or an organizer of the shared drive in +// which the file resides. +func (c *RevisionsGetCall) AcknowledgeAbuse(acknowledgeAbuse bool) *RevisionsGetCall { + c.urlParams_.Set("acknowledgeAbuse", fmt.Sprint(acknowledgeAbuse)) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *RepliesGetCall) Fields(s ...googleapi.Field) *RepliesGetCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *RevisionsGetCall) Fields(s ...googleapi.Field) *RevisionsGetCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *RepliesGetCall) IfNoneMatch(entityTag string) *RepliesGetCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *RevisionsGetCall) IfNoneMatch(entityTag string) *RevisionsGetCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *RepliesGetCall) Context(ctx context.Context) *RepliesGetCall { +// Context sets the context to be used in this call's Do and Download methods. +func (c *RevisionsGetCall) Context(ctx context.Context) *RevisionsGetCall { c.ctx_ = ctx return c } -func (c *RepliesGetCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *RevisionsGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RevisionsGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies/{replyId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/revisions/{revisionId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "commentId": c.commentId, - "replyId": c.replyId, + "fileId": c.fileId, + "revisionId": c.revisionId, }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Download fetches the API endpoint's "media" value, instead of the normal +// API response value. If the returned error is nil, the Response is guaranteed to +// have a 2xx status code. Callers must close the Response.Body as usual. +func (c *RevisionsGetCall) Download(opts ...googleapi.CallOption) (*http.Response, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("media") + if err != nil { + return nil, err } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + if err := googleapi.CheckResponse(res); err != nil { + res.Body.Close() + return nil, gensupport.WrapError(err) } - return c.s.client.Do(req) + return res, nil } -// Do executes the "drive.replies.get" call. -// Exactly one of *Reply or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Reply.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *RepliesGetCall) Do(opts ...googleapi.CallOption) (*Reply, error) { +// Do executes the "drive.revisions.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *Revision.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *RevisionsGetCall) Do(opts ...googleapi.CallOption) (*Revision, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Reply{ + ret := &Revision{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Gets a reply by ID.", - // "httpMethod": "GET", - // "id": "drive.replies.get", - // "parameterOrder": [ - // "fileId", - // "commentId", - // "replyId" - // ], - // "parameters": { - // "commentId": { - // "description": "The ID of the comment.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "includeDeleted": { - // "default": "false", - // "description": "Whether to return deleted replies. Deleted replies will not include their original content.", - // "location": "query", - // "type": "boolean" - // }, - // "replyId": { - // "description": "The ID of the reply.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/comments/{commentId}/replies/{replyId}", - // "response": { - // "$ref": "Reply" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// method id "drive.replies.list": +} -type RepliesListCall struct { +type RevisionsListCall struct { s *Service fileId string - commentId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// List: Lists a comment's replies. -func (r *RepliesService) List(fileId string, commentId string) *RepliesListCall { - c := &RepliesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} +// List: Lists a file's revisions. +// +// - fileId: The ID of the file. +func (r *RevisionsService) List(fileId string) *RevisionsListCall { + c := &RevisionsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} c.fileId = fileId - c.commentId = commentId - return c -} - -// IncludeDeleted sets the optional parameter "includeDeleted": Whether -// to include deleted replies. Deleted replies will not include their -// original content. -func (c *RepliesListCall) IncludeDeleted(includeDeleted bool) *RepliesListCall { - c.urlParams_.Set("includeDeleted", fmt.Sprint(includeDeleted)) return c } -// PageSize sets the optional parameter "pageSize": The maximum number -// of replies to return per page. -func (c *RepliesListCall) PageSize(pageSize int64) *RepliesListCall { +// PageSize sets the optional parameter "pageSize": The maximum number of +// revisions to return per page. +func (c *RevisionsListCall) PageSize(pageSize int64) *RevisionsListCall { c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) return c } -// PageToken sets the optional parameter "pageToken": The token for -// continuing a previous list request on the next page. This should be -// set to the value of 'nextPageToken' from the previous response. -func (c *RepliesListCall) PageToken(pageToken string) *RepliesListCall { +// PageToken sets the optional parameter "pageToken": The token for continuing +// a previous list request on the next page. This should be set to the value of +// 'nextPageToken' from the previous response. +func (c *RevisionsListCall) PageToken(pageToken string) *RevisionsListCall { c.urlParams_.Set("pageToken", pageToken) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *RepliesListCall) Fields(s ...googleapi.Field) *RepliesListCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *RevisionsListCall) Fields(s ...googleapi.Field) *RevisionsListCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *RepliesListCall) IfNoneMatch(entityTag string) *RepliesListCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *RevisionsListCall) IfNoneMatch(entityTag string) *RevisionsListCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *RepliesListCall) Context(ctx context.Context) *RepliesListCall { +// Context sets the context to be used in this call's Do method. +func (c *RevisionsListCall) Context(ctx context.Context) *RevisionsListCall { c.ctx_ = ctx return c } -func (c *RepliesListCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *RevisionsListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RevisionsListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/revisions") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "fileId": c.fileId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "drive.revisions.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *RevisionList.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *RevisionsListCall) Do(opts ...googleapi.CallOption) (*RevisionList, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, gensupport.WrapError(&googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + }) + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, gensupport.WrapError(err) + } + ret := &RevisionList{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil +} + +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *RevisionsListCall) Pages(ctx context.Context, f func(*RevisionList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } +} + +type RevisionsUpdateCall struct { + s *Service + fileId string + revisionId string + revision *Revision + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Update: Updates a revision with patch semantics. +// +// - fileId: The ID of the file. +// - revisionId: The ID of the revision. +func (r *RevisionsService) Update(fileId string, revisionId string, revision *Revision) *RevisionsUpdateCall { + c := &RevisionsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.fileId = fileId + c.revisionId = revisionId + c.revision = revision + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *RevisionsUpdateCall) Fields(s ...googleapi.Field) *RevisionsUpdateCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. +func (c *RevisionsUpdateCall) Context(ctx context.Context) *RevisionsUpdateCall { + c.ctx_ = ctx + return c +} + +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *RevisionsUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *RevisionsUpdateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.revision) + if err != nil { + return nil, err + } + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/revisions/{revisionId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "commentId": c.commentId, + "fileId": c.fileId, + "revisionId": c.revisionId, }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) - } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.replies.list" call. -// Exactly one of *ReplyList or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *ReplyList.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *RepliesListCall) Do(opts ...googleapi.CallOption) (*ReplyList, error) { +// Do executes the "drive.revisions.update" call. +// Any non-2xx status code is an error. Response headers are in either +// *Revision.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *RevisionsUpdateCall) Do(opts ...googleapi.CallOption) (*Revision, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &ReplyList{ + ret := &Revision{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Lists a comment's replies.", - // "httpMethod": "GET", - // "id": "drive.replies.list", - // "parameterOrder": [ - // "fileId", - // "commentId" - // ], - // "parameters": { - // "commentId": { - // "description": "The ID of the comment.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "includeDeleted": { - // "default": "false", - // "description": "Whether to include deleted replies. Deleted replies will not include their original content.", - // "location": "query", - // "type": "boolean" - // }, - // "pageSize": { - // "default": "20", - // "description": "The maximum number of replies to return per page.", - // "format": "int32", - // "location": "query", - // "maximum": "100", - // "minimum": "1", - // "type": "integer" - // }, - // "pageToken": { - // "description": "The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.", - // "location": "query", - // "type": "string" - // } - // }, - // "path": "files/{fileId}/comments/{commentId}/replies", - // "response": { - // "$ref": "ReplyList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// Pages invokes f for each page of results. -// A non-nil error returned from f will halt the iteration. -// The provided context supersedes any context provided to the Context method. -func (c *RepliesListCall) Pages(ctx context.Context, f func(*ReplyList) error) error { - c.ctx_ = ctx - defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point - for { - x, err := c.Do() - if err != nil { - return err - } - if err := f(x); err != nil { - return err - } - if x.NextPageToken == "" { - return nil - } - c.PageToken(x.NextPageToken) - } } -// method id "drive.replies.update": - -type RepliesUpdateCall struct { +type TeamdrivesCreateCall struct { s *Service - fileId string - commentId string - replyId string - reply *Reply + teamdrive *TeamDrive urlParams_ gensupport.URLParams ctx_ context.Context + header_ http.Header } -// Update: Updates a reply with patch semantics. -func (r *RepliesService) Update(fileId string, commentId string, replyId string, reply *Reply) *RepliesUpdateCall { - c := &RepliesUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId - c.commentId = commentId - c.replyId = replyId - c.reply = reply +// Create: Deprecated: Use `drives.create` instead. +// +// - requestId: An ID, such as a random UUID, which uniquely identifies this +// user's request for idempotent creation of a Team Drive. A repeated request +// by the same user and with the same request ID will avoid creating +// duplicates by attempting to create the same Team Drive. If the Team Drive +// already exists a 409 error will be returned. +func (r *TeamdrivesService) Create(requestId string, teamdrive *TeamDrive) *TeamdrivesCreateCall { + c := &TeamdrivesCreateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.urlParams_.Set("requestId", requestId) + c.teamdrive = teamdrive return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *RepliesUpdateCall) Fields(s ...googleapi.Field) *RepliesUpdateCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *TeamdrivesCreateCall) Fields(s ...googleapi.Field) *TeamdrivesCreateCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *RepliesUpdateCall) Context(ctx context.Context) *RepliesUpdateCall { +// Context sets the context to be used in this call's Do method. +func (c *TeamdrivesCreateCall) Context(ctx context.Context) *TeamdrivesCreateCall { c.ctx_ = ctx return c } -func (c *RepliesUpdateCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *TeamdrivesCreateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *TeamdrivesCreateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.reply) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.teamdrive) if err != nil { return nil, err } - ctype := "application/json" c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/comments/{commentId}/replies/{replyId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "teamdrives") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) - googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "commentId": c.commentId, - "replyId": c.replyId, - }) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.replies.update" call. -// Exactly one of *Reply or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Reply.ServerResponse.Header or (if a response was returned at all) -// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to -// check whether the returned error was because http.StatusNotModified -// was returned. -func (c *RepliesUpdateCall) Do(opts ...googleapi.CallOption) (*Reply, error) { +// Do executes the "drive.teamdrives.create" call. +// Any non-2xx status code is an error. Response headers are in either +// *TeamDrive.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *TeamdrivesCreateCall) Do(opts ...googleapi.CallOption) (*TeamDrive, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Reply{ + ret := &TeamDrive{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Updates a reply with patch semantics.", - // "httpMethod": "PATCH", - // "id": "drive.replies.update", - // "parameterOrder": [ - // "fileId", - // "commentId", - // "replyId" - // ], - // "parameters": { - // "commentId": { - // "description": "The ID of the comment.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "replyId": { - // "description": "The ID of the reply.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/comments/{commentId}/replies/{replyId}", - // "request": { - // "$ref": "Reply" - // }, - // "response": { - // "$ref": "Reply" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.revisions.delete": +} -type RevisionsDeleteCall struct { - s *Service - fileId string - revisionId string - urlParams_ gensupport.URLParams - ctx_ context.Context +type TeamdrivesDeleteCall struct { + s *Service + teamDriveId string + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header } -// Delete: Permanently deletes a revision. This method is only -// applicable to files with binary content in Drive. -func (r *RevisionsService) Delete(fileId string, revisionId string) *RevisionsDeleteCall { - c := &RevisionsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId - c.revisionId = revisionId +// Delete: Deprecated: Use `drives.delete` instead. +// +// - teamDriveId: The ID of the Team Drive. +func (r *TeamdrivesService) Delete(teamDriveId string) *TeamdrivesDeleteCall { + c := &TeamdrivesDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.teamDriveId = teamDriveId return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *RevisionsDeleteCall) Fields(s ...googleapi.Field) *RevisionsDeleteCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *TeamdrivesDeleteCall) Fields(s ...googleapi.Field) *TeamdrivesDeleteCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *RevisionsDeleteCall) Context(ctx context.Context) *RevisionsDeleteCall { +// Context sets the context to be used in this call's Do method. +func (c *TeamdrivesDeleteCall) Context(ctx context.Context) *TeamdrivesDeleteCall { c.ctx_ = ctx return c } -func (c *RevisionsDeleteCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *TeamdrivesDeleteCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *TeamdrivesDeleteCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/revisions/{revisionId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "teamdrives/{teamDriveId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("DELETE", urls, body) + req, err := http.NewRequest("DELETE", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "revisionId": c.revisionId, + "teamDriveId": c.teamDriveId, }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.revisions.delete" call. -func (c *RevisionsDeleteCall) Do(opts ...googleapi.CallOption) error { +// Do executes the "drive.teamdrives.delete" call. +func (c *TeamdrivesDeleteCall) Do(opts ...googleapi.CallOption) error { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if err != nil { @@ -5962,473 +10156,383 @@ func (c *RevisionsDeleteCall) Do(opts ...googleapi.CallOption) error { } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return err + return gensupport.WrapError(err) } return nil - // { - // "description": "Permanently deletes a revision. This method is only applicable to files with binary content in Drive.", - // "httpMethod": "DELETE", - // "id": "drive.revisions.delete", - // "parameterOrder": [ - // "fileId", - // "revisionId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "revisionId": { - // "description": "The ID of the revision.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/revisions/{revisionId}", - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - -} - -// method id "drive.revisions.get": +} -type RevisionsGetCall struct { +type TeamdrivesGetCall struct { s *Service - fileId string - revisionId string + teamDriveId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// Get: Gets a revision's metadata or content by ID. -func (r *RevisionsService) Get(fileId string, revisionId string) *RevisionsGetCall { - c := &RevisionsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId - c.revisionId = revisionId +// Get: Deprecated: Use `drives.get` instead. +// +// - teamDriveId: The ID of the Team Drive. +func (r *TeamdrivesService) Get(teamDriveId string) *TeamdrivesGetCall { + c := &TeamdrivesGetCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.teamDriveId = teamDriveId return c } -// AcknowledgeAbuse sets the optional parameter "acknowledgeAbuse": -// Whether the user is acknowledging the risk of downloading known -// malware or other abusive files. This is only applicable when -// alt=media. -func (c *RevisionsGetCall) AcknowledgeAbuse(acknowledgeAbuse bool) *RevisionsGetCall { - c.urlParams_.Set("acknowledgeAbuse", fmt.Sprint(acknowledgeAbuse)) +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if they are an administrator of the domain +// to which the Team Drive belongs. +func (c *TeamdrivesGetCall) UseDomainAdminAccess(useDomainAdminAccess bool) *TeamdrivesGetCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *RevisionsGetCall) Fields(s ...googleapi.Field) *RevisionsGetCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *TeamdrivesGetCall) Fields(s ...googleapi.Field) *TeamdrivesGetCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *RevisionsGetCall) IfNoneMatch(entityTag string) *RevisionsGetCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *TeamdrivesGetCall) IfNoneMatch(entityTag string) *TeamdrivesGetCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do and Download -// methods. Any pending HTTP request will be aborted if the provided -// context is canceled. -func (c *RevisionsGetCall) Context(ctx context.Context) *RevisionsGetCall { +// Context sets the context to be used in this call's Do method. +func (c *TeamdrivesGetCall) Context(ctx context.Context) *TeamdrivesGetCall { c.ctx_ = ctx return c } -func (c *RevisionsGetCall) doRequest(alt string) (*http.Response, error) { - var body io.Reader = nil - c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/revisions/{revisionId}") - urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "revisionId": c.revisionId, - }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *TeamdrivesGetCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return c.header_ } -// Download fetches the API endpoint's "media" value, instead of the normal -// API response value. If the returned error is nil, the Response is guaranteed to -// have a 2xx status code. Callers must close the Response.Body as usual. -func (c *RevisionsGetCall) Download(opts ...googleapi.CallOption) (*http.Response, error) { - gensupport.SetOptions(c.urlParams_, opts...) - res, err := c.doRequest("media") - if err != nil { - return nil, err +func (c *TeamdrivesGetCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) } - if err := googleapi.CheckMediaResponse(res); err != nil { - res.Body.Close() + var body io.Reader = nil + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "teamdrives/{teamDriveId}") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("GET", urls, body) + if err != nil { return nil, err } - return res, nil + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "teamDriveId": c.teamDriveId, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.revisions.get" call. -// Exactly one of *Revision or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Revision.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *RevisionsGetCall) Do(opts ...googleapi.CallOption) (*Revision, error) { +// Do executes the "drive.teamdrives.get" call. +// Any non-2xx status code is an error. Response headers are in either +// *TeamDrive.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *TeamdrivesGetCall) Do(opts ...googleapi.CallOption) (*TeamDrive, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Revision{ + ret := &TeamDrive{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Gets a revision's metadata or content by ID.", - // "httpMethod": "GET", - // "id": "drive.revisions.get", - // "parameterOrder": [ - // "fileId", - // "revisionId" - // ], - // "parameters": { - // "acknowledgeAbuse": { - // "default": "false", - // "description": "Whether the user is acknowledging the risk of downloading known malware or other abusive files. This is only applicable when alt=media.", - // "location": "query", - // "type": "boolean" - // }, - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "revisionId": { - // "description": "The ID of the revision.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/revisions/{revisionId}", - // "response": { - // "$ref": "Revision" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ], - // "supportsMediaDownload": true, - // "useMediaDownloadService": true - // } - -} - -// method id "drive.revisions.list": +} -type RevisionsListCall struct { +type TeamdrivesListCall struct { s *Service - fileId string urlParams_ gensupport.URLParams ifNoneMatch_ string ctx_ context.Context + header_ http.Header } -// List: Lists a file's revisions. -func (r *RevisionsService) List(fileId string) *RevisionsListCall { - c := &RevisionsListCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId +// List: Deprecated: Use `drives.list` instead. +func (r *TeamdrivesService) List() *TeamdrivesListCall { + c := &TeamdrivesListCall{s: r.s, urlParams_: make(gensupport.URLParams)} + return c +} + +// PageSize sets the optional parameter "pageSize": Maximum number of Team +// Drives to return. +func (c *TeamdrivesListCall) PageSize(pageSize int64) *TeamdrivesListCall { + c.urlParams_.Set("pageSize", fmt.Sprint(pageSize)) + return c +} + +// PageToken sets the optional parameter "pageToken": Page token for Team +// Drives. +func (c *TeamdrivesListCall) PageToken(pageToken string) *TeamdrivesListCall { + c.urlParams_.Set("pageToken", pageToken) + return c +} + +// Q sets the optional parameter "q": Query string for searching Team Drives. +func (c *TeamdrivesListCall) Q(q string) *TeamdrivesListCall { + c.urlParams_.Set("q", q) + return c +} + +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then all Team +// Drives of the domain in which the requester is an administrator are +// returned. +func (c *TeamdrivesListCall) UseDomainAdminAccess(useDomainAdminAccess bool) *TeamdrivesListCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *RevisionsListCall) Fields(s ...googleapi.Field) *RevisionsListCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *TeamdrivesListCall) Fields(s ...googleapi.Field) *TeamdrivesListCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// IfNoneMatch sets the optional parameter which makes the operation -// fail if the object's ETag matches the given value. This is useful for -// getting updates only after the object has changed since the last -// request. Use googleapi.IsNotModified to check whether the response -// error from Do is the result of In-None-Match. -func (c *RevisionsListCall) IfNoneMatch(entityTag string) *RevisionsListCall { +// IfNoneMatch sets an optional parameter which makes the operation fail if the +// object's ETag matches the given value. This is useful for getting updates +// only after the object has changed since the last request. +func (c *TeamdrivesListCall) IfNoneMatch(entityTag string) *TeamdrivesListCall { c.ifNoneMatch_ = entityTag return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *RevisionsListCall) Context(ctx context.Context) *RevisionsListCall { +// Context sets the context to be used in this call's Do method. +func (c *TeamdrivesListCall) Context(ctx context.Context) *TeamdrivesListCall { c.ctx_ = ctx return c } -func (c *RevisionsListCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *TeamdrivesListCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *TeamdrivesListCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "", c.header_) + if c.ifNoneMatch_ != "" { + reqHeaders.Set("If-None-Match", c.ifNoneMatch_) + } var body io.Reader = nil c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/revisions") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "teamdrives") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("GET", urls, body) - googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - }) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ifNoneMatch_ != "" { - req.Header.Set("If-None-Match", c.ifNoneMatch_) - } - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) + req, err := http.NewRequest("GET", urls, body) + if err != nil { + return nil, err } - return c.s.client.Do(req) + req.Header = reqHeaders + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.revisions.list" call. -// Exactly one of *RevisionList or error will be non-nil. Any non-2xx -// status code is an error. Response headers are in either -// *RevisionList.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *RevisionsListCall) Do(opts ...googleapi.CallOption) (*RevisionList, error) { +// Do executes the "drive.teamdrives.list" call. +// Any non-2xx status code is an error. Response headers are in either +// *TeamDriveList.ServerResponse.Header or (if a response was returned at all) +// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *TeamdrivesListCall) Do(opts ...googleapi.CallOption) (*TeamDriveList, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &RevisionList{ + ret := &TeamDriveList{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Lists a file's revisions.", - // "httpMethod": "GET", - // "id": "drive.revisions.list", - // "parameterOrder": [ - // "fileId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/revisions", - // "response": { - // "$ref": "RevisionList" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file", - // "https://www.googleapis.com/auth/drive.metadata", - // "https://www.googleapis.com/auth/drive.metadata.readonly", - // "https://www.googleapis.com/auth/drive.photos.readonly", - // "https://www.googleapis.com/auth/drive.readonly" - // ] - // } - -} - -// method id "drive.revisions.update": +} -type RevisionsUpdateCall struct { - s *Service - fileId string - revisionId string - revision *Revision - urlParams_ gensupport.URLParams - ctx_ context.Context +// Pages invokes f for each page of results. +// A non-nil error returned from f will halt the iteration. +// The provided context supersedes any context provided to the Context method. +func (c *TeamdrivesListCall) Pages(ctx context.Context, f func(*TeamDriveList) error) error { + c.ctx_ = ctx + defer c.PageToken(c.urlParams_.Get("pageToken")) + for { + x, err := c.Do() + if err != nil { + return err + } + if err := f(x); err != nil { + return err + } + if x.NextPageToken == "" { + return nil + } + c.PageToken(x.NextPageToken) + } } -// Update: Updates a revision with patch semantics. -func (r *RevisionsService) Update(fileId string, revisionId string, revision *Revision) *RevisionsUpdateCall { - c := &RevisionsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} - c.fileId = fileId - c.revisionId = revisionId - c.revision = revision +type TeamdrivesUpdateCall struct { + s *Service + teamDriveId string + teamdrive *TeamDrive + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// Update: Deprecated: Use `drives.update` instead. +// +// - teamDriveId: The ID of the Team Drive. +func (r *TeamdrivesService) Update(teamDriveId string, teamdrive *TeamDrive) *TeamdrivesUpdateCall { + c := &TeamdrivesUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.teamDriveId = teamDriveId + c.teamdrive = teamdrive + return c +} + +// UseDomainAdminAccess sets the optional parameter "useDomainAdminAccess": +// Issue the request as a domain administrator; if set to true, then the +// requester will be granted access if they are an administrator of the domain +// to which the Team Drive belongs. +func (c *TeamdrivesUpdateCall) UseDomainAdminAccess(useDomainAdminAccess bool) *TeamdrivesUpdateCall { + c.urlParams_.Set("useDomainAdminAccess", fmt.Sprint(useDomainAdminAccess)) return c } // Fields allows partial responses to be retrieved. See -// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse -// for more information. -func (c *RevisionsUpdateCall) Fields(s ...googleapi.Field) *RevisionsUpdateCall { +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse for more +// details. +func (c *TeamdrivesUpdateCall) Fields(s ...googleapi.Field) *TeamdrivesUpdateCall { c.urlParams_.Set("fields", googleapi.CombineFields(s)) return c } -// Context sets the context to be used in this call's Do method. Any -// pending HTTP request will be aborted if the provided context is -// canceled. -func (c *RevisionsUpdateCall) Context(ctx context.Context) *RevisionsUpdateCall { +// Context sets the context to be used in this call's Do method. +func (c *TeamdrivesUpdateCall) Context(ctx context.Context) *TeamdrivesUpdateCall { c.ctx_ = ctx return c } -func (c *RevisionsUpdateCall) doRequest(alt string) (*http.Response, error) { +// Header returns a http.Header that can be modified by the caller to add +// headers to the request. +func (c *TeamdrivesUpdateCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *TeamdrivesUpdateCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := gensupport.SetHeaders(c.s.userAgent(), "application/json", c.header_) var body io.Reader = nil - body, err := googleapi.WithoutDataWrapper.JSONReader(c.revision) + body, err := googleapi.WithoutDataWrapper.JSONReader(c.teamdrive) if err != nil { return nil, err } - ctype := "application/json" c.urlParams_.Set("alt", alt) - urls := googleapi.ResolveRelative(c.s.BasePath, "files/{fileId}/revisions/{revisionId}") + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "teamdrives/{teamDriveId}") urls += "?" + c.urlParams_.Encode() - req, _ := http.NewRequest("PATCH", urls, body) + req, err := http.NewRequest("PATCH", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders googleapi.Expand(req.URL, map[string]string{ - "fileId": c.fileId, - "revisionId": c.revisionId, + "teamDriveId": c.teamDriveId, }) - req.Header.Set("Content-Type", ctype) - req.Header.Set("User-Agent", c.s.userAgent()) - if c.ctx_ != nil { - return ctxhttp.Do(c.ctx_, c.s.client, req) - } - return c.s.client.Do(req) + return gensupport.SendRequest(c.ctx_, c.s.client, req) } -// Do executes the "drive.revisions.update" call. -// Exactly one of *Revision or error will be non-nil. Any non-2xx status -// code is an error. Response headers are in either -// *Revision.ServerResponse.Header or (if a response was returned at -// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified -// to check whether the returned error was because -// http.StatusNotModified was returned. -func (c *RevisionsUpdateCall) Do(opts ...googleapi.CallOption) (*Revision, error) { +// Do executes the "drive.teamdrives.update" call. +// Any non-2xx status code is an error. Response headers are in either +// *TeamDrive.ServerResponse.Header or (if a response was returned at all) in +// error.(*googleapi.Error).Header. Use googleapi.IsNotModified to check +// whether the returned error was because http.StatusNotModified was returned. +func (c *TeamdrivesUpdateCall) Do(opts ...googleapi.CallOption) (*TeamDrive, error) { gensupport.SetOptions(c.urlParams_, opts...) res, err := c.doRequest("json") if res != nil && res.StatusCode == http.StatusNotModified { if res.Body != nil { res.Body.Close() } - return nil, &googleapi.Error{ + return nil, gensupport.WrapError(&googleapi.Error{ Code: res.StatusCode, Header: res.Header, - } + }) } if err != nil { return nil, err } defer googleapi.CloseBody(res) if err := googleapi.CheckResponse(res); err != nil { - return nil, err + return nil, gensupport.WrapError(err) } - ret := &Revision{ + ret := &TeamDrive{ ServerResponse: googleapi.ServerResponse{ Header: res.Header, HTTPStatusCode: res.StatusCode, }, } - if err := json.NewDecoder(res.Body).Decode(&ret); err != nil { + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { return nil, err } return ret, nil - // { - // "description": "Updates a revision with patch semantics.", - // "httpMethod": "PATCH", - // "id": "drive.revisions.update", - // "parameterOrder": [ - // "fileId", - // "revisionId" - // ], - // "parameters": { - // "fileId": { - // "description": "The ID of the file.", - // "location": "path", - // "required": true, - // "type": "string" - // }, - // "revisionId": { - // "description": "The ID of the revision.", - // "location": "path", - // "required": true, - // "type": "string" - // } - // }, - // "path": "files/{fileId}/revisions/{revisionId}", - // "request": { - // "$ref": "Revision" - // }, - // "response": { - // "$ref": "Revision" - // }, - // "scopes": [ - // "https://www.googleapis.com/auth/drive", - // "https://www.googleapis.com/auth/drive.appdata", - // "https://www.googleapis.com/auth/drive.file" - // ] - // } - } diff --git a/vendor/google.golang.org/api/gensupport/backoff.go b/vendor/google.golang.org/api/gensupport/backoff.go deleted file mode 100644 index 13561404..00000000 --- a/vendor/google.golang.org/api/gensupport/backoff.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2016 The Go 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 gensupport - -import ( - "math/rand" - "time" -) - -type BackoffStrategy interface { - // Pause returns the duration of the next pause and true if the operation should be - // retried, or false if no further retries should be attempted. - Pause() (time.Duration, bool) - - // Reset restores the strategy to its initial state. - Reset() -} - -// ExponentialBackoff performs exponential backoff as per https://en.wikipedia.org/wiki/Exponential_backoff. -// The initial pause time is given by Base. -// Once the total pause time exceeds Max, Pause will indicate no further retries. -type ExponentialBackoff struct { - Base time.Duration - Max time.Duration - total time.Duration - n uint -} - -func (eb *ExponentialBackoff) Pause() (time.Duration, bool) { - if eb.total > eb.Max { - return 0, false - } - - // The next pause is selected from randomly from [0, 2^n * Base). - d := time.Duration(rand.Int63n((1 << eb.n) * int64(eb.Base))) - eb.total += d - eb.n++ - return d, true -} - -func (eb *ExponentialBackoff) Reset() { - eb.n = 0 - eb.total = 0 -} diff --git a/vendor/google.golang.org/api/gensupport/buffer.go b/vendor/google.golang.org/api/gensupport/buffer.go deleted file mode 100644 index 4b8ec142..00000000 --- a/vendor/google.golang.org/api/gensupport/buffer.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2016 The Go 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 gensupport - -import ( - "bytes" - "io" - - "google.golang.org/api/googleapi" -) - -// ResumableBuffer buffers data from an io.Reader to support uploading media in retryable chunks. -type ResumableBuffer struct { - media io.Reader - - chunk []byte // The current chunk which is pending upload. The capacity is the chunk size. - err error // Any error generated when populating chunk by reading media. - - // The absolute position of chunk in the underlying media. - off int64 -} - -func NewResumableBuffer(media io.Reader, chunkSize int) *ResumableBuffer { - return &ResumableBuffer{media: media, chunk: make([]byte, 0, chunkSize)} -} - -// Chunk returns the current buffered chunk, the offset in the underlying media -// from which the chunk is drawn, and the size of the chunk. -// Successive calls to Chunk return the same chunk between calls to Next. -func (rb *ResumableBuffer) Chunk() (chunk io.Reader, off int64, size int, err error) { - // There may already be data in chunk if Next has not been called since the previous call to Chunk. - if rb.err == nil && len(rb.chunk) == 0 { - rb.err = rb.loadChunk() - } - return bytes.NewReader(rb.chunk), rb.off, len(rb.chunk), rb.err -} - -// loadChunk will read from media into chunk, up to the capacity of chunk. -func (rb *ResumableBuffer) loadChunk() error { - bufSize := cap(rb.chunk) - rb.chunk = rb.chunk[:bufSize] - - read := 0 - var err error - for err == nil && read < bufSize { - var n int - n, err = rb.media.Read(rb.chunk[read:]) - read += n - } - rb.chunk = rb.chunk[:read] - return err -} - -// Next advances to the next chunk, which will be returned by the next call to Chunk. -// Calls to Next without a corresponding prior call to Chunk will have no effect. -func (rb *ResumableBuffer) Next() { - rb.off += int64(len(rb.chunk)) - rb.chunk = rb.chunk[0:0] -} - -type readerTyper struct { - io.Reader - googleapi.ContentTyper -} - -// ReaderAtToReader adapts a ReaderAt to be used as a Reader. -// If ra implements googleapi.ContentTyper, then the returned reader -// will also implement googleapi.ContentTyper, delegating to ra. -func ReaderAtToReader(ra io.ReaderAt, size int64) io.Reader { - r := io.NewSectionReader(ra, 0, size) - if typer, ok := ra.(googleapi.ContentTyper); ok { - return readerTyper{r, typer} - } - return r -} diff --git a/vendor/google.golang.org/api/gensupport/doc.go b/vendor/google.golang.org/api/gensupport/doc.go deleted file mode 100644 index 752c4b41..00000000 --- a/vendor/google.golang.org/api/gensupport/doc.go +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright 2016 The Go 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 gensupport is an internal implementation detail used by code -// generated by the google-api-go-generator tool. -// -// This package may be modified at any time without regard for backwards -// compatibility. It should not be used directly by API users. -package gensupport diff --git a/vendor/google.golang.org/api/gensupport/json.go b/vendor/google.golang.org/api/gensupport/json.go deleted file mode 100644 index dd7bcd2e..00000000 --- a/vendor/google.golang.org/api/gensupport/json.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright 2015 The Go 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 gensupport - -import ( - "encoding/json" - "fmt" - "reflect" - "strings" -) - -// MarshalJSON returns a JSON encoding of schema containing only selected fields. -// A field is selected if: -// * it has a non-empty value, or -// * its field name is present in forceSendFields, and -// * it is not a nil pointer or nil interface. -// The JSON key for each selected field is taken from the field's json: struct tag. -func MarshalJSON(schema interface{}, forceSendFields []string) ([]byte, error) { - if len(forceSendFields) == 0 { - return json.Marshal(schema) - } - - mustInclude := make(map[string]struct{}) - for _, f := range forceSendFields { - mustInclude[f] = struct{}{} - } - - dataMap, err := schemaToMap(schema, mustInclude) - if err != nil { - return nil, err - } - return json.Marshal(dataMap) -} - -func schemaToMap(schema interface{}, mustInclude map[string]struct{}) (map[string]interface{}, error) { - m := make(map[string]interface{}) - s := reflect.ValueOf(schema) - st := s.Type() - - for i := 0; i < s.NumField(); i++ { - jsonTag := st.Field(i).Tag.Get("json") - if jsonTag == "" { - continue - } - tag, err := parseJSONTag(jsonTag) - if err != nil { - return nil, err - } - if tag.ignore { - continue - } - - v := s.Field(i) - f := st.Field(i) - if !includeField(v, f, mustInclude) { - continue - } - - // nil maps are treated as empty maps. - if f.Type.Kind() == reflect.Map && v.IsNil() { - m[tag.apiName] = map[string]string{} - continue - } - - // nil slices are treated as empty slices. - if f.Type.Kind() == reflect.Slice && v.IsNil() { - m[tag.apiName] = []bool{} - continue - } - - if tag.stringFormat { - m[tag.apiName] = formatAsString(v, f.Type.Kind()) - } else { - m[tag.apiName] = v.Interface() - } - } - return m, nil -} - -// formatAsString returns a string representation of v, dereferencing it first if possible. -func formatAsString(v reflect.Value, kind reflect.Kind) string { - if kind == reflect.Ptr && !v.IsNil() { - v = v.Elem() - } - - return fmt.Sprintf("%v", v.Interface()) -} - -// jsonTag represents a restricted version of the struct tag format used by encoding/json. -// It is used to describe the JSON encoding of fields in a Schema struct. -type jsonTag struct { - apiName string - stringFormat bool - ignore bool -} - -// parseJSONTag parses a restricted version of the struct tag format used by encoding/json. -// The format of the tag must match that generated by the Schema.writeSchemaStruct method -// in the api generator. -func parseJSONTag(val string) (jsonTag, error) { - if val == "-" { - return jsonTag{ignore: true}, nil - } - - var tag jsonTag - - i := strings.Index(val, ",") - if i == -1 || val[:i] == "" { - return tag, fmt.Errorf("malformed json tag: %s", val) - } - - tag = jsonTag{ - apiName: val[:i], - } - - switch val[i+1:] { - case "omitempty": - case "omitempty,string": - tag.stringFormat = true - default: - return tag, fmt.Errorf("malformed json tag: %s", val) - } - - return tag, nil -} - -// Reports whether the struct field "f" with value "v" should be included in JSON output. -func includeField(v reflect.Value, f reflect.StructField, mustInclude map[string]struct{}) bool { - // The regular JSON encoding of a nil pointer is "null", which means "delete this field". - // Therefore, we could enable field deletion by honoring pointer fields' presence in the mustInclude set. - // However, many fields are not pointers, so there would be no way to delete these fields. - // Rather than partially supporting field deletion, we ignore mustInclude for nil pointer fields. - // Deletion will be handled by a separate mechanism. - if f.Type.Kind() == reflect.Ptr && v.IsNil() { - return false - } - - // The "any" type is represented as an interface{}. If this interface - // is nil, there is no reasonable representation to send. We ignore - // these fields, for the same reasons as given above for pointers. - if f.Type.Kind() == reflect.Interface && v.IsNil() { - return false - } - - _, ok := mustInclude[f.Name] - return ok || !isEmptyValue(v) -} - -// isEmptyValue reports whether v is the empty value for its type. This -// implementation is based on that of the encoding/json package, but its -// correctness does not depend on it being identical. What's important is that -// this function return false in situations where v should not be sent as part -// of a PATCH operation. -func isEmptyValue(v reflect.Value) bool { - switch v.Kind() { - case reflect.Array, reflect.Map, reflect.Slice, reflect.String: - return v.Len() == 0 - case reflect.Bool: - return !v.Bool() - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - return v.Int() == 0 - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - return v.Uint() == 0 - case reflect.Float32, reflect.Float64: - return v.Float() == 0 - case reflect.Interface, reflect.Ptr: - return v.IsNil() - } - return false -} diff --git a/vendor/google.golang.org/api/gensupport/media.go b/vendor/google.golang.org/api/gensupport/media.go deleted file mode 100644 index 817f46f5..00000000 --- a/vendor/google.golang.org/api/gensupport/media.go +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2016 The Go 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 gensupport - -import ( - "fmt" - "io" - "io/ioutil" - "mime/multipart" - "net/http" - "net/textproto" - - "google.golang.org/api/googleapi" -) - -const sniffBuffSize = 512 - -func newContentSniffer(r io.Reader) *contentSniffer { - return &contentSniffer{r: r} -} - -// contentSniffer wraps a Reader, and reports the content type determined by sniffing up to 512 bytes from the Reader. -type contentSniffer struct { - r io.Reader - start []byte // buffer for the sniffed bytes. - err error // set to any error encountered while reading bytes to be sniffed. - - ctype string // set on first sniff. - sniffed bool // set to true on first sniff. -} - -func (cs *contentSniffer) Read(p []byte) (n int, err error) { - // Ensure that the content type is sniffed before any data is consumed from Reader. - _, _ = cs.ContentType() - - if len(cs.start) > 0 { - n := copy(p, cs.start) - cs.start = cs.start[n:] - return n, nil - } - - // We may have read some bytes into start while sniffing, even if the read ended in an error. - // We should first return those bytes, then the error. - if cs.err != nil { - return 0, cs.err - } - - // Now we have handled all bytes that were buffered while sniffing. Now just delegate to the underlying reader. - return cs.r.Read(p) -} - -// ContentType returns the sniffed content type, and whether the content type was succesfully sniffed. -func (cs *contentSniffer) ContentType() (string, bool) { - if cs.sniffed { - return cs.ctype, cs.ctype != "" - } - cs.sniffed = true - // If ReadAll hits EOF, it returns err==nil. - cs.start, cs.err = ioutil.ReadAll(io.LimitReader(cs.r, sniffBuffSize)) - - // Don't try to detect the content type based on possibly incomplete data. - if cs.err != nil { - return "", false - } - - cs.ctype = http.DetectContentType(cs.start) - return cs.ctype, true -} - -// DetermineContentType determines the content type of the supplied reader. -// If the content type is already known, it can be specified via ctype. -// Otherwise, the content of media will be sniffed to determine the content type. -// If media implements googleapi.ContentTyper (deprecated), this will be used -// instead of sniffing the content. -// After calling DetectContentType the caller must not perform further reads on -// media, but rather read from the Reader that is returned. -func DetermineContentType(media io.Reader, ctype string) (io.Reader, string) { - // Note: callers could avoid calling DetectContentType if ctype != "", - // but doing the check inside this function reduces the amount of - // generated code. - if ctype != "" { - return media, ctype - } - - // For backwards compatability, allow clients to set content - // type by providing a ContentTyper for media. - if typer, ok := media.(googleapi.ContentTyper); ok { - return media, typer.ContentType() - } - - sniffer := newContentSniffer(media) - if ctype, ok := sniffer.ContentType(); ok { - return sniffer, ctype - } - // If content type could not be sniffed, reads from sniffer will eventually fail with an error. - return sniffer, "" -} - -type typeReader struct { - io.Reader - typ string -} - -// multipartReader combines the contents of multiple readers to creat a multipart/related HTTP body. -// Close must be called if reads from the multipartReader are abandoned before reaching EOF. -type multipartReader struct { - pr *io.PipeReader - pipeOpen bool - ctype string -} - -func newMultipartReader(parts []typeReader) *multipartReader { - mp := &multipartReader{pipeOpen: true} - var pw *io.PipeWriter - mp.pr, pw = io.Pipe() - mpw := multipart.NewWriter(pw) - mp.ctype = "multipart/related; boundary=" + mpw.Boundary() - go func() { - for _, part := range parts { - w, err := mpw.CreatePart(typeHeader(part.typ)) - if err != nil { - mpw.Close() - pw.CloseWithError(fmt.Errorf("googleapi: CreatePart failed: %v", err)) - return - } - _, err = io.Copy(w, part.Reader) - if err != nil { - mpw.Close() - pw.CloseWithError(fmt.Errorf("googleapi: Copy failed: %v", err)) - return - } - } - - mpw.Close() - pw.Close() - }() - return mp -} - -func (mp *multipartReader) Read(data []byte) (n int, err error) { - return mp.pr.Read(data) -} - -func (mp *multipartReader) Close() error { - if !mp.pipeOpen { - return nil - } - mp.pipeOpen = false - return mp.pr.Close() -} - -// CombineBodyMedia combines a json body with media content to create a multipart/related HTTP body. -// It returns a ReadCloser containing the combined body, and the overall "multipart/related" content type, with random boundary. -// -// The caller must call Close on the returned ReadCloser if reads are abandoned before reaching EOF. -func CombineBodyMedia(body io.Reader, bodyContentType string, media io.Reader, mediaContentType string) (io.ReadCloser, string) { - mp := newMultipartReader([]typeReader{ - {body, bodyContentType}, - {media, mediaContentType}, - }) - return mp, mp.ctype -} - -func typeHeader(contentType string) textproto.MIMEHeader { - h := make(textproto.MIMEHeader) - if contentType != "" { - h.Set("Content-Type", contentType) - } - return h -} - -// PrepareUpload determines whether the data in the supplied reader should be -// uploaded in a single request, or in sequential chunks. -// chunkSize is the size of the chunk that media should be split into. -// If chunkSize is non-zero and the contents of media do not fit in a single -// chunk (or there is an error reading media), then media will be returned as a -// ResumableBuffer. Otherwise, media will be returned as a Reader. -// -// After PrepareUpload has been called, media should no longer be used: the -// media content should be accessed via one of the return values. -func PrepareUpload(media io.Reader, chunkSize int) (io.Reader, - *ResumableBuffer) { - if chunkSize == 0 { // do not chunk - return media, nil - } - - rb := NewResumableBuffer(media, chunkSize) - rdr, _, _, err := rb.Chunk() - - if err == io.EOF { // we can upload this in a single request - return rdr, nil - } - // err might be a non-EOF error. If it is, the next call to rb.Chunk will - // return the same error. Returning a ResumableBuffer ensures that this error - // will be handled at some point. - - return nil, rb -} diff --git a/vendor/google.golang.org/api/gensupport/params.go b/vendor/google.golang.org/api/gensupport/params.go deleted file mode 100644 index 3b3c7439..00000000 --- a/vendor/google.golang.org/api/gensupport/params.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2015 The Go 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 gensupport - -import ( - "net/url" - - "google.golang.org/api/googleapi" -) - -// URLParams is a simplified replacement for url.Values -// that safely builds up URL parameters for encoding. -type URLParams map[string][]string - -// Get returns the first value for the given key, or "". -func (u URLParams) Get(key string) string { - vs := u[key] - if len(vs) == 0 { - return "" - } - return vs[0] -} - -// Set sets the key to value. -// It replaces any existing values. -func (u URLParams) Set(key, value string) { - u[key] = []string{value} -} - -// SetMulti sets the key to an array of values. -// It replaces any existing values. -// Note that values must not be modified after calling SetMulti -// so the caller is responsible for making a copy if necessary. -func (u URLParams) SetMulti(key string, values []string) { - u[key] = values -} - -// Encode encodes the values into ``URL encoded'' form -// ("bar=baz&foo=quux") sorted by key. -func (u URLParams) Encode() string { - return url.Values(u).Encode() -} - -func SetOptions(u URLParams, opts ...googleapi.CallOption) { - for _, o := range opts { - u.Set(o.Get()) - } -} diff --git a/vendor/google.golang.org/api/gensupport/resumable.go b/vendor/google.golang.org/api/gensupport/resumable.go deleted file mode 100644 index b3e774aa..00000000 --- a/vendor/google.golang.org/api/gensupport/resumable.go +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright 2016 The Go 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 gensupport - -import ( - "fmt" - "io" - "net/http" - "sync" - "time" - - "golang.org/x/net/context" - "golang.org/x/net/context/ctxhttp" -) - -const ( - // statusResumeIncomplete is the code returned by the Google uploader - // when the transfer is not yet complete. - statusResumeIncomplete = 308 - - // statusTooManyRequests is returned by the storage API if the - // per-project limits have been temporarily exceeded. The request - // should be retried. - // https://cloud.google.com/storage/docs/json_api/v1/status-codes#standardcodes - statusTooManyRequests = 429 -) - -// ResumableUpload is used by the generated APIs to provide resumable uploads. -// It is not used by developers directly. -type ResumableUpload struct { - Client *http.Client - // URI is the resumable resource destination provided by the server after specifying "&uploadType=resumable". - URI string - UserAgent string // User-Agent for header of the request - // Media is the object being uploaded. - Media *ResumableBuffer - // MediaType defines the media type, e.g. "image/jpeg". - MediaType string - - mu sync.Mutex // guards progress - progress int64 // number of bytes uploaded so far - - // Callback is an optional function that will be periodically called with the cumulative number of bytes uploaded. - Callback func(int64) - - // If not specified, a default exponential backoff strategy will be used. - Backoff BackoffStrategy -} - -// Progress returns the number of bytes uploaded at this point. -func (rx *ResumableUpload) Progress() int64 { - rx.mu.Lock() - defer rx.mu.Unlock() - return rx.progress -} - -// doUploadRequest performs a single HTTP request to upload data. -// off specifies the offset in rx.Media from which data is drawn. -// size is the number of bytes in data. -// final specifies whether data is the final chunk to be uploaded. -func (rx *ResumableUpload) doUploadRequest(ctx context.Context, data io.Reader, off, size int64, final bool) (*http.Response, error) { - req, err := http.NewRequest("POST", rx.URI, data) - if err != nil { - return nil, err - } - - req.ContentLength = size - var contentRange string - if final { - if size == 0 { - contentRange = fmt.Sprintf("bytes */%v", off) - } else { - contentRange = fmt.Sprintf("bytes %v-%v/%v", off, off+size-1, off+size) - } - } else { - contentRange = fmt.Sprintf("bytes %v-%v/*", off, off+size-1) - } - req.Header.Set("Content-Range", contentRange) - req.Header.Set("Content-Type", rx.MediaType) - req.Header.Set("User-Agent", rx.UserAgent) - return ctxhttp.Do(ctx, rx.Client, req) - -} - -// reportProgress calls a user-supplied callback to report upload progress. -// If old==updated, the callback is not called. -func (rx *ResumableUpload) reportProgress(old, updated int64) { - if updated-old == 0 { - return - } - rx.mu.Lock() - rx.progress = updated - rx.mu.Unlock() - if rx.Callback != nil { - rx.Callback(updated) - } -} - -// transferChunk performs a single HTTP request to upload a single chunk from rx.Media. -func (rx *ResumableUpload) transferChunk(ctx context.Context) (*http.Response, error) { - chunk, off, size, err := rx.Media.Chunk() - - done := err == io.EOF - if !done && err != nil { - return nil, err - } - - res, err := rx.doUploadRequest(ctx, chunk, off, int64(size), done) - if err != nil { - return res, err - } - - if res.StatusCode == statusResumeIncomplete || res.StatusCode == http.StatusOK { - rx.reportProgress(off, off+int64(size)) - } - - if res.StatusCode == statusResumeIncomplete { - rx.Media.Next() - } - return res, nil -} - -func contextDone(ctx context.Context) bool { - select { - case <-ctx.Done(): - return true - default: - return false - } -} - -// Upload starts the process of a resumable upload with a cancellable context. -// It retries using the provided back off strategy until cancelled or the -// strategy indicates to stop retrying. -// It is called from the auto-generated API code and is not visible to the user. -// rx is private to the auto-generated API code. -// Exactly one of resp or err will be nil. If resp is non-nil, the caller must call resp.Body.Close. -func (rx *ResumableUpload) Upload(ctx context.Context) (resp *http.Response, err error) { - var pause time.Duration - backoff := rx.Backoff - if backoff == nil { - backoff = DefaultBackoffStrategy() - } - - for { - // Ensure that we return in the case of cancelled context, even if pause is 0. - if contextDone(ctx) { - return nil, ctx.Err() - } - select { - case <-ctx.Done(): - return nil, ctx.Err() - case <-time.After(pause): - } - - resp, err = rx.transferChunk(ctx) - - var status int - if resp != nil { - status = resp.StatusCode - } - - // Check if we should retry the request. - if shouldRetry(status, err) { - var retry bool - pause, retry = backoff.Pause() - if retry { - if resp != nil && resp.Body != nil { - resp.Body.Close() - } - continue - } - } - - // If the chunk was uploaded successfully, but there's still - // more to go, upload the next chunk without any delay. - if status == statusResumeIncomplete { - pause = 0 - backoff.Reset() - resp.Body.Close() - continue - } - - // It's possible for err and resp to both be non-nil here, but we expose a simpler - // contract to our callers: exactly one of resp and err will be non-nil. This means - // that any response body must be closed here before returning a non-nil error. - if err != nil { - if resp != nil && resp.Body != nil { - resp.Body.Close() - } - return nil, err - } - - return resp, nil - } -} diff --git a/vendor/google.golang.org/api/gensupport/retry.go b/vendor/google.golang.org/api/gensupport/retry.go deleted file mode 100644 index 7f83d1da..00000000 --- a/vendor/google.golang.org/api/gensupport/retry.go +++ /dev/null @@ -1,77 +0,0 @@ -package gensupport - -import ( - "io" - "net" - "net/http" - "time" - - "golang.org/x/net/context" -) - -// Retry invokes the given function, retrying it multiple times if the connection failed or -// the HTTP status response indicates the request should be attempted again. ctx may be nil. -func Retry(ctx context.Context, f func() (*http.Response, error), backoff BackoffStrategy) (*http.Response, error) { - for { - resp, err := f() - - var status int - if resp != nil { - status = resp.StatusCode - } - - // Return if we shouldn't retry. - pause, retry := backoff.Pause() - if !shouldRetry(status, err) || !retry { - return resp, err - } - - // Ensure the response body is closed, if any. - if resp != nil && resp.Body != nil { - resp.Body.Close() - } - - // Pause, but still listen to ctx.Done if context is not nil. - var done <-chan struct{} - if ctx != nil { - done = ctx.Done() - } - select { - case <-done: - return nil, ctx.Err() - case <-time.After(pause): - } - } -} - -// DefaultBackoffStrategy returns a default strategy to use for retrying failed upload requests. -func DefaultBackoffStrategy() BackoffStrategy { - return &ExponentialBackoff{ - Base: 250 * time.Millisecond, - Max: 16 * time.Second, - } -} - -// shouldRetry returns true if the HTTP response / error indicates that the -// request should be attempted again. -func shouldRetry(status int, err error) bool { - // Retry for 5xx response codes. - if 500 <= status && status < 600 { - return true - } - - // Retry on statusTooManyRequests{ - if status == statusTooManyRequests { - return true - } - - // Retry on unexpected EOFs and temporary network errors. - if err == io.ErrUnexpectedEOF { - return true - } - if err, ok := err.(net.Error); ok { - return err.Temporary() - } - - return false -} diff --git a/vendor/google.golang.org/api/googleapi/googleapi.go b/vendor/google.golang.org/api/googleapi/googleapi.go index 858537e0..04a10f51 100644 --- a/vendor/google.golang.org/api/googleapi/googleapi.go +++ b/vendor/google.golang.org/api/googleapi/googleapi.go @@ -1,22 +1,22 @@ -// Copyright 2011 Google Inc. All rights reserved. +// Copyright 2011 Google LLC. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package googleapi contains the common code shared by all Google API // libraries. -package googleapi +package googleapi // import "google.golang.org/api/googleapi" import ( "bytes" "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" + "time" - "google.golang.org/api/googleapi/internal/uritemplates" + "google.golang.org/api/internal/third_party/uritemplates" ) // ContentTyper is an interface for Readers which know (or would like @@ -37,24 +37,28 @@ type SizeReaderAt interface { // ServerResponse is embedded in each Do response and // provides the HTTP status code and header sent by the server. type ServerResponse struct { - // HTTPStatusCode is the server's response status code. - // When using a resource method's Do call, this will always be in the 2xx range. + // HTTPStatusCode is the server's response status code. When using a + // resource method's Do call, this will always be in the 2xx range. HTTPStatusCode int // Header contains the response header fields from the server. Header http.Header } const ( + // Version defines the gax version being used. This is typically sent + // in an HTTP header to services. Version = "0.5" // UserAgent is the header string used to identify this package. UserAgent = "google-api-go-client/" + Version - // The default chunk size to use for resumable uplods if not specified by the user. - DefaultUploadChunkSize = 8 * 1024 * 1024 + // DefaultUploadChunkSize is the default chunk size to use for resumable + // uploads if not specified by the user. + DefaultUploadChunkSize = 16 * 1024 * 1024 - // The minimum chunk size that can be used for resumable uploads. All - // user-specified chunk sizes must be multiple of this value. + // MinUploadChunkSize is the minimum chunk size that can be used for + // resumable uploads. All user-specified chunk sizes must be multiple of + // this value. MinUploadChunkSize = 256 * 1024 ) @@ -65,6 +69,8 @@ type Error struct { // Message is the server response message and is only populated when // explicitly referenced by the JSON server response. Message string `json:"message"` + // Details provide more context to an error. + Details []interface{} `json:"details"` // Body is the raw response returned by the server. // It is often but not always JSON, depending on how the request fails. Body string @@ -72,6 +78,9 @@ type Error struct { Header http.Header Errors []ErrorItem + // err is typically a wrapped apierror.APIError, see + // google-api-go-client/internal/gensupport/error.go. + err error } // ErrorItem is a detailed error code & message from the Google API frontend. @@ -91,6 +100,16 @@ func (e *Error) Error() string { if e.Message != "" { fmt.Fprintf(&buf, "%s", e.Message) } + if len(e.Details) > 0 { + var detailBuf bytes.Buffer + enc := json.NewEncoder(&detailBuf) + enc.SetIndent("", " ") + if err := enc.Encode(e.Details); err == nil { + fmt.Fprint(&buf, "\nDetails:") + fmt.Fprintf(&buf, "\n%s", detailBuf.String()) + + } + } if len(e.Errors) == 0 { return strings.TrimSpace(buf.String()) } @@ -105,6 +124,15 @@ func (e *Error) Error() string { return buf.String() } +// Wrap allows an existing Error to wrap another error. See also [Error.Unwrap]. +func (e *Error) Wrap(err error) { + e.err = err +} + +func (e *Error) Unwrap() error { + return e.err +} + type errorReply struct { Error *Error `json:"error"` } @@ -115,7 +143,7 @@ func CheckResponse(res *http.Response) error { if res.StatusCode >= 200 && res.StatusCode <= 299 { return nil } - slurp, err := ioutil.ReadAll(res.Body) + slurp, err := io.ReadAll(res.Body) if err == nil { jerr := new(errorReply) err = json.Unmarshal(slurp, jerr) @@ -124,6 +152,7 @@ func CheckResponse(res *http.Response) error { jerr.Error.Code = res.StatusCode } jerr.Error.Body = string(slurp) + jerr.Error.Header = res.Header return jerr.Error } } @@ -149,21 +178,26 @@ func IsNotModified(err error) bool { // CheckMediaResponse returns an error (of type *Error) if the response // status code is not 2xx. Unlike CheckResponse it does not assume the // body is a JSON error document. +// It is the caller's responsibility to close res.Body. func CheckMediaResponse(res *http.Response) error { if res.StatusCode >= 200 && res.StatusCode <= 299 { return nil } - slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 1<<20)) - res.Body.Close() + slurp, _ := io.ReadAll(io.LimitReader(res.Body, 1<<20)) return &Error{ - Code: res.StatusCode, - Body: string(slurp), + Code: res.StatusCode, + Body: string(slurp), + Header: res.Header, } } +// MarshalStyle defines whether to marshal JSON with a {"data": ...} wrapper. type MarshalStyle bool +// WithDataWrapper marshals JSON with a {"data": ...} wrapper. var WithDataWrapper = MarshalStyle(true) + +// WithoutDataWrapper marshals JSON without a {"data": ...} wrapper. var WithoutDataWrapper = MarshalStyle(false) func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, error) { @@ -181,37 +215,12 @@ func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, error) { return buf, nil } -// endingWithErrorReader from r until it returns an error. If the -// final error from r is io.EOF and e is non-nil, e is used instead. -type endingWithErrorReader struct { - r io.Reader - e error -} - -func (er endingWithErrorReader) Read(p []byte) (n int, err error) { - n, err = er.r.Read(p) - if err == io.EOF && er.e != nil { - err = er.e - } - return -} - -// countingWriter counts the number of bytes it receives to write, but -// discards them. -type countingWriter struct { - n *int64 -} - -func (w countingWriter) Write(p []byte) (int, error) { - *w.n += int64(len(p)) - return len(p), nil -} - // ProgressUpdater is a function that is called upon every progress update of a resumable upload. // This is the only part of a resumable upload (from googleapi) that is usable by the developer. // The remaining usable pieces of resumable uploads is exposed in each auto-generated API. type ProgressUpdater func(current, total int64) +// MediaOption defines the interface for setting media options. type MediaOption interface { setOptions(o *MediaOptions) } @@ -250,12 +259,45 @@ func ChunkSize(size int) MediaOption { return chunkSizeOption(size) } +type chunkTransferTimeoutOption time.Duration + +func (cd chunkTransferTimeoutOption) setOptions(o *MediaOptions) { + o.ChunkTransferTimeout = time.Duration(cd) +} + +// ChunkTransferTimeout returns a MediaOption which sets a per-chunk +// transfer timeout for resumable uploads. If a single chunk has been +// attempting to upload for longer than this time then the old req got canceled and retried. +// The default is no timeout for the request. +func ChunkTransferTimeout(timeout time.Duration) MediaOption { + return chunkTransferTimeoutOption(timeout) +} + +type chunkRetryDeadlineOption time.Duration + +func (cd chunkRetryDeadlineOption) setOptions(o *MediaOptions) { + o.ChunkRetryDeadline = time.Duration(cd) +} + +// ChunkRetryDeadline returns a MediaOption which sets a per-chunk retry +// deadline. If a single chunk has been attempting to upload for longer than +// this time and the request fails, it will no longer be retried, and the error +// will be returned to the caller. +// This is only applicable for files which are large enough to require +// a multi-chunk resumable upload. +// The default value is 32s. +// To set a deadline on the entire upload, use context timeout or cancellation. +func ChunkRetryDeadline(deadline time.Duration) MediaOption { + return chunkRetryDeadlineOption(deadline) +} + // MediaOptions stores options for customizing media upload. It is not used by developers directly. type MediaOptions struct { ContentType string ForceEmptyContentType bool - - ChunkSize int + ChunkSize int + ChunkRetryDeadline time.Duration + ChunkTransferTimeout time.Duration } // ProcessMediaOptions stores options from opts in a MediaOptions. @@ -268,51 +310,47 @@ func ProcessMediaOptions(opts []MediaOption) *MediaOptions { return mo } +// ResolveRelative resolves relatives such as "http://www.golang.org/" and +// "topics/myproject/mytopic" into a single string, such as +// "http://www.golang.org/topics/myproject/mytopic". It strips all parent +// references (e.g. ../..) as well as anything after the host +// (e.g. /bar/gaz gets stripped out of foo.com/bar/gaz). +// +// ResolveRelative panics if either basestr or relstr is not able to be parsed. func ResolveRelative(basestr, relstr string) string { - u, _ := url.Parse(basestr) - rel, _ := url.Parse(relstr) + u, err := url.Parse(basestr) + if err != nil { + panic(fmt.Sprintf("failed to parse %q", basestr)) + } + afterColonPath := "" + if i := strings.IndexRune(relstr, ':'); i > 0 { + afterColonPath = relstr[i+1:] + relstr = relstr[:i] + } + rel, err := url.Parse(relstr) + if err != nil { + panic(fmt.Sprintf("failed to parse %q", relstr)) + } u = u.ResolveReference(rel) us := u.String() + if afterColonPath != "" { + us = fmt.Sprintf("%s:%s", us, afterColonPath) + } us = strings.Replace(us, "%7B", "{", -1) us = strings.Replace(us, "%7D", "}", -1) + us = strings.Replace(us, "%2A", "*", -1) return us } -// has4860Fix is whether this Go environment contains the fix for -// http://golang.org/issue/4860 -var has4860Fix bool - -// init initializes has4860Fix by checking the behavior of the net/http package. -func init() { - r := http.Request{ - URL: &url.URL{ - Scheme: "http", - Opaque: "//opaque", - }, - } - b := &bytes.Buffer{} - r.Write(b) - has4860Fix = bytes.HasPrefix(b.Bytes(), []byte("GET http")) -} - -// SetOpaque sets u.Opaque from u.Path such that HTTP requests to it -// don't alter any hex-escaped characters in u.Path. -func SetOpaque(u *url.URL) { - u.Opaque = "//" + u.Host + u.Path - if !has4860Fix { - u.Opaque = u.Scheme + ":" + u.Opaque - } -} - // Expand subsitutes any {encoded} strings in the URL passed in using // the map supplied. // // This calls SetOpaque to avoid encoding of the parameters in the URL path. func Expand(u *url.URL, expansions map[string]string) { - expanded, err := uritemplates.Expand(u.Path, expansions) + escaped, unescaped, err := uritemplates.Expand(u.Path, expansions) if err == nil { - u.Path = expanded - SetOpaque(u) + u.Path = unescaped + u.RawPath = escaped } } @@ -360,7 +398,7 @@ func ConvertVariant(v map[string]interface{}, dst interface{}) bool { } // A Field names a field to be retrieved with a partial response. -// See https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// https://cloud.google.com/storage/docs/json_api/v1/how-tos/performance // // Partial responses can dramatically reduce the amount of data that must be sent to your application. // In order to request partial responses, you can specify the full list of fields @@ -371,14 +409,11 @@ func ConvertVariant(v map[string]interface{}, dst interface{}) bool { // For example, if your response has a "NextPageToken" and a slice of "Items" with "Id" fields, // you could request just those fields like this: // -// svc.Events.List().Fields("nextPageToken", "items/id").Do() +// svc.Events.List().Fields("nextPageToken", "items/id").Do() // // or if you were also interested in each Item's "Updated" field, you can combine them like this: // -// svc.Events.List().Fields("nextPageToken", "items(id,updated)").Do() -// -// More information about field formatting can be found here: -// https://developers.google.com/+/api/#fields-syntax +// svc.Events.List().Fields("nextPageToken", "items(id,updated)").Do() // // Another way to find field names is through the Google API explorer: // https://developers.google.com/apis-explorer/#p/ @@ -403,6 +438,14 @@ type CallOption interface { Get() (key, value string) } +// A MultiCallOption is an option argument to an API call and can be passed +// anywhere a CallOption is accepted. It additionally supports returning a slice +// of values for a given key. +type MultiCallOption interface { + CallOption + GetMulti() (key string, value []string) +} + // QuotaUser returns a CallOption that will set the quota user for a call. // The quota user can be used by server-side applications to control accounting. // It can be an arbitrary string up to 40 characters, and will override UserIP @@ -429,4 +472,24 @@ type traceTok string func (t traceTok) Get() (string, string) { return "trace", "token:" + string(t) } +type queryParameter struct { + key string + values []string +} + +// QueryParameter allows setting the value(s) of an arbitrary key. +func QueryParameter(key string, values ...string) CallOption { + return queryParameter{key: key, values: append([]string{}, values...)} +} + +// Get will never actually be called -- GetMulti will. +func (q queryParameter) Get() (string, string) { + return "", "" +} + +// GetMulti returns the key and values values associated to that key. +func (q queryParameter) GetMulti() (string, []string) { + return q.key, q.values +} + // TODO: Fields too diff --git a/vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE b/vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE deleted file mode 100644 index de9c88cb..00000000 --- a/vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE +++ /dev/null @@ -1,18 +0,0 @@ -Copyright (c) 2013 Joshua Tacoma - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go b/vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go deleted file mode 100644 index 7c103ba1..00000000 --- a/vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go +++ /dev/null @@ -1,220 +0,0 @@ -// Copyright 2013 Joshua Tacoma. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package uritemplates is a level 3 implementation of RFC 6570 (URI -// Template, http://tools.ietf.org/html/rfc6570). -// uritemplates does not support composite values (in Go: slices or maps) -// and so does not qualify as a level 4 implementation. -package uritemplates - -import ( - "bytes" - "errors" - "regexp" - "strconv" - "strings" -) - -var ( - unreserved = regexp.MustCompile("[^A-Za-z0-9\\-._~]") - reserved = regexp.MustCompile("[^A-Za-z0-9\\-._~:/?#[\\]@!$&'()*+,;=]") - validname = regexp.MustCompile("^([A-Za-z0-9_\\.]|%[0-9A-Fa-f][0-9A-Fa-f])+$") - hex = []byte("0123456789ABCDEF") -) - -func pctEncode(src []byte) []byte { - dst := make([]byte, len(src)*3) - for i, b := range src { - buf := dst[i*3 : i*3+3] - buf[0] = 0x25 - buf[1] = hex[b/16] - buf[2] = hex[b%16] - } - return dst -} - -func escape(s string, allowReserved bool) string { - if allowReserved { - return string(reserved.ReplaceAllFunc([]byte(s), pctEncode)) - } - return string(unreserved.ReplaceAllFunc([]byte(s), pctEncode)) -} - -// A uriTemplate is a parsed representation of a URI template. -type uriTemplate struct { - raw string - parts []templatePart -} - -// parse parses a URI template string into a uriTemplate object. -func parse(rawTemplate string) (*uriTemplate, error) { - split := strings.Split(rawTemplate, "{") - parts := make([]templatePart, len(split)*2-1) - for i, s := range split { - if i == 0 { - if strings.Contains(s, "}") { - return nil, errors.New("unexpected }") - } - parts[i].raw = s - continue - } - subsplit := strings.Split(s, "}") - if len(subsplit) != 2 { - return nil, errors.New("malformed template") - } - expression := subsplit[0] - var err error - parts[i*2-1], err = parseExpression(expression) - if err != nil { - return nil, err - } - parts[i*2].raw = subsplit[1] - } - return &uriTemplate{ - raw: rawTemplate, - parts: parts, - }, nil -} - -type templatePart struct { - raw string - terms []templateTerm - first string - sep string - named bool - ifemp string - allowReserved bool -} - -type templateTerm struct { - name string - explode bool - truncate int -} - -func parseExpression(expression string) (result templatePart, err error) { - switch expression[0] { - case '+': - result.sep = "," - result.allowReserved = true - expression = expression[1:] - case '.': - result.first = "." - result.sep = "." - expression = expression[1:] - case '/': - result.first = "/" - result.sep = "/" - expression = expression[1:] - case ';': - result.first = ";" - result.sep = ";" - result.named = true - expression = expression[1:] - case '?': - result.first = "?" - result.sep = "&" - result.named = true - result.ifemp = "=" - expression = expression[1:] - case '&': - result.first = "&" - result.sep = "&" - result.named = true - result.ifemp = "=" - expression = expression[1:] - case '#': - result.first = "#" - result.sep = "," - result.allowReserved = true - expression = expression[1:] - default: - result.sep = "," - } - rawterms := strings.Split(expression, ",") - result.terms = make([]templateTerm, len(rawterms)) - for i, raw := range rawterms { - result.terms[i], err = parseTerm(raw) - if err != nil { - break - } - } - return result, err -} - -func parseTerm(term string) (result templateTerm, err error) { - // TODO(djd): Remove "*" suffix parsing once we check that no APIs have - // mistakenly used that attribute. - if strings.HasSuffix(term, "*") { - result.explode = true - term = term[:len(term)-1] - } - split := strings.Split(term, ":") - if len(split) == 1 { - result.name = term - } else if len(split) == 2 { - result.name = split[0] - var parsed int64 - parsed, err = strconv.ParseInt(split[1], 10, 0) - result.truncate = int(parsed) - } else { - err = errors.New("multiple colons in same term") - } - if !validname.MatchString(result.name) { - err = errors.New("not a valid name: " + result.name) - } - if result.explode && result.truncate > 0 { - err = errors.New("both explode and prefix modifers on same term") - } - return result, err -} - -// Expand expands a URI template with a set of values to produce a string. -func (t *uriTemplate) Expand(values map[string]string) string { - var buf bytes.Buffer - for _, p := range t.parts { - p.expand(&buf, values) - } - return buf.String() -} - -func (tp *templatePart) expand(buf *bytes.Buffer, values map[string]string) { - if len(tp.raw) > 0 { - buf.WriteString(tp.raw) - return - } - var first = true - for _, term := range tp.terms { - value, exists := values[term.name] - if !exists { - continue - } - if first { - buf.WriteString(tp.first) - first = false - } else { - buf.WriteString(tp.sep) - } - tp.expandString(buf, term, value) - } -} - -func (tp *templatePart) expandName(buf *bytes.Buffer, name string, empty bool) { - if tp.named { - buf.WriteString(name) - if empty { - buf.WriteString(tp.ifemp) - } else { - buf.WriteString("=") - } - } -} - -func (tp *templatePart) expandString(buf *bytes.Buffer, t templateTerm, s string) { - if len(s) > t.truncate && t.truncate > 0 { - s = s[:t.truncate] - } - tp.expandName(buf, t.name, len(s) == 0) - buf.WriteString(escape(s, tp.allowReserved)) -} diff --git a/vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go b/vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go deleted file mode 100644 index eff260a6..00000000 --- a/vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2016 The Go 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 uritemplates - -func Expand(path string, values map[string]string) (string, error) { - template, err := parse(path) - if err != nil { - return "", err - } - return template.Expand(values), nil -} diff --git a/vendor/google.golang.org/api/googleapi/types.go b/vendor/google.golang.org/api/googleapi/types.go index a02b4b07..fabf74d5 100644 --- a/vendor/google.golang.org/api/googleapi/types.go +++ b/vendor/google.golang.org/api/googleapi/types.go @@ -1,4 +1,4 @@ -// Copyright 2013 Google Inc. All rights reserved. +// Copyright 2013 Google LLC. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. @@ -6,6 +6,7 @@ package googleapi import ( "encoding/json" + "errors" "strconv" ) @@ -119,36 +120,55 @@ func quotedList(n int, fn func(dst []byte, i int) []byte) ([]byte, error) { return dst, nil } -func (s Int64s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendInt(dst, s[i], 10) +func (q Int64s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendInt(dst, q[i], 10) }) } -func (s Int32s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendInt(dst, int64(s[i]), 10) +func (q Int32s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendInt(dst, int64(q[i]), 10) }) } -func (s Uint64s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendUint(dst, s[i], 10) +func (q Uint64s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendUint(dst, q[i], 10) }) } -func (s Uint32s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendUint(dst, uint64(s[i]), 10) +func (q Uint32s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendUint(dst, uint64(q[i]), 10) }) } -func (s Float64s) MarshalJSON() ([]byte, error) { - return quotedList(len(s), func(dst []byte, i int) []byte { - return strconv.AppendFloat(dst, s[i], 'g', -1, 64) +func (q Float64s) MarshalJSON() ([]byte, error) { + return quotedList(len(q), func(dst []byte, i int) []byte { + return strconv.AppendFloat(dst, q[i], 'g', -1, 64) }) } +// RawMessage is a raw encoded JSON value. +// It is identical to json.RawMessage, except it does not suffer from +// https://golang.org/issue/14493. +type RawMessage []byte + +// MarshalJSON returns m. +func (m RawMessage) MarshalJSON() ([]byte, error) { + return m, nil +} + +// UnmarshalJSON sets *m to a copy of data. +func (m *RawMessage) UnmarshalJSON(data []byte) error { + if m == nil { + return errors.New("googleapi.RawMessage: UnmarshalJSON on nil pointer") + } + *m = append((*m)[:0], data...) + return nil +} + /* * Helper routines for simplifying the creation of optional fields of basic type. */