internal/fetch: implement fetch and insert version to postgres

An initial version FetchAndInsertVersion is implemented, which:

(1) Downloads the given module version from the module proxy
(2) Process the contents:
  - Calculate series name
  - Get the contents of the README
  - Get the contents of the license
  - Get packages for the module
(3) Writes the data to postgres.

Change-Id: Iabce23879124a03599dc5779302e69cc5e432f88
Reviewed-on: https://team-review.git.corp.google.com/c/422995
Reviewed-by: Andrew Bonventre <andybons@google.com>
This commit is contained in:
Julie Qiu 2019-02-26 12:06:56 -05:00
Родитель b8bb5b03f7
Коммит 79ac5ae337
21 изменённых файлов: 550 добавлений и 236 удалений

2
go.mod
Просмотреть файл

@ -3,5 +3,5 @@ module golang.org/x/discovery
require (
github.com/lib/pq v1.0.0
gocloud.dev v0.10.0
golang.org/x/tools v0.0.0-20190220190617-97f80cd5504d
golang.org/x/tools v0.0.0-20181221154417-3ad2d988d5e2
)

41
go.sum
Просмотреть файл

@ -41,12 +41,14 @@ github.com/SAP/go-hdb v0.13.1/go.mod h1:etBT+FAi1t5k3K3tf5vQTnosgYmhDkRi8jEnQqCn
github.com/SAP/go-hdb v0.13.2/go.mod h1:etBT+FAi1t5k3K3tf5vQTnosgYmhDkRi8jEnQqCnxF0=
github.com/SermoDigital/jose v0.9.1/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA=
github.com/SermoDigital/jose v0.9.2-0.20161205224733-f6df55f235c2/go.mod h1:ARgCUhI1MHQH+ONky/PAtmVHQrP5JlGY0F3poXOp/fA=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190122153857-e0ace9b64d22/go.mod h1:T9M45xf79ahXVelWoOBmH0y4aC1t5kXO5BxwyakgIGA=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ=
github.com/apache/arrow/go/arrow v0.0.0-20181031164735-a56c009257a7/go.mod h1:GjvccvtI06FGFvRU1In/maF7tKp3h7GBV9Sexo5rNPM=
@ -114,9 +116,11 @@ github.com/duosecurity/duo_api_golang v0.0.0-20181024123116-92fea9203dbc/go.mod
github.com/duosecurity/duo_api_golang v0.0.0-20190107154727-539434bf0d45/go.mod h1:UqXY1lYT/ERa4OEAywUqdok1T4RCRdArkhic1Opuavo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/emirpasic/gods v1.9.0 h1:rUF4PuzEjMChMiNsVjdI+SyLu7rEqpQ5reNFnhC7oFo=
github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@ -126,6 +130,7 @@ github.com/gammazero/workerpool v0.0.0-20181230203049-86a96b5d5d92/go.mod h1:w9R
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/getkin/kin-openapi v0.1.0/go.mod h1:+0ZtELZf+SlWH8ZdA/IeFb3L/PKOKJx8eGxAlUZ/sOU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.1.1 h1:j3L6gSLQalDETeEg/Jg0mGY0/y/N6zI2xX1978P0Uqw=
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
@ -139,6 +144,7 @@ github.com/go-stomp/stomp v2.0.2+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiF
github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gocql/gocql v0.0.0-20181117210152-33c0e89ca93a/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
github.com/gocql/gocql v0.0.0-20190122205811-30de9a1866a8/go.mod h1:4Fw1eo5iaEhDUs8XyuhSVCVy52Jq3L+/3GJgYkwc+/0=
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/gddo v0.0.0-20181116215533-9bd4a3295021/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
@ -152,11 +158,15 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@ -175,10 +185,13 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR
github.com/goreleaser/goreleaser v0.94.0/go.mod h1:OjbYR2NhOI6AEUWCowMSBzo9nP1aRif3sYtx+rhp+Zo=
github.com/goreleaser/nfpm v0.9.7/go.mod h1:F2yzin6cBAL9gb+mSiReuXdsfTrOQwDMsuSpULof+y4=
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
@ -234,6 +247,7 @@ github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKe
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo=
github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/flux v0.13.0/go.mod h1:81jeDcHVn1rN5uj9aQ81S72Q8ol8If7N0zM0G8TnxTE=
@ -243,6 +257,7 @@ github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1
github.com/influxdata/platform v0.0.0-20190117200541-d500d3cf5589/go.mod h1:YVhys+JOY4wmXtJvdtkzLhS2K/r/px/vPc+EAddK+pg=
github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0=
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jeffchao/backoff v0.0.0-20140404060208-9d7fd7aa17f2/go.mod h1:xkfESuHriIekR+4RoV+fu91j/CfnYM29Zi2tMFw5iD4=
github.com/jefferai/jsonx v0.0.0-20160721235117-9cc31c3135ee/go.mod h1:N0t2vlmpe8nyZB5ouIbJQPDSR+mH6oe7xHB9VZHSUzM=
@ -253,6 +268,7 @@ github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5i
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.5 h1:gL2yXlmiIo4+t+y32d4WGwOjKGYcGOuyrg46vadswDE=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
@ -260,6 +276,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
github.com/kevinburke/go-bindata v3.11.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM=
github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e h1:RgQk53JHp/Cjunrr1WlsXSZpqXn+uREuHvUVcK82CV8=
github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/keybase/go-crypto v0.0.0-20181031135447-f919bfda4fc1/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
github.com/keybase/go-crypto v0.0.0-20181127160227-255a5089e85a/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
@ -288,6 +305,7 @@ github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00v
github.com/miekg/dns v1.1.1/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
@ -297,6 +315,7 @@ github.com/mitchellh/mapstructure v1.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mna/pigeon v1.0.1-0.20180808201053-bb0192cfc2ae/go.mod h1:Iym28+kJVnC1hfQvv5MUtI6AiFFzvQjHcvI4RFTG/04=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
@ -322,11 +341,13 @@ github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnh
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -346,9 +367,11 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
@ -386,8 +409,10 @@ github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgK
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stevvooe/resumable v0.0.0-20180830230917-22b14a53ba50/go.mod h1:1pdIZTAHUz+HDKDVZ++5xg/duPlhKAIzw9qy42CWYp4=
github.com/streadway/amqp v0.0.0-20181205114330-a314942b2fd9/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY=
@ -408,6 +433,7 @@ github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMW
github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/ugorji/go/codec v0.0.0-20181012064053-8333dd449516/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/xanzy/ssh-agent v0.2.0 h1:Adglfbi5p9Z0BmK2oKU9nTG+zKfniSfnaMYB+ULd+Ro=
github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
@ -431,6 +457,7 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190122013713-64072686203f h1:u1CmMhe3a44hy8VIgpInORnI01UVaUYheqR7x9BxT3c=
golang.org/x/crypto v0.0.0-20190122013713-64072686203f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20181112044915-a3060d491354/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -448,8 +475,6 @@ golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190119204137-ed066c81e75e h1:MDa3fSUp6MdYHouVmCCNz/zaH2a6CRcxY3VhT/K3C5Q=
golang.org/x/net v0.0.0-20190119204137-ed066c81e75e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/oauth2 v0.0.0-20180603041954-1e0a3fa8ba9a/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -476,6 +501,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c h1:fqgJT0MGcGpPgpWU7VRdRjuArfcOvC4AoJmILihzhDg=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -483,8 +509,6 @@ golang.org/x/tools v0.0.0-20181017214349-06f26fdaaa28/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181221154417-3ad2d988d5e2 h1:M7NLB69gFpUH4s6SJLwXiVs45aZfVjqGKynfNFKSGcI=
golang.org/x/tools v0.0.0-20181221154417-3ad2d988d5e2/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190220190617-97f80cd5504d h1:c7LLuMAYgBPaDC7+tYrCSMtjTYFZRQOtDBnVJ5sV79w=
golang.org/x/tools v0.0.0-20190220190617-97f80cd5504d/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/xerrors v0.0.0-20190129162528-20feca13ea86 h1:kMgZCSynBSIN3PHpvuFeMExQwPWtUZ/xfnt2Yr2cp20=
golang.org/x/xerrors v0.0.0-20190129162528-20feca13ea86/go.mod h1:/lyp46tcDBI65C0XC8F4d0/XVb7MT7RScVRech7dX/4=
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
@ -526,6 +550,7 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/fatih/pool.v2 v2.0.0/go.mod h1:8xVGeu1/2jr2wm5V9SPuMht2H5AEmf5aFMGSQixtjTY=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gorethink/gorethink.v4 v4.1.0/go.mod h1:M7JgwrUAmshJ3iUbEK0Pt049MPyPK+CYDGGaEjdZb/c=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ldap.v2 v2.5.1/go.mod h1:oI0cpe/D7HRtBQl8aTg+ZmzFUAvu4lsv3eLXMLGFxWk=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
@ -533,11 +558,15 @@ gopkg.in/ory-am/dockertest.v2 v2.2.3/go.mod h1:kDHEsan1UcKFYH1c28sDmqnmeqIpB4Nj6
gopkg.in/pipe.v2 v2.0.0-20140414041502-3c2ca4d52544/go.mod h1:UhTeH/yXCK/KY7TX24mqPkaQ7gZeqmWd/8SSS8B3aHw=
gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5/go.mod h1:hiOFpYm0ZJbusNj2ywpbrXowU3G8U6GIQzqn2mw1UIE=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/src-d/go-billy.v4 v4.2.1 h1:omN5CrMrMcQ+4I8bJ0wEhOBPanIRWzFC953IiXKdYzo=
gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
gopkg.in/src-d/go-git-fixtures.v3 v3.1.1 h1:XWW/s5W18RaJpmo1l0IYGqXKuJITWRFuA45iOf1dKJs=
gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
gopkg.in/src-d/go-git.v4 v4.8.1 h1:aAyBmkdE1QUUEHcP4YFCGKmsMQRAuRmUcPEQR7lOAa0=
gopkg.in/src-d/go-git.v4 v4.8.1/go.mod h1:Vtut8izDyrM8BUVQnzJ+YvmNcem2J89EmfZYCkLokZk=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/vmihailenco/msgpack.v2 v2.9.1/go.mod h1:/3Dn1Npt9+MYyLpYYXjInO/5jvMLamn+AEGwNEOatn8=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -546,12 +575,16 @@ grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJd
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20181108184350-ae8f1f9103cc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.0.0-20181221193117-173ce66c1e39 h1:iGq7zEPXFb0IeXAQK5RiYT1SVKX/af9F9Wv0M+yudPY=
k8s.io/api v0.0.0-20181221193117-173ce66c1e39/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
k8s.io/apimachinery v0.0.0-20190119020841-d41becfba9ee h1:3MH/wGFP+9PjyLIMnPN2GYatdJosd+5TnSO2BzQqqo4=
k8s.io/apimachinery v0.0.0-20190119020841-d41becfba9ee/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/klog v0.1.0 h1:I5HMfc/DtuVaGR1KPwUrTc476K8NCqNBldC7H4dYEzk=
k8s.io/klog v0.1.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
layeh.com/radius v0.0.0-20190118135028-0f678f039617/go.mod h1:fywZKyu//X7iRzaxLgPWsvc0L26IUpVvE/aeIL2JtIQ=
pack.ag/amqp v0.8.0/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
pack.ag/amqp v0.10.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=

Просмотреть файл

@ -16,10 +16,14 @@ import (
"strings"
"golang.org/x/discovery/internal"
"golang.org/x/discovery/internal/postgres"
"golang.org/x/discovery/internal/proxy"
"golang.org/x/tools/go/packages"
)
var errReadmeNotFound = errors.New("fetch: zip file does not contain a README")
var (
errModuleContainsNoPackages = errors.New("module contains 0 packages")
)
// ParseNameAndVersion returns the module and version specified by u. u is
// assumed to be a valid url following the structure http(s)://<fetchURL>/<module>@<version>.
@ -40,50 +44,72 @@ func ParseNameAndVersion(u *url.URL) (string, string, error) {
return parts[0], parts[1], nil
}
// isReadme checks if file is the README. It is case insensitive.
func isReadme(file string) bool {
base := filepath.Base(file)
f := strings.TrimSuffix(base, filepath.Ext(base))
return strings.ToUpper(f) == "README"
}
// containsReadme checks if rc contains a README file.
func containsReadme(rc *zip.ReadCloser) bool {
for _, zipFile := range rc.File {
if isReadme(zipFile.Name) {
return true
}
}
return false
}
// readReadme reads the contents of the first file from rc that passes the
// isReadme check. It returns an error if such a file does not exist.
func readReadme(rc *zip.ReadCloser) ([]byte, error) {
for _, zipFile := range rc.File {
if isReadme(zipFile.Name) {
return readZipFile(zipFile)
}
}
return nil, errReadmeNotFound
}
// readZipFile returns the uncompressed contents of f or an error if the
// uncompressed size of f exceeds 1MB.
func readZipFile(f *zip.File) ([]byte, error) {
if f.UncompressedSize64 > 1e6 {
return nil, fmt.Errorf("file size %d exceeds 1MB, skipping", f.UncompressedSize64)
}
rc, err := f.Open()
// FetchAndInsertVersion downloads the given module version from the module proxy, processes
// the contents, and writes the data to the database. The fetch service will:
// (1) Get the version commit time from the proxy
// (2) Download the version zip from the proxy
// (3) Process the contents (series name, readme, license, and packages)
// (4) Write the data to the discovery database
func FetchAndInsertVersion(name, version string, proxyClient *proxy.Client, db *postgres.DB) error {
info, err := proxyClient.GetInfo(name, version)
if err != nil {
return nil, err
return fmt.Errorf("proxyClient.GetInfo(%q, %q): %v", name, version, err)
}
defer rc.Close()
return ioutil.ReadAll(rc)
zipReader, err := proxyClient.GetZip(name, version)
if err != nil {
return fmt.Errorf("proxyClient.GetZip(%q, %q): %v", name, version, err)
}
var readme []byte
readmeFile := "README"
if containsFile(zipReader, readmeFile) {
readme, err = extractFile(zipReader, readmeFile)
if err != nil {
return fmt.Errorf("extractFile(%v, %q): %v", zipReader, readmeFile, err)
}
}
var license []byte
licenseFile := "LICENSE"
if containsFile(zipReader, licenseFile) {
license, err = extractFile(zipReader, licenseFile)
if err != nil {
return fmt.Errorf("extractFile(%v, %q): %v", zipReader, licenseFile, err)
}
}
seriesName, err := seriesNameForModule(name)
if err != nil {
return fmt.Errorf("seriesNameForModule(%q): %v", name, err)
}
packages, err := extractPackagesFromZip(name, version, zipReader)
if err != nil && err != errModuleContainsNoPackages {
return fmt.Errorf("extractPackagesFromZip(%q, %q, %v): %v", name, version, zipReader, err)
}
v := internal.Version{
Module: &internal.Module{
Name: name,
Series: &internal.Series{
Name: seriesName,
},
},
Version: version,
CommitTime: info.Time,
ReadMe: string(readme),
License: string(license),
Packages: packages,
}
if err = db.InsertVersion(&v); err != nil {
return fmt.Errorf("db.InsertVersion(%+v): %v", v, err)
}
return nil
}
// extractPackagesFromZip returns a slice of packages from the module zip r.
func extractPackagesFromZip(module string, r *zip.ReadCloser) ([]*internal.Package, error) {
func extractPackagesFromZip(module, version string, r *zip.Reader) ([]*internal.Package, error) {
// Create a temporary directory to write the contents of the module zip.
tempPrefix := "discovery_"
dir, err := ioutil.TempDir("", tempPrefix)
@ -121,7 +147,7 @@ func extractPackagesFromZip(module string, r *zip.ReadCloser) ([]*internal.Packa
config := &packages.Config{
Mode: packages.LoadSyntax,
Dir: fmt.Sprintf("%s/%s", dir, module),
Dir: fmt.Sprintf("%s/%s@%s", dir, module, version),
}
pattern := fmt.Sprintf("%s/...", module)
pkgs, err := packages.Load(config, pattern)
@ -130,7 +156,7 @@ func extractPackagesFromZip(module string, r *zip.ReadCloser) ([]*internal.Packa
}
if len(pkgs) == 0 {
return nil, fmt.Errorf("packages.Load(%+v, %q) returned 0 packages", config, pattern)
return nil, errModuleContainsNoPackages
}
packages := []*internal.Package{}
@ -174,3 +200,51 @@ func seriesNameForModule(name string) (string, error) {
}
return name, nil
}
// extractFile reads the contents of the first file from r that passes the
// hasFilename check for expectedFile. It returns an error if such a file
// does not exist.
func extractFile(r *zip.Reader, expectedFile string) ([]byte, error) {
for _, zipFile := range r.File {
if hasFilename(zipFile.Name, expectedFile) {
c, err := readZipFile(zipFile)
return c, err
}
}
return nil, fmt.Errorf("zip does not contain %q", expectedFile)
}
// containsFile checks if r contains expectedFile.
func containsFile(r *zip.Reader, expectedFile string) bool {
for _, zipFile := range r.File {
if hasFilename(zipFile.Name, expectedFile) {
return true
}
}
return false
}
// hasFilename checks if:
// (1) file is expectedFile, or
// (2) the name of file, without the base, is equal to expectedFile.
// It is case insensitive.
func hasFilename(file string, expectedFile string) bool {
base := filepath.Base(file)
return strings.EqualFold(base, expectedFile) ||
strings.EqualFold(strings.TrimSuffix(base, filepath.Ext(base)), expectedFile)
}
// readZipFile returns the uncompressed contents of f or an error if the
// uncompressed size of f exceeds 1MB.
func readZipFile(f *zip.File) ([]byte, error) {
if f.UncompressedSize64 > 1e6 {
return nil, fmt.Errorf("file size %d exceeds 1MB, skipping", f.UncompressedSize64)
}
rc, err := f.Open()
if err != nil {
return nil, err
}
defer rc.Close()
b, err := ioutil.ReadAll(rc)
return b, err
}

Просмотреть файл

@ -8,12 +8,91 @@ import (
"archive/zip"
"bytes"
"errors"
"fmt"
"io/ioutil"
"net/url"
"path/filepath"
"reflect"
"strings"
"testing"
"time"
"golang.org/x/discovery/internal"
"golang.org/x/discovery/internal/postgres"
"golang.org/x/discovery/internal/proxy"
)
// structToString returns a string containing the fields and values of a given
// struct i. It is used in error messages for tests.
func structToString(i interface{}) string {
s := reflect.ValueOf(i).Elem()
typeOfT := s.Type()
var b strings.Builder
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
fmt.Fprintf(&b, fmt.Sprintf("%d: %s %s = %v \n", i, typeOfT.Field(i).Name, f.Type(), f.Interface()))
}
return b.String()
}
func TestFetchAndInsertVersion(t *testing.T) {
testCases := []struct {
name string
version string
versionData *internal.Version
}{
{
name: "my/module",
version: "v1.0.0",
versionData: &internal.Version{
Module: &internal.Module{
Name: "my/module",
},
Version: "v1.0.0",
CommitTime: time.Date(2019, 1, 30, 0, 0, 0, 0, time.UTC),
ReadMe: "README FILE FOR TESTING.",
License: "LICENSE FILE FOR TESTING.",
},
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
teardownDB, db := postgres.SetupCleanDB(t)
defer teardownDB(t)
teardownProxyClient, client := proxy.SetupTestProxyClient(t)
defer teardownProxyClient(t)
if err := FetchAndInsertVersion(tc.name, tc.version, client, db); err != nil {
t.Fatalf("FetchVersion(%q, %q, %v, %v): %v", tc.name, tc.version, client, db, err)
}
got, err := db.GetVersion(tc.name, tc.version)
if err != nil {
t.Fatalf("db.GetVersion(%q, %q): %v", tc.name, tc.version, err)
}
// Set CreatedAt and UpdatedAt to nil for testing, since these are
// set by the database.
got.CreatedAt = time.Time{}
got.UpdatedAt = time.Time{}
// got.CommitTime has a timezone location of +0000, while
// tc.versionData.CommitTime has a timezone location of UTC.
// These are equal according to time.Equal, but fail for
// reflect.DeepEqual. Convert the DB time to UTC.
got.CommitTime = got.CommitTime.UTC()
if !reflect.DeepEqual(*got, *tc.versionData) {
t.Errorf("db.GetVersion(%q, %q): \n %s \n want: \n %s",
tc.name, tc.version, structToString(got), structToString(tc.versionData))
}
})
}
}
func TestParseNameAndVersion(t *testing.T) {
testCases := []struct {
name string
@ -75,89 +154,58 @@ func TestParseNameAndVersion(t *testing.T) {
}
}
func TestIsReadme(t *testing.T) {
for input, want := range map[string]bool{
"rEaDme": true,
"README.FOO": true,
"FOO_README": false,
"README_FOO": false,
"README.FOO.FOO": false,
func TestHasFilename(t *testing.T) {
for _, tc := range []struct {
name string
file string
expectedFile string
want bool
}{
{
file: "my/module@v1.0.0/README.md",
expectedFile: "README.md",
want: true,
},
{
file: "rEaDme",
expectedFile: "README",
want: true,
}, {
file: "README.FOO",
expectedFile: "README",
want: true,
},
{
file: "FOO_README",
expectedFile: "README",
want: false,
},
{
file: "README_FOO",
expectedFile: "README",
want: false,
},
{
file: "README.FOO.FOO",
expectedFile: "README",
want: false,
},
{
file: "",
expectedFile: "README",
want: false,
},
} {
got := isReadme(input)
if got != want {
t.Errorf("isReadme(%q) = %t: %t", input, got, want)
{
t.Run(tc.file, func(t *testing.T) {
got := hasFilename(tc.file, tc.expectedFile)
if got != tc.want {
t.Errorf("hasFilename(%q, %q) = %t: %t", tc.file, tc.expectedFile, got, tc.want)
}
})
}
}
got := isReadme("")
if got != false {
t.Errorf("isReadme(%q) = %t: %t", "", got, false)
}
}
func TestContainsReadme(t *testing.T) {
testZip := "testdata/module.zip"
zipReader, err := zip.OpenReader(testZip)
if err != nil {
t.Fatalf("zip.OpenReader(%q) error: %v", testZip, err)
}
defer zipReader.Close()
if !containsReadme(zipReader) {
t.Errorf("containsReadme(%q) = false, want true", testZip)
}
}
func TestContainsReadmeEmptyZip(t *testing.T) {
testZip := "testdata/empty.zip"
zipReader, err := zip.OpenReader(testZip)
if err != nil {
t.Fatalf("zip.OpenReader(%q) error: %v", testZip, err)
}
defer zipReader.Close()
if containsReadme(zipReader) {
t.Errorf("containsReadme(%q) = true, want false", testZip)
}
}
func TestReadZip(t *testing.T) {
testZip := "testdata/module.zip"
zipReader, err := zip.OpenReader(testZip)
if err != nil {
t.Fatalf("zip.OpenReader(%q) error: %v", testZip, err)
}
defer zipReader.Close()
got, err := readReadme(zipReader)
if err != nil {
t.Errorf("readReadme(%q) error: %v", testZip, err)
}
testReadmeFilename := "testdata/my/module/README.md"
want, err := ioutil.ReadFile(testReadmeFilename)
if err != nil {
t.Errorf("readReadme(%q) error: %v", testReadmeFilename, err)
}
if !bytes.Equal(want, got) {
t.Errorf("readReadme(%q) = %q, want %q", testZip, got, want)
}
}
func TestReadZipEmptyZip(t *testing.T) {
testZip := "testdata/empty.zip"
zipReader, err := zip.OpenReader(testZip)
if err != nil {
t.Fatalf("zip.OpenReader(%q) error: %v", testZip, err)
}
defer zipReader.Close()
_, err = readReadme(zipReader)
if err != errReadmeNotFound {
t.Errorf("readReadme(%q) error: %v, want %v", testZip, err, errReadmeNotFound)
}
}
func TestSeriesNameForModule(t *testing.T) {
@ -171,6 +219,7 @@ func TestSeriesNameForModule(t *testing.T) {
"my/module/v23456": "my/module",
"v2/": "v2",
} {
t.Run(input, func(t *testing.T) {
got, err := seriesNameForModule(input)
if err != nil {
t.Errorf("seriesNameForModule(%q): %v", input, err)
@ -178,54 +227,161 @@ func TestSeriesNameForModule(t *testing.T) {
if got != want {
t.Errorf("seriesNameForModule(%q) = %q, want %q", input, got, want)
}
})
}
want := errors.New("module name cannot be empty")
if _, got := seriesNameForModule(""); got.Error() != want.Error() {
t.Errorf("seriesNameForModule(%q) returned error: %v; want %v", "", got, want)
wantErr := "module name cannot be empty"
if _, err := seriesNameForModule(""); err == nil || err.Error() != wantErr {
t.Errorf("seriesNameForModule(%q) returned error: %v; want %v", "", err, wantErr)
}
}
func TestContainsFile(t *testing.T) {
for _, tc := range []struct {
zip string
File string
Want bool
}{
{
zip: "module.zip",
File: "README",
Want: true,
},
{
zip: "module.zip",
File: "LICENSE",
Want: false,
},
{
zip: "empty.zip",
File: "README",
Want: false,
},
{
zip: "empty.zip",
File: "LICENSE",
Want: false,
},
} {
t.Run(tc.zip, func(t *testing.T) {
name := filepath.Join("testdata", tc.zip)
rc, err := zip.OpenReader(name)
if err != nil {
t.Fatalf("zip.OpenReader(%q): %v", name, err)
}
defer rc.Close()
z := &rc.Reader
if got := containsFile(z, tc.File); got != tc.Want {
t.Errorf("containsFile(%q, %q) = %t, want %t", name, tc.File, got, tc.Want)
}
})
}
}
func TestExtractFile(t *testing.T) {
for _, tc := range []struct {
zip string
file string
err error
}{
{
zip: "testdata/module.zip",
file: "my/module@v1.0.0/README.md",
err: nil,
},
{
zip: "testdata/empty.zip",
file: "empty/nonexistent/README.md",
err: errors.New(`zip does not contain "README.md"`),
},
} {
t.Run(tc.zip, func(t *testing.T) {
rc, err := zip.OpenReader(tc.zip)
if err != nil {
t.Fatalf("zip.OpenReader(%q): %v", tc.zip, err)
}
defer rc.Close()
z := &rc.Reader
got, err := extractFile(z, filepath.Base(tc.file))
if err != nil {
if tc.err == nil || tc.err.Error() != err.Error() {
t.Errorf("extractFile(%q, %q): \n %v, want \n %v",
tc.zip, filepath.Base(tc.file), err, tc.err)
} else {
return
}
}
f := filepath.Join("testdata", tc.file)
want, err := ioutil.ReadFile(f)
if err != nil {
t.Fatalf("ioutfil.ReadFile(%q) error: %v", f, err)
}
if !bytes.Equal(want, got) {
t.Errorf("extractFile(%q, %q) = %q, want %q", tc.zip, tc.file, got, want)
}
})
}
}
func TestExtractPackagesFromZip(t *testing.T) {
testZip := "testdata/module.zip"
zipReader, err := zip.OpenReader(testZip)
for _, tc := range []struct {
zip string
name string
version string
packages map[string]*internal.Package
err error
}{
{
zip: "testdata/module.zip",
name: "my/module",
version: "v1.0.0",
packages: map[string]*internal.Package{
"foo": &internal.Package{
Name: "foo",
Path: "my/module/foo",
},
"bar": &internal.Package{
Name: "bar",
Path: "my/module/bar",
},
},
},
{
zip: "testdata/empty.zip",
name: "empty/module",
version: "v1.0.0",
packages: map[string]*internal.Package{},
},
} {
t.Run(tc.name, func(t *testing.T) {
rc, err := zip.OpenReader(tc.zip)
if err != nil {
t.Fatalf("zip.OpenReader(%q): %v", testZip, err)
t.Fatalf("zip.OpenReader(%q): %v", tc.zip, err)
}
defer rc.Close()
z := &rc.Reader
packages, err := extractPackagesFromZip(tc.name, tc.version, z)
if err != nil && len(tc.packages) != 0 {
t.Fatalf("zipToPackages(%q, %q): %v", tc.name, tc.zip, err)
}
name := "my/module"
packages, err := extractPackagesFromZip(name, zipReader)
if err != nil {
t.Fatalf("zipToPackages(%q, %q): %v", name, testZip, err)
}
expectedNamesToPath := map[string]string{
"foo": "my/module/foo",
"bar": "my/module/bar",
}
for _, p := range packages {
expectedPath, ok := expectedNamesToPath[p.Name]
for _, got := range packages {
want, ok := tc.packages[got.Name]
if !ok {
t.Errorf("zipToPackages(%q, %q) returned unexpected package: %q", name, testZip, p.Name)
t.Errorf("zipToPackages(%q, %q) returned unexpected package: %q", tc.name, tc.zip, got.Name)
}
if expectedPath != p.Path {
t.Errorf("zipToPackages(%q, %q) returned unexpected path for package %q: %q, want %q", name, testZip, p.Name, p.Path, expectedPath)
if want.Path != got.Path {
t.Errorf("zipToPackages(%q, %q) returned unexpected path for package %q: %q, want %q",
tc.name, tc.zip, got.Name, got.Path, want.Path)
}
delete(expectedNamesToPath, p.Name)
}
}
func TestExtractPackagesFromZipEmptyZip(t *testing.T) {
testZip := "testdata/empty.zip"
zipReader, err := zip.OpenReader(testZip)
if err != nil {
t.Fatalf("zip.OpenReader(%q): %v", testZip, err)
}
name := "empty/module"
_, err = extractPackagesFromZip(name, zipReader)
if !strings.HasSuffix(err.Error(), "returned 0 packages") {
t.Fatalf("zipToPackages(%q, %q): %v", name, testZip, err)
delete(tc.packages, got.Name)
}
})
}
}

Двоичные данные
internal/fetch/testdata/empty.zip поставляемый

Двоичный файл не отображается.

Просмотреть файл

Двоичные данные
internal/fetch/testdata/module.zip поставляемый

Двоичный файл не отображается.

0
internal/fetch/testdata/my/module/@v/v1.0.0.info поставляемый Normal file
Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -5,44 +5,13 @@
package postgres
import (
"fmt"
"os"
"reflect"
"testing"
"time"
_ "github.com/lib/pq"
"golang.org/x/discovery/internal"
)
var (
user = getEnv("GO_DISCOVERY_DATABASE_TEST_USER", "postgres")
password = getEnv("GO_DISCOVERY_DATABASE_TEST_PASSWORD", "")
host = getEnv("GO_DISCOVERY_DATABASE_TEST_HOST", "localhost")
testdbname = getEnv("GO_DISCOVERY_DATABASE_TEST_NAME", "discovery-database-test")
testdb = fmt.Sprintf("user=%s host=%s dbname=%s sslmode=disable", user, host, testdbname)
)
func getEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return fallback
}
func setupCleanDB(t *testing.T) (func(t *testing.T), *DB) {
t.Helper()
db, err := Open(testdb)
if err != nil {
t.Fatalf("Open(%q), error: %v", testdb, err)
}
cleanup := func(t *testing.T) {
db.Exec(`TRUNCATE version_logs;`) // truncates version_logs
db.Exec(`TRUNCATE versions CASCADE;`) // truncates versions and any tables that use versions as a foreign key.
}
return cleanup, db
}
func TestPostgres_ReadAndWriteVersion(t *testing.T) {
var series = &internal.Series{
Name: "myseries",
@ -103,7 +72,7 @@ func TestPostgres_ReadAndWriteVersion(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
teardownTestCase, db := setupCleanDB(t)
teardownTestCase, db := SetupCleanDB(t)
defer teardownTestCase(t)
if err := db.InsertVersion(tc.versionData); tc.wantWriteErr != (err != nil) {
@ -134,7 +103,7 @@ func TestPostgres_ReadAndWriteVersion(t *testing.T) {
}
func TestPostgress_InsertVersionLogs(t *testing.T) {
teardownTestCase, db := setupCleanDB(t)
teardownTestCase, db := SetupCleanDB(t)
defer teardownTestCase(t)
now := time.Now().UTC()

Просмотреть файл

@ -0,0 +1,47 @@
// Copyright 2019 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 postgres
import (
"fmt"
"os"
"testing"
_ "github.com/lib/pq"
)
var (
user = getEnv("GO_DISCOVERY_DATABASE_TEST_USER", "postgres")
password = getEnv("GO_DISCOVERY_DATABASE_TEST_PASSWORD", "")
host = getEnv("GO_DISCOVERY_DATABASE_TEST_HOST", "localhost")
testdbname = getEnv("GO_DISCOVERY_DATABASE_TEST_NAME", "discovery-database-test")
testdb = fmt.Sprintf("user=%s host=%s dbname=%s sslmode=disable", user, host, testdbname)
)
func getEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
return value
}
return fallback
}
// SetupCleanDB is used to test functions that execute Postgres queries. It
// should only ever be used for testing. It makes a connection to a test
// Postgres database and truncates all the tables in the database after the
// test is complete.
func SetupCleanDB(t *testing.T) (func(t *testing.T), *DB) {
t.Helper()
db, err := Open(testdb)
if err != nil {
t.Fatalf("Open(%q), error: %v", testdb, err)
}
cleanup := func(t *testing.T) {
// truncates series and any tables that uses it as a foreign key.
// This includes: modules, versions, documents, packages, and dependencies.
db.Exec(`TRUNCATE series CASCADE;`)
db.Exec(`TRUNCATE version_logs;`) // truncates version_logs
}
return cleanup, db
}

Просмотреть файл

@ -17,7 +17,6 @@ import (
// A Client is used by the fetch service to communicate with a module
// proxy. It handles all methods defined by go help goproxy.
// TODO(julieqiu): Implement GetList, GetMod, and GetZip.
type Client struct {
url string // URL of the module proxy web server
}
@ -54,6 +53,11 @@ func (c *Client) GetInfo(name, version string) (*VersionInfo, error) {
}
defer r.Body.Close()
if r.StatusCode < 200 || r.StatusCode >= 300 {
return nil, fmt.Errorf("http.Get(%q) returned response: %d (%q)",
c.infoURL(name, version), r.StatusCode, r.Status)
}
var v VersionInfo
if err = json.NewDecoder(r.Body).Decode(&v); err != nil {
return nil, err

Просмотреть файл

@ -6,30 +6,10 @@ package proxy
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"
)
type testCase struct {
proxy *httptest.Server
client *Client
}
func setupTestCase(t *testing.T) (func(t *testing.T), *testCase) {
proxy := httptest.NewServer(http.FileServer(http.Dir("testdata/modproxy/proxy")))
tc := testCase{
proxy: proxy,
client: New(proxy.URL),
}
fn := func(t *testing.T) {
proxy.Close()
}
return fn, &tc
}
func TestCleanURL(t *testing.T) {
for raw, expected := range map[string]string{
"http://localhost:7000/index": "http://localhost:7000/index",
@ -43,12 +23,12 @@ func TestCleanURL(t *testing.T) {
}
func TestGetInfo(t *testing.T) {
teardownTestCase, testCase := setupTestCase(t)
teardownTestCase, client := SetupTestProxyClient(t)
defer teardownTestCase(t)
name := "my/module"
version := "v1.0.0"
info, err := testCase.client.GetInfo(name, version)
info, err := client.GetInfo(name, version)
if err != nil {
t.Errorf("GetInfo(%q, %q) error: %v", name, version, err)
}
@ -64,24 +44,24 @@ func TestGetInfo(t *testing.T) {
}
func TestGetInfoVersionDoesNotExist(t *testing.T) {
teardownTestCase, testCase := setupTestCase(t)
teardownTestCase, client := SetupTestProxyClient(t)
defer teardownTestCase(t)
name := "my/module"
version := "v3.0.0"
info, _ := testCase.client.GetInfo(name, version)
info, _ := client.GetInfo(name, version)
if info != nil {
t.Errorf("GetInfo(%q, %q) = %v, want %v", name, version, info, nil)
}
}
func TestGetZip(t *testing.T) {
teardownTestCase, testCase := setupTestCase(t)
teardownTestCase, client := SetupTestProxyClient(t)
defer teardownTestCase(t)
name := "my/module"
version := "v1.0.0"
zipReader, err := testCase.client.GetZip(name, version)
zipReader, err := client.GetZip(name, version)
if err != nil {
t.Errorf("GetZip(%q, %q) error: %v", name, version, err)
}
@ -108,15 +88,15 @@ func TestGetZip(t *testing.T) {
}
func TestGetZipNonExist(t *testing.T) {
teardownTestCase, testCase := setupTestCase(t)
teardownTestCase, client := SetupTestProxyClient(t)
defer teardownTestCase(t)
name := "my/nonexistmodule"
version := "v1.0.0"
expectedErr := fmt.Sprintf("http.Get(%q) returned response: %d (%q)",
testCase.client.zipURL(name, version), 404, "404 Not Found")
client.zipURL(name, version), 404, "404 Not Found")
if _, err := testCase.client.GetZip(name, version); err.Error() != expectedErr {
if _, err := client.GetZip(name, version); err.Error() != expectedErr {
t.Errorf("GetZip(%q, %q) returned error %v, want %v", name, version, err, expectedErr)
}
}

Просмотреть файл

@ -0,0 +1,48 @@
// Copyright 2019 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 proxy
import (
"net/http"
"net/http/httptest"
"path/filepath"
"testing"
)
// SetupTestProxyClient creates a module proxy for testing using static files
// stored in internal/proxy/testdata/modproxy/proxy. It returns a function
// for tearing down the proxy after the test is completed and a Client for
// interacting with the test proxy. The following module versions are supported
// by the proxy: (1) my/module v1.0.0 (2) my/module v1.1.0 (3) my/module v1.1.1
// (4) my/module/v2 v2.0.0.
func SetupTestProxyClient(t *testing.T) (func(t *testing.T), *Client) {
t.Helper()
proxyDataDir := "../proxy/testdata/modproxy/proxy"
absPath, err := filepath.Abs(proxyDataDir)
if err != nil {
t.Fatalf("filepath.Abs(%q): %v", proxyDataDir, err)
}
p := httptest.NewServer(http.FileServer(http.Dir(absPath)))
client := New(p.URL)
expectedVersions := [][]string{
[]string{"my/module", "v1.0.0"},
[]string{"my/module", "v1.1.0"},
[]string{"my/module", "v1.1.1"},
[]string{"my/module/v2", "v2.0.0"},
}
for _, v := range expectedVersions {
if _, err := client.GetInfo(v[0], v[1]); err != nil {
t.Fatalf("client.GetInfo(%q, %q): %v", v[0], v[1], err)
}
}
fn := func(t *testing.T) {
p.Close()
}
return fn, client
}

Просмотреть файл

@ -0,0 +1 @@
LICENSE FILE FOR TESTING.

Просмотреть файл

@ -0,0 +1 @@
README FILE FOR TESTING.

Просмотреть файл

@ -0,0 +1 @@
module my/module

Двоичные данные
internal/proxy/testdata/modproxy/proxy/my/module/@v/v1.0.0.zip поставляемый

Двоичный файл не отображается.