Merge pull request #10690 from rhatdan/VENDOR

Vendor in containers/common v0.40.0
This commit is contained in:
OpenShift Merge Robot
2021-06-18 10:37:37 -04:00
committed by GitHub
135 changed files with 5564 additions and 389 deletions

View File

@ -28,6 +28,26 @@ For more details about format and configurations of the auth.json file, please r
## OPTIONS
#### **--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry.
Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
#### **--get-login**
Return the logged-in user for the registry. Return error if no login is found.
#### **--help**, **-h**
Print usage statement
#### **--password**, **-p**=*password*
Password for registry
@ -36,35 +56,19 @@ Password for registry
Take the password from stdin
#### **--username**, **-u**=*username*
Username for registry
#### **--authfile**=*path*
Path of the authentication file. Default is ${XDG\_RUNTIME\_DIR}/containers/auth.json.
Note: You can also override the default path of the authentication file by setting the REGISTRY\_AUTH\_FILE
environment variable. `export REGISTRY_AUTH_FILE=path`
#### **--get-login**
Return the logged-in user for the registry. Return error if no login is found.
#### **--cert-dir**=*path*
Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry.
Please refer to containers-certs.d(5) for details. (This option is not available with the remote Podman client)
#### **--tls-verify**=*true|false*
Require HTTPS and verify certificates when contacting registries (default: true). If explicitly set to true,
then TLS verification will be used. If set to false, then TLS verification will not be used. If not specified,
TLS verification will be used unless the target registry is listed as an insecure registry in registries.conf.
#### **--help**, **-h**
#### **--username**, **-u**=*username*
Print usage statement
Username for registry
#### **--verbose**, **-v**
print detailed information about credential store
## EXAMPLES

6
go.mod
View File

@ -12,9 +12,9 @@ require (
github.com/containernetworking/cni v0.8.1
github.com/containernetworking/plugins v0.9.1
github.com/containers/buildah v1.21.1
github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a
github.com/containers/common v0.40.0
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.12.0
github.com/containers/image/v5 v5.13.2
github.com/containers/ocicrypt v1.1.1
github.com/containers/psgo v1.5.2
github.com/containers/storage v1.32.2
@ -64,7 +64,7 @@ require (
go.etcd.io/bbolt v1.3.6
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015
golang.org/x/sys v0.0.0-20210603125802-9665404d3644
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
k8s.io/api v0.21.1
k8s.io/apimachinery v0.21.1

30
go.sum
View File

@ -221,12 +221,14 @@ github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRD
github.com/containers/buildah v1.21.1 h1:e9LmTCUKUBLg72v5DnIOT/wc8ffkfB7LbpQBywLZo20=
github.com/containers/buildah v1.21.1/go.mod h1:yPdlpVd93T+i91yGxrJbW1YOWrqN64j5ZhHOZmHUejs=
github.com/containers/common v0.38.4/go.mod h1:egfpX/Y3+19Dz4Wa1eRZDdgzoEOeneieF9CQppKzLBg=
github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a h1:XzYOUf7qjgVJ59YGqAzehlbT63EgjUJhMnfhsPSSJV0=
github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a/go.mod h1:CxHAf4iQOZZ8nASIjMdYHHRyA8dMR4tINSS7WQWlv90=
github.com/containers/common v0.40.0 h1:6Q40GoVS3AI2QZbQPLRDS+K7G61JgHqlqvkOYYAJrOo=
github.com/containers/common v0.40.0/go.mod h1:qLkP2aIaPfiXJS4u/QSSNkUFEEV+dg5d6GOTKsdlZ7g=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.12.0 h1:1hNS2QkzFQ4lH3GYQLyAXB0acRMhS1Ubm6oV++8vw4w=
github.com/containers/image/v5 v5.12.0/go.mod h1:VasTuHmOw+uD0oHCfApQcMO2+36SfyncoSahU7513Xs=
github.com/containers/image/v5 v5.13.0/go.mod h1:GkWursKDlDcUIT7L7vZf70tADvZCk/Ga0wgS0MuF0ag=
github.com/containers/image/v5 v5.13.2 h1:AgYunV/9d2fRkrmo23wH2MkqeHolFd6oQCkK+1PpuFA=
github.com/containers/image/v5 v5.13.2/go.mod h1:GkWursKDlDcUIT7L7vZf70tADvZCk/Ga0wgS0MuF0ag=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE=
github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv8iPl1ZP7aqh9YA68wnZv2NUDbXdcdPHVz0pFbPY=
github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc=
@ -238,7 +240,6 @@ github.com/containers/psgo v1.5.2/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzP
github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM=
github.com/containers/storage v1.30.1/go.mod h1:NDJkiwxnSHD1Is+4DGcyR3SIEYSDOa0xnAW+uGQFx9E=
github.com/containers/storage v1.31.1/go.mod h1:IFEf+yRTS0pvCGQt2tBv1Kzz2XUSPvED6uFBmWG7V/E=
github.com/containers/storage v1.32.0/go.mod h1:J3q772EVbN9vgqoN/dkvInKnp4xK9ZXm7wHNfuiIDgE=
github.com/containers/storage v1.32.2 h1:V1oKAKmH5e6OTgP7Uf8+T+ntVVYk2MNFnDDkPBI9kxU=
github.com/containers/storage v1.32.2/go.mod h1:YIBxxjfXZTi04Ah49sh1uSGfmT1V89+I5i3deRobzQo=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@ -277,6 +278,7 @@ github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1S
github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s=
github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8=
github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I=
github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
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=
@ -300,8 +302,9 @@ github.com/docker/docker v20.10.3-0.20210216175712-646072ed6524+incompatible/go.
github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
@ -499,8 +502,9 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/insomniacslk/dhcp v0.0.0-20210120172423-cc9239ac6294/go.mod h1:TKl4jN3Voofo4UJIicyNhWGp/nlQqQkFxmwIFTvBkKI=
@ -508,8 +512,9 @@ github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee h1:PAXLXk1heNZ5y
github.com/ishidawataru/sctp v0.0.0-20210226210310-f2269e66cdee/go.mod h1:co9pwDoBCm1kGxawmb4sPq0cSIOOWNPT4KnHotMP1Zg=
github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA=
github.com/jamescun/tuntap v0.0.0-20190712092105-cb1fb277045c/go.mod h1:zzwpsgcYhzzIP5WyF8g9ivCv38cY9uAV9Gu0m3lThhE=
github.com/jinzhu/copier v0.3.0 h1:P5zN9OYSxmtzZmwgcVmt5Iu8egfP53BGMPAFgEksKPI=
github.com/jinzhu/copier v0.3.0/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
github.com/jinzhu/copier v0.3.2 h1:QdBOCbaouLDYaIPFfi1bKv5F5tPpeTwXe4sD0jqtz5w=
github.com/jinzhu/copier v0.3.2/go.mod h1:24xnZezI2Yqac9J61UC6/dG/k76ttpq0DdJI3QmUvro=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@ -536,8 +541,9 @@ github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.0 h1:2T7tUoQrQT+fQWdaY5rjWztFGAFwbGD04iPJg90ZiOs=
github.com/klauspost/compress v1.13.0/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.13.1 h1:wXr2uRxZTJXHLly6qhJabee5JqIhTRoLBhDOA74hDEQ=
github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -572,8 +578,9 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y=
@ -848,6 +855,8 @@ github.com/vbatts/tar-split v0.11.1/go.mod h1:LEuURwDEiWjRjwu46yU3KVGuUdVv/dcnpc
github.com/vbauerster/mpb/v6 v6.0.3/go.mod h1:5luBx4rDLWxpA4t6I5sdeeQuZhqDxc+wr5Nqf35+tnM=
github.com/vbauerster/mpb/v6 v6.0.4 h1:h6J5zM/2wimP5Hj00unQuV8qbo5EPcj6wbkCqgj7KcY=
github.com/vbauerster/mpb/v6 v6.0.4/go.mod h1:a/+JT57gqh6Du0Ay5jSR+uBMfXGdlR7VQlGP52fJxLM=
github.com/vbauerster/mpb/v7 v7.0.2 h1:eN6AD/ytv1nqCO7Dm8MO0/pGMKmMyH/WMnTJhAUuc/w=
github.com/vbauerster/mpb/v7 v7.0.2/go.mod h1:Mnq3gESXJ9eQhccbGZDggJ1faTCrmaA4iN57fUloRGE=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852 h1:cPXZWzzG0NllBLdjWoD1nDfaqu98YMv+OneaKc8sPOA=
@ -1076,8 +1085,9 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201113234701-d7a72108b828/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -23,6 +23,10 @@ type ImportOptions struct {
CommitMessage string
// Tag the imported image with this value.
Tag string
// Overwrite OS of imported image.
OS string
// Overwrite Arch of imported image.
Arch string
}
// Import imports a custom tarball at the specified path. Returns the name of
@ -50,6 +54,8 @@ func (r *Runtime) Import(ctx context.Context, path string, options *ImportOption
config := v1.Image{
Config: ic,
History: hist,
OS: options.OS,
Architecture: options.Arch,
}
u, err := url.ParseRequestURI(path)

View File

@ -351,7 +351,7 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str
// attempt pulling that instead of doing the full short-name dance.
localImage, resolvedImageName, err = r.LookupImage(imageName, nil)
if err != nil && errors.Cause(err) != storage.ErrImageUnknown {
return nil, errors.Wrap(err, "error looking up local image")
logrus.Errorf("Looking up %s in local storage: %v", imageName, err)
}
if pullPolicy == config.PullPolicyNever {

View File

@ -132,13 +132,21 @@ func (r *Runtime) storageToImage(storageImage *storage.Image, ref types.ImageRef
}
// Exists returns true if the specicifed image exists in the local containers
// storage.
// storage. Note that it may return false if an image corrupted.
func (r *Runtime) Exists(name string) (bool, error) {
image, _, err := r.LookupImage(name, &LookupImageOptions{IgnorePlatform: true})
if err != nil && errors.Cause(err) != storage.ErrImageUnknown {
return false, err
}
return image != nil, nil
if image == nil {
return false, nil
}
// Inspect the image to make sure if it's corrupted or not.
if _, err := image.Inspect(context.Background(), false); err != nil {
logrus.Errorf("Image %s exists in local storage but may be corrupted: %v", name, err)
return false, nil
}
return true, nil
}
// LookupImageOptions allow for customizing local image lookups.

View File

@ -134,9 +134,13 @@ func Login(ctx context.Context, systemContext *types.SystemContext, opts *LoginO
if err = docker.CheckAuth(ctx, systemContext, username, password, server); err == nil {
// Write the new credentials to the authfile
if err := config.SetAuthentication(systemContext, server, username, password); err != nil {
desc, err := config.SetCredentials(systemContext, server, username, password)
if err != nil {
return err
}
if opts.Verbose {
fmt.Fprintln(opts.Stdout, "Used: ", desc)
}
}
if err == nil {
fmt.Fprintln(opts.Stdout, "Login Succeeded!")

View File

@ -20,6 +20,7 @@ type LoginOptions struct {
Username string
StdinPassword bool
GetLoginSet bool
Verbose bool // set to true for verbose output
// Options caller can set
Stdin io.Reader // set to os.Stdin
Stdout io.Writer // set to os.Stdout
@ -47,6 +48,7 @@ func GetLoginFlags(flags *LoginOptions) *pflag.FlagSet {
fs.StringVarP(&flags.Username, "username", "u", "", "Username for registry")
fs.BoolVar(&flags.StdinPassword, "password-stdin", false, "Take the password from stdin")
fs.BoolVar(&flags.GetLoginSet, "get-login", false, "Return the current login user for the registry")
fs.BoolVarP(&flags.Verbose, "verbose", "v", false, "Write more detailed information to stdout")
return &fs
}

View File

@ -5,6 +5,7 @@ import (
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
"sync"
@ -23,7 +24,7 @@ const (
_configPath = "containers/containers.conf"
// DefaultContainersConfig holds the default containers config path
DefaultContainersConfig = "/usr/share/" + _configPath
// OverrideContainersConfig holds the default config paths overridden by the root user
// OverrideContainersConfig holds the default config path overridden by the root user
OverrideContainersConfig = "/etc/" + _configPath
// UserOverrideContainersConfig holds the containers config path overridden by the rootless user
UserOverrideContainersConfig = ".config/" + _configPath
@ -55,6 +56,8 @@ type Config struct {
Engine EngineConfig `toml:"engine"`
// Network section defines the configuration of CNI Plugins
Network NetworkConfig `toml:"network"`
// Secret section defines configurations for the secret management
Secrets SecretConfig `toml:"secrets"`
}
// ContainersConfig represents the "containers" TOML config table
@ -137,6 +140,11 @@ type ContainersConfig struct {
// Negative values indicate that the log file won't be truncated.
LogSizeMax int64 `toml:"log_size_max,omitempty"`
// Specifies default format tag for container log messages.
// This is useful for creating a specific tag for container log messages.
// Containers logs default to truncated container ID as a tag.
LogTag string `toml:"log_tag,omitempty"`
// NetNS indicates how to create a network namespace for the container
NetNS string `toml:"netns,omitempty"`
@ -440,6 +448,17 @@ type NetworkConfig struct {
NetworkConfigDir string `toml:"network_config_dir,omitempty"`
}
// SecretConfig represents the "secret" TOML config table
type SecretConfig struct {
// Driver specifies the secret driver to use.
// Current valid value:
// * file
// * pass
Driver string `toml:"driver,omitempty"`
// Opts contains driver specific options
Opts map[string]string `toml:"opts,omitempty"`
}
// Destination represents destination for remote service
type Destination struct {
// URI, required. Example: ssh://root@example.com:22/run/podman/podman.sock
@ -513,10 +532,49 @@ func readConfigFromFile(path string, config *Config) error {
return nil
}
// addConfigs will search one level in the config dirPath for config files
// If the dirPath does not exist, addConfigs will return nil
func addConfigs(dirPath string, configs []string) ([]string, error) {
newConfigs := []string{}
err := filepath.Walk(dirPath,
// WalkFunc to read additional configs
func(path string, info os.FileInfo, err error) error {
switch {
case err != nil:
// return error (could be a permission problem)
return err
case info == nil:
// this should only happen when err != nil but let's be sure
return nil
case info.IsDir():
if path != dirPath {
// make sure to not recurse into sub-directories
return filepath.SkipDir
}
// ignore directories
return nil
default:
// only add *.conf files
if strings.HasSuffix(path, ".conf") {
newConfigs = append(newConfigs, path)
}
return nil
}
},
)
if os.IsNotExist(err) {
err = nil
}
sort.Strings(newConfigs)
return append(configs, newConfigs...), err
}
// Returns the list of configuration files, if they exist in order of hierarchy.
// The files are read in order and each new file can/will override previous
// file settings.
func systemConfigs() ([]string, error) {
var err error
configs := []string{}
path := os.Getenv("CONTAINERS_CONF")
if path != "" {
@ -531,7 +589,12 @@ func systemConfigs() ([]string, error) {
if _, err := os.Stat(OverrideContainersConfig); err == nil {
configs = append(configs, OverrideContainersConfig)
}
path, err := ifRootlessConfigPath()
configs, err = addConfigs(OverrideContainersConfig+".d", configs)
if err != nil {
return nil, err
}
path, err = ifRootlessConfigPath()
if err != nil {
return nil, err
}
@ -539,6 +602,10 @@ func systemConfigs() ([]string, error) {
if _, err := os.Stat(path); err == nil {
configs = append(configs, path)
}
configs, err = addConfigs(path+".d", configs)
if err != nil {
return nil, err
}
}
return configs, nil
}

View File

@ -16,30 +16,16 @@
[containers]
# List of devices. Specified as
# "<device-on-host>:<device-on-container>:<permissions>", for example:
# "/dev/sdc:/dev/xvdc:rwm".
# If it is empty or commented out, only the default devices will be used
# List of annotation. Specified as
# "key = value"
# If it is empty or commented out, no annotations will be added
#
# devices = []
# List of volumes. Specified as
# "<directory-on-host>:<directory-in-container>:<options>", for example:
# "/db:/var/lib/db:ro".
# If it is empty or commented out, no volumes will be added
#
# volumes = []
# annotations = []
# Used to change the name of the default AppArmor profile of container engine.
#
# apparmor_profile = "container-default"
# List of annotation. Specified as
# "key=value"
# If it is empty or commented out, no annotations will be added
#
# annotations = []
# Default way to to create a cgroup namespace for the container
# Options are:
# `private` Create private Cgroup Namespace for the container.
@ -93,6 +79,13 @@ default_sysctls = [
# "nofile=1280:2560",
# ]
# List of devices. Specified as
# "<device-on-host>:<device-on-container>:<permissions>", for example:
# "/dev/sdc:/dev/xvdc:rwm".
# If it is empty or commented out, only the default devices will be used
#
# devices = []
# List of default DNS options to be added to /etc/resolv.conf inside of the container.
#
# dns_options = []
@ -166,6 +159,12 @@ default_sysctls = [
#
# log_size_max = -1
# Specifies default format tag for container log messages.
# This is useful for creating a specific tag for container log messages.
# Containers logs default to truncated container ID as a tag.
#
# log_tag = ""
# Default way to to create a Network namespace for the container
# Options are:
# `private` Create private Network Namespace for the container.
@ -179,10 +178,6 @@ default_sysctls = [
#
# no_hosts = false
# Maximum number of processes allowed in a container.
#
# pids_limit = 2048
# Default way to to create a PID namespace for the container
# Options are:
# `private` Create private PID Namespace for the container.
@ -190,6 +185,13 @@ default_sysctls = [
#
# pidns = "private"
# Maximum number of processes allowed in a container.
#
# pids_limit = 2048
# Indicates the networking to be used for rootless containers
# rootless_networking = "slirp4netns"
# Path to the seccomp.json profile which is used as the default seccomp profile
# for the runtime.
#
@ -209,14 +211,7 @@ default_sysctls = [
# Set umask inside the container
#
# umask="0022"
# Default way to to create a UTS namespace for the container
# Options are:
# `private` Create private UTS Namespace for the container.
# `host` Share host UTS Namespace with the container.
#
# utsns = "private"
# umask = "0022"
# Default way to to create a User namespace for the container
# Options are:
@ -229,7 +224,21 @@ default_sysctls = [
# UIDs are allocated from the "container" UIDs listed in
# /etc/subuid & /etc/subgid
#
# userns_size=65536
# userns_size = 65536
# Default way to to create a UTS namespace for the container
# Options are:
# `private` Create private UTS Namespace for the container.
# `host` Share host UTS Namespace with the container.
#
# utsns = "private"
# List of volumes. Specified as
# "<directory-on-host>:<directory-in-container>:<options>", for example:
# "/db:/var/lib/db:ro".
# If it is empty or commented out, no volumes will be added
#
# volumes = []
# The network table contains settings pertaining to the management of
# CNI plugins.
@ -254,14 +263,8 @@ default_sysctls = [
# network_config_dir = "/etc/cni/net.d/"
[engine]
# Maximum number of image layers to be copied (pulled/pushed) simultaneously.
# Not setting this field, or setting it to zero, will fall back to containers/image defaults.
# image_parallel_copies=0
# Manifest Type (oci, v2s2, or v2s1) to use when pulling, pushing, building
# container images. By default image pulled and pushed match the format of the
# source image. Building/committing defaults to OCI.
# image_default_format = ""
# Index to the active service
# active_service = production
# Cgroup management implementation used for the runtime.
# Valid options "systemd" or "cgroupfs"
@ -319,10 +322,19 @@ default_sysctls = [
# "/usr/share/containers/oci/hooks.d",
# ]
# Manifest Type (oci, v2s2, or v2s1) to use when pulling, pushing, building
# container images. By default image pulled and pushed match the format of the
# source image. Building/committing defaults to OCI.
# image_default_format = ""
# Default transport method for pulling and pushing for images
#
# image_default_transport = "docker://"
# Maximum number of image layers to be copied (pulled/pushed) simultaneously.
# Not setting this field, or setting it to zero, will fall back to containers/image defaults.
# image_parallel_copies = 0
# Default command to run the infra container
#
# infra_command = "/pause"
@ -345,7 +357,7 @@ default_sysctls = [
# Indicates if Podman is running inside a VM via Podman Machine.
# Podman uses this value to do extra setup around networking from the
# container inside the VM to to host.
# machine_enabled=false
# machine_enabled = false
# MultiImageArchive - if true, the container engine allows for storing archives
# (e.g., of the docker-archive transport) with multiple images. By default,
@ -364,12 +376,12 @@ default_sysctls = [
# Path to the slirp4netns binary
#
# network_cmd_path=""
# network_cmd_path = ""
# Default options to pass to the slirp4netns binary.
# For example "allow_host_loopback=true"
#
# network_cmd_options=[]
# network_cmd_options = []
# Whether to use chroot instead of pivot_root in the runtime
#
@ -389,8 +401,22 @@ default_sysctls = [
# `podman --remote=true` for access to the remote Podman service.
# remote = false
# Indicates the networking to be used for rootless containers
# rootless_networking="slirp4netns"
# Default OCI runtime
#
# runtime = "crun"
# List of the OCI runtimes that support --format=json. When json is supported
# engine will use it for reporting nicer errors.
#
# runtime_supports_json = ["crun", "runc", "kata", "runsc"]
# List of the OCI runtimes that supports running containers with KVM Separation.
#
# runtime_supports_kvm = ["kata"]
# List of the OCI runtimes that supports running containers without cgroups.
#
# runtime_supports_nocgroups = ["crun"]
# Directory for persistent engine files (database, etc)
# By default, this will be configured relative to where the containers/storage
@ -399,6 +425,22 @@ default_sysctls = [
#
# static_dir = "/var/lib/containers/storage/libpod"
# Number of seconds to wait for container to exit before sending kill signal.
# stop_timeout = 10
# map of service destinations
# [service_destinations]
# [service_destinations.production]
# URI to access the Podman service
# Examples:
# rootless "unix://run/user/$UID/podman/podman.sock" (Default)
# rootfull "unix://run/podman/podman.sock (Default)
# remote rootless ssh://engineering.lab.company.com/run/user/1000/podman/podman.sock
# remote rootfull ssh://root@10.10.1.136:22/run/podman/podman.sock
# uri = "ssh://user@production.example.com/run/user/1001/podman/podman.sock"
# Path to file containing ssh identity key
# identity = "~/.ssh/id_rsa"
# Directory for temporary files. Must be tmpfs (wiped after reboot)
#
# tmp_dir = "/run/libpod"
@ -410,42 +452,6 @@ default_sysctls = [
#
# volume_path = "/var/lib/containers/storage/volumes"
# Default OCI runtime
#
# runtime = "crun"
# List of the OCI runtimes that support --format=json. When json is supported
# engine will use it for reporting nicer errors.
#
# runtime_supports_json = ["crun", "runc", "kata", "runsc"]
# List of the OCI runtimes that supports running containers without cgroups.
#
# runtime_supports_nocgroups = ["crun"]
# List of the OCI runtimes that supports running containers with KVM Separation.
#
# runtime_supports_kvm = ["kata"]
# Number of seconds to wait for container to exit before sending kill signal.
# stop_timeout = 10
# Index to the active service
# active_service = production
# map of service destinations
# [service_destinations]
# [service_destinations.production]
# URI to access the Podman service
# Examples:
# rootless "unix://run/user/$UID/podman/podman.sock" (Default)
# rootfull "unix://run/podman/podman.sock (Default)
# remote rootless ssh://engineering.lab.company.com/run/user/1000/podman/podman.sock
# remote rootfull ssh://root@10.10.1.136:22/run/podman/podman.sock
# uri="ssh://user@production.example.com/run/user/1001/podman/podman.sock"
# Path to file containing ssh identity key
# identity = "~/.ssh/id_rsa"
# Paths to look for a valid OCI runtime (crun, runc, kata, runsc, etc)
[engine.runtimes]
# crun = [
@ -458,16 +464,6 @@ default_sysctls = [
# "/run/current-system/sw/bin/crun",
# ]
# runc = [
# "/usr/bin/runc",
# "/usr/sbin/runc",
# "/usr/local/bin/runc",
# "/usr/local/sbin/runc",
# "/sbin/runc",
# "/bin/runc",
# "/usr/lib/cri-o-runc/sbin/runc",
# ]
# kata = [
# "/usr/bin/kata-runtime",
# "/usr/sbin/kata-runtime",
@ -479,6 +475,16 @@ default_sysctls = [
# "/usr/bin/kata-fc",
# ]
# runc = [
# "/usr/bin/runc",
# "/usr/sbin/runc",
# "/usr/local/bin/runc",
# "/usr/local/sbin/runc",
# "/sbin/runc",
# "/bin/runc",
# "/usr/lib/cri-o-runc/sbin/runc",
# ]
# runsc = [
# "/usr/bin/runsc",
# "/usr/sbin/runsc",
@ -497,3 +503,9 @@ default_sysctls = [
# TOML does not provide a way to end a table other than a further table being
# defined, so every key hereafter will be part of [volume_plugins] and not the
# main config.
[secret]
# driver = "file"
[secret.opts]
# root = "/example/directory"

View File

@ -144,8 +144,6 @@ func DefaultConfig() (*Config, error) {
return nil, err
}
netns := "bridge"
cniConfig := _cniConfigDir
defaultEngineConfig.SignaturePolicyPath = DefaultSignaturePolicyPath
@ -161,7 +159,6 @@ func DefaultConfig() (*Config, error) {
defaultEngineConfig.SignaturePolicyPath = DefaultSignaturePolicyPath
}
}
netns = "slirp4netns"
cniConfig = filepath.Join(configHome, _cniConfigDirRootless)
}
@ -197,12 +194,10 @@ func DefaultConfig() (*Config, error) {
IPCNS: "private",
LogDriver: defaultLogDriver(),
LogSizeMax: DefaultLogSizeMax,
NetNS: netns,
NoHosts: false,
PidsLimit: DefaultPidsLimit,
PidNS: "private",
RootlessNetworking: DefaultRootlessNetwork,
SeccompProfile: SeccompDefaultPath,
ShmSize: DefaultShmSize,
TZ: "",
Umask: "0022",
@ -217,9 +212,18 @@ func DefaultConfig() (*Config, error) {
CNIPluginDirs: cniBinDir,
},
Engine: *defaultEngineConfig,
Secrets: defaultSecretConfig(),
}, nil
}
// defaultSecretConfig returns the default secret configuration.
// Please note that the default is choosing the "file" driver.
func defaultSecretConfig() SecretConfig {
return SecretConfig{
Driver: "file",
}
}
// defaultConfigFromMemory returns a default engine configuration. Note that the
// config is different for root and rootless. It also parses the storage.conf.
func defaultConfigFromMemory() (*EngineConfig, error) {

View File

@ -130,7 +130,7 @@ func NewTemplate(name string) *Template {
func (t *Template) Parse(text string) (*Template, error) {
if strings.HasPrefix(text, "table ") {
t.isTable = true
text = "{{range .}}" + NormalizeFormat(text) + "{{end}}"
text = "{{range .}}" + NormalizeFormat(text) + "{{end -}}"
} else {
text = NormalizeFormat(text)
}
@ -157,12 +157,12 @@ func (t *Template) IsTable() bool {
return t.isTable
}
var rangeRegex = regexp.MustCompile(`{{\s*range\s*\.\s*}}.*{{\s*end\s*}}`)
var rangeRegex = regexp.MustCompile(`{{\s*range\s*\.\s*}}.*{{\s*end\s*-?\s*}}`)
// EnforceRange ensures that the format string contains a range
func EnforceRange(format string) string {
if !rangeRegex.MatchString(format) {
return "{{range .}}" + format + "{{end}}"
return "{{range .}}" + format + "{{end -}}"
}
return format
}

View File

@ -118,6 +118,7 @@ func specToSeccomp(spec *specs.LinuxSeccomp) (*Seccomp, error) {
return nil, errors.Wrap(err, "convert default action")
}
res.DefaultAction = newDefaultAction
res.DefaultErrnoRet = spec.DefaultErrnoRet
// Loop through all syscall blocks and convert them to the internal format
for _, call := range spec.Syscalls {

View File

@ -44,8 +44,54 @@ func arches() []Architecture {
// DefaultProfile defines the allowlist for the default seccomp profile.
func DefaultProfile() *Seccomp {
einval := uint(unix.EINVAL)
enosys := uint(unix.ENOSYS)
eperm := uint(unix.EPERM)
syscalls := []*Syscall{
{
Names: []string{
"bdflush",
"clone3",
"io_pgetevents",
"io_uring_enter",
"io_uring_register",
"io_uring_setup",
"kexec_file_load",
"kexec_load",
"membarrier",
"migrate_pages",
"move_pages",
"nfsservctl",
"nice",
"oldfstat",
"oldlstat",
"oldolduname",
"oldstat",
"olduname",
"pciconfig_iobase",
"pciconfig_read",
"pciconfig_write",
"pkey_alloc",
"pkey_free",
"pkey_mprotect",
"rseq",
"sgetmask",
"ssetmask",
"swapcontext",
"swapoff",
"swapon",
"sysfs",
"uselib",
"userfaultfd",
"ustat",
"vm86",
"vm86old",
"vmsplice",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
},
{
Names: []string{
"_llseek",
@ -128,6 +174,7 @@ func DefaultProfile() *Seccomp {
"ftruncate",
"ftruncate64",
"futex",
"futex_time64",
"futimesat",
"get_robust_list",
"get_thread_area",
@ -212,7 +259,9 @@ func DefaultProfile() *Seccomp {
"mq_notify",
"mq_open",
"mq_timedreceive",
"mq_timedreceive_time64",
"mq_timedsend",
"mq_timedsend_time64",
"mq_unlink",
"mremap",
"msgctl",
@ -252,6 +301,7 @@ func DefaultProfile() *Seccomp {
"pwritev2",
"read",
"readahead",
"readdir",
"readlink",
"readlinkat",
"readv",
@ -259,6 +309,7 @@ func DefaultProfile() *Seccomp {
"recv",
"recvfrom",
"recvmmsg",
"recvmmsg_time64",
"recvmsg",
"remap_file_pages",
"removexattr",
@ -274,6 +325,7 @@ func DefaultProfile() *Seccomp {
"rt_sigreturn",
"rt_sigsuspend",
"rt_sigtimedwait",
"rt_sigtimedwait_time64",
"rt_tgsigqueueinfo",
"sched_get_priority_max",
"sched_get_priority_min",
@ -282,6 +334,7 @@ func DefaultProfile() *Seccomp {
"sched_getparam",
"sched_getscheduler",
"sched_rr_get_interval",
"sched_rr_get_interval_time64",
"sched_setaffinity",
"sched_setattr",
"sched_setparam",
@ -293,6 +346,7 @@ func DefaultProfile() *Seccomp {
"semget",
"semop",
"semtimedop",
"semtimedop_time64",
"send",
"sendfile",
"sendfile64",
@ -361,6 +415,7 @@ func DefaultProfile() *Seccomp {
"timer_gettime",
"timer_gettime64",
"timer_settime",
"timer_settime64",
"timerfd_create",
"timerfd_gettime",
"timerfd_gettime64",
@ -514,6 +569,17 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_DAC_READ_SEARCH"},
},
},
{
Names: []string{
"open_by_handle_at",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_DAC_READ_SEARCH"},
},
},
{
Names: []string{
"bpf",
@ -531,6 +597,24 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_SYS_ADMIN"},
},
},
{
Names: []string{
"bpf",
"fanotify_init",
"lookup_dcookie",
"perf_event_open",
"quotactl",
"setdomainname",
"sethostname",
"setns",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_SYS_ADMIN"},
},
},
{
Names: []string{
"chroot",
@ -541,6 +625,17 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_SYS_CHROOT"},
},
},
{
Names: []string{
"chroot",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_SYS_CHROOT"},
},
},
{
Names: []string{
"delete_module",
@ -554,6 +649,20 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_SYS_MODULE"},
},
},
{
Names: []string{
"delete_module",
"init_module",
"finit_module",
"query_module",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_SYS_MODULE"},
},
},
{
Names: []string{
"get_mempolicy",
@ -566,6 +675,19 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_SYS_NICE"},
},
},
{
Names: []string{
"get_mempolicy",
"mbind",
"set_mempolicy",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_SYS_NICE"},
},
},
{
Names: []string{
"acct",
@ -576,6 +698,17 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_SYS_PACCT"},
},
},
{
Names: []string{
"acct",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_SYS_PACCT"},
},
},
{
Names: []string{
"kcmp",
@ -590,6 +723,21 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_SYS_PTRACE"},
},
},
{
Names: []string{
"kcmp",
"process_madvise",
"process_vm_readv",
"process_vm_writev",
"ptrace",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_SYS_PTRACE"},
},
},
{
Names: []string{
"iopl",
@ -601,6 +749,18 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_SYS_RAWIO"},
},
},
{
Names: []string{
"iopl",
"ioperm",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_SYS_RAWIO"},
},
},
{
Names: []string{
"settimeofday",
@ -614,6 +774,20 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_SYS_TIME"},
},
},
{
Names: []string{
"settimeofday",
"stime",
"clock_settime",
"clock_settime64",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_SYS_TIME"},
},
},
{
Names: []string{
"vhangup",
@ -624,6 +798,17 @@ func DefaultProfile() *Seccomp {
Caps: []string{"CAP_SYS_TTY_CONFIG"},
},
},
{
Names: []string{
"vhangup",
},
Action: ActErrno,
ErrnoRet: &eperm,
Args: []*Arg{},
Excludes: Filter{
Caps: []string{"CAP_SYS_TTY_CONFIG"},
},
},
{
Names: []string{
"socket",
@ -707,6 +892,7 @@ func DefaultProfile() *Seccomp {
return &Seccomp{
DefaultAction: ActErrno,
DefaultErrnoRet: &enosys,
ArchMap: arches(),
Syscalls: syscalls,
}

View File

@ -41,7 +41,7 @@ func BuildFilter(spec *specs.LinuxSeccomp) (*libseccomp.ScmpFilter, error) {
return nil, errors.Wrap(err, "convert spec to seccomp profile")
}
defaultAction, err := toAction(profile.DefaultAction, nil)
defaultAction, err := toAction(profile.DefaultAction, profile.DefaultErrnoRet)
if err != nil {
return nil, errors.Wrapf(err, "convert default action %s", profile.DefaultAction)
}

View File

@ -1,5 +1,6 @@
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"archMap": [
{
"architecture": "SCMP_ARCH_X86_64",
@ -50,6 +51,53 @@
}
],
"syscalls": [
{
"names": [
"bdflush",
"clone3",
"io_pgetevents",
"io_uring_enter",
"io_uring_register",
"io_uring_setup",
"kexec_file_load",
"kexec_load",
"membarrier",
"migrate_pages",
"move_pages",
"nfsservctl",
"nice",
"oldfstat",
"oldlstat",
"oldolduname",
"oldstat",
"olduname",
"pciconfig_iobase",
"pciconfig_read",
"pciconfig_write",
"pkey_alloc",
"pkey_free",
"pkey_mprotect",
"rseq",
"sgetmask",
"ssetmask",
"swapcontext",
"swapoff",
"swapon",
"sysfs",
"uselib",
"userfaultfd",
"ustat",
"vm86",
"vm86old",
"vmsplice"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {},
"errnoRet": 1
},
{
"names": [
"_llseek",
@ -132,6 +180,7 @@
"ftruncate",
"ftruncate64",
"futex",
"futex_time64",
"futimesat",
"get_robust_list",
"get_thread_area",
@ -216,7 +265,9 @@
"mq_notify",
"mq_open",
"mq_timedreceive",
"mq_timedreceive_time64",
"mq_timedsend",
"mq_timedsend_time64",
"mq_unlink",
"mremap",
"msgctl",
@ -256,6 +307,7 @@
"pwritev2",
"read",
"readahead",
"readdir",
"readlink",
"readlinkat",
"readv",
@ -263,6 +315,7 @@
"recv",
"recvfrom",
"recvmmsg",
"recvmmsg_time64",
"recvmsg",
"remap_file_pages",
"removexattr",
@ -278,6 +331,7 @@
"rt_sigreturn",
"rt_sigsuspend",
"rt_sigtimedwait",
"rt_sigtimedwait_time64",
"rt_tgsigqueueinfo",
"sched_get_priority_max",
"sched_get_priority_min",
@ -286,6 +340,7 @@
"sched_getparam",
"sched_getscheduler",
"sched_rr_get_interval",
"sched_rr_get_interval_time64",
"sched_setaffinity",
"sched_setattr",
"sched_setparam",
@ -297,6 +352,7 @@
"semget",
"semop",
"semtimedop",
"semtimedop_time64",
"send",
"sendfile",
"sendfile64",
@ -365,6 +421,7 @@
"timer_gettime",
"timer_gettime64",
"timer_settime",
"timer_settime64",
"timerfd_create",
"timerfd_gettime",
"timerfd_gettime64",
@ -580,6 +637,21 @@
},
"excludes": {}
},
{
"names": [
"open_by_handle_at"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_DAC_READ_SEARCH"
]
},
"errnoRet": 1
},
{
"names": [
"bpf",
@ -601,6 +673,28 @@
},
"excludes": {}
},
{
"names": [
"bpf",
"fanotify_init",
"lookup_dcookie",
"perf_event_open",
"quotactl",
"setdomainname",
"sethostname",
"setns"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_ADMIN"
]
},
"errnoRet": 1
},
{
"names": [
"chroot"
@ -615,6 +709,21 @@
},
"excludes": {}
},
{
"names": [
"chroot"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_CHROOT"
]
},
"errnoRet": 1
},
{
"names": [
"delete_module",
@ -632,6 +741,24 @@
},
"excludes": {}
},
{
"names": [
"delete_module",
"init_module",
"finit_module",
"query_module"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_MODULE"
]
},
"errnoRet": 1
},
{
"names": [
"get_mempolicy",
@ -648,6 +775,23 @@
},
"excludes": {}
},
{
"names": [
"get_mempolicy",
"mbind",
"set_mempolicy"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_NICE"
]
},
"errnoRet": 1
},
{
"names": [
"acct"
@ -662,6 +806,21 @@
},
"excludes": {}
},
{
"names": [
"acct"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_PACCT"
]
},
"errnoRet": 1
},
{
"names": [
"kcmp",
@ -680,6 +839,25 @@
},
"excludes": {}
},
{
"names": [
"kcmp",
"process_madvise",
"process_vm_readv",
"process_vm_writev",
"ptrace"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_PTRACE"
]
},
"errnoRet": 1
},
{
"names": [
"iopl",
@ -695,6 +873,22 @@
},
"excludes": {}
},
{
"names": [
"iopl",
"ioperm"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_RAWIO"
]
},
"errnoRet": 1
},
{
"names": [
"settimeofday",
@ -712,6 +906,24 @@
},
"excludes": {}
},
{
"names": [
"settimeofday",
"stime",
"clock_settime",
"clock_settime64"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_TIME"
]
},
"errnoRet": 1
},
{
"names": [
"vhangup"
@ -726,6 +938,21 @@
},
"excludes": {}
},
{
"names": [
"vhangup"
],
"action": "SCMP_ACT_ERRNO",
"args": [],
"comment": "",
"includes": {},
"excludes": {
"caps": [
"CAP_SYS_TTY_CONFIG"
]
},
"errnoRet": 1
},
{
"names": [
"socket"

View File

@ -111,6 +111,7 @@ func setupSeccomp(config *Seccomp, rs *specs.Spec) (*specs.LinuxSeccomp, error)
}
newConfig.DefaultAction = specs.LinuxSeccompAction(config.DefaultAction)
newConfig.DefaultErrnoRet = config.DefaultErrnoRet
Loop:
// Loop through all syscall blocks and convert them to libcontainer format after filtering them

View File

@ -7,6 +7,7 @@ package seccomp
// Seccomp represents the config for a seccomp profile for syscall restriction.
type Seccomp struct {
DefaultAction Action `json:"defaultAction"`
DefaultErrnoRet *uint `json:"defaultErrnoRet"`
// Architectures is kept to maintain backward compatibility with the old
// seccomp profile.
Architectures []Arch `json:"architectures,omitempty"`

View File

@ -0,0 +1,176 @@
package passdriver
import (
"bytes"
"context"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
"github.com/pkg/errors"
)
var (
// errNoSecretData indicates that there is not data associated with an id
errNoSecretData = errors.New("no secret data with ID")
// errNoSecretData indicates that there is secret data already associated with an id
errSecretIDExists = errors.New("secret data with ID already exists")
// errInvalidKey indicates that something about your key is wrong
errInvalidKey = errors.New("invalid key")
)
type driverConfig struct {
// Root contains the root directory where the secrets are stored
Root string
// KeyID contains the key id that will be used for encryption (i.e. user@domain.tld)
KeyID string
}
func (cfg *driverConfig) ParseOpts(opts map[string]string) {
if val, ok := opts["root"]; ok {
cfg.Root = val
cfg.findGpgID() // try to find a .gpg-id in the parent directories of Root
}
if val, ok := opts["key"]; ok {
cfg.KeyID = val
}
}
func defaultDriverConfig() *driverConfig {
cfg := &driverConfig{}
if home, err := os.UserHomeDir(); err == nil {
defaultLocations := []string{
filepath.Join(home, ".password-store"),
filepath.Join(home, ".local/share/gopass/stores/root"),
}
for _, path := range defaultLocations {
if stat, err := os.Stat(path); err != nil || !stat.IsDir() {
continue
}
cfg.Root = path
bs, err := ioutil.ReadFile(filepath.Join(path, ".gpg-id"))
if err != nil {
continue
}
cfg.KeyID = string(bytes.Trim(bs, "\r\n"))
break
}
}
return cfg
}
func (cfg *driverConfig) findGpgID() {
path := cfg.Root
for len(path) > 1 {
if _, err := os.Stat(filepath.Join(path, ".gpg-id")); err == nil {
bs, err := ioutil.ReadFile(filepath.Join(path, ".gpg-id"))
if err != nil {
continue
}
cfg.KeyID = string(bytes.Trim(bs, "\r\n"))
break
}
path = filepath.Dir(path)
}
}
// Driver is the passdriver object
type Driver struct {
driverConfig
}
// NewDriver creates a new secret driver.
func NewDriver(opts map[string]string) (*Driver, error) {
cfg := defaultDriverConfig()
cfg.ParseOpts(opts)
driver := &Driver{
driverConfig: *cfg,
}
return driver, nil
}
// List returns all secret IDs
func (d *Driver) List() (secrets []string, err error) {
files, err := ioutil.ReadDir(d.Root)
if err != nil {
return nil, errors.Wrap(err, "failed to read secret directory")
}
for _, f := range files {
fileName := f.Name()
withoutSuffix := fileName[:len(fileName)-len(".gpg")]
secrets = append(secrets, withoutSuffix)
}
sort.Strings(secrets)
return secrets, nil
}
// Lookup returns the bytes associated with a secret ID
func (d *Driver) Lookup(id string) ([]byte, error) {
out := &bytes.Buffer{}
key, err := d.getPath(id)
if err != nil {
return nil, err
}
if err := d.gpg(context.TODO(), nil, out, "--decrypt", key); err != nil {
return nil, errors.Wrapf(errNoSecretData, id)
}
if out.Len() == 0 {
return nil, errors.Wrapf(errNoSecretData, id)
}
return out.Bytes(), nil
}
// Store saves the bytes associated with an ID. An error is returned if the ID already exists
func (d *Driver) Store(id string, data []byte) error {
if _, err := d.Lookup(id); err == nil {
return errors.Wrap(errSecretIDExists, id)
}
in := bytes.NewReader(data)
key, err := d.getPath(id)
if err != nil {
return err
}
return d.gpg(context.TODO(), in, nil, "--encrypt", "-r", d.KeyID, "-o", key)
}
// Delete removes the secret associated with the specified ID. An error is returned if no matching secret is found.
func (d *Driver) Delete(id string) error {
key, err := d.getPath(id)
if err != nil {
return err
}
if err := os.Remove(key); err != nil {
return errors.Wrap(errNoSecretData, id)
}
return nil
}
func (d *Driver) gpg(ctx context.Context, in io.Reader, out io.Writer, args ...string) error {
cmd := exec.CommandContext(ctx, "gpg", args...)
cmd.Env = os.Environ()
cmd.Stdin = in
cmd.Stdout = out
cmd.Stderr = ioutil.Discard
return cmd.Run()
}
func (d *Driver) getPath(id string) (string, error) {
path, err := filepath.Abs(filepath.Join(d.Root, id))
if err != nil {
return "", errInvalidKey
}
if !strings.HasPrefix(path, d.Root) {
return "", errInvalidKey
}
return path + ".gpg", nil
}

View File

@ -8,6 +8,7 @@ import (
"time"
"github.com/containers/common/pkg/secrets/filedriver"
"github.com/containers/common/pkg/secrets/passdriver"
"github.com/containers/storage/pkg/lockfile"
"github.com/containers/storage/pkg/stringid"
"github.com/pkg/errors"
@ -271,12 +272,15 @@ func validateSecretName(name string) error {
// getDriver creates a new driver.
func getDriver(name string, opts map[string]string) (SecretsDriver, error) {
if name == "file" {
switch name {
case "file":
if path, ok := opts["path"]; ok {
return filedriver.NewDriver(path)
} else {
return nil, errors.Wrap(errInvalidDriverOpt, "need path for filedriver")
}
case "pass":
return passdriver.NewDriver(opts)
}
return nil, errInvalidDriver
}

View File

@ -1,4 +1,4 @@
package version
// Version is the version of the build.
const Version = "0.39.1-dev"
const Version = "0.40.0"

View File

@ -29,10 +29,10 @@ import (
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/vbauerster/mpb/v6"
"github.com/vbauerster/mpb/v6/decor"
"golang.org/x/crypto/ssh/terminal"
"github.com/vbauerster/mpb/v7"
"github.com/vbauerster/mpb/v7/decor"
"golang.org/x/sync/semaphore"
"golang.org/x/term"
)
type digestingReader struct {
@ -43,10 +43,6 @@ type digestingReader struct {
validationSucceeded bool
}
// FIXME: disable early layer commits temporarily until a solid solution to
// address #1205 has been found.
const enableEarlyCommit = false
var (
// ErrDecryptParamsMissing is returned if there is missing decryption parameters
ErrDecryptParamsMissing = errors.New("Necessary DecryptParameters not present")
@ -864,7 +860,7 @@ func (ic *imageCopier) noPendingManifestUpdates() bool {
// isTTY returns true if the io.Writer is a file and a tty.
func isTTY(w io.Writer) bool {
if f, ok := w.(*os.File); ok {
return terminal.IsTerminal(int(f.Fd()))
return term.IsTerminal(int(f.Fd()))
}
return false
}
@ -893,6 +889,18 @@ func (ic *imageCopier) copyLayers(ctx context.Context) error {
err error
}
// The manifest is used to extract the information whether a given
// layer is empty.
manifestBlob, manifestType, err := ic.src.Manifest(ctx)
if err != nil {
return err
}
man, err := manifest.FromBlob(manifestBlob, manifestType)
if err != nil {
return err
}
manifestLayerInfos := man.LayerInfos()
// copyGroup is used to determine if all layers are copied
copyGroup := sync.WaitGroup{}
@ -925,7 +933,7 @@ func (ic *imageCopier) copyLayers(ctx context.Context) error {
logrus.Debugf("Skipping foreign layer %q copy to %s", cld.destInfo.Digest, ic.c.dest.Reference().Transport().Name())
}
} else {
cld.destInfo, cld.diffID, cld.err = ic.copyLayer(ctx, srcLayer, toEncrypt, pool, index, srcRef)
cld.destInfo, cld.diffID, cld.err = ic.copyLayer(ctx, srcLayer, toEncrypt, pool, index, srcRef, manifestLayerInfos[index].EmptyLayer)
}
data[index] = cld
}
@ -1094,8 +1102,9 @@ func (c *copier) createProgressBar(pool *mpb.Progress, info types.BlobInfo, kind
),
)
} else {
sstyle := mpb.SpinnerStyle(".", "..", "...", "....", "").PositionLeft()
bar = pool.Add(0,
mpb.NewSpinnerFiller([]string{".", "..", "...", "....", ""}, mpb.SpinnerOnLeft),
sstyle.Build(),
mpb.BarFillerClearOnComplete(),
mpb.PrependDecorators(
decor.OnComplete(decor.Name(prefix), onComplete),
@ -1121,7 +1130,7 @@ func (c *copier) copyConfig(ctx context.Context, src types.Image) error {
progressPool, progressCleanup := c.newProgressPool(ctx)
defer progressCleanup()
bar := c.createProgressBar(progressPool, srcInfo, "config", "done")
destInfo, err := c.copyBlobFromStream(ctx, bytes.NewReader(configBlob), srcInfo, nil, false, true, false, bar, -1)
destInfo, err := c.copyBlobFromStream(ctx, bytes.NewReader(configBlob), srcInfo, nil, false, true, false, bar, -1, false)
if err != nil {
return types.BlobInfo{}, err
}
@ -1148,7 +1157,7 @@ type diffIDResult struct {
// copyLayer copies a layer with srcInfo (with known Digest and Annotations and possibly known Size) in src to dest, perhaps (de/re/)compressing it,
// and returns a complete blobInfo of the copied layer, and a value for LayerDiffIDs if diffIDIsNeeded
// srcRef can be used as an additional hint to the destination during checking whehter a layer can be reused but srcRef can be nil.
func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, toEncrypt bool, pool *mpb.Progress, layerIndex int, srcRef reference.Named) (types.BlobInfo, digest.Digest, error) {
func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, toEncrypt bool, pool *mpb.Progress, layerIndex int, srcRef reference.Named, emptyLayer bool) (types.BlobInfo, digest.Digest, error) {
// If the srcInfo doesn't contain compression information, try to compute it from the
// MediaType, which was either read from a manifest by way of LayerInfos() or constructed
// by LayerInfosForCopy(), if it was supplied at all. If we succeed in copying the blob,
@ -1195,10 +1204,9 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to
Cache: ic.c.blobInfoCache,
CanSubstitute: ic.canSubstituteBlobs,
SrcRef: srcRef,
EmptyLayer: emptyLayer,
}
if enableEarlyCommit {
options.LayerIndex = &layerIndex
}
reused, blobInfo, err = dest.TryReusingBlobWithOptions(ctx, srcInfo, options)
} else {
reused, blobInfo, err = ic.c.dest.TryReusingBlob(ctx, srcInfo, ic.c.blobInfoCache, ic.canSubstituteBlobs)
@ -1245,7 +1253,7 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to
bar := ic.c.createProgressBar(pool, srcInfo, "blob", "done")
blobInfo, diffIDChan, err := ic.copyLayerFromStream(ctx, srcStream, types.BlobInfo{Digest: srcInfo.Digest, Size: srcBlobSize, MediaType: srcInfo.MediaType, Annotations: srcInfo.Annotations}, diffIDIsNeeded, toEncrypt, bar, layerIndex)
blobInfo, diffIDChan, err := ic.copyLayerFromStream(ctx, srcStream, types.BlobInfo{Digest: srcInfo.Digest, Size: srcBlobSize, MediaType: srcInfo.MediaType, Annotations: srcInfo.Annotations}, diffIDIsNeeded, toEncrypt, bar, layerIndex, emptyLayer)
if err != nil {
return types.BlobInfo{}, "", err
}
@ -1276,7 +1284,7 @@ func (ic *imageCopier) copyLayer(ctx context.Context, srcInfo types.BlobInfo, to
// perhaps (de/re/)compressing the stream,
// and returns a complete blobInfo of the copied blob and perhaps a <-chan diffIDResult if diffIDIsNeeded, to be read by the caller.
func (ic *imageCopier) copyLayerFromStream(ctx context.Context, srcStream io.Reader, srcInfo types.BlobInfo,
diffIDIsNeeded bool, toEncrypt bool, bar *mpb.Bar, layerIndex int) (types.BlobInfo, <-chan diffIDResult, error) {
diffIDIsNeeded bool, toEncrypt bool, bar *mpb.Bar, layerIndex int, emptyLayer bool) (types.BlobInfo, <-chan diffIDResult, error) {
var getDiffIDRecorder func(compression.DecompressorFunc) io.Writer // = nil
var diffIDChan chan diffIDResult
@ -1301,7 +1309,7 @@ func (ic *imageCopier) copyLayerFromStream(ctx context.Context, srcStream io.Rea
}
}
blobInfo, err := ic.c.copyBlobFromStream(ctx, srcStream, srcInfo, getDiffIDRecorder, ic.canModifyManifest, false, toEncrypt, bar, layerIndex) // Sets err to nil on success
blobInfo, err := ic.c.copyBlobFromStream(ctx, srcStream, srcInfo, getDiffIDRecorder, ic.canModifyManifest, false, toEncrypt, bar, layerIndex, emptyLayer) // Sets err to nil on success
return blobInfo, diffIDChan, err
// We need the defer … pipeWriter.CloseWithError() to happen HERE so that the caller can block on reading from diffIDChan
}
@ -1353,7 +1361,7 @@ func (r errorAnnotationReader) Read(b []byte) (n int, err error) {
// and returns a complete blobInfo of the copied blob.
func (c *copier) copyBlobFromStream(ctx context.Context, srcStream io.Reader, srcInfo types.BlobInfo,
getOriginalLayerCopyWriter func(decompressor compression.DecompressorFunc) io.Writer,
canModifyBlob bool, isConfig bool, toEncrypt bool, bar *mpb.Bar, layerIndex int) (types.BlobInfo, error) {
canModifyBlob bool, isConfig bool, toEncrypt bool, bar *mpb.Bar, layerIndex int, emptyLayer bool) (types.BlobInfo, error) {
if isConfig { // This is guaranteed by the caller, but set it here to be explicit.
canModifyBlob = false
}
@ -1558,8 +1566,9 @@ func (c *copier) copyBlobFromStream(ctx context.Context, srcStream io.Reader, sr
options := internalTypes.PutBlobOptions{
Cache: c.blobInfoCache,
IsConfig: isConfig,
EmptyLayer: emptyLayer,
}
if !isConfig && enableEarlyCommit {
if !isConfig {
options.LayerIndex = &layerIndex
}
uploadedInfo, err = dest.PutBlobWithOptions(ctx, &errorAnnotationReader{destStream}, inputInfo, options)

View File

@ -9,7 +9,7 @@ package platform
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// https://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

View File

@ -39,6 +39,8 @@ type PutBlobOptions struct {
Cache publicTypes.BlobInfoCache
// Denotes whether the blob is a config or not.
IsConfig bool
// Indicates an empty layer.
EmptyLayer bool
// The corresponding index in the layer slice.
LayerIndex *int
}
@ -49,6 +51,8 @@ type TryReusingBlobOptions struct {
Cache publicTypes.BlobInfoCache
// Use an equivalent of the desired blob.
CanSubstitute bool
// Indicates an empty layer.
EmptyLayer bool
// The corresponding index in the layer slice.
LayerIndex *int
// The reference of the image that contains the target blob.

View File

@ -51,21 +51,26 @@ var (
ErrNotSupported = errors.New("not supported")
)
// SetAuthentication stores the username and password in the credential helper or file
func SetAuthentication(sys *types.SystemContext, registry, username, password string) error {
// SetCredentials stores the username and password in the credential helper or file
// and returns path to file or helper name in format (helper:%s).
// Returns a human-redable description of the location that was updated.
// NOTE: The return value is only intended to be read by humans; its form is not an API,
// it may change (or new forms can be added) any time.
func SetCredentials(sys *types.SystemContext, registry, username, password string) (string, error) {
helpers, err := sysregistriesv2.CredentialHelpers(sys)
if err != nil {
return err
return "", err
}
// Make sure to collect all errors.
var multiErr error
for _, helper := range helpers {
var desc string
var err error
switch helper {
// Special-case the built-in helpers for auth files.
case sysregistriesv2.AuthenticationFileHelper:
err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) {
desc, err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) {
if ch, exists := auths.CredHelpers[registry]; exists {
return false, setAuthToCredHelper(ch, registry, username, password)
}
@ -76,6 +81,7 @@ func SetAuthentication(sys *types.SystemContext, registry, username, password st
})
// External helpers.
default:
desc = fmt.Sprintf("credential helper: %s", helper)
err = setAuthToCredHelper(helper, registry, username, password)
}
if err != nil {
@ -84,9 +90,15 @@ func SetAuthentication(sys *types.SystemContext, registry, username, password st
continue
}
logrus.Debugf("Stored credentials for %s in credential helper %s", registry, helper)
return nil
return desc, nil
}
return multiErr
return "", multiErr
}
// SetAuthentication stores the username and password in the credential helper or file
func SetAuthentication(sys *types.SystemContext, registry, username, password string) error {
_, err := SetCredentials(sys, registry, username, password)
return err
}
// GetAllCredentials returns the registry credentials for all registries stored
@ -322,7 +334,7 @@ func RemoveAuthentication(sys *types.SystemContext, registry string) error {
switch helper {
// Special-case the built-in helper for auth files.
case sysregistriesv2.AuthenticationFileHelper:
err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) {
_, err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) {
if innerHelper, exists := auths.CredHelpers[registry]; exists {
removeFromCredHelper(innerHelper)
}
@ -368,7 +380,7 @@ func RemoveAllAuthentication(sys *types.SystemContext) error {
switch helper {
// Special-case the built-in helper for auth files.
case sysregistriesv2.AuthenticationFileHelper:
err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) {
_, err = modifyJSON(sys, func(auths *dockerConfigFile) (bool, error) {
for registry, helper := range auths.CredHelpers {
// Helpers in auth files are expected
// to exist, so no special treatment
@ -493,42 +505,44 @@ func readJSONFile(path string, legacyFormat bool) (dockerConfigFile, error) {
return auths, nil
}
// modifyJSON writes to auth.json if the dockerConfigFile has been updated
func modifyJSON(sys *types.SystemContext, editor func(auths *dockerConfigFile) (bool, error)) error {
// modifyJSON finds an auth.json file, calls editor on the contents, and
// writes it back if editor returns true.
// Returns a human-redable description of the file, to be returned by SetCredentials.
func modifyJSON(sys *types.SystemContext, editor func(auths *dockerConfigFile) (bool, error)) (string, error) {
path, legacyFormat, err := getPathToAuth(sys)
if err != nil {
return err
return "", err
}
if legacyFormat {
return fmt.Errorf("writes to %s using legacy format are not supported", path)
return "", fmt.Errorf("writes to %s using legacy format are not supported", path)
}
dir := filepath.Dir(path)
if err = os.MkdirAll(dir, 0700); err != nil {
return err
return "", err
}
auths, err := readJSONFile(path, false)
if err != nil {
return errors.Wrapf(err, "error reading JSON file %q", path)
return "", errors.Wrapf(err, "error reading JSON file %q", path)
}
updated, err := editor(&auths)
if err != nil {
return errors.Wrapf(err, "error updating %q", path)
return "", errors.Wrapf(err, "error updating %q", path)
}
if updated {
newData, err := json.MarshalIndent(auths, "", "\t")
if err != nil {
return errors.Wrapf(err, "error marshaling JSON %q", path)
return "", errors.Wrapf(err, "error marshaling JSON %q", path)
}
if err = ioutil.WriteFile(path, newData, 0600); err != nil {
return errors.Wrapf(err, "error writing to file %q", path)
return "", errors.Wrapf(err, "error writing to file %q", path)
}
}
return nil
return path, nil
}
func getAuthFromCredHelper(credHelper, registry string) (types.DockerAuthConfig, error) {

View File

@ -13,9 +13,9 @@ import (
// reenable keyring support, we should introduce a similar built-in credential
// helpers as for `sysregistriesv2.AuthenticationFileHelper`.
const keyDescribePrefix = "container-registry-login:" // nolint
const keyDescribePrefix = "container-registry-login:" //nolint:deadcode,unused
func getAuthFromKernelKeyring(registry string) (string, string, error) { // nolint
func getAuthFromKernelKeyring(registry string) (string, string, error) { //nolint:deadcode,unused
userkeyring, err := keyctl.UserKeyring()
if err != nil {
return "", "", err
@ -35,7 +35,7 @@ func getAuthFromKernelKeyring(registry string) (string, string, error) { // noli
return parts[0], parts[1], nil
}
func deleteAuthFromKernelKeyring(registry string) error { // nolint
func deleteAuthFromKernelKeyring(registry string) error { //nolint:deadcode,unused
userkeyring, err := keyctl.UserKeyring()
if err != nil {
@ -48,7 +48,7 @@ func deleteAuthFromKernelKeyring(registry string) error { // nolint
return key.Unlink()
}
func removeAllAuthFromKernelKeyring() error { // nolint
func removeAllAuthFromKernelKeyring() error { //nolint:deadcode,unused
keys, err := keyctl.ReadUserKeyring()
if err != nil {
return err
@ -81,7 +81,7 @@ func removeAllAuthFromKernelKeyring() error { // nolint
return nil
}
func setAuthToKernelKeyring(registry, username, password string) error { // nolint
func setAuthToKernelKeyring(registry, username, password string) error { //nolint:deadcode,unused
keyring, err := keyctl.SessionKeyring()
if err != nil {
return err
@ -114,6 +114,6 @@ func setAuthToKernelKeyring(registry, username, password string) error { // noli
return nil
}
func genDescription(registry string) string { // nolint
func genDescription(registry string) string { //nolint:deadcode,unused
return fmt.Sprintf("%s%s", keyDescribePrefix, registry)
}

View File

@ -3,18 +3,18 @@
package config
func getAuthFromKernelKeyring(registry string) (string, string, error) {
func getAuthFromKernelKeyring(registry string) (string, string, error) { //nolint:deadcode,unused
return "", "", ErrNotSupported
}
func deleteAuthFromKernelKeyring(registry string) error {
func deleteAuthFromKernelKeyring(registry string) error { //nolint:deadcode,unused
return ErrNotSupported
}
func setAuthToKernelKeyring(registry, username, password string) error {
func setAuthToKernelKeyring(registry, username, password string) error { //nolint:deadcode,unused
return ErrNotSupported
}
func removeAllAuthFromKernelKeyring() error {
func removeAllAuthFromKernelKeyring() error { //nolint:deadcode,unused
return ErrNotSupported
}

View File

@ -11,7 +11,7 @@ import (
"github.com/manifoldco/promptui"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/term"
)
// IsShortName returns true if the specified input is a "short name". A "short
@ -343,7 +343,7 @@ func Resolve(ctx *types.SystemContext, name string) (*Resolved, error) {
}
// If we don't have a TTY, act according to the mode.
if !terminal.IsTerminal(int(os.Stdout.Fd())) || !terminal.IsTerminal(int(os.Stdin.Fd())) {
if !term.IsTerminal(int(os.Stdout.Fd())) || !term.IsTerminal(int(os.Stdin.Fd())) {
switch mode {
case types.ShortNameModePermissive:
// Permissive falls back to using all candidates.

View File

@ -80,7 +80,7 @@ type storageImageDestination struct {
fileSizes map[digest.Digest]int64 // Mapping from layer blobsums to their sizes
filenames map[digest.Digest]string // Mapping from layer blobsums to names of files we used to hold them
currentIndex int // The index of the layer to be committed (i.e., lower indices have already been committed)
indexToPulledBlob map[int]*types.BlobInfo // Mapping from layer (by index) to pulled down blob
indexToPulledLayerInfo map[int]*manifest.LayerInfo // Mapping from layer (by index) to pulled down blob
blobAdditionalLayer map[digest.Digest]storage.AdditionalLayer // Mapping from layer blobsums to their corresponding additional layer
}
@ -402,7 +402,7 @@ func newImageDestination(sys *types.SystemContext, imageRef storageReference) (*
SignatureSizes: []int{},
SignaturesSizes: make(map[digest.Digest][]int),
indexToStorageID: make(map[int]*string),
indexToPulledBlob: make(map[int]*types.BlobInfo),
indexToPulledLayerInfo: make(map[int]*manifest.LayerInfo),
}
return image, nil
}
@ -449,7 +449,7 @@ func (s *storageImageDestination) PutBlobWithOptions(ctx context.Context, stream
return info, nil
}
return info, s.queueOrCommit(ctx, info, *options.LayerIndex)
return info, s.queueOrCommit(ctx, info, *options.LayerIndex, options.EmptyLayer)
}
// HasThreadSafePutBlob indicates whether PutBlob can be executed concurrently.
@ -542,7 +542,7 @@ func (s *storageImageDestination) TryReusingBlobWithOptions(ctx context.Context,
return reused, info, err
}
return reused, info, s.queueOrCommit(ctx, info, *options.LayerIndex)
return reused, info, s.queueOrCommit(ctx, info, *options.LayerIndex, options.EmptyLayer)
}
// tryReusingBlobWithSrcRef is a wrapper around TryReusingBlob.
@ -731,7 +731,7 @@ func (s *storageImageDestination) getConfigBlob(info types.BlobInfo) ([]byte, er
// queueOrCommit queues in the specified blob to be committed to the storage.
// If no other goroutine is already committing layers, the layer and all
// subsequent layers (if already queued) will be committed to the storage.
func (s *storageImageDestination) queueOrCommit(ctx context.Context, blob types.BlobInfo, index int) error {
func (s *storageImageDestination) queueOrCommit(ctx context.Context, blob types.BlobInfo, index int, emptyLayer bool) error {
// NOTE: whenever the code below is touched, make sure that all code
// paths unlock the lock and to unlock it exactly once.
//
@ -751,7 +751,10 @@ func (s *storageImageDestination) queueOrCommit(ctx context.Context, blob types.
// caller is the "worker" routine comitting layers. All other routines
// can continue pulling and queuing in layers.
s.lock.Lock()
s.indexToPulledBlob[index] = &blob
s.indexToPulledLayerInfo[index] = &manifest.LayerInfo{
BlobInfo: blob,
EmptyLayer: emptyLayer,
}
// We're still waiting for at least one previous/parent layer to be
// committed, so there's nothing to do.
@ -760,14 +763,10 @@ func (s *storageImageDestination) queueOrCommit(ctx context.Context, blob types.
return nil
}
for info := s.indexToPulledBlob[index]; info != nil; info = s.indexToPulledBlob[index] {
for info := s.indexToPulledLayerInfo[index]; info != nil; info = s.indexToPulledLayerInfo[index] {
s.lock.Unlock()
layerInfo := manifest.LayerInfo{
BlobInfo: *info,
EmptyLayer: info.Digest == image.GzippedEmptyLayerDigest,
}
// Note: commitLayer locks on-demand.
if err := s.commitLayer(ctx, layerInfo, index); err != nil {
if err := s.commitLayer(ctx, *info, index); err != nil {
return err
}
s.lock.Lock()
@ -1034,25 +1033,6 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
return errors.Wrapf(err, "error saving big data %q for image %q", blob.String(), img.ID)
}
}
// Set the reference's name on the image. We don't need to worry about avoiding duplicate
// values because SetNames() will deduplicate the list that we pass to it.
if name := s.imageRef.DockerReference(); len(oldNames) > 0 || name != nil {
names := []string{}
if name != nil {
names = append(names, name.String())
}
if len(oldNames) > 0 {
names = append(names, oldNames...)
}
if err := s.imageRef.transport.store.SetNames(img.ID, names); err != nil {
if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil {
logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2)
}
logrus.Debugf("error setting names %v on image %q: %v", names, img.ID, err)
return errors.Wrapf(err, "error setting names %v on image %q", names, img.ID)
}
logrus.Debugf("set names of image %q to %v", img.ID, names)
}
// Save the unparsedToplevel's manifest.
if len(toplevelManifest) != 0 {
manifestDigest, err := manifest.Digest(toplevelManifest)
@ -1130,6 +1110,25 @@ func (s *storageImageDestination) Commit(ctx context.Context, unparsedToplevel t
}
logrus.Debugf("saved image metadata %q", string(metadata))
}
// Set the reference's name on the image. We don't need to worry about avoiding duplicate
// values because SetNames() will deduplicate the list that we pass to it.
if name := s.imageRef.DockerReference(); len(oldNames) > 0 || name != nil {
names := []string{}
if name != nil {
names = append(names, name.String())
}
if len(oldNames) > 0 {
names = append(names, oldNames...)
}
if err := s.imageRef.transport.store.SetNames(img.ID, names); err != nil {
if _, err2 := s.imageRef.transport.store.DeleteImage(img.ID, true); err2 != nil {
logrus.Debugf("error deleting incomplete image %q: %v", img.ID, err2)
}
logrus.Debugf("error setting names %v on image %q: %v", names, img.ID, err)
return errors.Wrapf(err, "error setting names %v on image %q", names, img.ID)
}
logrus.Debugf("set names of image %q to %v", img.ID, names)
}
return nil
}

View File

@ -6,9 +6,9 @@ const (
// VersionMajor is for an API incompatible changes
VersionMajor = 5
// VersionMinor is for functionality in a backwards-compatible manner
VersionMinor = 12
VersionMinor = 13
// VersionPatch is for backwards-compatible bug fixes
VersionPatch = 0
VersionPatch = 2
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = ""

View File

@ -4,7 +4,8 @@ import (
"fmt"
"io"
"os"
"os/exec"
exec "golang.org/x/sys/execabs"
)
// Program is an interface to execute external programs.

View File

@ -1,4 +1,4 @@
package credentials
// Version holds a string describing the current version
const Version = "0.6.3"
const Version = "0.6.4"

View File

@ -1,4 +1,7 @@
language: go
arch:
- amd64
- ppc64le
install:
- go get -t
- go get golang.org/x/tools/cmd/cover

View File

@ -97,7 +97,7 @@ If Mergo is useful to you, consider buying me a coffee, a beer, or making a mont
- [mantasmatelis/whooplist-server](https://github.com/mantasmatelis/whooplist-server)
- [jnuthong/item_search](https://github.com/jnuthong/item_search)
- [bukalapak/snowboard](https://github.com/bukalapak/snowboard)
- [janoszen/containerssh](https://github.com/janoszen/containerssh)
- [containerssh/containerssh](https://github.com/containerssh/containerssh)
## Install

View File

@ -95,13 +95,18 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co
}
}
} else {
if (isReflectNil(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc) {
if dst.CanSet() && (isReflectNil(dst) || overwrite) && (!isEmptyValue(src) || overwriteWithEmptySrc) {
dst.Set(src)
}
}
case reflect.Map:
if dst.IsNil() && !src.IsNil() {
if dst.CanSet() {
dst.Set(reflect.MakeMap(dst.Type()))
} else {
dst = src
return
}
}
if src.Kind() != reflect.Map {

View File

@ -30,6 +30,7 @@ type User struct {
Name string
Role string
Age int32
EmployeCode int64 `copier:"EmployeNum"` // specify field name
// Explicitly ignored in the destination struct.
Salary int
@ -52,7 +53,7 @@ type Employee struct {
Salary int `copier:"-"`
DoubleAge int32
EmployeId int64
EmployeId int64 `copier:"EmployeNum"` // specify field name
SuperRole string
}

View File

@ -3,9 +3,11 @@ package copier
import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"reflect"
"strings"
"unicode"
)
// These flags define options for tag handling
@ -32,6 +34,19 @@ type Option struct {
DeepCopy bool
}
// Tag Flags
type flags struct {
BitFlags map[string]uint8
SrcNames tagNameMapping
DestNames tagNameMapping
}
// Field Tag name mapping
type tagNameMapping struct {
FieldNameToTag map[string]string
TagToFieldName map[string]string
}
// Copy copy things
func Copy(toValue interface{}, fromValue interface{}) (err error) {
return copier(toValue, fromValue, Option{})
@ -134,7 +149,8 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
}
if !set(to.Index(i), from.Index(i), opt.DeepCopy) {
err = CopyWithOption(to.Index(i).Addr().Interface(), from.Index(i).Interface(), opt)
// ignore error while copy slice element
err = copier(to.Index(i).Addr().Interface(), from.Index(i).Interface(), opt)
if err != nil {
continue
}
@ -148,7 +164,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
return
}
if to.Kind() == reflect.Slice {
if from.Kind() == reflect.Slice || to.Kind() == reflect.Slice {
isSlice = true
if from.Kind() == reflect.Slice {
amount = from.Len()
@ -180,9 +196,9 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
}
// Get tag options
tagBitFlags := map[string]uint8{}
if dest.IsValid() {
tagBitFlags = getBitFlags(toType)
flgs, err := getFlags(dest, source, toType, fromType)
if err != nil {
return err
}
// check source
@ -193,17 +209,18 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
name := field.Name
// Get bit flags for field
fieldFlags, _ := tagBitFlags[name]
fieldFlags, _ := flgs.BitFlags[name]
// Check if we should ignore copying
if (fieldFlags & tagIgnore) != 0 {
continue
}
if fromField := source.FieldByName(name); fromField.IsValid() && !shouldIgnore(fromField, opt.IgnoreEmpty) {
srcFieldName, destFieldName := getFieldName(name, flgs)
if fromField := source.FieldByName(srcFieldName); fromField.IsValid() && !shouldIgnore(fromField, opt.IgnoreEmpty) {
// process for nested anonymous field
destFieldNotSet := false
if f, ok := dest.Type().FieldByName(name); ok {
if f, ok := dest.Type().FieldByName(destFieldName); ok {
for idx := range f.Index {
destField := dest.FieldByIndex(f.Index[:idx+1])
@ -229,7 +246,7 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
break
}
toField := dest.FieldByName(name)
toField := dest.FieldByName(destFieldName)
if toField.IsValid() {
if toField.CanSet() {
if !set(toField, fromField, opt.DeepCopy) {
@ -239,16 +256,16 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
}
if fieldFlags != 0 {
// Note that a copy was made
tagBitFlags[name] = fieldFlags | hasCopied
flgs.BitFlags[name] = fieldFlags | hasCopied
}
}
} else {
// try to set to method
var toMethod reflect.Value
if dest.CanAddr() {
toMethod = dest.Addr().MethodByName(name)
toMethod = dest.Addr().MethodByName(destFieldName)
} else {
toMethod = dest.MethodByName(name)
toMethod = dest.MethodByName(destFieldName)
}
if toMethod.IsValid() && toMethod.Type().NumIn() == 1 && fromField.Type().AssignableTo(toMethod.Type().In(0)) {
@ -261,16 +278,17 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
// Copy from from method to dest field
for _, field := range deepFields(toType) {
name := field.Name
srcFieldName, destFieldName := getFieldName(name, flgs)
var fromMethod reflect.Value
if source.CanAddr() {
fromMethod = source.Addr().MethodByName(name)
fromMethod = source.Addr().MethodByName(srcFieldName)
} else {
fromMethod = source.MethodByName(name)
fromMethod = source.MethodByName(srcFieldName)
}
if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 && !shouldIgnore(fromMethod, opt.IgnoreEmpty) {
if toField := dest.FieldByName(name); toField.IsValid() && toField.CanSet() {
if toField := dest.FieldByName(destFieldName); toField.IsValid() && toField.CanSet() {
values := fromMethod.Call([]reflect.Value{})
if len(values) >= 1 {
set(toField, values[0], opt.DeepCopy)
@ -280,25 +298,37 @@ func copier(toValue interface{}, fromValue interface{}, opt Option) (err error)
}
}
if isSlice {
if isSlice && to.Kind() == reflect.Slice {
if dest.Addr().Type().AssignableTo(to.Type().Elem()) {
if to.Len() < i+1 {
to.Set(reflect.Append(to, dest.Addr()))
} else {
set(to.Index(i), dest.Addr(), opt.DeepCopy)
if !set(to.Index(i), dest.Addr(), opt.DeepCopy) {
// ignore error while copy slice element
err = copier(to.Index(i).Addr().Interface(), dest.Addr().Interface(), opt)
if err != nil {
continue
}
}
}
} else if dest.Type().AssignableTo(to.Type().Elem()) {
if to.Len() < i+1 {
to.Set(reflect.Append(to, dest))
} else {
set(to.Index(i), dest, opt.DeepCopy)
if !set(to.Index(i), dest, opt.DeepCopy) {
// ignore error while copy slice element
err = copier(to.Index(i).Addr().Interface(), dest.Interface(), opt)
if err != nil {
continue
}
}
}
}
} else if initDest {
to.Set(dest)
}
err = checkBitFlags(tagBitFlags)
err = checkBitFlags(flgs.BitFlags)
}
return
@ -432,46 +462,90 @@ func set(to, from reflect.Value, deepCopy bool) bool {
}
// parseTags Parses struct tags and returns uint8 bit flags.
func parseTags(tag string) (flags uint8) {
func parseTags(tag string) (flg uint8, name string, err error) {
for _, t := range strings.Split(tag, ",") {
switch t {
case "-":
flags = tagIgnore
flg = tagIgnore
return
case "must":
flags = flags | tagMust
flg = flg | tagMust
case "nopanic":
flags = flags | tagNoPanic
flg = flg | tagNoPanic
default:
if unicode.IsUpper([]rune(t)[0]) {
name = strings.TrimSpace(t)
} else {
err = errors.New("copier field name tag must be start upper case")
}
}
}
return
}
// getBitFlags Parses struct tags for bit flags.
func getBitFlags(toType reflect.Type) map[string]uint8 {
flags := map[string]uint8{}
toTypeFields := deepFields(toType)
// getTagFlags Parses struct tags for bit flags, field name.
func getFlags(dest, src reflect.Value, toType, fromType reflect.Type) (flags, error) {
flgs := flags{
BitFlags: map[string]uint8{},
SrcNames: tagNameMapping{
FieldNameToTag: map[string]string{},
TagToFieldName: map[string]string{},
},
DestNames: tagNameMapping{
FieldNameToTag: map[string]string{},
TagToFieldName: map[string]string{},
},
}
var toTypeFields, fromTypeFields []reflect.StructField
if dest.IsValid() {
toTypeFields = deepFields(toType)
}
if src.IsValid() {
fromTypeFields = deepFields(fromType)
}
// Get a list dest of tags
for _, field := range toTypeFields {
tags := field.Tag.Get("copier")
if tags != "" {
flags[field.Name] = parseTags(tags)
var name string
var err error
if flgs.BitFlags[field.Name], name, err = parseTags(tags); err != nil {
return flags{}, err
} else if name != "" {
flgs.DestNames.FieldNameToTag[field.Name] = name
flgs.DestNames.TagToFieldName[name] = field.Name
}
}
return flags
}
// Get a list source of tags
for _, field := range fromTypeFields {
tags := field.Tag.Get("copier")
if tags != "" {
var name string
var err error
if _, name, err = parseTags(tags); err != nil {
return flags{}, err
} else if name != "" {
flgs.SrcNames.FieldNameToTag[field.Name] = name
flgs.SrcNames.TagToFieldName[name] = field.Name
}
}
}
return flgs, nil
}
// checkBitFlags Checks flags for error or panic conditions.
func checkBitFlags(flagsList map[string]uint8) (err error) {
// Check flag conditions were met
for name, flags := range flagsList {
if flags&hasCopied == 0 {
for name, flgs := range flagsList {
if flgs&hasCopied == 0 {
switch {
case flags&tagMust != 0 && flags&tagNoPanic != 0:
case flgs&tagMust != 0 && flgs&tagNoPanic != 0:
err = fmt.Errorf("field %s has must tag but was not copied", name)
return
case flags&(tagMust) != 0:
case flgs&(tagMust) != 0:
panic(fmt.Sprintf("Field %s has must tag but was not copied", name))
}
}
@ -479,6 +553,40 @@ func checkBitFlags(flagsList map[string]uint8) (err error) {
return
}
func getFieldName(fieldName string, flgs flags) (srcFieldName string, destFieldName string) {
// get dest field name
if srcTagName, ok := flgs.SrcNames.FieldNameToTag[fieldName]; ok {
destFieldName = srcTagName
if destTagName, ok := flgs.DestNames.TagToFieldName[srcTagName]; ok {
destFieldName = destTagName
}
} else {
if destTagName, ok := flgs.DestNames.TagToFieldName[fieldName]; ok {
destFieldName = destTagName
}
}
if destFieldName == "" {
destFieldName = fieldName
}
// get source field name
if destTagName, ok := flgs.DestNames.FieldNameToTag[fieldName]; ok {
srcFieldName = destTagName
if srcField, ok := flgs.SrcNames.TagToFieldName[destTagName]; ok {
srcFieldName = srcField
}
} else {
if srcField, ok := flgs.SrcNames.TagToFieldName[fieldName]; ok {
srcFieldName = srcField
}
}
if srcFieldName == "" {
srcFieldName = fieldName
}
return
}
func driverValuer(v reflect.Value) (i driver.Valuer, ok bool) {
if !v.CanAddr() {

View File

@ -168,10 +168,10 @@ func (b *blockDec) reset(br byteBuffer, windowSize uint64) error {
// Read block data.
if cap(b.dataStorage) < cSize {
if b.lowMem {
if b.lowMem || cSize > maxCompressedBlockSize {
b.dataStorage = make([]byte, 0, cSize)
} else {
b.dataStorage = make([]byte, 0, maxBlockSize)
b.dataStorage = make([]byte, 0, maxCompressedBlockSize)
}
}
if cap(b.dst) <= maxSize {

View File

@ -17,6 +17,7 @@ type decoderOptions struct {
lowMem bool
concurrent int
maxDecodedSize uint64
maxWindowSize uint64
dicts []dict
}
@ -25,6 +26,7 @@ func (o *decoderOptions) setDefault() {
// use less ram: true for now, but may change.
lowMem: true,
concurrent: runtime.GOMAXPROCS(0),
maxWindowSize: MaxWindowSize,
}
o.maxDecodedSize = 1 << 63
}
@ -52,7 +54,6 @@ func WithDecoderConcurrency(n int) DOption {
// WithDecoderMaxMemory allows to set a maximum decoded size for in-memory
// non-streaming operations or maximum window size for streaming operations.
// This can be used to control memory usage of potentially hostile content.
// For streaming operations, the maximum window size is capped at 1<<30 bytes.
// Maximum and default is 1 << 63 bytes.
func WithDecoderMaxMemory(n uint64) DOption {
return func(o *decoderOptions) error {
@ -81,3 +82,21 @@ func WithDecoderDicts(dicts ...[]byte) DOption {
return nil
}
}
// WithDecoderMaxWindow allows to set a maximum window size for decodes.
// This allows rejecting packets that will cause big memory usage.
// The Decoder will likely allocate more memory based on the WithDecoderLowmem setting.
// If WithDecoderMaxMemory is set to a lower value, that will be used.
// Default is 512MB, Maximum is ~3.75 TB as per zstandard spec.
func WithDecoderMaxWindow(size uint64) DOption {
return func(o *decoderOptions) error {
if size < MinWindowSize {
return errors.New("WithMaxWindowSize must be at least 1KB, 1024 bytes")
}
if size > (1<<41)+7*(1<<38) {
return errors.New("WithMaxWindowSize must be less than (1<<41) + 7*(1<<38) ~ 3.75TB")
}
o.maxWindowSize = size
return nil
}
}

View File

@ -22,10 +22,6 @@ type frameDec struct {
WindowSize uint64
// maxWindowSize is the maximum windows size to support.
// should never be bigger than max-int.
maxWindowSize uint64
// In order queue of blocks being decoded.
decoding chan *blockDec
@ -50,8 +46,11 @@ type frameDec struct {
}
const (
// The minimum Window_Size is 1 KB.
// MinWindowSize is the minimum Window Size, which is 1 KB.
MinWindowSize = 1 << 10
// MaxWindowSize is the maximum encoder window size
// and the default decoder maximum window size.
MaxWindowSize = 1 << 29
)
@ -61,12 +60,11 @@ var (
)
func newFrameDec(o decoderOptions) *frameDec {
if o.maxWindowSize > o.maxDecodedSize {
o.maxWindowSize = o.maxDecodedSize
}
d := frameDec{
o: o,
maxWindowSize: MaxWindowSize,
}
if d.maxWindowSize > o.maxDecodedSize {
d.maxWindowSize = o.maxDecodedSize
}
return &d
}
@ -251,13 +249,17 @@ func (d *frameDec) reset(br byteBuffer) error {
}
}
if d.WindowSize > d.maxWindowSize {
printf("window size %d > max %d\n", d.WindowSize, d.maxWindowSize)
if d.WindowSize > uint64(d.o.maxWindowSize) {
if debugDecoder {
printf("window size %d > max %d\n", d.WindowSize, d.o.maxWindowSize)
}
return ErrWindowSizeExceeded
}
// The minimum Window_Size is 1 KB.
if d.WindowSize < MinWindowSize {
if debugDecoder {
println("got window size: ", d.WindowSize)
}
return ErrWindowSizeTooSmall
}
d.history.windowSize = int(d.WindowSize)
@ -352,8 +354,8 @@ func (d *frameDec) checkCRC() error {
func (d *frameDec) initAsync() {
if !d.o.lowMem && !d.SingleSegment {
// set max extra size history to 10MB.
d.history.maxSize = d.history.windowSize + maxBlockSize*5
// set max extra size history to 2MB.
d.history.maxSize = d.history.windowSize + maxBlockSize
}
// re-alloc if more than one extra block size.
if d.o.lowMem && cap(d.history.b) > d.history.maxSize+maxBlockSize {

View File

@ -2,4 +2,4 @@ module github.com/mattn/go-runewidth
go 1.9
require github.com/rivo/uniseg v0.1.0
require github.com/rivo/uniseg v0.2.0

View File

@ -1,2 +1,2 @@
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=

5
vendor/github.com/vbauerster/mpb/v7/.gitignore generated vendored Normal file
View File

@ -0,0 +1,5 @@
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

11
vendor/github.com/vbauerster/mpb/v7/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,11 @@
language: go
arch:
- amd64
- ppc64le
go:
- 1.14.x
script:
- go test -race ./...
- for i in _examples/*/; do go build $i/*.go || exit 1; done

121
vendor/github.com/vbauerster/mpb/v7/README.md generated vendored Normal file
View File

@ -0,0 +1,121 @@
# Multi Progress Bar
[![GoDoc](https://pkg.go.dev/badge/github.com/vbauerster/mpb)](https://pkg.go.dev/github.com/vbauerster/mpb/v7)
[![Build Status](https://travis-ci.org/vbauerster/mpb.svg?branch=master)](https://travis-ci.org/vbauerster/mpb)
[![Go Report Card](https://goreportcard.com/badge/github.com/vbauerster/mpb)](https://goreportcard.com/report/github.com/vbauerster/mpb)
[![Donate with PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.me/vbauerster)
**mpb** is a Go lib for rendering progress bars in terminal applications.
## Features
- **Multiple Bars**: Multiple progress bars are supported
- **Dynamic Total**: Set total while bar is running
- **Dynamic Add/Remove**: Dynamically add or remove bars
- **Cancellation**: Cancel whole rendering process
- **Predefined Decorators**: Elapsed time, [ewma](https://github.com/VividCortex/ewma) based ETA, Percentage, Bytes counter
- **Decorator's width sync**: Synchronized decorator's width among multiple bars
## Usage
#### [Rendering single bar](_examples/singleBar/main.go)
```go
package main
import (
"math/rand"
"time"
"github.com/vbauerster/mpb/v7"
"github.com/vbauerster/mpb/v7/decor"
)
func main() {
// initialize progress container, with custom width
p := mpb.New(mpb.WithWidth(64))
total := 100
name := "Single Bar:"
// adding a single bar, which will inherit container's width
bar := p.Add(int64(total),
// progress bar filler with customized style
mpb.NewBarFiller(mpb.BarStyle().Lbound("╢").Filler("▌").Tip("▌").Padding("░").Rbound("╟")),
mpb.PrependDecorators(
// display our name with one space on the right
decor.Name(name, decor.WC{W: len(name) + 1, C: decor.DidentRight}),
// replace ETA decorator with "done" message, OnComplete event
decor.OnComplete(
decor.AverageETA(decor.ET_STYLE_GO, decor.WC{W: 4}), "done",
),
),
mpb.AppendDecorators(decor.Percentage()),
)
// simulating some work
max := 100 * time.Millisecond
for i := 0; i < total; i++ {
time.Sleep(time.Duration(rand.Intn(10)+1) * max / 10)
bar.Increment()
}
// wait for our bar to complete and flush
p.Wait()
}
```
#### [Rendering multiple bars](_examples/multiBars/main.go)
```go
var wg sync.WaitGroup
// passed &wg will be accounted at p.Wait() call
p := mpb.New(mpb.WithWaitGroup(&wg))
total, numBars := 100, 3
wg.Add(numBars)
for i := 0; i < numBars; i++ {
name := fmt.Sprintf("Bar#%d:", i)
bar := p.AddBar(int64(total),
mpb.PrependDecorators(
// simple name decorator
decor.Name(name),
// decor.DSyncWidth bit enables column width synchronization
decor.Percentage(decor.WCSyncSpace),
),
mpb.AppendDecorators(
// replace ETA decorator with "done" message, OnComplete event
decor.OnComplete(
// ETA decorator with ewma age of 60
decor.EwmaETA(decor.ET_STYLE_GO, 60), "done",
),
),
)
// simulating some work
go func() {
defer wg.Done()
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
max := 100 * time.Millisecond
for i := 0; i < total; i++ {
// start variable is solely for EWMA calculation
// EWMA's unit of measure is an iteration's duration
start := time.Now()
time.Sleep(time.Duration(rng.Intn(10)+1) * max / 10)
bar.Increment()
// we need to call DecoratorEwmaUpdate to fulfill ewma decorator's contract
bar.DecoratorEwmaUpdate(time.Since(start))
}
}()
}
// Waiting for passed &wg and for all bars to complete and flush
p.Wait()
```
#### [Dynamic total](_examples/dynTotal/main.go)
![dynamic total](_svg/godEMrCZmJkHYH1X9dN4Nm0U7.svg)
#### [Complex example](_examples/complex/main.go)
![complex](_svg/wHzf1M7sd7B3zVa2scBMnjqRf.svg)
#### [Bytes counters](_examples/io/main.go)
![byte counters](_svg/hIpTa3A5rQz65ssiVuRJu87X6.svg)

24
vendor/github.com/vbauerster/mpb/v7/UNLICENSE generated vendored Normal file
View File

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
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 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.
For more information, please refer to <http://unlicense.org/>

492
vendor/github.com/vbauerster/mpb/v7/bar.go generated vendored Normal file
View File

@ -0,0 +1,492 @@
package mpb
import (
"bytes"
"context"
"fmt"
"io"
"log"
"runtime/debug"
"strings"
"time"
"github.com/acarl005/stripansi"
"github.com/mattn/go-runewidth"
"github.com/vbauerster/mpb/v7/decor"
)
// Bar represents a progress bar.
type Bar struct {
priority int // used by heap
index int // used by heap
extendedLines int
toShutdown bool
toDrop bool
noPop bool
hasEwmaDecorators bool
operateState chan func(*bState)
frameCh chan io.Reader
syncTableCh chan [][]chan int
completed chan bool
// cancel is called either by user or on complete event
cancel func()
// done is closed after cacheState is assigned
done chan struct{}
// cacheState is populated, right after close(shutdown)
cacheState *bState
container *Progress
dlogger *log.Logger
recoveredPanic interface{}
}
type extenderFunc func(in io.Reader, reqWidth int, st decor.Statistics) (out io.Reader, lines int)
// bState is actual bar state. It gets passed to *Bar.serve(...) monitor
// goroutine.
type bState struct {
id int
priority int
reqWidth int
total int64
current int64
refill int64
lastN int64
iterated bool
trimSpace bool
completed bool
completeFlushed bool
triggerComplete bool
dropOnComplete bool
noPop bool
aDecorators []decor.Decorator
pDecorators []decor.Decorator
averageDecorators []decor.AverageDecorator
ewmaDecorators []decor.EwmaDecorator
shutdownListeners []decor.ShutdownListener
bufP, bufB, bufA *bytes.Buffer
filler BarFiller
middleware func(BarFiller) BarFiller
extender extenderFunc
// runningBar is a key for *pState.parkedBars
runningBar *Bar
debugOut io.Writer
}
func newBar(container *Progress, bs *bState) *Bar {
logPrefix := fmt.Sprintf("%sbar#%02d ", container.dlogger.Prefix(), bs.id)
ctx, cancel := context.WithCancel(container.ctx)
bar := &Bar{
container: container,
priority: bs.priority,
toDrop: bs.dropOnComplete,
noPop: bs.noPop,
operateState: make(chan func(*bState)),
frameCh: make(chan io.Reader, 1),
syncTableCh: make(chan [][]chan int, 1),
completed: make(chan bool, 1),
done: make(chan struct{}),
cancel: cancel,
dlogger: log.New(bs.debugOut, logPrefix, log.Lshortfile),
}
go bar.serve(ctx, bs)
return bar
}
// ProxyReader wraps r with metrics required for progress tracking.
// Panics if r is nil.
func (b *Bar) ProxyReader(r io.Reader) io.ReadCloser {
if r == nil {
panic("expected non nil io.Reader")
}
return newProxyReader(r, b)
}
// ID returs id of the bar.
func (b *Bar) ID() int {
result := make(chan int)
select {
case b.operateState <- func(s *bState) { result <- s.id }:
return <-result
case <-b.done:
return b.cacheState.id
}
}
// Current returns bar's current number, in other words sum of all increments.
func (b *Bar) Current() int64 {
result := make(chan int64)
select {
case b.operateState <- func(s *bState) { result <- s.current }:
return <-result
case <-b.done:
return b.cacheState.current
}
}
// SetRefill sets refill flag with specified amount.
// The underlying BarFiller will change its visual representation, to
// indicate refill event. Refill event may be referred to some retry
// operation for example.
func (b *Bar) SetRefill(amount int64) {
select {
case b.operateState <- func(s *bState) {
s.refill = amount
}:
case <-b.done:
}
}
// TraverseDecorators traverses all available decorators and calls cb func on each.
func (b *Bar) TraverseDecorators(cb func(decor.Decorator)) {
select {
case b.operateState <- func(s *bState) {
for _, decorators := range [...][]decor.Decorator{
s.pDecorators,
s.aDecorators,
} {
for _, d := range decorators {
cb(extractBaseDecorator(d))
}
}
}:
case <-b.done:
}
}
// SetTotal sets total dynamically.
// If total is less than or equal to zero it takes progress' current value.
func (b *Bar) SetTotal(total int64, triggerComplete bool) {
select {
case b.operateState <- func(s *bState) {
s.triggerComplete = triggerComplete
if total <= 0 {
s.total = s.current
} else {
s.total = total
}
if s.triggerComplete && !s.completed {
s.current = s.total
s.completed = true
go b.refreshTillShutdown()
}
}:
case <-b.done:
}
}
// SetCurrent sets progress' current to an arbitrary value.
// Setting a negative value will cause a panic.
func (b *Bar) SetCurrent(current int64) {
select {
case b.operateState <- func(s *bState) {
s.iterated = true
s.lastN = current - s.current
s.current = current
if s.triggerComplete && s.current >= s.total {
s.current = s.total
s.completed = true
go b.refreshTillShutdown()
}
}:
case <-b.done:
}
}
// Increment is a shorthand for b.IncrInt64(1).
func (b *Bar) Increment() {
b.IncrInt64(1)
}
// IncrBy is a shorthand for b.IncrInt64(int64(n)).
func (b *Bar) IncrBy(n int) {
b.IncrInt64(int64(n))
}
// IncrInt64 increments progress by amount of n.
func (b *Bar) IncrInt64(n int64) {
select {
case b.operateState <- func(s *bState) {
s.iterated = true
s.lastN = n
s.current += n
if s.triggerComplete && s.current >= s.total {
s.current = s.total
s.completed = true
go b.refreshTillShutdown()
}
}:
case <-b.done:
}
}
// DecoratorEwmaUpdate updates all EWMA based decorators. Should be
// called on each iteration, because EWMA's unit of measure is an
// iteration's duration. Panics if called before *Bar.Incr... family
// methods.
func (b *Bar) DecoratorEwmaUpdate(dur time.Duration) {
select {
case b.operateState <- func(s *bState) {
ewmaIterationUpdate(false, s, dur)
}:
case <-b.done:
ewmaIterationUpdate(true, b.cacheState, dur)
}
}
// DecoratorAverageAdjust adjusts all average based decorators. Call
// if you need to adjust start time of all average based decorators
// or after progress resume.
func (b *Bar) DecoratorAverageAdjust(start time.Time) {
select {
case b.operateState <- func(s *bState) {
for _, d := range s.averageDecorators {
d.AverageAdjust(start)
}
}:
case <-b.done:
}
}
// SetPriority changes bar's order among multiple bars. Zero is highest
// priority, i.e. bar will be on top. If you don't need to set priority
// dynamically, better use BarPriority option.
func (b *Bar) SetPriority(priority int) {
select {
case <-b.done:
default:
b.container.setBarPriority(b, priority)
}
}
// Abort interrupts bar's running goroutine. Call this, if you'd like
// to stop/remove bar before completion event. It has no effect after
// completion event. If drop is true bar will be removed as well.
func (b *Bar) Abort(drop bool) {
select {
case <-b.done:
default:
if drop {
b.container.dropBar(b)
}
b.cancel()
}
}
// Completed reports whether the bar is in completed state.
func (b *Bar) Completed() bool {
select {
case b.operateState <- func(s *bState) { b.completed <- s.completed }:
return <-b.completed
case <-b.done:
return true
}
}
func (b *Bar) serve(ctx context.Context, s *bState) {
defer b.container.bwg.Done()
for {
select {
case op := <-b.operateState:
op(s)
case <-ctx.Done():
b.cacheState = s
close(b.done)
// Notifying decorators about shutdown event
for _, sl := range s.shutdownListeners {
sl.Shutdown()
}
return
}
}
}
func (b *Bar) render(tw int) {
select {
case b.operateState <- func(s *bState) {
stat := newStatistics(tw, s)
defer func() {
// recovering if user defined decorator panics for example
if p := recover(); p != nil {
if b.recoveredPanic == nil {
s.extender = makePanicExtender(p)
b.toShutdown = !b.toShutdown
b.recoveredPanic = p
}
frame, lines := s.extender(nil, s.reqWidth, stat)
b.extendedLines = lines
b.frameCh <- frame
b.dlogger.Println(p)
}
s.completeFlushed = s.completed
}()
frame, lines := s.extender(s.draw(stat), s.reqWidth, stat)
b.extendedLines = lines
b.toShutdown = s.completed && !s.completeFlushed
b.frameCh <- frame
}:
case <-b.done:
s := b.cacheState
stat := newStatistics(tw, s)
var r io.Reader
if b.recoveredPanic == nil {
r = s.draw(stat)
}
frame, lines := s.extender(r, s.reqWidth, stat)
b.extendedLines = lines
b.frameCh <- frame
}
}
func (b *Bar) subscribeDecorators() {
var averageDecorators []decor.AverageDecorator
var ewmaDecorators []decor.EwmaDecorator
var shutdownListeners []decor.ShutdownListener
b.TraverseDecorators(func(d decor.Decorator) {
if d, ok := d.(decor.AverageDecorator); ok {
averageDecorators = append(averageDecorators, d)
}
if d, ok := d.(decor.EwmaDecorator); ok {
ewmaDecorators = append(ewmaDecorators, d)
}
if d, ok := d.(decor.ShutdownListener); ok {
shutdownListeners = append(shutdownListeners, d)
}
})
select {
case b.operateState <- func(s *bState) {
s.averageDecorators = averageDecorators
s.ewmaDecorators = ewmaDecorators
s.shutdownListeners = shutdownListeners
}:
b.hasEwmaDecorators = len(ewmaDecorators) != 0
case <-b.done:
}
}
func (b *Bar) refreshTillShutdown() {
for {
select {
case b.container.refreshCh <- time.Now():
case <-b.done:
return
}
}
}
func (b *Bar) wSyncTable() [][]chan int {
select {
case b.operateState <- func(s *bState) { b.syncTableCh <- s.wSyncTable() }:
return <-b.syncTableCh
case <-b.done:
return b.cacheState.wSyncTable()
}
}
func (s *bState) draw(stat decor.Statistics) io.Reader {
nlr := strings.NewReader("\n")
tw := stat.AvailableWidth
for _, d := range s.pDecorators {
str := d.Decor(stat)
stat.AvailableWidth -= runewidth.StringWidth(stripansi.Strip(str))
s.bufP.WriteString(str)
}
if stat.AvailableWidth < 1 {
trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(s.bufP.String()), tw, "…"))
s.bufP.Reset()
return io.MultiReader(trunc, nlr)
}
if !s.trimSpace && stat.AvailableWidth > 1 {
stat.AvailableWidth -= 2
s.bufB.WriteByte(' ')
defer s.bufB.WriteByte(' ')
}
tw = stat.AvailableWidth
for _, d := range s.aDecorators {
str := d.Decor(stat)
stat.AvailableWidth -= runewidth.StringWidth(stripansi.Strip(str))
s.bufA.WriteString(str)
}
if stat.AvailableWidth < 1 {
trunc := strings.NewReader(runewidth.Truncate(stripansi.Strip(s.bufA.String()), tw, "…"))
s.bufA.Reset()
return io.MultiReader(s.bufP, s.bufB, trunc, nlr)
}
s.filler.Fill(s.bufB, s.reqWidth, stat)
return io.MultiReader(s.bufP, s.bufB, s.bufA, nlr)
}
func (s *bState) wSyncTable() [][]chan int {
columns := make([]chan int, 0, len(s.pDecorators)+len(s.aDecorators))
var pCount int
for _, d := range s.pDecorators {
if ch, ok := d.Sync(); ok {
columns = append(columns, ch)
pCount++
}
}
var aCount int
for _, d := range s.aDecorators {
if ch, ok := d.Sync(); ok {
columns = append(columns, ch)
aCount++
}
}
table := make([][]chan int, 2)
table[0] = columns[0:pCount]
table[1] = columns[pCount : pCount+aCount : pCount+aCount]
return table
}
func newStatistics(tw int, s *bState) decor.Statistics {
return decor.Statistics{
ID: s.id,
AvailableWidth: tw,
Total: s.total,
Current: s.current,
Refill: s.refill,
Completed: s.completeFlushed,
}
}
func extractBaseDecorator(d decor.Decorator) decor.Decorator {
if d, ok := d.(decor.Wrapper); ok {
return extractBaseDecorator(d.Base())
}
return d
}
func ewmaIterationUpdate(done bool, s *bState, dur time.Duration) {
if !done && !s.iterated {
panic("increment required before ewma iteration update")
} else {
s.iterated = false
}
for _, d := range s.ewmaDecorators {
d.EwmaUpdate(s.lastN, dur)
}
}
func makePanicExtender(p interface{}) extenderFunc {
pstr := fmt.Sprint(p)
stack := debug.Stack()
stackLines := bytes.Count(stack, []byte("\n"))
return func(_ io.Reader, _ int, st decor.Statistics) (io.Reader, int) {
mr := io.MultiReader(
strings.NewReader(runewidth.Truncate(pstr, st.AvailableWidth, "…")),
strings.NewReader(fmt.Sprintf("\n%#v\n", st)),
bytes.NewReader(stack),
)
return mr, stackLines + 1
}
}

39
vendor/github.com/vbauerster/mpb/v7/bar_filler.go generated vendored Normal file
View File

@ -0,0 +1,39 @@
package mpb
import (
"io"
"github.com/vbauerster/mpb/v7/decor"
)
// BarFiller interface.
// Bar (without decorators) renders itself by calling BarFiller's Fill method.
//
// reqWidth is requested width, set by `func WithWidth(int) ContainerOption`.
// If not set, it defaults to terminal width.
//
// Default implementations can be obtained via:
//
// func NewBarFiller(BarStyle()) BarFiller
// func NewBarFiller(SpinnerStyle()) BarFiller
//
type BarFiller interface {
Fill(w io.Writer, reqWidth int, stat decor.Statistics)
}
// BarFillerBuilder interface.
type BarFillerBuilder interface {
Build() BarFiller
}
// BarFillerFunc is function type adapter to convert function into BarFiller.
type BarFillerFunc func(w io.Writer, reqWidth int, stat decor.Statistics)
func (f BarFillerFunc) Fill(w io.Writer, reqWidth int, stat decor.Statistics) {
f(w, reqWidth, stat)
}
// NewBarFiller constructs a BarFiller from provided BarFillerBuilder.
func NewBarFiller(b BarFillerBuilder) BarFiller {
return b.Build()
}

219
vendor/github.com/vbauerster/mpb/v7/bar_filler_bar.go generated vendored Normal file
View File

@ -0,0 +1,219 @@
package mpb
import (
"io"
"github.com/acarl005/stripansi"
"github.com/mattn/go-runewidth"
"github.com/vbauerster/mpb/v7/decor"
"github.com/vbauerster/mpb/v7/internal"
)
const (
iLbound = iota
iRbound
iFiller
iRefiller
iPadding
components
)
// BarStyleComposer interface.
type BarStyleComposer interface {
BarFillerBuilder
Lbound(string) BarStyleComposer
Rbound(string) BarStyleComposer
Filler(string) BarStyleComposer
Refiller(string) BarStyleComposer
Padding(string) BarStyleComposer
Tip(...string) BarStyleComposer
Reverse() BarStyleComposer
}
type bFiller struct {
components [components]*component
tip struct {
count uint
frames []*component
}
flush func(dst io.Writer, filling, padding [][]byte)
}
type component struct {
width int
bytes []byte
}
type barStyle struct {
lbound string
rbound string
filler string
refiller string
padding string
tip []string
rev bool
}
// BarStyle constructs default bar style which can be altered via
// BarStyleComposer interface.
func BarStyle() BarStyleComposer {
return &barStyle{
lbound: "[",
rbound: "]",
filler: "=",
refiller: "+",
padding: "-",
tip: []string{">"},
}
}
func (s *barStyle) Lbound(bound string) BarStyleComposer {
s.lbound = bound
return s
}
func (s *barStyle) Rbound(bound string) BarStyleComposer {
s.rbound = bound
return s
}
func (s *barStyle) Filler(filler string) BarStyleComposer {
s.filler = filler
return s
}
func (s *barStyle) Refiller(refiller string) BarStyleComposer {
s.refiller = refiller
return s
}
func (s *barStyle) Padding(padding string) BarStyleComposer {
s.padding = padding
return s
}
func (s *barStyle) Tip(tip ...string) BarStyleComposer {
if len(tip) != 0 {
s.tip = append(s.tip[:0], tip...)
}
return s
}
func (s *barStyle) Reverse() BarStyleComposer {
s.rev = true
return s
}
func (s *barStyle) Build() BarFiller {
bf := new(bFiller)
if s.rev {
bf.flush = func(dst io.Writer, filling, padding [][]byte) {
flush(dst, padding, filling)
}
} else {
bf.flush = flush
}
bf.components[iLbound] = &component{
width: runewidth.StringWidth(stripansi.Strip(s.lbound)),
bytes: []byte(s.lbound),
}
bf.components[iRbound] = &component{
width: runewidth.StringWidth(stripansi.Strip(s.rbound)),
bytes: []byte(s.rbound),
}
bf.components[iFiller] = &component{
width: runewidth.StringWidth(stripansi.Strip(s.filler)),
bytes: []byte(s.filler),
}
bf.components[iRefiller] = &component{
width: runewidth.StringWidth(stripansi.Strip(s.refiller)),
bytes: []byte(s.refiller),
}
bf.components[iPadding] = &component{
width: runewidth.StringWidth(stripansi.Strip(s.padding)),
bytes: []byte(s.padding),
}
bf.tip.frames = make([]*component, len(s.tip))
for i, t := range s.tip {
bf.tip.frames[i] = &component{
width: runewidth.StringWidth(stripansi.Strip(t)),
bytes: []byte(t),
}
}
return bf
}
func (s *bFiller) Fill(w io.Writer, width int, stat decor.Statistics) {
width = internal.CheckRequestedWidth(width, stat.AvailableWidth)
brackets := s.components[iLbound].width + s.components[iRbound].width
if width < brackets {
return
}
// don't count brackets as progress
width -= brackets
w.Write(s.components[iLbound].bytes)
defer w.Write(s.components[iRbound].bytes)
curWidth := int(internal.PercentageRound(stat.Total, stat.Current, width))
refWidth, filled := 0, curWidth
filling := make([][]byte, 0, curWidth)
if curWidth > 0 && curWidth != width {
tipFrame := s.tip.frames[s.tip.count%uint(len(s.tip.frames))]
filling = append(filling, tipFrame.bytes)
curWidth -= tipFrame.width
s.tip.count++
}
if stat.Refill > 0 && curWidth > 0 {
refWidth = int(internal.PercentageRound(stat.Total, int64(stat.Refill), width))
if refWidth > curWidth {
refWidth = curWidth
}
curWidth -= refWidth
}
for curWidth > 0 && curWidth >= s.components[iFiller].width {
filling = append(filling, s.components[iFiller].bytes)
curWidth -= s.components[iFiller].width
if s.components[iFiller].width == 0 {
break
}
}
for refWidth > 0 && refWidth >= s.components[iRefiller].width {
filling = append(filling, s.components[iRefiller].bytes)
refWidth -= s.components[iRefiller].width
if s.components[iRefiller].width == 0 {
break
}
}
filled -= curWidth + refWidth
padWidth := width - filled
padding := make([][]byte, 0, padWidth)
for padWidth > 0 && padWidth >= s.components[iPadding].width {
padding = append(padding, s.components[iPadding].bytes)
padWidth -= s.components[iPadding].width
if s.components[iPadding].width == 0 {
break
}
}
for padWidth > 0 {
padding = append(padding, []byte("…"))
padWidth--
}
s.flush(w, filling, padding)
}
func flush(dst io.Writer, filling, padding [][]byte) {
for i := len(filling) - 1; i >= 0; i-- {
dst.Write(filling[i])
}
for i := 0; i < len(padding); i++ {
dst.Write(padding[i])
}
}

View File

@ -0,0 +1,87 @@
package mpb
import (
"io"
"strings"
"github.com/acarl005/stripansi"
"github.com/mattn/go-runewidth"
"github.com/vbauerster/mpb/v7/decor"
"github.com/vbauerster/mpb/v7/internal"
)
const (
positionLeft = 1 + iota
positionRight
)
// SpinnerStyleComposer interface.
type SpinnerStyleComposer interface {
BarFillerBuilder
PositionLeft() SpinnerStyleComposer
PositionRight() SpinnerStyleComposer
}
type sFiller struct {
count uint
position uint
frames []string
}
type spinnerStyle struct {
position uint
frames []string
}
// SpinnerStyle constructs default spinner style which can be altered via
// SpinnerStyleComposer interface.
func SpinnerStyle(frames ...string) SpinnerStyleComposer {
ss := new(spinnerStyle)
if len(frames) != 0 {
ss.frames = append(ss.frames, frames...)
} else {
ss.frames = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
}
return ss
}
func (s *spinnerStyle) PositionLeft() SpinnerStyleComposer {
s.position = positionLeft
return s
}
func (s *spinnerStyle) PositionRight() SpinnerStyleComposer {
s.position = positionRight
return s
}
func (s *spinnerStyle) Build() BarFiller {
sf := &sFiller{
position: s.position,
frames: s.frames,
}
return sf
}
func (s *sFiller) Fill(w io.Writer, width int, stat decor.Statistics) {
width = internal.CheckRequestedWidth(width, stat.AvailableWidth)
frame := s.frames[s.count%uint(len(s.frames))]
frameWidth := runewidth.StringWidth(stripansi.Strip(frame))
if width < frameWidth {
return
}
rest := width - frameWidth
switch s.position {
case positionLeft:
io.WriteString(w, frame+strings.Repeat(" ", rest))
case positionRight:
io.WriteString(w, strings.Repeat(" ", rest)+frame)
default:
str := strings.Repeat(" ", rest/2) + frame + strings.Repeat(" ", rest/2+rest%2)
io.WriteString(w, str)
}
s.count++
}

153
vendor/github.com/vbauerster/mpb/v7/bar_option.go generated vendored Normal file
View File

@ -0,0 +1,153 @@
package mpb
import (
"bytes"
"io"
"github.com/vbauerster/mpb/v7/decor"
"github.com/vbauerster/mpb/v7/internal"
)
// BarOption is a func option to alter default behavior of a bar.
type BarOption func(*bState)
func (s *bState) addDecorators(dest *[]decor.Decorator, decorators ...decor.Decorator) {
type mergeWrapper interface {
MergeUnwrap() []decor.Decorator
}
for _, decorator := range decorators {
if mw, ok := decorator.(mergeWrapper); ok {
*dest = append(*dest, mw.MergeUnwrap()...)
}
*dest = append(*dest, decorator)
}
}
// AppendDecorators let you inject decorators to the bar's right side.
func AppendDecorators(decorators ...decor.Decorator) BarOption {
return func(s *bState) {
s.addDecorators(&s.aDecorators, decorators...)
}
}
// PrependDecorators let you inject decorators to the bar's left side.
func PrependDecorators(decorators ...decor.Decorator) BarOption {
return func(s *bState) {
s.addDecorators(&s.pDecorators, decorators...)
}
}
// BarID sets bar id.
func BarID(id int) BarOption {
return func(s *bState) {
s.id = id
}
}
// BarWidth sets bar width independent of the container.
func BarWidth(width int) BarOption {
return func(s *bState) {
s.reqWidth = width
}
}
// BarQueueAfter queues this (being constructed) bar to relplace
// runningBar after it has been completed.
func BarQueueAfter(runningBar *Bar) BarOption {
if runningBar == nil {
return nil
}
return func(s *bState) {
s.runningBar = runningBar
}
}
// BarRemoveOnComplete removes both bar's filler and its decorators
// on complete event.
func BarRemoveOnComplete() BarOption {
return func(s *bState) {
s.dropOnComplete = true
}
}
// BarFillerClearOnComplete clears bar's filler on complete event.
// It's shortcut for BarFillerOnComplete("").
func BarFillerClearOnComplete() BarOption {
return BarFillerOnComplete("")
}
// BarFillerOnComplete replaces bar's filler with message, on complete event.
func BarFillerOnComplete(message string) BarOption {
return BarFillerMiddleware(func(base BarFiller) BarFiller {
return BarFillerFunc(func(w io.Writer, reqWidth int, st decor.Statistics) {
if st.Completed {
io.WriteString(w, message)
} else {
base.Fill(w, reqWidth, st)
}
})
})
}
// BarFillerMiddleware provides a way to augment the underlying BarFiller.
func BarFillerMiddleware(middle func(BarFiller) BarFiller) BarOption {
return func(s *bState) {
s.middleware = middle
}
}
// BarPriority sets bar's priority. Zero is highest priority, i.e. bar
// will be on top. If `BarReplaceOnComplete` option is supplied, this
// option is ignored.
func BarPriority(priority int) BarOption {
return func(s *bState) {
s.priority = priority
}
}
// BarExtender provides a way to extend bar to the next new line.
func BarExtender(filler BarFiller) BarOption {
if filler == nil {
return nil
}
return func(s *bState) {
s.extender = makeExtenderFunc(filler)
}
}
func makeExtenderFunc(filler BarFiller) extenderFunc {
buf := new(bytes.Buffer)
return func(r io.Reader, reqWidth int, st decor.Statistics) (io.Reader, int) {
filler.Fill(buf, reqWidth, st)
return io.MultiReader(r, buf), bytes.Count(buf.Bytes(), []byte("\n"))
}
}
// BarFillerTrim removes leading and trailing space around the underlying BarFiller.
func BarFillerTrim() BarOption {
return func(s *bState) {
s.trimSpace = true
}
}
// BarNoPop disables bar pop out of container. Effective when
// PopCompletedMode of container is enabled.
func BarNoPop() BarOption {
return func(s *bState) {
s.noPop = true
}
}
// BarOptional will invoke provided option only when pick is true.
func BarOptional(option BarOption, pick bool) BarOption {
return BarOptOn(option, internal.Predicate(pick))
}
// BarOptOn will invoke provided option only when higher order predicate
// evaluates to true.
func BarOptOn(option BarOption, predicate func() bool) BarOption {
if predicate() {
return option
}
return nil
}

112
vendor/github.com/vbauerster/mpb/v7/container_option.go generated vendored Normal file
View File

@ -0,0 +1,112 @@
package mpb
import (
"io"
"io/ioutil"
"sync"
"time"
"github.com/vbauerster/mpb/v7/internal"
)
// ContainerOption is a func option to alter default behavior of a bar
// container. Container term refers to a Progress struct which can
// hold one or more Bars.
type ContainerOption func(*pState)
// WithWaitGroup provides means to have a single joint point. If
// *sync.WaitGroup is provided, you can safely call just p.Wait()
// without calling Wait() on provided *sync.WaitGroup. Makes sense
// when there are more than one bar to render.
func WithWaitGroup(wg *sync.WaitGroup) ContainerOption {
return func(s *pState) {
s.uwg = wg
}
}
// WithWidth sets container width. If not set it defaults to terminal
// width. A bar added to the container will inherit its width, unless
// overridden by `func BarWidth(int) BarOption`.
func WithWidth(width int) ContainerOption {
return func(s *pState) {
s.reqWidth = width
}
}
// WithRefreshRate overrides default 120ms refresh rate.
func WithRefreshRate(d time.Duration) ContainerOption {
return func(s *pState) {
s.rr = d
}
}
// WithManualRefresh disables internal auto refresh time.Ticker.
// Refresh will occur upon receive value from provided ch.
func WithManualRefresh(ch <-chan interface{}) ContainerOption {
return func(s *pState) {
s.externalRefresh = ch
}
}
// WithRenderDelay delays rendering. By default rendering starts as
// soon as bar is added, with this option it's possible to delay
// rendering process by keeping provided chan unclosed. In other words
// rendering will start as soon as provided chan is closed.
func WithRenderDelay(ch <-chan struct{}) ContainerOption {
return func(s *pState) {
s.renderDelay = ch
}
}
// WithShutdownNotifier provided chanel will be closed, after all bars
// have been rendered.
func WithShutdownNotifier(ch chan struct{}) ContainerOption {
return func(s *pState) {
s.shutdownNotifier = ch
}
}
// WithOutput overrides default os.Stdout output. Setting it to nil
// will effectively disable auto refresh rate and discard any output,
// useful if you want to disable progress bars with little overhead.
func WithOutput(w io.Writer) ContainerOption {
return func(s *pState) {
if w == nil {
s.output = ioutil.Discard
s.outputDiscarded = true
return
}
s.output = w
}
}
// WithDebugOutput sets debug output.
func WithDebugOutput(w io.Writer) ContainerOption {
if w == nil {
return nil
}
return func(s *pState) {
s.debugOut = w
}
}
// PopCompletedMode will pop and stop rendering completed bars.
func PopCompletedMode() ContainerOption {
return func(s *pState) {
s.popCompleted = true
}
}
// ContainerOptional will invoke provided option only when pick is true.
func ContainerOptional(option ContainerOption, pick bool) ContainerOption {
return ContainerOptOn(option, internal.Predicate(pick))
}
// ContainerOptOn will invoke provided option only when higher order
// predicate evaluates to true.
func ContainerOptOn(option ContainerOption, predicate func() bool) ContainerOption {
if predicate() {
return option
}
return nil
}

2
vendor/github.com/vbauerster/mpb/v7/cwriter/doc.go generated vendored Normal file
View File

@ -0,0 +1,2 @@
// Package cwriter is a console writer abstraction for the underlying OS.
package cwriter

View File

@ -0,0 +1,7 @@
// +build darwin dragonfly freebsd netbsd openbsd
package cwriter
import "golang.org/x/sys/unix"
const ioctlReadTermios = unix.TIOCGETA

View File

@ -0,0 +1,7 @@
// +build aix linux
package cwriter
import "golang.org/x/sys/unix"
const ioctlReadTermios = unix.TCGETS

View File

@ -0,0 +1,7 @@
// +build solaris
package cwriter
import "golang.org/x/sys/unix"
const ioctlReadTermios = unix.TCGETA

84
vendor/github.com/vbauerster/mpb/v7/cwriter/writer.go generated vendored Normal file
View File

@ -0,0 +1,84 @@
package cwriter
import (
"bytes"
"errors"
"io"
"os"
"strconv"
)
// ErrNotTTY not a TeleTYpewriter error.
var ErrNotTTY = errors.New("not a terminal")
// http://ascii-table.com/ansi-escape-sequences.php
const (
escOpen = "\x1b["
cuuAndEd = "A\x1b[J"
)
// Writer is a buffered the writer that updates the terminal. The
// contents of writer will be flushed when Flush is called.
type Writer struct {
out io.Writer
buf bytes.Buffer
lineCount int
fd int
isTerminal bool
}
// New returns a new Writer with defaults.
func New(out io.Writer) *Writer {
w := &Writer{out: out}
if f, ok := out.(*os.File); ok {
w.fd = int(f.Fd())
w.isTerminal = IsTerminal(w.fd)
}
return w
}
// Flush flushes the underlying buffer.
func (w *Writer) Flush(lineCount int) (err error) {
// some terminals interpret 'cursor up 0' as 'cursor up 1'
if w.lineCount > 0 {
err = w.clearLines()
if err != nil {
return
}
}
w.lineCount = lineCount
_, err = w.buf.WriteTo(w.out)
return
}
// Write appends the contents of p to the underlying buffer.
func (w *Writer) Write(p []byte) (n int, err error) {
return w.buf.Write(p)
}
// WriteString writes string to the underlying buffer.
func (w *Writer) WriteString(s string) (n int, err error) {
return w.buf.WriteString(s)
}
// ReadFrom reads from the provided io.Reader and writes to the
// underlying buffer.
func (w *Writer) ReadFrom(r io.Reader) (n int64, err error) {
return w.buf.ReadFrom(r)
}
// GetWidth returns width of underlying terminal.
func (w *Writer) GetWidth() (int, error) {
if !w.isTerminal {
return -1, ErrNotTTY
}
tw, _, err := GetSize(w.fd)
return tw, err
}
func (w *Writer) ansiCuuAndEd() (err error) {
buf := make([]byte, 8)
buf = strconv.AppendInt(buf[:copy(buf, escOpen)], int64(w.lineCount), 10)
_, err = w.out.Write(append(buf, cuuAndEd...))
return
}

View File

@ -0,0 +1,26 @@
// +build !windows
package cwriter
import (
"golang.org/x/sys/unix"
)
func (w *Writer) clearLines() error {
return w.ansiCuuAndEd()
}
// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (width, height int, err error) {
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
if err != nil {
return -1, -1, err
}
return int(ws.Col), int(ws.Row), nil
}
// IsTerminal returns whether the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
_, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
return err == nil
}

View File

@ -0,0 +1,73 @@
// +build windows
package cwriter
import (
"unsafe"
"golang.org/x/sys/windows"
)
var kernel32 = windows.NewLazySystemDLL("kernel32.dll")
var (
procSetConsoleCursorPosition = kernel32.NewProc("SetConsoleCursorPosition")
procFillConsoleOutputCharacter = kernel32.NewProc("FillConsoleOutputCharacterW")
)
func (w *Writer) clearLines() error {
if !w.isTerminal {
// hope it's cygwin or similar
return w.ansiCuuAndEd()
}
var info windows.ConsoleScreenBufferInfo
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(w.fd), &info); err != nil {
return err
}
info.CursorPosition.Y -= int16(w.lineCount)
if info.CursorPosition.Y < 0 {
info.CursorPosition.Y = 0
}
_, _, _ = procSetConsoleCursorPosition.Call(
uintptr(w.fd),
uintptr(uint32(uint16(info.CursorPosition.Y))<<16|uint32(uint16(info.CursorPosition.X))),
)
// clear the lines
cursor := &windows.Coord{
X: info.Window.Left,
Y: info.CursorPosition.Y,
}
count := uint32(info.Size.X) * uint32(w.lineCount)
_, _, _ = procFillConsoleOutputCharacter.Call(
uintptr(w.fd),
uintptr(' '),
uintptr(count),
*(*uintptr)(unsafe.Pointer(cursor)),
uintptr(unsafe.Pointer(new(uint32))),
)
return nil
}
// GetSize returns the visible dimensions of the given terminal.
//
// These dimensions don't include any scrollback buffer height.
func GetSize(fd int) (width, height int, err error) {
var info windows.ConsoleScreenBufferInfo
if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil {
return 0, 0, err
}
// terminal.GetSize from crypto/ssh adds "+ 1" to both width and height:
// https://go.googlesource.com/crypto/+/refs/heads/release-branch.go1.14/ssh/terminal/util_windows.go#75
// but looks like this is a root cause of issue #66, so removing both "+ 1" have fixed it.
return int(info.Window.Right - info.Window.Left), int(info.Window.Bottom - info.Window.Top), nil
}
// IsTerminal returns whether the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
var st uint32
err := windows.GetConsoleMode(windows.Handle(fd), &st)
return err == nil
}

21
vendor/github.com/vbauerster/mpb/v7/decor/any.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
package decor
// Any decorator displays text, that can be changed during decorator's
// lifetime via provided DecorFunc.
//
// `fn` DecorFunc callback
//
// `wcc` optional WC config
//
func Any(fn DecorFunc, wcc ...WC) Decorator {
return &any{initWC(wcc...), fn}
}
type any struct {
WC
fn DecorFunc
}
func (d *any) Decor(s Statistics) string {
return d.FormatMsg(d.fn(s))
}

243
vendor/github.com/vbauerster/mpb/v7/decor/counters.go generated vendored Normal file
View File

@ -0,0 +1,243 @@
package decor
import (
"fmt"
"strings"
)
const (
_ = iota
UnitKiB
UnitKB
)
// CountersNoUnit is a wrapper around Counters with no unit param.
func CountersNoUnit(pairFmt string, wcc ...WC) Decorator {
return Counters(0, pairFmt, wcc...)
}
// CountersKibiByte is a wrapper around Counters with predefined unit
// UnitKiB (bytes/1024).
func CountersKibiByte(pairFmt string, wcc ...WC) Decorator {
return Counters(UnitKiB, pairFmt, wcc...)
}
// CountersKiloByte is a wrapper around Counters with predefined unit
// UnitKB (bytes/1000).
func CountersKiloByte(pairFmt string, wcc ...WC) Decorator {
return Counters(UnitKB, pairFmt, wcc...)
}
// Counters decorator with dynamic unit measure adjustment.
//
// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
// `pairFmt` printf compatible verbs for current and total pair
//
// `wcc` optional WC config
//
// pairFmt example if unit=UnitKB:
//
// pairFmt="%.1f / %.1f" output: "1.0MB / 12.0MB"
// pairFmt="% .1f / % .1f" output: "1.0 MB / 12.0 MB"
// pairFmt="%d / %d" output: "1MB / 12MB"
// pairFmt="% d / % d" output: "1 MB / 12 MB"
//
func Counters(unit int, pairFmt string, wcc ...WC) Decorator {
producer := func(unit int, pairFmt string) DecorFunc {
if pairFmt == "" {
pairFmt = "%d / %d"
} else if strings.Count(pairFmt, "%") != 2 {
panic("expected pairFmt with exactly 2 verbs")
}
switch unit {
case UnitKiB:
return func(s Statistics) string {
return fmt.Sprintf(pairFmt, SizeB1024(s.Current), SizeB1024(s.Total))
}
case UnitKB:
return func(s Statistics) string {
return fmt.Sprintf(pairFmt, SizeB1000(s.Current), SizeB1000(s.Total))
}
default:
return func(s Statistics) string {
return fmt.Sprintf(pairFmt, s.Current, s.Total)
}
}
}
return Any(producer(unit, pairFmt), wcc...)
}
// TotalNoUnit is a wrapper around Total with no unit param.
func TotalNoUnit(format string, wcc ...WC) Decorator {
return Total(0, format, wcc...)
}
// TotalKibiByte is a wrapper around Total with predefined unit
// UnitKiB (bytes/1024).
func TotalKibiByte(format string, wcc ...WC) Decorator {
return Total(UnitKiB, format, wcc...)
}
// TotalKiloByte is a wrapper around Total with predefined unit
// UnitKB (bytes/1000).
func TotalKiloByte(format string, wcc ...WC) Decorator {
return Total(UnitKB, format, wcc...)
}
// Total decorator with dynamic unit measure adjustment.
//
// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
// `format` printf compatible verb for Total
//
// `wcc` optional WC config
//
// format example if unit=UnitKiB:
//
// format="%.1f" output: "12.0MiB"
// format="% .1f" output: "12.0 MiB"
// format="%d" output: "12MiB"
// format="% d" output: "12 MiB"
//
func Total(unit int, format string, wcc ...WC) Decorator {
producer := func(unit int, format string) DecorFunc {
if format == "" {
format = "%d"
} else if strings.Count(format, "%") != 1 {
panic("expected format with exactly 1 verb")
}
switch unit {
case UnitKiB:
return func(s Statistics) string {
return fmt.Sprintf(format, SizeB1024(s.Total))
}
case UnitKB:
return func(s Statistics) string {
return fmt.Sprintf(format, SizeB1000(s.Total))
}
default:
return func(s Statistics) string {
return fmt.Sprintf(format, s.Total)
}
}
}
return Any(producer(unit, format), wcc...)
}
// CurrentNoUnit is a wrapper around Current with no unit param.
func CurrentNoUnit(format string, wcc ...WC) Decorator {
return Current(0, format, wcc...)
}
// CurrentKibiByte is a wrapper around Current with predefined unit
// UnitKiB (bytes/1024).
func CurrentKibiByte(format string, wcc ...WC) Decorator {
return Current(UnitKiB, format, wcc...)
}
// CurrentKiloByte is a wrapper around Current with predefined unit
// UnitKB (bytes/1000).
func CurrentKiloByte(format string, wcc ...WC) Decorator {
return Current(UnitKB, format, wcc...)
}
// Current decorator with dynamic unit measure adjustment.
//
// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
// `format` printf compatible verb for Current
//
// `wcc` optional WC config
//
// format example if unit=UnitKiB:
//
// format="%.1f" output: "12.0MiB"
// format="% .1f" output: "12.0 MiB"
// format="%d" output: "12MiB"
// format="% d" output: "12 MiB"
//
func Current(unit int, format string, wcc ...WC) Decorator {
producer := func(unit int, format string) DecorFunc {
if format == "" {
format = "%d"
} else if strings.Count(format, "%") != 1 {
panic("expected format with exactly 1 verb")
}
switch unit {
case UnitKiB:
return func(s Statistics) string {
return fmt.Sprintf(format, SizeB1024(s.Current))
}
case UnitKB:
return func(s Statistics) string {
return fmt.Sprintf(format, SizeB1000(s.Current))
}
default:
return func(s Statistics) string {
return fmt.Sprintf(format, s.Current)
}
}
}
return Any(producer(unit, format), wcc...)
}
// InvertedCurrentNoUnit is a wrapper around InvertedCurrent with no unit param.
func InvertedCurrentNoUnit(format string, wcc ...WC) Decorator {
return InvertedCurrent(0, format, wcc...)
}
// InvertedCurrentKibiByte is a wrapper around InvertedCurrent with predefined unit
// UnitKiB (bytes/1024).
func InvertedCurrentKibiByte(format string, wcc ...WC) Decorator {
return InvertedCurrent(UnitKiB, format, wcc...)
}
// InvertedCurrentKiloByte is a wrapper around InvertedCurrent with predefined unit
// UnitKB (bytes/1000).
func InvertedCurrentKiloByte(format string, wcc ...WC) Decorator {
return InvertedCurrent(UnitKB, format, wcc...)
}
// InvertedCurrent decorator with dynamic unit measure adjustment.
//
// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
// `format` printf compatible verb for InvertedCurrent
//
// `wcc` optional WC config
//
// format example if unit=UnitKiB:
//
// format="%.1f" output: "12.0MiB"
// format="% .1f" output: "12.0 MiB"
// format="%d" output: "12MiB"
// format="% d" output: "12 MiB"
//
func InvertedCurrent(unit int, format string, wcc ...WC) Decorator {
producer := func(unit int, format string) DecorFunc {
if format == "" {
format = "%d"
} else if strings.Count(format, "%") != 1 {
panic("expected format with exactly 1 verb")
}
switch unit {
case UnitKiB:
return func(s Statistics) string {
return fmt.Sprintf(format, SizeB1024(s.Total-s.Current))
}
case UnitKB:
return func(s Statistics) string {
return fmt.Sprintf(format, SizeB1000(s.Total-s.Current))
}
default:
return func(s Statistics) string {
return fmt.Sprintf(format, s.Total-s.Current)
}
}
}
return Any(producer(unit, format), wcc...)
}

191
vendor/github.com/vbauerster/mpb/v7/decor/decorator.go generated vendored Normal file
View File

@ -0,0 +1,191 @@
package decor
import (
"fmt"
"time"
"github.com/acarl005/stripansi"
"github.com/mattn/go-runewidth"
)
const (
// DidentRight bit specifies identation direction.
// |foo |b | With DidentRight
// | foo| b| Without DidentRight
DidentRight = 1 << iota
// DextraSpace bit adds extra space, makes sense with DSyncWidth only.
// When DidentRight bit set, the space will be added to the right,
// otherwise to the left.
DextraSpace
// DSyncWidth bit enables same column width synchronization.
// Effective with multiple bars only.
DSyncWidth
// DSyncWidthR is shortcut for DSyncWidth|DidentRight
DSyncWidthR = DSyncWidth | DidentRight
// DSyncSpace is shortcut for DSyncWidth|DextraSpace
DSyncSpace = DSyncWidth | DextraSpace
// DSyncSpaceR is shortcut for DSyncWidth|DextraSpace|DidentRight
DSyncSpaceR = DSyncWidth | DextraSpace | DidentRight
)
// TimeStyle enum.
type TimeStyle int
// TimeStyle kinds.
const (
ET_STYLE_GO TimeStyle = iota
ET_STYLE_HHMMSS
ET_STYLE_HHMM
ET_STYLE_MMSS
)
// Statistics consists of progress related statistics, that Decorator
// may need.
type Statistics struct {
ID int
AvailableWidth int
Total int64
Current int64
Refill int64
Completed bool
}
// Decorator interface.
// Most of the time there is no need to implement this interface
// manually, as decor package already provides a wide range of decorators
// which implement this interface. If however built-in decorators don't
// meet your needs, you're free to implement your own one by implementing
// this particular interface. The easy way to go is to convert a
// `DecorFunc` into a `Decorator` interface by using provided
// `func Any(DecorFunc, ...WC) Decorator`.
type Decorator interface {
Configurator
Synchronizer
Decor(Statistics) string
}
// DecorFunc func type.
// To be used with `func Any`(DecorFunc, ...WC) Decorator`.
type DecorFunc func(Statistics) string
// Synchronizer interface.
// All decorators implement this interface implicitly. Its Sync
// method exposes width sync channel, if DSyncWidth bit is set.
type Synchronizer interface {
Sync() (chan int, bool)
}
// Configurator interface.
type Configurator interface {
GetConf() WC
SetConf(WC)
}
// Wrapper interface.
// If you're implementing custom Decorator by wrapping a built-in one,
// it is necessary to implement this interface to retain functionality
// of built-in Decorator.
type Wrapper interface {
Base() Decorator
}
// EwmaDecorator interface.
// EWMA based decorators should implement this one.
type EwmaDecorator interface {
EwmaUpdate(int64, time.Duration)
}
// AverageDecorator interface.
// Average decorators should implement this interface to provide start
// time adjustment facility, for resume-able tasks.
type AverageDecorator interface {
AverageAdjust(time.Time)
}
// ShutdownListener interface.
// If decorator needs to be notified once upon bar shutdown event, so
// this is the right interface to implement.
type ShutdownListener interface {
Shutdown()
}
// Global convenience instances of WC with sync width bit set.
// To be used with multiple bars only, i.e. not effective for single bar usage.
var (
WCSyncWidth = WC{C: DSyncWidth}
WCSyncWidthR = WC{C: DSyncWidthR}
WCSyncSpace = WC{C: DSyncSpace}
WCSyncSpaceR = WC{C: DSyncSpaceR}
)
// WC is a struct with two public fields W and C, both of int type.
// W represents width and C represents bit set of width related config.
// A decorator should embed WC, to enable width synchronization.
type WC struct {
W int
C int
fill func(s string, w int) string
wsync chan int
}
// FormatMsg formats final message according to WC.W and WC.C.
// Should be called by any Decorator implementation.
func (wc *WC) FormatMsg(msg string) string {
pureWidth := runewidth.StringWidth(msg)
stripWidth := runewidth.StringWidth(stripansi.Strip(msg))
maxCell := wc.W
if (wc.C & DSyncWidth) != 0 {
cellCount := stripWidth
if (wc.C & DextraSpace) != 0 {
cellCount++
}
wc.wsync <- cellCount
maxCell = <-wc.wsync
}
return wc.fill(msg, maxCell+(pureWidth-stripWidth))
}
// Init initializes width related config.
func (wc *WC) Init() WC {
wc.fill = runewidth.FillLeft
if (wc.C & DidentRight) != 0 {
wc.fill = runewidth.FillRight
}
if (wc.C & DSyncWidth) != 0 {
// it's deliberate choice to override wsync on each Init() call,
// this way globals like WCSyncSpace can be reused
wc.wsync = make(chan int)
}
return *wc
}
// Sync is implementation of Synchronizer interface.
func (wc *WC) Sync() (chan int, bool) {
if (wc.C&DSyncWidth) != 0 && wc.wsync == nil {
panic(fmt.Sprintf("%T is not initialized", wc))
}
return wc.wsync, (wc.C & DSyncWidth) != 0
}
// GetConf is implementation of Configurator interface.
func (wc *WC) GetConf() WC {
return *wc
}
// SetConf is implementation of Configurator interface.
func (wc *WC) SetConf(conf WC) {
*wc = conf.Init()
}
func initWC(wcc ...WC) WC {
var wc WC
for _, nwc := range wcc {
wc = nwc
}
return wc.Init()
}

19
vendor/github.com/vbauerster/mpb/v7/decor/doc.go generated vendored Normal file
View File

@ -0,0 +1,19 @@
// Package decor provides common decorators for "github.com/vbauerster/mpb/v7" module.
//
// Some decorators returned by this package might have a closure state. It is ok to use
// decorators concurrently, unless you share the same decorator among multiple
// *mpb.Bar instances. To avoid data races, create new decorator per *mpb.Bar instance.
//
// Don't:
//
// p := mpb.New()
// name := decor.Name("bar")
// p.AddBar(100, mpb.AppendDecorators(name))
// p.AddBar(100, mpb.AppendDecorators(name))
//
// Do:
//
// p := mpb.New()
// p.AddBar(100, mpb.AppendDecorators(decor.Name("bar1")))
// p.AddBar(100, mpb.AppendDecorators(decor.Name("bar2")))
package decor

35
vendor/github.com/vbauerster/mpb/v7/decor/elapsed.go generated vendored Normal file
View File

@ -0,0 +1,35 @@
package decor
import (
"time"
)
// Elapsed decorator. It's wrapper of NewElapsed.
//
// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
//
// `wcc` optional WC config
//
func Elapsed(style TimeStyle, wcc ...WC) Decorator {
return NewElapsed(style, time.Now(), wcc...)
}
// NewElapsed returns elapsed time decorator.
//
// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
//
// `startTime` start time
//
// `wcc` optional WC config
//
func NewElapsed(style TimeStyle, startTime time.Time, wcc ...WC) Decorator {
var msg string
producer := chooseTimeProducer(style)
fn := func(s Statistics) string {
if !s.Completed {
msg = producer(time.Since(startTime))
}
return msg
}
return Any(fn, wcc...)
}

203
vendor/github.com/vbauerster/mpb/v7/decor/eta.go generated vendored Normal file
View File

@ -0,0 +1,203 @@
package decor
import (
"fmt"
"math"
"time"
"github.com/VividCortex/ewma"
)
// TimeNormalizer interface. Implementors could be passed into
// MovingAverageETA, in order to affect i.e. normalize its output.
type TimeNormalizer interface {
Normalize(time.Duration) time.Duration
}
// TimeNormalizerFunc is function type adapter to convert function
// into TimeNormalizer.
type TimeNormalizerFunc func(time.Duration) time.Duration
func (f TimeNormalizerFunc) Normalize(src time.Duration) time.Duration {
return f(src)
}
// EwmaETA exponential-weighted-moving-average based ETA decorator.
// For this decorator to work correctly you have to measure each
// iteration's duration and pass it to the
// *Bar.DecoratorEwmaUpdate(time.Duration) method after each increment.
func EwmaETA(style TimeStyle, age float64, wcc ...WC) Decorator {
var average ewma.MovingAverage
if age == 0 {
average = ewma.NewMovingAverage()
} else {
average = ewma.NewMovingAverage(age)
}
return MovingAverageETA(style, NewThreadSafeMovingAverage(average), nil, wcc...)
}
// MovingAverageETA decorator relies on MovingAverage implementation to calculate its average.
//
// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
//
// `average` implementation of MovingAverage interface
//
// `normalizer` available implementations are [FixedIntervalTimeNormalizer|MaxTolerateTimeNormalizer]
//
// `wcc` optional WC config
//
func MovingAverageETA(style TimeStyle, average ewma.MovingAverage, normalizer TimeNormalizer, wcc ...WC) Decorator {
d := &movingAverageETA{
WC: initWC(wcc...),
average: average,
normalizer: normalizer,
producer: chooseTimeProducer(style),
}
return d
}
type movingAverageETA struct {
WC
average ewma.MovingAverage
normalizer TimeNormalizer
producer func(time.Duration) string
}
func (d *movingAverageETA) Decor(s Statistics) string {
v := math.Round(d.average.Value())
remaining := time.Duration((s.Total - s.Current) * int64(v))
if d.normalizer != nil {
remaining = d.normalizer.Normalize(remaining)
}
return d.FormatMsg(d.producer(remaining))
}
func (d *movingAverageETA) EwmaUpdate(n int64, dur time.Duration) {
durPerItem := float64(dur) / float64(n)
if math.IsInf(durPerItem, 0) || math.IsNaN(durPerItem) {
return
}
d.average.Add(durPerItem)
}
// AverageETA decorator. It's wrapper of NewAverageETA.
//
// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
//
// `wcc` optional WC config
//
func AverageETA(style TimeStyle, wcc ...WC) Decorator {
return NewAverageETA(style, time.Now(), nil, wcc...)
}
// NewAverageETA decorator with user provided start time.
//
// `style` one of [ET_STYLE_GO|ET_STYLE_HHMMSS|ET_STYLE_HHMM|ET_STYLE_MMSS]
//
// `startTime` start time
//
// `normalizer` available implementations are [FixedIntervalTimeNormalizer|MaxTolerateTimeNormalizer]
//
// `wcc` optional WC config
//
func NewAverageETA(style TimeStyle, startTime time.Time, normalizer TimeNormalizer, wcc ...WC) Decorator {
d := &averageETA{
WC: initWC(wcc...),
startTime: startTime,
normalizer: normalizer,
producer: chooseTimeProducer(style),
}
return d
}
type averageETA struct {
WC
startTime time.Time
normalizer TimeNormalizer
producer func(time.Duration) string
}
func (d *averageETA) Decor(s Statistics) string {
var remaining time.Duration
if s.Current != 0 {
durPerItem := float64(time.Since(d.startTime)) / float64(s.Current)
durPerItem = math.Round(durPerItem)
remaining = time.Duration((s.Total - s.Current) * int64(durPerItem))
if d.normalizer != nil {
remaining = d.normalizer.Normalize(remaining)
}
}
return d.FormatMsg(d.producer(remaining))
}
func (d *averageETA) AverageAdjust(startTime time.Time) {
d.startTime = startTime
}
// MaxTolerateTimeNormalizer returns implementation of TimeNormalizer.
func MaxTolerateTimeNormalizer(maxTolerate time.Duration) TimeNormalizer {
var normalized time.Duration
var lastCall time.Time
return TimeNormalizerFunc(func(remaining time.Duration) time.Duration {
if diff := normalized - remaining; diff <= 0 || diff > maxTolerate || remaining < time.Minute {
normalized = remaining
lastCall = time.Now()
return remaining
}
normalized -= time.Since(lastCall)
lastCall = time.Now()
return normalized
})
}
// FixedIntervalTimeNormalizer returns implementation of TimeNormalizer.
func FixedIntervalTimeNormalizer(updInterval int) TimeNormalizer {
var normalized time.Duration
var lastCall time.Time
var count int
return TimeNormalizerFunc(func(remaining time.Duration) time.Duration {
if count == 0 || remaining < time.Minute {
count = updInterval
normalized = remaining
lastCall = time.Now()
return remaining
}
count--
normalized -= time.Since(lastCall)
lastCall = time.Now()
return normalized
})
}
func chooseTimeProducer(style TimeStyle) func(time.Duration) string {
switch style {
case ET_STYLE_HHMMSS:
return func(remaining time.Duration) string {
hours := int64(remaining/time.Hour) % 60
minutes := int64(remaining/time.Minute) % 60
seconds := int64(remaining/time.Second) % 60
return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
}
case ET_STYLE_HHMM:
return func(remaining time.Duration) string {
hours := int64(remaining/time.Hour) % 60
minutes := int64(remaining/time.Minute) % 60
return fmt.Sprintf("%02d:%02d", hours, minutes)
}
case ET_STYLE_MMSS:
return func(remaining time.Duration) string {
hours := int64(remaining/time.Hour) % 60
minutes := int64(remaining/time.Minute) % 60
seconds := int64(remaining/time.Second) % 60
if hours > 0 {
return fmt.Sprintf("%02d:%02d:%02d", hours, minutes, seconds)
}
return fmt.Sprintf("%02d:%02d", minutes, seconds)
}
default:
return func(remaining time.Duration) string {
// strip off nanoseconds
return ((remaining / time.Second) * time.Second).String()
}
}
}

107
vendor/github.com/vbauerster/mpb/v7/decor/merge.go generated vendored Normal file
View File

@ -0,0 +1,107 @@
package decor
import (
"strings"
"github.com/acarl005/stripansi"
"github.com/mattn/go-runewidth"
)
// Merge wraps its decorator argument with intention to sync width
// with several decorators of another bar. Visual example:
//
// +----+--------+---------+--------+
// | B1 | MERGE(D, P1, Pn) |
// +----+--------+---------+--------+
// | B2 | D0 | D1 | Dn |
// +----+--------+---------+--------+
//
func Merge(decorator Decorator, placeholders ...WC) Decorator {
if _, ok := decorator.Sync(); !ok || len(placeholders) == 0 {
return decorator
}
md := &mergeDecorator{
Decorator: decorator,
wc: decorator.GetConf(),
placeHolders: make([]*placeHolderDecorator, len(placeholders)),
}
decorator.SetConf(WC{})
for i, wc := range placeholders {
if (wc.C & DSyncWidth) == 0 {
return decorator
}
md.placeHolders[i] = &placeHolderDecorator{wc.Init()}
}
return md
}
type mergeDecorator struct {
Decorator
wc WC
placeHolders []*placeHolderDecorator
}
func (d *mergeDecorator) GetConf() WC {
return d.wc
}
func (d *mergeDecorator) SetConf(conf WC) {
d.wc = conf.Init()
}
func (d *mergeDecorator) MergeUnwrap() []Decorator {
decorators := make([]Decorator, len(d.placeHolders))
for i, ph := range d.placeHolders {
decorators[i] = ph
}
return decorators
}
func (d *mergeDecorator) Sync() (chan int, bool) {
return d.wc.Sync()
}
func (d *mergeDecorator) Base() Decorator {
return d.Decorator
}
func (d *mergeDecorator) Decor(s Statistics) string {
msg := d.Decorator.Decor(s)
pureWidth := runewidth.StringWidth(msg)
stripWidth := runewidth.StringWidth(stripansi.Strip(msg))
cellCount := stripWidth
if (d.wc.C & DextraSpace) != 0 {
cellCount++
}
total := runewidth.StringWidth(d.placeHolders[0].FormatMsg(""))
pw := (cellCount - total) / len(d.placeHolders)
rem := (cellCount - total) % len(d.placeHolders)
var diff int
for i := 1; i < len(d.placeHolders); i++ {
ph := d.placeHolders[i]
width := pw - diff
if (ph.WC.C & DextraSpace) != 0 {
width--
if width < 0 {
width = 0
}
}
max := runewidth.StringWidth(ph.FormatMsg(strings.Repeat(" ", width)))
total += max
diff = max - pw
}
d.wc.wsync <- pw + rem
max := <-d.wc.wsync
return d.wc.fill(msg, max+total+(pureWidth-stripWidth))
}
type placeHolderDecorator struct {
WC
}
func (d *placeHolderDecorator) Decor(Statistics) string {
return ""
}

View File

@ -0,0 +1,68 @@
package decor
import (
"sort"
"sync"
"github.com/VividCortex/ewma"
)
type threadSafeMovingAverage struct {
ewma.MovingAverage
mu sync.Mutex
}
func (s *threadSafeMovingAverage) Add(value float64) {
s.mu.Lock()
s.MovingAverage.Add(value)
s.mu.Unlock()
}
func (s *threadSafeMovingAverage) Value() float64 {
s.mu.Lock()
defer s.mu.Unlock()
return s.MovingAverage.Value()
}
func (s *threadSafeMovingAverage) Set(value float64) {
s.mu.Lock()
s.MovingAverage.Set(value)
s.mu.Unlock()
}
// NewThreadSafeMovingAverage converts provided ewma.MovingAverage
// into thread safe ewma.MovingAverage.
func NewThreadSafeMovingAverage(average ewma.MovingAverage) ewma.MovingAverage {
if tsma, ok := average.(*threadSafeMovingAverage); ok {
return tsma
}
return &threadSafeMovingAverage{MovingAverage: average}
}
type medianWindow [3]float64
func (s *medianWindow) Len() int { return len(s) }
func (s *medianWindow) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s *medianWindow) Less(i, j int) bool { return s[i] < s[j] }
func (s *medianWindow) Add(value float64) {
s[0], s[1] = s[1], s[2]
s[2] = value
}
func (s *medianWindow) Value() float64 {
tmp := *s
sort.Sort(&tmp)
return tmp[1]
}
func (s *medianWindow) Set(value float64) {
for i := 0; i < len(s); i++ {
s[i] = value
}
}
// NewMedian is fixed last 3 samples median MovingAverage.
func NewMedian() ewma.MovingAverage {
return NewThreadSafeMovingAverage(new(medianWindow))
}

12
vendor/github.com/vbauerster/mpb/v7/decor/name.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
package decor
// Name decorator displays text that is set once and can't be changed
// during decorator's lifetime.
//
// `str` string to display
//
// `wcc` optional WC config
//
func Name(str string, wcc ...WC) Decorator {
return Any(func(Statistics) string { return str }, wcc...)
}

View File

@ -0,0 +1,37 @@
package decor
// OnComplete returns decorator, which wraps provided decorator, with
// sole purpose to display provided message on complete event.
//
// `decorator` Decorator to wrap
//
// `message` message to display on complete event
//
func OnComplete(decorator Decorator, message string) Decorator {
d := &onCompleteWrapper{
Decorator: decorator,
msg: message,
}
if md, ok := decorator.(*mergeDecorator); ok {
d.Decorator, md.Decorator = md.Decorator, d
return md
}
return d
}
type onCompleteWrapper struct {
Decorator
msg string
}
func (d *onCompleteWrapper) Decor(s Statistics) string {
if s.Completed {
wc := d.GetConf()
return wc.FormatMsg(d.msg)
}
return d.Decorator.Decor(s)
}
func (d *onCompleteWrapper) Base() Decorator {
return d.Decorator
}

View File

@ -0,0 +1,58 @@
package decor
import (
"fmt"
"io"
"strconv"
"github.com/vbauerster/mpb/v7/internal"
)
type percentageType float64
func (s percentageType) Format(st fmt.State, verb rune) {
var prec int
switch verb {
case 'd':
case 's':
prec = -1
default:
if p, ok := st.Precision(); ok {
prec = p
} else {
prec = 6
}
}
io.WriteString(st, strconv.FormatFloat(float64(s), 'f', prec, 64))
if st.Flag(' ') {
io.WriteString(st, " ")
}
io.WriteString(st, "%")
}
// Percentage returns percentage decorator. It's a wrapper of NewPercentage.
func Percentage(wcc ...WC) Decorator {
return NewPercentage("% d", wcc...)
}
// NewPercentage percentage decorator with custom format string.
//
// format examples:
//
// format="%.1f" output: "1.0%"
// format="% .1f" output: "1.0 %"
// format="%d" output: "1%"
// format="% d" output: "1 %"
//
func NewPercentage(format string, wcc ...WC) Decorator {
if format == "" {
format = "% d"
}
f := func(s Statistics) string {
p := internal.Percentage(s.Total, s.Current, 100)
return fmt.Sprintf(format, percentageType(p))
}
return Any(f, wcc...)
}

109
vendor/github.com/vbauerster/mpb/v7/decor/size_type.go generated vendored Normal file
View File

@ -0,0 +1,109 @@
package decor
import (
"fmt"
"io"
"math"
"strconv"
)
//go:generate stringer -type=SizeB1024 -trimprefix=_i
//go:generate stringer -type=SizeB1000 -trimprefix=_
const (
_ib SizeB1024 = iota + 1
_iKiB SizeB1024 = 1 << (iota * 10)
_iMiB
_iGiB
_iTiB
)
// SizeB1024 named type, which implements fmt.Formatter interface. It
// adjusts its value according to byte size multiple by 1024 and appends
// appropriate size marker (KiB, MiB, GiB, TiB).
type SizeB1024 int64
func (self SizeB1024) Format(st fmt.State, verb rune) {
var prec int
switch verb {
case 'd':
case 's':
prec = -1
default:
if p, ok := st.Precision(); ok {
prec = p
} else {
prec = 6
}
}
var unit SizeB1024
switch {
case self < _iKiB:
unit = _ib
case self < _iMiB:
unit = _iKiB
case self < _iGiB:
unit = _iMiB
case self < _iTiB:
unit = _iGiB
case self <= math.MaxInt64:
unit = _iTiB
}
io.WriteString(st, strconv.FormatFloat(float64(self)/float64(unit), 'f', prec, 64))
if st.Flag(' ') {
io.WriteString(st, " ")
}
io.WriteString(st, unit.String())
}
const (
_b SizeB1000 = 1
_KB SizeB1000 = _b * 1000
_MB SizeB1000 = _KB * 1000
_GB SizeB1000 = _MB * 1000
_TB SizeB1000 = _GB * 1000
)
// SizeB1000 named type, which implements fmt.Formatter interface. It
// adjusts its value according to byte size multiple by 1000 and appends
// appropriate size marker (KB, MB, GB, TB).
type SizeB1000 int64
func (self SizeB1000) Format(st fmt.State, verb rune) {
var prec int
switch verb {
case 'd':
case 's':
prec = -1
default:
if p, ok := st.Precision(); ok {
prec = p
} else {
prec = 6
}
}
var unit SizeB1000
switch {
case self < _KB:
unit = _b
case self < _MB:
unit = _KB
case self < _GB:
unit = _MB
case self < _TB:
unit = _GB
case self <= math.MaxInt64:
unit = _TB
}
io.WriteString(st, strconv.FormatFloat(float64(self)/float64(unit), 'f', prec, 64))
if st.Flag(' ') {
io.WriteString(st, " ")
}
io.WriteString(st, unit.String())
}

View File

@ -0,0 +1,41 @@
// Code generated by "stringer -type=SizeB1000 -trimprefix=_"; DO NOT EDIT.
package decor
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[_b-1]
_ = x[_KB-1000]
_ = x[_MB-1000000]
_ = x[_GB-1000000000]
_ = x[_TB-1000000000000]
}
const (
_SizeB1000_name_0 = "b"
_SizeB1000_name_1 = "KB"
_SizeB1000_name_2 = "MB"
_SizeB1000_name_3 = "GB"
_SizeB1000_name_4 = "TB"
)
func (i SizeB1000) String() string {
switch {
case i == 1:
return _SizeB1000_name_0
case i == 1000:
return _SizeB1000_name_1
case i == 1000000:
return _SizeB1000_name_2
case i == 1000000000:
return _SizeB1000_name_3
case i == 1000000000000:
return _SizeB1000_name_4
default:
return "SizeB1000(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

View File

@ -0,0 +1,41 @@
// Code generated by "stringer -type=SizeB1024 -trimprefix=_i"; DO NOT EDIT.
package decor
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[_ib-1]
_ = x[_iKiB-1024]
_ = x[_iMiB-1048576]
_ = x[_iGiB-1073741824]
_ = x[_iTiB-1099511627776]
}
const (
_SizeB1024_name_0 = "b"
_SizeB1024_name_1 = "KiB"
_SizeB1024_name_2 = "MiB"
_SizeB1024_name_3 = "GiB"
_SizeB1024_name_4 = "TiB"
)
func (i SizeB1024) String() string {
switch {
case i == 1:
return _SizeB1024_name_0
case i == 1024:
return _SizeB1024_name_1
case i == 1048576:
return _SizeB1024_name_2
case i == 1073741824:
return _SizeB1024_name_3
case i == 1099511627776:
return _SizeB1024_name_4
default:
return "SizeB1024(" + strconv.FormatInt(int64(i), 10) + ")"
}
}

171
vendor/github.com/vbauerster/mpb/v7/decor/speed.go generated vendored Normal file
View File

@ -0,0 +1,171 @@
package decor
import (
"fmt"
"io"
"math"
"time"
"github.com/VividCortex/ewma"
)
// FmtAsSpeed adds "/s" to the end of the input formatter. To be
// used with SizeB1000 or SizeB1024 types, for example:
//
// fmt.Printf("%.1f", FmtAsSpeed(SizeB1024(2048)))
//
func FmtAsSpeed(input fmt.Formatter) fmt.Formatter {
return &speedFormatter{input}
}
type speedFormatter struct {
fmt.Formatter
}
func (self *speedFormatter) Format(st fmt.State, verb rune) {
self.Formatter.Format(st, verb)
io.WriteString(st, "/s")
}
// EwmaSpeed exponential-weighted-moving-average based speed decorator.
// For this decorator to work correctly you have to measure each
// iteration's duration and pass it to the
// *Bar.DecoratorEwmaUpdate(time.Duration) method after each increment.
func EwmaSpeed(unit int, format string, age float64, wcc ...WC) Decorator {
var average ewma.MovingAverage
if age == 0 {
average = ewma.NewMovingAverage()
} else {
average = ewma.NewMovingAverage(age)
}
return MovingAverageSpeed(unit, format, NewThreadSafeMovingAverage(average), wcc...)
}
// MovingAverageSpeed decorator relies on MovingAverage implementation
// to calculate its average.
//
// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
// `format` printf compatible verb for value, like "%f" or "%d"
//
// `average` MovingAverage implementation
//
// `wcc` optional WC config
//
// format examples:
//
// unit=UnitKiB, format="%.1f" output: "1.0MiB/s"
// unit=UnitKiB, format="% .1f" output: "1.0 MiB/s"
// unit=UnitKB, format="%.1f" output: "1.0MB/s"
// unit=UnitKB, format="% .1f" output: "1.0 MB/s"
//
func MovingAverageSpeed(unit int, format string, average ewma.MovingAverage, wcc ...WC) Decorator {
if format == "" {
format = "%.0f"
}
d := &movingAverageSpeed{
WC: initWC(wcc...),
average: average,
producer: chooseSpeedProducer(unit, format),
}
return d
}
type movingAverageSpeed struct {
WC
producer func(float64) string
average ewma.MovingAverage
msg string
}
func (d *movingAverageSpeed) Decor(s Statistics) string {
if !s.Completed {
var speed float64
if v := d.average.Value(); v > 0 {
speed = 1 / v
}
d.msg = d.producer(speed * 1e9)
}
return d.FormatMsg(d.msg)
}
func (d *movingAverageSpeed) EwmaUpdate(n int64, dur time.Duration) {
durPerByte := float64(dur) / float64(n)
if math.IsInf(durPerByte, 0) || math.IsNaN(durPerByte) {
return
}
d.average.Add(durPerByte)
}
// AverageSpeed decorator with dynamic unit measure adjustment. It's
// a wrapper of NewAverageSpeed.
func AverageSpeed(unit int, format string, wcc ...WC) Decorator {
return NewAverageSpeed(unit, format, time.Now(), wcc...)
}
// NewAverageSpeed decorator with dynamic unit measure adjustment and
// user provided start time.
//
// `unit` one of [0|UnitKiB|UnitKB] zero for no unit
//
// `format` printf compatible verb for value, like "%f" or "%d"
//
// `startTime` start time
//
// `wcc` optional WC config
//
// format examples:
//
// unit=UnitKiB, format="%.1f" output: "1.0MiB/s"
// unit=UnitKiB, format="% .1f" output: "1.0 MiB/s"
// unit=UnitKB, format="%.1f" output: "1.0MB/s"
// unit=UnitKB, format="% .1f" output: "1.0 MB/s"
//
func NewAverageSpeed(unit int, format string, startTime time.Time, wcc ...WC) Decorator {
if format == "" {
format = "%.0f"
}
d := &averageSpeed{
WC: initWC(wcc...),
startTime: startTime,
producer: chooseSpeedProducer(unit, format),
}
return d
}
type averageSpeed struct {
WC
startTime time.Time
producer func(float64) string
msg string
}
func (d *averageSpeed) Decor(s Statistics) string {
if !s.Completed {
speed := float64(s.Current) / float64(time.Since(d.startTime))
d.msg = d.producer(speed * 1e9)
}
return d.FormatMsg(d.msg)
}
func (d *averageSpeed) AverageAdjust(startTime time.Time) {
d.startTime = startTime
}
func chooseSpeedProducer(unit int, format string) func(float64) string {
switch unit {
case UnitKiB:
return func(speed float64) string {
return fmt.Sprintf(format, FmtAsSpeed(SizeB1024(math.Round(speed))))
}
case UnitKB:
return func(speed float64) string {
return fmt.Sprintf(format, FmtAsSpeed(SizeB1000(math.Round(speed))))
}
default:
return func(speed float64) string {
return fmt.Sprintf(format, speed)
}
}
}

21
vendor/github.com/vbauerster/mpb/v7/decor/spinner.go generated vendored Normal file
View File

@ -0,0 +1,21 @@
package decor
var defaultSpinnerStyle = []string{"⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"}
// Spinner returns spinner decorator.
//
// `frames` spinner frames, if nil or len==0, default is used
//
// `wcc` optional WC config
func Spinner(frames []string, wcc ...WC) Decorator {
if len(frames) == 0 {
frames = defaultSpinnerStyle
}
var count uint
f := func(s Statistics) string {
frame := frames[count%uint(len(frames))]
count++
return frame
}
return Any(f, wcc...)
}

2
vendor/github.com/vbauerster/mpb/v7/doc.go generated vendored Normal file
View File

@ -0,0 +1,2 @@
// Package mpb is a library for rendering progress bars in terminal applications.
package mpb

10
vendor/github.com/vbauerster/mpb/v7/go.mod generated vendored Normal file
View File

@ -0,0 +1,10 @@
module github.com/vbauerster/mpb/v7
require (
github.com/VividCortex/ewma v1.2.0
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
github.com/mattn/go-runewidth v0.0.13
golang.org/x/sys v0.0.0-20210603125802-9665404d3644
)
go 1.14

10
vendor/github.com/vbauerster/mpb/v7/go.sum generated vendored Normal file
View File

@ -0,0 +1,10 @@
github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1ow=
github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644 h1:CA1DEQ4NdKphKeL70tvsWNdT5oFh1lOjihRcEDROi0I=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@ -0,0 +1,19 @@
package internal
import "math"
// Percentage is a helper function, to calculate percentage.
func Percentage(total, current int64, width int) float64 {
if total <= 0 {
return 0
}
if current >= total {
return float64(width)
}
return float64(int64(width)*current) / float64(total)
}
// PercentageRound same as Percentage but with math.Round.
func PercentageRound(total, current int64, width int) float64 {
return math.Round(Percentage(total, current, width))
}

View File

@ -0,0 +1,6 @@
package internal
// Predicate helper for internal use.
func Predicate(pick bool) func() bool {
return func() bool { return pick }
}

10
vendor/github.com/vbauerster/mpb/v7/internal/width.go generated vendored Normal file
View File

@ -0,0 +1,10 @@
package internal
// CheckRequestedWidth checks that requested width doesn't overflow
// available width
func CheckRequestedWidth(requested, available int) int {
if requested < 1 || requested >= available {
return available
}
return requested
}

32
vendor/github.com/vbauerster/mpb/v7/priority_queue.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
package mpb
// A priorityQueue implements heap.Interface
type priorityQueue []*Bar
func (pq priorityQueue) Len() int { return len(pq) }
func (pq priorityQueue) Less(i, j int) bool {
return pq[i].priority < pq[j].priority
}
func (pq priorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
pq[i].index = i
pq[j].index = j
}
func (pq *priorityQueue) Push(x interface{}) {
s := *pq
bar := x.(*Bar)
bar.index = len(s)
s = append(s, bar)
*pq = s
}
func (pq *priorityQueue) Pop() interface{} {
s := *pq
*pq = s[0 : len(s)-1]
bar := s[len(s)-1]
bar.index = -1 // for safety
return bar
}

412
vendor/github.com/vbauerster/mpb/v7/progress.go generated vendored Normal file
View File

@ -0,0 +1,412 @@
package mpb
import (
"bytes"
"container/heap"
"context"
"fmt"
"io"
"io/ioutil"
"log"
"math"
"os"
"sync"
"time"
"github.com/vbauerster/mpb/v7/cwriter"
"github.com/vbauerster/mpb/v7/decor"
)
const (
// default RefreshRate
prr = 120 * time.Millisecond
)
// Progress represents a container that renders one or more progress
// bars.
type Progress struct {
ctx context.Context
uwg *sync.WaitGroup
cwg *sync.WaitGroup
bwg *sync.WaitGroup
operateState chan func(*pState)
done chan struct{}
refreshCh chan time.Time
once sync.Once
dlogger *log.Logger
}
// pState holds bars in its priorityQueue. It gets passed to
// *Progress.serve(...) monitor goroutine.
type pState struct {
bHeap priorityQueue
heapUpdated bool
pMatrix map[int][]chan int
aMatrix map[int][]chan int
barShutdownQueue []*Bar
// following are provided/overrided by user
idCount int
reqWidth int
popCompleted bool
outputDiscarded bool
rr time.Duration
uwg *sync.WaitGroup
externalRefresh <-chan interface{}
renderDelay <-chan struct{}
shutdownNotifier chan struct{}
parkedBars map[*Bar]*Bar
output io.Writer
debugOut io.Writer
}
// New creates new Progress container instance. It's not possible to
// reuse instance after *Progress.Wait() method has been called.
func New(options ...ContainerOption) *Progress {
return NewWithContext(context.Background(), options...)
}
// NewWithContext creates new Progress container instance with provided
// context. It's not possible to reuse instance after *Progress.Wait()
// method has been called.
func NewWithContext(ctx context.Context, options ...ContainerOption) *Progress {
s := &pState{
bHeap: priorityQueue{},
rr: prr,
parkedBars: make(map[*Bar]*Bar),
output: os.Stdout,
debugOut: ioutil.Discard,
}
for _, opt := range options {
if opt != nil {
opt(s)
}
}
p := &Progress{
ctx: ctx,
uwg: s.uwg,
cwg: new(sync.WaitGroup),
bwg: new(sync.WaitGroup),
operateState: make(chan func(*pState)),
done: make(chan struct{}),
dlogger: log.New(s.debugOut, "[mpb] ", log.Lshortfile),
}
p.cwg.Add(1)
go p.serve(s, cwriter.New(s.output))
return p
}
// AddBar creates a bar with default bar filler. Different filler can
// be chosen and applied via `*Progress.Add(...) *Bar` method.
func (p *Progress) AddBar(total int64, options ...BarOption) *Bar {
return p.Add(total, NewBarFiller(BarStyle()), options...)
}
// AddSpinner creates a bar with default spinner filler. Different
// filler can be chosen and applied via `*Progress.Add(...) *Bar`
// method.
func (p *Progress) AddSpinner(total int64, options ...BarOption) *Bar {
return p.Add(total, NewBarFiller(SpinnerStyle()), options...)
}
// Add creates a bar which renders itself by provided filler.
// If `total <= 0` trigger complete event is disabled until reset with *bar.SetTotal(int64, bool).
// Panics if *Progress instance is done, i.e. called after *Progress.Wait().
func (p *Progress) Add(total int64, filler BarFiller, options ...BarOption) *Bar {
if filler == nil {
filler = BarFillerFunc(func(io.Writer, int, decor.Statistics) {})
}
p.bwg.Add(1)
result := make(chan *Bar)
select {
case p.operateState <- func(ps *pState) {
bs := ps.makeBarState(total, filler, options...)
bar := newBar(p, bs)
if bs.runningBar != nil {
bs.runningBar.noPop = true
ps.parkedBars[bs.runningBar] = bar
} else {
heap.Push(&ps.bHeap, bar)
ps.heapUpdated = true
}
ps.idCount++
result <- bar
}:
bar := <-result
bar.subscribeDecorators()
return bar
case <-p.done:
p.bwg.Done()
panic(fmt.Sprintf("%T instance can't be reused after it's done!", p))
}
}
func (p *Progress) dropBar(b *Bar) {
select {
case p.operateState <- func(s *pState) {
if b.index < 0 {
return
}
heap.Remove(&s.bHeap, b.index)
s.heapUpdated = true
}:
case <-p.done:
}
}
func (p *Progress) setBarPriority(b *Bar, priority int) {
select {
case p.operateState <- func(s *pState) {
if b.index < 0 {
return
}
b.priority = priority
heap.Fix(&s.bHeap, b.index)
}:
case <-p.done:
}
}
// UpdateBarPriority same as *Bar.SetPriority(int).
func (p *Progress) UpdateBarPriority(b *Bar, priority int) {
p.setBarPriority(b, priority)
}
// BarCount returns bars count.
func (p *Progress) BarCount() int {
result := make(chan int, 1)
select {
case p.operateState <- func(s *pState) { result <- s.bHeap.Len() }:
return <-result
case <-p.done:
return 0
}
}
// Wait waits for all bars to complete and finally shutdowns container.
// After this method has been called, there is no way to reuse *Progress
// instance.
func (p *Progress) Wait() {
if p.uwg != nil {
// wait for user wg
p.uwg.Wait()
}
// wait for bars to quit, if any
p.bwg.Wait()
p.once.Do(p.shutdown)
// wait for container to quit
p.cwg.Wait()
}
func (p *Progress) shutdown() {
close(p.done)
}
func (p *Progress) serve(s *pState, cw *cwriter.Writer) {
defer p.cwg.Done()
p.refreshCh = s.newTicker(p.done)
for {
select {
case op := <-p.operateState:
op(s)
case <-p.refreshCh:
if err := s.render(cw); err != nil {
p.dlogger.Println(err)
}
case <-s.shutdownNotifier:
if s.heapUpdated {
if err := s.render(cw); err != nil {
p.dlogger.Println(err)
}
}
return
}
}
}
func (s *pState) newTicker(done <-chan struct{}) chan time.Time {
ch := make(chan time.Time)
if s.shutdownNotifier == nil {
s.shutdownNotifier = make(chan struct{})
}
go func() {
if s.renderDelay != nil {
<-s.renderDelay
}
var internalRefresh <-chan time.Time
if !s.outputDiscarded {
if s.externalRefresh == nil {
ticker := time.NewTicker(s.rr)
defer ticker.Stop()
internalRefresh = ticker.C
}
} else {
s.externalRefresh = nil
}
for {
select {
case t := <-internalRefresh:
ch <- t
case x := <-s.externalRefresh:
if t, ok := x.(time.Time); ok {
ch <- t
} else {
ch <- time.Now()
}
case <-done:
close(s.shutdownNotifier)
return
}
}
}()
return ch
}
func (s *pState) render(cw *cwriter.Writer) error {
if s.heapUpdated {
s.updateSyncMatrix()
s.heapUpdated = false
}
syncWidth(s.pMatrix)
syncWidth(s.aMatrix)
tw, err := cw.GetWidth()
if err != nil {
tw = s.reqWidth
}
for i := 0; i < s.bHeap.Len(); i++ {
bar := s.bHeap[i]
go bar.render(tw)
}
return s.flush(cw)
}
func (s *pState) flush(cw *cwriter.Writer) error {
var lineCount int
bm := make(map[*Bar]struct{}, s.bHeap.Len())
for s.bHeap.Len() > 0 {
b := heap.Pop(&s.bHeap).(*Bar)
cw.ReadFrom(<-b.frameCh)
if b.toShutdown {
if b.recoveredPanic != nil {
s.barShutdownQueue = append(s.barShutdownQueue, b)
b.toShutdown = false
} else {
// shutdown at next flush
// this ensures no bar ends up with less than 100% rendered
defer func() {
s.barShutdownQueue = append(s.barShutdownQueue, b)
}()
}
}
lineCount += b.extendedLines + 1
bm[b] = struct{}{}
}
for _, b := range s.barShutdownQueue {
if parkedBar := s.parkedBars[b]; parkedBar != nil {
parkedBar.priority = b.priority
heap.Push(&s.bHeap, parkedBar)
delete(s.parkedBars, b)
b.toDrop = true
}
if s.popCompleted && !b.noPop {
lineCount -= b.extendedLines + 1
b.toDrop = true
}
if b.toDrop {
delete(bm, b)
s.heapUpdated = true
}
b.cancel()
}
s.barShutdownQueue = s.barShutdownQueue[0:0]
for b := range bm {
heap.Push(&s.bHeap, b)
}
return cw.Flush(lineCount)
}
func (s *pState) updateSyncMatrix() {
s.pMatrix = make(map[int][]chan int)
s.aMatrix = make(map[int][]chan int)
for i := 0; i < s.bHeap.Len(); i++ {
bar := s.bHeap[i]
table := bar.wSyncTable()
pRow, aRow := table[0], table[1]
for i, ch := range pRow {
s.pMatrix[i] = append(s.pMatrix[i], ch)
}
for i, ch := range aRow {
s.aMatrix[i] = append(s.aMatrix[i], ch)
}
}
}
func (s *pState) makeBarState(total int64, filler BarFiller, options ...BarOption) *bState {
bs := &bState{
id: s.idCount,
priority: s.idCount,
reqWidth: s.reqWidth,
total: total,
filler: filler,
extender: func(r io.Reader, _ int, _ decor.Statistics) (io.Reader, int) { return r, 0 },
debugOut: s.debugOut,
}
if total > 0 {
bs.triggerComplete = true
}
for _, opt := range options {
if opt != nil {
opt(bs)
}
}
if bs.middleware != nil {
bs.filler = bs.middleware(filler)
bs.middleware = nil
}
if s.popCompleted && !bs.noPop {
bs.priority = -(math.MaxInt32 - s.idCount)
}
bs.bufP = bytes.NewBuffer(make([]byte, 0, 128))
bs.bufB = bytes.NewBuffer(make([]byte, 0, 256))
bs.bufA = bytes.NewBuffer(make([]byte, 0, 128))
return bs
}
func syncWidth(matrix map[int][]chan int) {
for _, column := range matrix {
go maxWidthDistributor(column)
}
}
var maxWidthDistributor = func(column []chan int) {
var maxWidth int
for _, ch := range column {
if w := <-ch; w > maxWidth {
maxWidth = w
}
}
for _, ch := range column {
ch <- maxWidth
}
}

90
vendor/github.com/vbauerster/mpb/v7/proxyreader.go generated vendored Normal file
View File

@ -0,0 +1,90 @@
package mpb
import (
"io"
"io/ioutil"
"time"
)
type proxyReader struct {
io.ReadCloser
bar *Bar
}
func (x *proxyReader) Read(p []byte) (int, error) {
n, err := x.ReadCloser.Read(p)
x.bar.IncrBy(n)
if err == io.EOF {
go x.bar.SetTotal(0, true)
}
return n, err
}
type proxyWriterTo struct {
io.ReadCloser // *proxyReader
wt io.WriterTo
bar *Bar
}
func (x *proxyWriterTo) WriteTo(w io.Writer) (int64, error) {
n, err := x.wt.WriteTo(w)
x.bar.IncrInt64(n)
if err == io.EOF {
go x.bar.SetTotal(0, true)
}
return n, err
}
type ewmaProxyReader struct {
io.ReadCloser // *proxyReader
bar *Bar
iT time.Time
}
func (x *ewmaProxyReader) Read(p []byte) (int, error) {
n, err := x.ReadCloser.Read(p)
if n > 0 {
x.bar.DecoratorEwmaUpdate(time.Since(x.iT))
x.iT = time.Now()
}
return n, err
}
type ewmaProxyWriterTo struct {
io.ReadCloser // *ewmaProxyReader
wt io.WriterTo // *proxyWriterTo
bar *Bar
iT time.Time
}
func (x *ewmaProxyWriterTo) WriteTo(w io.Writer) (int64, error) {
n, err := x.wt.WriteTo(w)
if n > 0 {
x.bar.DecoratorEwmaUpdate(time.Since(x.iT))
x.iT = time.Now()
}
return n, err
}
func newProxyReader(r io.Reader, bar *Bar) io.ReadCloser {
rc := toReadCloser(r)
rc = &proxyReader{rc, bar}
if wt, isWriterTo := r.(io.WriterTo); bar.hasEwmaDecorators {
now := time.Now()
rc = &ewmaProxyReader{rc, bar, now}
if isWriterTo {
rc = &ewmaProxyWriterTo{rc, wt, bar, now}
}
} else if isWriterTo {
rc = &proxyWriterTo{rc, wt, bar}
}
return rc
}
func toReadCloser(r io.Reader) io.ReadCloser {
if rc, ok := r.(io.ReadCloser); ok {
return rc
}
return ioutil.NopCloser(r)
}

View File

@ -76,7 +76,7 @@ arguments can be passed to the kernel. The third is for low-level use by the
ForkExec wrapper. Unlike the first two, it does not call into the scheduler to
let it know that a system call is running.
When porting Go to an new architecture/OS, this file must be implemented for
When porting Go to a new architecture/OS, this file must be implemented for
each GOOS/GOARCH pair.
### mksysnum
@ -107,7 +107,7 @@ prototype can be exported (capitalized) or not.
Adding a new syscall often just requires adding a new `//sys` function prototype
with the desired arguments and a capitalized name so it is exported. However, if
you want the interface to the syscall to be different, often one will make an
unexported `//sys` prototype, an then write a custom wrapper in
unexported `//sys` prototype, and then write a custom wrapper in
`syscall_${GOOS}.go`.
### types files
@ -137,7 +137,7 @@ some `#if/#elif` macros in your include statements.
This script is used to generate the system's various constants. This doesn't
just include the error numbers and error strings, but also the signal numbers
an a wide variety of miscellaneous constants. The constants come from the list
and a wide variety of miscellaneous constants. The constants come from the list
of include files in the `includes_${uname}` variable. A regex then picks out
the desired `#define` statements, and generates the corresponding Go constants.
The error numbers and strings are generated from `#include <errno.h>`, and the

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (darwin || freebsd || netbsd || openbsd) && gc
// +build darwin freebsd netbsd openbsd
//go:build (freebsd || netbsd || openbsd) && gc
// +build freebsd netbsd openbsd
// +build gc
#include "textflag.h"

View File

@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (darwin || freebsd || netbsd || openbsd) && gc
// +build darwin freebsd netbsd openbsd
//go:build (freebsd || netbsd || openbsd) && gc
// +build freebsd netbsd openbsd
// +build gc
#include "textflag.h"

View File

@ -239,6 +239,7 @@ struct ltchars {
#include <linux/netfilter/nfnetlink.h>
#include <linux/netlink.h>
#include <linux/net_namespace.h>
#include <linux/nfc.h>
#include <linux/nsfs.h>
#include <linux/perf_event.h>
#include <linux/pps.h>
@ -258,6 +259,7 @@ struct ltchars {
#include <linux/watchdog.h>
#include <mtd/ubi-user.h>
#include <mtd/mtd-user.h>
#include <net/route.h>
#if defined(__sparc__)
@ -501,6 +503,9 @@ ccflags="$@"
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
$2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL)_/ ||
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
$2 ~ /^RAW_PAYLOAD_/ ||
$2 ~ /^TP_STATUS_/ ||
$2 ~ /^FALLOC_/ ||
$2 ~ /^ICMPV?6?_(FILTER|SEC)/ ||
@ -593,6 +598,9 @@ ccflags="$@"
$2 == "HID_MAX_DESCRIPTOR_SIZE" ||
$2 ~ /^_?HIDIOC/ ||
$2 ~ /^BUS_(USB|HIL|BLUETOOTH|VIRTUAL)$/ ||
$2 ~ /^MTD/ ||
$2 ~ /^OTP/ ||
$2 ~ /^MEM/ ||
$2 ~ /^BLK[A-Z]*(GET$|SET$|BUF$|PART$|SIZE)/ {printf("\t%s = C.%s\n", $2, $2)}
$2 ~ /^__WCOREFLAG$/ {next}
$2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)}

View File

@ -904,6 +904,46 @@ func (sa *SockaddrIUCV) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrIUCV, nil
}
type SockaddrNFC struct {
DeviceIdx uint32
TargetIdx uint32
NFCProtocol uint32
raw RawSockaddrNFC
}
func (sa *SockaddrNFC) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Sa_family = AF_NFC
sa.raw.Dev_idx = sa.DeviceIdx
sa.raw.Target_idx = sa.TargetIdx
sa.raw.Nfc_protocol = sa.NFCProtocol
return unsafe.Pointer(&sa.raw), SizeofSockaddrNFC, nil
}
type SockaddrNFCLLCP struct {
DeviceIdx uint32
TargetIdx uint32
NFCProtocol uint32
DestinationSAP uint8
SourceSAP uint8
ServiceName string
raw RawSockaddrNFCLLCP
}
func (sa *SockaddrNFCLLCP) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Sa_family = AF_NFC
sa.raw.Dev_idx = sa.DeviceIdx
sa.raw.Target_idx = sa.TargetIdx
sa.raw.Nfc_protocol = sa.NFCProtocol
sa.raw.Dsap = sa.DestinationSAP
sa.raw.Ssap = sa.SourceSAP
if len(sa.ServiceName) > len(sa.raw.Service_name) {
return nil, 0, EINVAL
}
copy(sa.raw.Service_name[:], sa.ServiceName)
sa.raw.SetServiceNameLen(len(sa.ServiceName))
return unsafe.Pointer(&sa.raw), SizeofSockaddrNFCLLCP, nil
}
var socketProtocol = func(fd int) (int, error) {
return GetsockoptInt(fd, SOL_SOCKET, SO_PROTOCOL)
}
@ -1144,6 +1184,37 @@ func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) {
}
return sa, nil
}
case AF_NFC:
proto, err := socketProtocol(fd)
if err != nil {
return nil, err
}
switch proto {
case NFC_SOCKPROTO_RAW:
pp := (*RawSockaddrNFC)(unsafe.Pointer(rsa))
sa := &SockaddrNFC{
DeviceIdx: pp.Dev_idx,
TargetIdx: pp.Target_idx,
NFCProtocol: pp.Nfc_protocol,
}
return sa, nil
case NFC_SOCKPROTO_LLCP:
pp := (*RawSockaddrNFCLLCP)(unsafe.Pointer(rsa))
if uint64(pp.Service_name_len) > uint64(len(pp.Service_name)) {
return nil, EINVAL
}
sa := &SockaddrNFCLLCP{
DeviceIdx: pp.Dev_idx,
TargetIdx: pp.Target_idx,
NFCProtocol: pp.Nfc_protocol,
DestinationSAP: pp.Dsap,
SourceSAP: pp.Ssap,
ServiceName: string(pp.Service_name[:pp.Service_name_len]),
}
return sa, nil
default:
return nil, EINVAL
}
}
return nil, EAFNOSUPPORT
}

View File

@ -378,6 +378,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint32(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {

View File

@ -172,6 +172,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {

View File

@ -256,6 +256,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint32(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {

View File

@ -207,6 +207,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length)
}
func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}

View File

@ -217,6 +217,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length)
}
func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}

View File

@ -229,6 +229,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint32(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {

View File

@ -215,6 +215,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint32(length)
}
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {

View File

@ -100,6 +100,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length)
}
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {

View File

@ -188,6 +188,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length)
}
func InotifyInit() (fd int, err error) {
return InotifyInit1(0)
}

View File

@ -129,6 +129,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length)
}
// Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct.
// mmap2 also requires arguments to be passed in a struct; it is currently not exposed in <asm/unistd.h>.
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {

View File

@ -116,6 +116,10 @@ func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
func (rsa *RawSockaddrNFCLLCP) SetServiceNameLen(length int) {
rsa.Service_name_len = uint64(length)
}
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {

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