├── .github └── workflows │ ├── build-and-release.yaml │ └── test.yaml ├── .gitignore ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── rustfmt.toml └── src ├── args.rs ├── crates.rs └── main.rs /.github/workflows/build-and-release.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | release: 4 | types: [published] 5 | 6 | name: build-and-release 7 | 8 | jobs: 9 | build-and-release: 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | include: 14 | # x86_64-linux-gnu 15 | - arch-name: x86_64-linux-gnu 16 | os: ubuntu-latest 17 | target: x86_64-unknown-linux-gnu 18 | cross: false 19 | file-ext: 20 | # x86_64-linux-musl 21 | - arch-name: x86_64-linux-musl 22 | os: ubuntu-latest 23 | target: x86_64-unknown-linux-musl 24 | cross: true 25 | file-ext: 26 | # x86_64-windows-msvc 27 | - arch-name: x86_64-windows-msvc 28 | os: windows-latest 29 | target: x86_64-pc-windows-msvc 30 | cross: false 31 | file-ext: .exe 32 | # x86_64-windows-gnu 33 | - arch-name: x86_64-windows-gnu 34 | os: ubuntu-latest 35 | target: x86_64-pc-windows-gnu 36 | cross: true 37 | file-ext: .exe 38 | # x86_64-macos 39 | - arch-name: x86_64-macos 40 | os: macos-latest 41 | target: x86_64-apple-darwin 42 | cross: false 43 | file-ext: 44 | # aarch64-linux-gnu 45 | - arch-name: aarch64-linux-gnu 46 | os: ubuntu-latest 47 | target: aarch64-unknown-linux-gnu 48 | cross: true 49 | file-ext: 50 | # aarch64-linux-musl 51 | - arch-name: aarch64-linux-musl 52 | os: ubuntu-latest 53 | target: aarch64-unknown-linux-musl 54 | cross: true 55 | file-ext: 56 | # aarch64-macos 57 | - arch-name: aarch64-macos 58 | os: macos-latest 59 | target: aarch64-apple-darwin 60 | cross: true 61 | file-ext: 62 | runs-on: ${{ matrix.os }} 63 | 64 | steps: 65 | - name: Checkout repository 66 | uses: actions/checkout@v2 67 | with: 68 | fetch-depth: 0 69 | 70 | - name: Get the latest tag 71 | id: tag 72 | uses: "WyriHaximus/github-action-get-previous-tag@v1" 73 | 74 | - name: Install toolchain 75 | uses: actions-rs/toolchain@v1 76 | with: 77 | toolchain: stable 78 | target: ${{ matrix.target }} 79 | override: true 80 | 81 | - name: Build 82 | uses: actions-rs/cargo@v1 83 | with: 84 | use-cross: ${{ matrix.cross }} 85 | command: build 86 | args: --release --target ${{ matrix.target }} 87 | 88 | - name: Move binaries 89 | run: | 90 | mkdir artifacts/ 91 | mv target/${{ matrix.target }}/release/cargo-info${{ matrix.file-ext }} artifacts/cargo-info-${{ steps.tag.outputs.tag }}-${{ matrix.arch-name }}${{ matrix.file-ext }} 92 | 93 | - name: Calculate SHA256 94 | run: | 95 | cd artifacts/ 96 | openssl dgst -sha256 -r cargo-info-${{ steps.tag.outputs.tag }}-${{ matrix.arch-name }}${{ matrix.file-ext }} > cargo-info-${{ steps.tag.outputs.tag }}-${{ matrix.arch-name }}${{ matrix.file-ext }}.sha256sum 97 | 98 | - name: Release binaries 99 | uses: ncipollo/release-action@v1 100 | with: 101 | artifacts: "artifacts/*" 102 | tag: ${{ steps.tag.outputs.tag }} 103 | name: ${{ steps.tag.outputs.tag }} 104 | allowUpdates: true 105 | token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} 106 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | 3 | name: CI 4 | 5 | jobs: 6 | lint: 7 | name: Lint 8 | runs-on: ubuntu-latest 9 | env: 10 | RUSTFLAGS: -D warnings 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Install Rust 14 | uses: actions-rs/toolchain@v1 15 | with: 16 | toolchain: nightly 17 | override: true 18 | components: rustfmt, clippy 19 | - name: Run Rustfmt 20 | uses: actions-rs/cargo@v1 21 | with: 22 | command: fmt 23 | args: -- --check 24 | - name: Run Clippy 25 | uses: actions-rs/cargo@v1 26 | with: 27 | command: clippy 28 | build_and_test: 29 | name: Test 30 | runs-on: ubuntu-latest 31 | env: 32 | RUST_BACKTRACE: "1" 33 | RUSTFLAGS: "-D dead_code -D unused-variables -D unused" 34 | steps: 35 | - uses: actions/checkout@master 36 | - name: Install Rust 37 | uses: actions-rs/toolchain@v1 38 | with: 39 | toolchain: stable 40 | override: true 41 | - name: Test 42 | uses: actions-rs/cargo@v1 43 | with: 44 | command: run 45 | args: -- info serde 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.5.14 - 2017-07-31 2 | 3 | Pull up dependencies 4 | 5 | ## 0.5.13 - 2017-10-20 6 | 7 | No need for openssl on macOS 8 | 9 | ## 0.5.12 - 2017-09-02 10 | 11 | Pull up dependencies 12 | 13 | ## 0.5.11 - 2017-07-05 14 | 15 | Pull up dependencies 16 | 17 | ## 0.5.10 - 2017-06-05 18 | 19 | Drop unused -s/--summary option 20 | 21 | ## 0.5.9 - 2017-04-09 22 | 23 | Respin for another dependency update 24 | 25 | ## 0.5.8 - 2017-04-06 26 | 27 | Dependency updates 28 | 29 | ## 0.5.7 - 2017-02-12 30 | 31 | Fix badges 32 | 33 | ## 0.5.6 - 2017-02-12 34 | 35 | Add crates.io categories and badges 36 | Update dependencies 37 | 38 | ## 0.5.5 39 | 40 | [Internal] Adjust request headers (crates.io wants 'Accept: application/json') 41 | 42 | ## 0.5.4 43 | 44 | Update to use pager 0.9.3 which allows things like 'PAGER=less -S' 45 | 46 | ## 0.5.3 47 | 48 | Fix displaying yanked versions 49 | 50 | ## 0.5.2 51 | 52 | Report brief crate version history by default 53 | 54 | ## 0.5.1 55 | 56 | Fix incorrect 'update at' timestamp 57 | 58 | ## 0.5.0 59 | 60 | Handle network error and give appropriate error description if any 61 | Pipe output through an external pager 62 | 63 | ## 0.4.3 64 | 65 | Fix dependency issue 66 | 67 | ## 0.4.2 68 | 69 | Report timestamp in humanized form 70 | 71 | ## 0.4.0 72 | 73 | Report crate version history with -V/--versions flag 74 | 75 | ## 0.3.4 76 | 77 | Decode timestamps and report in more human readable form 78 | 79 | ## 0.3.3 80 | 81 | No new functionality - dependency updates 82 | 83 | ## 0.3.2 84 | 85 | No new functionality - dependency updates 86 | 87 | ## 0.3.1 88 | 89 | Make -jv print pretty JSON 90 | 91 | ## 0.3.0 92 | 93 | Add support for raw JSON output (-j) 94 | Replace serde with json for JSON decode 95 | Support stable Rust channel 96 | 97 | ## 0.2.0 98 | 99 | Add flags for getting a specific crate detail 100 | -H - homepage 101 | -d - documentation 102 | -D - downloads 103 | -r - repository 104 | 105 | ## 0.1.2 106 | 107 | Add support for -v 108 | 109 | ## 0.0.1 110 | 111 | Initial drop 112 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.21.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "android-tzdata" 22 | version = "0.1.1" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 25 | 26 | [[package]] 27 | name = "android_system_properties" 28 | version = "0.1.5" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 31 | dependencies = [ 32 | "libc", 33 | ] 34 | 35 | [[package]] 36 | name = "anstyle" 37 | version = "1.0.2" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" 40 | 41 | [[package]] 42 | name = "autocfg" 43 | version = "1.1.0" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 46 | 47 | [[package]] 48 | name = "backtrace" 49 | version = "0.3.69" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" 52 | dependencies = [ 53 | "addr2line", 54 | "cc", 55 | "cfg-if", 56 | "libc", 57 | "miniz_oxide", 58 | "object", 59 | "rustc-demangle", 60 | ] 61 | 62 | [[package]] 63 | name = "base64" 64 | version = "0.21.3" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" 67 | 68 | [[package]] 69 | name = "bumpalo" 70 | version = "3.13.0" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" 73 | 74 | [[package]] 75 | name = "cargo-info" 76 | version = "0.7.0" 77 | dependencies = [ 78 | "chrono", 79 | "chrono-humanize", 80 | "clap", 81 | "color-eyre", 82 | "json", 83 | "ureq", 84 | ] 85 | 86 | [[package]] 87 | name = "cc" 88 | version = "1.0.83" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" 91 | dependencies = [ 92 | "libc", 93 | ] 94 | 95 | [[package]] 96 | name = "cfg-if" 97 | version = "1.0.0" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 100 | 101 | [[package]] 102 | name = "chrono" 103 | version = "0.4.26" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" 106 | dependencies = [ 107 | "android-tzdata", 108 | "iana-time-zone", 109 | "num-traits", 110 | "winapi", 111 | ] 112 | 113 | [[package]] 114 | name = "chrono-humanize" 115 | version = "0.2.3" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | checksum = "799627e6b4d27827a814e837b9d8a504832086081806d45b1afa34dc982b023b" 118 | dependencies = [ 119 | "chrono", 120 | ] 121 | 122 | [[package]] 123 | name = "clap" 124 | version = "4.4.0" 125 | source = "registry+https://github.com/rust-lang/crates.io-index" 126 | checksum = "1d5f1946157a96594eb2d2c10eb7ad9a2b27518cb3000209dec700c35df9197d" 127 | dependencies = [ 128 | "clap_builder", 129 | "clap_derive", 130 | "once_cell", 131 | ] 132 | 133 | [[package]] 134 | name = "clap_builder" 135 | version = "4.4.0" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "78116e32a042dd73c2901f0dc30790d20ff3447f3e3472fad359e8c3d282bcd6" 138 | dependencies = [ 139 | "anstyle", 140 | "clap_lex", 141 | ] 142 | 143 | [[package]] 144 | name = "clap_derive" 145 | version = "4.4.0" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "c9fd1a5729c4548118d7d70ff234a44868d00489a4b6597b0b020918a0e91a1a" 148 | dependencies = [ 149 | "heck", 150 | "proc-macro2", 151 | "quote", 152 | "syn", 153 | ] 154 | 155 | [[package]] 156 | name = "clap_lex" 157 | version = "0.5.1" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" 160 | 161 | [[package]] 162 | name = "color-eyre" 163 | version = "0.6.2" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" 166 | dependencies = [ 167 | "backtrace", 168 | "color-spantrace", 169 | "eyre", 170 | "indenter", 171 | "once_cell", 172 | "owo-colors", 173 | "tracing-error", 174 | ] 175 | 176 | [[package]] 177 | name = "color-spantrace" 178 | version = "0.2.0" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce" 181 | dependencies = [ 182 | "once_cell", 183 | "owo-colors", 184 | "tracing-core", 185 | "tracing-error", 186 | ] 187 | 188 | [[package]] 189 | name = "core-foundation-sys" 190 | version = "0.8.4" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" 193 | 194 | [[package]] 195 | name = "crc32fast" 196 | version = "1.3.2" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 199 | dependencies = [ 200 | "cfg-if", 201 | ] 202 | 203 | [[package]] 204 | name = "eyre" 205 | version = "0.6.8" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb" 208 | dependencies = [ 209 | "indenter", 210 | "once_cell", 211 | ] 212 | 213 | [[package]] 214 | name = "flate2" 215 | version = "1.0.27" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" 218 | dependencies = [ 219 | "crc32fast", 220 | "miniz_oxide", 221 | ] 222 | 223 | [[package]] 224 | name = "form_urlencoded" 225 | version = "1.2.0" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" 228 | dependencies = [ 229 | "percent-encoding", 230 | ] 231 | 232 | [[package]] 233 | name = "gimli" 234 | version = "0.28.0" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" 237 | 238 | [[package]] 239 | name = "heck" 240 | version = "0.4.1" 241 | source = "registry+https://github.com/rust-lang/crates.io-index" 242 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 243 | 244 | [[package]] 245 | name = "iana-time-zone" 246 | version = "0.1.57" 247 | source = "registry+https://github.com/rust-lang/crates.io-index" 248 | checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" 249 | dependencies = [ 250 | "android_system_properties", 251 | "core-foundation-sys", 252 | "iana-time-zone-haiku", 253 | "js-sys", 254 | "wasm-bindgen", 255 | "windows", 256 | ] 257 | 258 | [[package]] 259 | name = "iana-time-zone-haiku" 260 | version = "0.1.2" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 263 | dependencies = [ 264 | "cc", 265 | ] 266 | 267 | [[package]] 268 | name = "idna" 269 | version = "0.4.0" 270 | source = "registry+https://github.com/rust-lang/crates.io-index" 271 | checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" 272 | dependencies = [ 273 | "unicode-bidi", 274 | "unicode-normalization", 275 | ] 276 | 277 | [[package]] 278 | name = "indenter" 279 | version = "0.3.3" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" 282 | 283 | [[package]] 284 | name = "js-sys" 285 | version = "0.3.64" 286 | source = "registry+https://github.com/rust-lang/crates.io-index" 287 | checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" 288 | dependencies = [ 289 | "wasm-bindgen", 290 | ] 291 | 292 | [[package]] 293 | name = "json" 294 | version = "0.12.4" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" 297 | 298 | [[package]] 299 | name = "lazy_static" 300 | version = "1.4.0" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 303 | 304 | [[package]] 305 | name = "libc" 306 | version = "0.2.147" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 309 | 310 | [[package]] 311 | name = "log" 312 | version = "0.4.20" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 315 | 316 | [[package]] 317 | name = "memchr" 318 | version = "2.5.0" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 321 | 322 | [[package]] 323 | name = "miniz_oxide" 324 | version = "0.7.1" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" 327 | dependencies = [ 328 | "adler", 329 | ] 330 | 331 | [[package]] 332 | name = "num-traits" 333 | version = "0.2.16" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" 336 | dependencies = [ 337 | "autocfg", 338 | ] 339 | 340 | [[package]] 341 | name = "object" 342 | version = "0.32.0" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" 345 | dependencies = [ 346 | "memchr", 347 | ] 348 | 349 | [[package]] 350 | name = "once_cell" 351 | version = "1.18.0" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 354 | 355 | [[package]] 356 | name = "owo-colors" 357 | version = "3.5.0" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" 360 | 361 | [[package]] 362 | name = "percent-encoding" 363 | version = "2.3.0" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" 366 | 367 | [[package]] 368 | name = "pin-project-lite" 369 | version = "0.2.13" 370 | source = "registry+https://github.com/rust-lang/crates.io-index" 371 | checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" 372 | 373 | [[package]] 374 | name = "proc-macro2" 375 | version = "1.0.66" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" 378 | dependencies = [ 379 | "unicode-ident", 380 | ] 381 | 382 | [[package]] 383 | name = "quote" 384 | version = "1.0.33" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" 387 | dependencies = [ 388 | "proc-macro2", 389 | ] 390 | 391 | [[package]] 392 | name = "ring" 393 | version = "0.16.20" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" 396 | dependencies = [ 397 | "cc", 398 | "libc", 399 | "once_cell", 400 | "spin", 401 | "untrusted", 402 | "web-sys", 403 | "winapi", 404 | ] 405 | 406 | [[package]] 407 | name = "rustc-demangle" 408 | version = "0.1.23" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 411 | 412 | [[package]] 413 | name = "rustls" 414 | version = "0.21.6" 415 | source = "registry+https://github.com/rust-lang/crates.io-index" 416 | checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" 417 | dependencies = [ 418 | "log", 419 | "ring", 420 | "rustls-webpki 0.101.4", 421 | "sct", 422 | ] 423 | 424 | [[package]] 425 | name = "rustls-webpki" 426 | version = "0.100.2" 427 | source = "registry+https://github.com/rust-lang/crates.io-index" 428 | checksum = "e98ff011474fa39949b7e5c0428f9b4937eda7da7848bbb947786b7be0b27dab" 429 | dependencies = [ 430 | "ring", 431 | "untrusted", 432 | ] 433 | 434 | [[package]] 435 | name = "rustls-webpki" 436 | version = "0.101.4" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" 439 | dependencies = [ 440 | "ring", 441 | "untrusted", 442 | ] 443 | 444 | [[package]] 445 | name = "sct" 446 | version = "0.7.0" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" 449 | dependencies = [ 450 | "ring", 451 | "untrusted", 452 | ] 453 | 454 | [[package]] 455 | name = "sharded-slab" 456 | version = "0.1.4" 457 | source = "registry+https://github.com/rust-lang/crates.io-index" 458 | checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" 459 | dependencies = [ 460 | "lazy_static", 461 | ] 462 | 463 | [[package]] 464 | name = "spin" 465 | version = "0.5.2" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 468 | 469 | [[package]] 470 | name = "syn" 471 | version = "2.0.29" 472 | source = "registry+https://github.com/rust-lang/crates.io-index" 473 | checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" 474 | dependencies = [ 475 | "proc-macro2", 476 | "quote", 477 | "unicode-ident", 478 | ] 479 | 480 | [[package]] 481 | name = "thread_local" 482 | version = "1.1.7" 483 | source = "registry+https://github.com/rust-lang/crates.io-index" 484 | checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" 485 | dependencies = [ 486 | "cfg-if", 487 | "once_cell", 488 | ] 489 | 490 | [[package]] 491 | name = "tinyvec" 492 | version = "1.6.0" 493 | source = "registry+https://github.com/rust-lang/crates.io-index" 494 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 495 | dependencies = [ 496 | "tinyvec_macros", 497 | ] 498 | 499 | [[package]] 500 | name = "tinyvec_macros" 501 | version = "0.1.1" 502 | source = "registry+https://github.com/rust-lang/crates.io-index" 503 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 504 | 505 | [[package]] 506 | name = "tracing" 507 | version = "0.1.37" 508 | source = "registry+https://github.com/rust-lang/crates.io-index" 509 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 510 | dependencies = [ 511 | "cfg-if", 512 | "pin-project-lite", 513 | "tracing-core", 514 | ] 515 | 516 | [[package]] 517 | name = "tracing-core" 518 | version = "0.1.31" 519 | source = "registry+https://github.com/rust-lang/crates.io-index" 520 | checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" 521 | dependencies = [ 522 | "once_cell", 523 | "valuable", 524 | ] 525 | 526 | [[package]] 527 | name = "tracing-error" 528 | version = "0.2.0" 529 | source = "registry+https://github.com/rust-lang/crates.io-index" 530 | checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e" 531 | dependencies = [ 532 | "tracing", 533 | "tracing-subscriber", 534 | ] 535 | 536 | [[package]] 537 | name = "tracing-subscriber" 538 | version = "0.3.17" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" 541 | dependencies = [ 542 | "sharded-slab", 543 | "thread_local", 544 | "tracing-core", 545 | ] 546 | 547 | [[package]] 548 | name = "unicode-bidi" 549 | version = "0.3.13" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" 552 | 553 | [[package]] 554 | name = "unicode-ident" 555 | version = "1.0.11" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" 558 | 559 | [[package]] 560 | name = "unicode-normalization" 561 | version = "0.1.22" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 564 | dependencies = [ 565 | "tinyvec", 566 | ] 567 | 568 | [[package]] 569 | name = "untrusted" 570 | version = "0.7.1" 571 | source = "registry+https://github.com/rust-lang/crates.io-index" 572 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 573 | 574 | [[package]] 575 | name = "ureq" 576 | version = "2.7.1" 577 | source = "registry+https://github.com/rust-lang/crates.io-index" 578 | checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" 579 | dependencies = [ 580 | "base64", 581 | "flate2", 582 | "log", 583 | "once_cell", 584 | "rustls", 585 | "rustls-webpki 0.100.2", 586 | "url", 587 | "webpki-roots", 588 | ] 589 | 590 | [[package]] 591 | name = "url" 592 | version = "2.4.0" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" 595 | dependencies = [ 596 | "form_urlencoded", 597 | "idna", 598 | "percent-encoding", 599 | ] 600 | 601 | [[package]] 602 | name = "valuable" 603 | version = "0.1.0" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 606 | 607 | [[package]] 608 | name = "wasm-bindgen" 609 | version = "0.2.87" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" 612 | dependencies = [ 613 | "cfg-if", 614 | "wasm-bindgen-macro", 615 | ] 616 | 617 | [[package]] 618 | name = "wasm-bindgen-backend" 619 | version = "0.2.87" 620 | source = "registry+https://github.com/rust-lang/crates.io-index" 621 | checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" 622 | dependencies = [ 623 | "bumpalo", 624 | "log", 625 | "once_cell", 626 | "proc-macro2", 627 | "quote", 628 | "syn", 629 | "wasm-bindgen-shared", 630 | ] 631 | 632 | [[package]] 633 | name = "wasm-bindgen-macro" 634 | version = "0.2.87" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" 637 | dependencies = [ 638 | "quote", 639 | "wasm-bindgen-macro-support", 640 | ] 641 | 642 | [[package]] 643 | name = "wasm-bindgen-macro-support" 644 | version = "0.2.87" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" 647 | dependencies = [ 648 | "proc-macro2", 649 | "quote", 650 | "syn", 651 | "wasm-bindgen-backend", 652 | "wasm-bindgen-shared", 653 | ] 654 | 655 | [[package]] 656 | name = "wasm-bindgen-shared" 657 | version = "0.2.87" 658 | source = "registry+https://github.com/rust-lang/crates.io-index" 659 | checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" 660 | 661 | [[package]] 662 | name = "web-sys" 663 | version = "0.3.64" 664 | source = "registry+https://github.com/rust-lang/crates.io-index" 665 | checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" 666 | dependencies = [ 667 | "js-sys", 668 | "wasm-bindgen", 669 | ] 670 | 671 | [[package]] 672 | name = "webpki-roots" 673 | version = "0.23.1" 674 | source = "registry+https://github.com/rust-lang/crates.io-index" 675 | checksum = "b03058f88386e5ff5310d9111d53f48b17d732b401aeb83a8d5190f2ac459338" 676 | dependencies = [ 677 | "rustls-webpki 0.100.2", 678 | ] 679 | 680 | [[package]] 681 | name = "winapi" 682 | version = "0.3.9" 683 | source = "registry+https://github.com/rust-lang/crates.io-index" 684 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 685 | dependencies = [ 686 | "winapi-i686-pc-windows-gnu", 687 | "winapi-x86_64-pc-windows-gnu", 688 | ] 689 | 690 | [[package]] 691 | name = "winapi-i686-pc-windows-gnu" 692 | version = "0.4.0" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 695 | 696 | [[package]] 697 | name = "winapi-x86_64-pc-windows-gnu" 698 | version = "0.4.0" 699 | source = "registry+https://github.com/rust-lang/crates.io-index" 700 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 701 | 702 | [[package]] 703 | name = "windows" 704 | version = "0.48.0" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" 707 | dependencies = [ 708 | "windows-targets", 709 | ] 710 | 711 | [[package]] 712 | name = "windows-targets" 713 | version = "0.48.5" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 716 | dependencies = [ 717 | "windows_aarch64_gnullvm", 718 | "windows_aarch64_msvc", 719 | "windows_i686_gnu", 720 | "windows_i686_msvc", 721 | "windows_x86_64_gnu", 722 | "windows_x86_64_gnullvm", 723 | "windows_x86_64_msvc", 724 | ] 725 | 726 | [[package]] 727 | name = "windows_aarch64_gnullvm" 728 | version = "0.48.5" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 731 | 732 | [[package]] 733 | name = "windows_aarch64_msvc" 734 | version = "0.48.5" 735 | source = "registry+https://github.com/rust-lang/crates.io-index" 736 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 737 | 738 | [[package]] 739 | name = "windows_i686_gnu" 740 | version = "0.48.5" 741 | source = "registry+https://github.com/rust-lang/crates.io-index" 742 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 743 | 744 | [[package]] 745 | name = "windows_i686_msvc" 746 | version = "0.48.5" 747 | source = "registry+https://github.com/rust-lang/crates.io-index" 748 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 749 | 750 | [[package]] 751 | name = "windows_x86_64_gnu" 752 | version = "0.48.5" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 755 | 756 | [[package]] 757 | name = "windows_x86_64_gnullvm" 758 | version = "0.48.5" 759 | source = "registry+https://github.com/rust-lang/crates.io-index" 760 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 761 | 762 | [[package]] 763 | name = "windows_x86_64_msvc" 764 | version = "0.48.5" 765 | source = "registry+https://github.com/rust-lang/crates.io-index" 766 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 767 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | authors = [ 3 | "Cyril Plisko ", 4 | "lightning1141@gmail.com", 5 | ] 6 | categories = ["development-tools::cargo-plugins"] 7 | description = "Extends cargo to query crates.io registry for crates details" 8 | documentation = "https://github.com/light4/cargo-info" 9 | keywords = ["cargo", "info", "subcommand"] 10 | license = "Apache-2.0/MIT" 11 | name = "cargo-info" 12 | repository = "https://github.com/light4/cargo-info" 13 | version = "0.7.0" 14 | edition = "2021" 15 | 16 | [dependencies] 17 | chrono = { version = "0.4", default-features = false, features = [ 18 | "std", 19 | "clock", 20 | ] } 21 | chrono-humanize = "0.2" 22 | clap = { version = "4.4", default-features = false, features = [ 23 | "std", 24 | "help", 25 | "usage", 26 | "derive", 27 | "error-context", 28 | ] } 29 | color-eyre = "0.6" 30 | json = "0.12" 31 | ureq = "2.7" 32 | 33 | [profile.release] 34 | lto = "thin" 35 | codegen-units = 4 36 | strip = "debuginfo" 37 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2016 Cyril Plisko 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022-2023 Light Ning 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cargo-info 2 | Query crates.io for crates details 3 | 4 | [![CI](https://github.com/light4/cargo-info/actions/workflows/test.yaml/badge.svg)](https://github.com/light4/cargo-info/actions/workflows/test.yaml) 5 | [![build-and-release](https://github.com/light4/cargo-info/actions/workflows/build-and-release.yaml/badge.svg)](https://github.com/light4/cargo-info/actions/workflows/build-and-release.yaml) 6 | 7 | ## Install 8 | 9 | ```bash 10 | cargo install --git https://github.com/light4/cargo-info.git --force 11 | # Archlinux aur https://aur.archlinux.org/packages/cargo-info 12 | yay -S cargo-info 13 | ``` 14 | 15 | ## Usage 16 | 17 | ```bash 18 | ~ on  master via 🐍 v3.10.2 🕙 12:59:50 19 | ❯ cargo info serde 20 | 21 | Crate: serde (https://crates.io/crates/serde) 22 | Version: 1.0.136 23 | Default features: ["std"] 24 | Features: ["alloc", "derive", "rc", "std", "unstable"] 25 | Description: A generic serialization/deserialization framework 26 | Downloads: 83622745 27 | Homepage: https://serde.rs 28 | Documentation: https://docs.serde.rs/serde/ 29 | Repository: https://github.com/serde-rs/serde 30 | License: MIT OR Apache-2.0 31 | Keywords: ["serde", "serialization", "no_std"] 32 | Last updated: 2 months ago 33 | Version history: 34 | 35 | VERSION RELEASED DOWNLOADS 36 | 37 | 1.0.136 2 months ago 4297338 38 | 1.0.135 2 months ago 446780 39 | 1.0.134 2 months ago 326650 40 | 1.0.133 2 months ago 4868915 41 | 1.0.132 3 months ago 1097574 42 | 43 | ... use -VV to show all 222 versions 44 | 45 | ``` 46 | 47 | ## Credit 48 | 49 | Forked from [imp/cargo-info](https://gitlab.com/imp/cargo-info) 50 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # error_on_line_overflow = true 2 | # error_on_unformatted = true 3 | edition = "2021" 4 | version = "Two" 5 | newline_style = "Unix" 6 | imports_granularity = "Crate" 7 | group_imports = "StdExternalCrate" 8 | 9 | # They are kept here since they are useful to run from time to time. 10 | format_code_in_doc_comments = true 11 | reorder_impl_items = true 12 | comment_width = 100 13 | wrap_comments = true 14 | normalize_comments = true 15 | -------------------------------------------------------------------------------- /src/args.rs: -------------------------------------------------------------------------------- 1 | //! Handle `cargo info` arguments 2 | use clap::Parser; 3 | 4 | #[derive(Debug, Parser)] 5 | #[command(bin_name = "cargo")] 6 | pub enum Command { 7 | /// Query crates.io for crates details. 8 | #[command(name = "info")] 9 | Info(Args), 10 | } 11 | 12 | #[derive(Debug, Parser)] 13 | pub struct Args { 14 | /// Crate name to be queried 15 | #[arg(name = "crate", required = true)] 16 | pub crates: Vec, 17 | 18 | /// Report documentation URL 19 | #[arg(short)] 20 | pub documentation: bool, 21 | 22 | /// Report number of crate downloads 23 | #[arg(short = 'D')] 24 | pub downloads: bool, 25 | 26 | /// Report home page URL 27 | #[arg(short = 'H')] 28 | pub homepage: bool, 29 | 30 | /// Report crate repository URL 31 | #[arg(short)] 32 | pub repository: bool, 33 | 34 | /// Report crate keywords 35 | #[arg(short)] 36 | pub keywords: bool, 37 | 38 | /// Report raw JSON data from crates.io 39 | #[arg( 40 | short, 41 | conflicts_with_all = &["documentation", "downloads", "homepage", "repository", "keywords"] 42 | )] 43 | pub json: bool, 44 | 45 | /// Report more details 46 | #[arg(short)] 47 | pub verbose: bool, 48 | 49 | /// Report version history of the crate (5 last versions), twice for full history 50 | #[arg(short = 'V', action = clap::ArgAction::Count)] 51 | pub versions: u8, 52 | 53 | /// Include prerelease versions when fetching from crates.io (e.g. 54 | /// '0.6.0-alpha'). 55 | #[arg(short)] 56 | pub allow_prerelease: bool, 57 | 58 | /// Run without accessing the network 59 | #[arg(short)] 60 | pub offline: bool, 61 | } 62 | 63 | #[cfg(test)] 64 | impl Default for Args { 65 | fn default() -> Args { 66 | Args { 67 | crates: vec!["demo".to_owned()], 68 | documentation: true, 69 | downloads: true, 70 | homepage: true, 71 | repository: true, 72 | keywords: true, 73 | json: false, 74 | verbose: false, 75 | versions: 5, 76 | allow_prerelease: true, 77 | offline: false, 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/crates.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use chrono::{DateTime, Local, NaiveDateTime, TimeZone}; 4 | use chrono_humanize::HumanTime; 5 | use json::JsonValue; 6 | 7 | #[derive(Debug)] 8 | struct TimeStamp(Option>); 9 | 10 | impl<'a> From<&'a JsonValue> for TimeStamp { 11 | fn from(jv: &JsonValue) -> Self { 12 | let parse_naive = |s: &str| s.parse::(); 13 | let naive_to_local = |n: NaiveDateTime| Local.from_utc_datetime(&n); 14 | let parse_local = |s: &str| s.parse::>(); 15 | let parse = |s: &str| { 16 | parse_local(s) 17 | .or_else(|_| parse_naive(s).map(naive_to_local)) 18 | .ok() 19 | }; 20 | TimeStamp(jv.as_str().and_then(parse)) 21 | } 22 | } 23 | 24 | impl fmt::Display for TimeStamp { 25 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 26 | if let Some(ts) = self.0 { 27 | if f.alternate() { 28 | f.pad(&format!("{}", HumanTime::from(ts))) 29 | } else { 30 | f.pad(&format!("{}", ts.naive_local())) 31 | } 32 | } else { 33 | f.pad("") 34 | } 35 | } 36 | } 37 | 38 | #[derive(Debug)] 39 | pub struct Crate { 40 | krate: Krate, 41 | versions: JsonValue, 42 | keywords: JsonValue, 43 | } 44 | 45 | #[derive(Debug)] 46 | struct Krate { 47 | name: String, 48 | downloads: u64, 49 | max_version: String, 50 | description: String, 51 | documentation: String, 52 | homepage: String, 53 | repository: String, 54 | license: String, 55 | keywords: Vec, 56 | features: Vec, 57 | default_features: Vec, 58 | created_at: TimeStamp, 59 | updated_at: TimeStamp, 60 | } 61 | 62 | impl Crate { 63 | pub fn new(json: &JsonValue) -> Self { 64 | let crate_jv = json["crate"].clone(); 65 | let versions = json["versions"].clone(); 66 | 67 | let name = crate_jv["name"].to_string(); 68 | let license = versions[0]["license"].to_string(); 69 | let keywords = crate_jv["keywords"] 70 | .members() 71 | .map(|jv| jv.to_string()) 72 | .collect::>(); 73 | 74 | let features = versions[0]["features"] 75 | .entries() 76 | .filter_map(|(k, _)| { 77 | if k != "default" { 78 | Some(k.to_string()) 79 | } else { 80 | None 81 | } 82 | }) 83 | .collect::>(); 84 | let default_features = versions[0]["features"]["default"] 85 | .members() 86 | .map(|jv| jv.to_string()) 87 | .collect::>(); 88 | 89 | let created_at = TimeStamp::from(&crate_jv["created_at"]); 90 | let updated_at = TimeStamp::from(&crate_jv["updated_at"]); 91 | 92 | let doc = &crate_jv["documentation"]; 93 | let documentation = if doc.is_empty() { 94 | format!("https://docs.rs/{name}") 95 | } else { 96 | doc.to_string() 97 | }; 98 | 99 | let krate = Krate { 100 | name, 101 | downloads: crate_jv["downloads"].as_u64().unwrap_or_default(), 102 | max_version: crate_jv["max_version"].to_string(), 103 | description: crate_jv["description"].to_string(), 104 | documentation, 105 | homepage: crate_jv["homepage"].to_string(), 106 | repository: crate_jv["repository"].to_string(), 107 | license, 108 | keywords, 109 | features, 110 | default_features, 111 | created_at, 112 | updated_at, 113 | }; 114 | 115 | Crate { 116 | krate, 117 | versions, 118 | keywords: json["keywords"].clone(), 119 | } 120 | } 121 | 122 | pub fn print_repository(&self, verbose: bool) -> String { 123 | if verbose { 124 | format!("{:<16}{}", "Repository:", self.krate.repository) 125 | } else { 126 | self.krate.repository.to_string() 127 | } 128 | } 129 | 130 | pub fn print_documentation(&self, verbose: bool) -> String { 131 | if verbose { 132 | format!("{:<16}{}", "Documentation:", self.krate.documentation) 133 | } else { 134 | self.krate.documentation.to_string() 135 | } 136 | } 137 | 138 | pub fn print_downloads(&self, verbose: bool) -> String { 139 | if verbose { 140 | format!("{:<16}{}", "Downloads:", self.krate.downloads) 141 | } else { 142 | self.krate.downloads.to_string() 143 | } 144 | } 145 | 146 | pub fn print_homepage(&self, verbose: bool) -> String { 147 | if verbose { 148 | format!("{:<16}{}", "Homepage:", self.krate.homepage) 149 | } else { 150 | self.krate.homepage.to_string() 151 | } 152 | } 153 | 154 | fn print_version(v: &JsonValue, _verbose: bool) -> String { 155 | let created_at = TimeStamp::from(&v["created_at"]); 156 | let mut output = format!("{:<16}{created_at:<#16}{:<16}", v["num"], v["downloads"]); 157 | 158 | if v["yanked"].as_bool() == Some(true) { 159 | output += "\t\t(yanked)"; 160 | } 161 | 162 | // Consider adding some more useful information in verbose mode 163 | // if verbose { 164 | // } 165 | 166 | output + "\n" 167 | } 168 | 169 | fn print_version_header(_verbose: bool) -> String { 170 | let output = format!("{:<16}{:<#16}{:<16}\n", "VERSION", "RELEASED", "DOWNLOADS"); 171 | 172 | // Consider adding some more useful information in verbose mode 173 | // if verbose { 174 | // } 175 | 176 | output + "\n" 177 | } 178 | 179 | pub fn print_last_versions(&self, limit: usize, verbose: bool) -> String { 180 | let mut output = Crate::print_version_header(verbose); 181 | for version in self.versions.members().take(limit) { 182 | output = output + &Crate::print_version(version, verbose); 183 | } 184 | let length = self.versions.len(); 185 | if limit < length { 186 | output = output + &format!("\n... use -VV to show all {length} versions\n"); 187 | } 188 | output 189 | } 190 | 191 | pub fn print_keywords(&self, verbose: bool) -> String { 192 | if verbose { 193 | format!("{:#}", self.keywords) 194 | } else { 195 | format!("{}", self.keywords) 196 | } 197 | } 198 | } 199 | 200 | impl fmt::Display for Crate { 201 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 202 | write!( 203 | f, 204 | "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n", 205 | format_args!( 206 | "{:<18}{} (https://crates.io/crates/{})", 207 | "Crate:", self.krate.name, self.krate.name 208 | ), 209 | format_args!("{:<18}{}", "Version:", self.krate.max_version), 210 | format_args!( 211 | "{:<18}{:?}", 212 | "Default features:", self.krate.default_features 213 | ), 214 | format_args!("{:<18}{:?}", "Features:", self.krate.features), 215 | format_args!("{:<18}{}", "Description:", self.krate.description), 216 | format_args!("{:<18}{}", "Downloads:", self.krate.downloads), 217 | format_args!("{:<18}{}", "Homepage:", self.krate.homepage), 218 | format_args!("{:<18}{}", "Documentation:", self.krate.documentation), 219 | format_args!("{:<18}{}", "Repository:", self.krate.repository), 220 | format_args!("{:<18}{}", "License:", self.krate.license), 221 | format_args!("{:<18}{:?}", "Keywords:", self.krate.keywords), 222 | )?; 223 | 224 | if f.alternate() { 225 | write!( 226 | f, 227 | "{}\n{}", 228 | format_args!( 229 | "{:<18}{} ({:#})", 230 | "Created at:", self.krate.created_at, self.krate.created_at 231 | ), 232 | format_args!( 233 | "{:<18}{} ({:#})", 234 | "Updated at:", self.krate.updated_at, self.krate.updated_at 235 | ) 236 | ) 237 | } else { 238 | let mut versions = String::new(); 239 | for line in self.print_last_versions(5, false).lines() { 240 | versions += "\n"; 241 | if !line.is_empty() { 242 | versions = versions + " " + line; 243 | } 244 | } 245 | 246 | write!( 247 | f, 248 | "{}\n{}\n", 249 | format_args!("{:<18}{:#}", "Last updated:", self.krate.updated_at), 250 | format_args!("{:<18}\n{versions}", "Version history:") 251 | ) 252 | } 253 | } 254 | } 255 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use clap::Parser; 4 | use color_eyre::Result; 5 | 6 | use crate::args::{Args, Command}; 7 | 8 | mod args; 9 | mod crates; 10 | 11 | static USER_AGENT: &str = concat!( 12 | env!("CARGO_PKG_NAME"), 13 | "/", 14 | env!("CARGO_PKG_VERSION"), 15 | " (", 16 | env!("CARGO_PKG_HOMEPAGE"), 17 | ")" 18 | ); 19 | 20 | #[derive(Debug, PartialEq)] 21 | enum Flag { 22 | Repository, 23 | Documentation, 24 | Downloads, 25 | Homepage, 26 | Default, 27 | } 28 | 29 | #[derive(Debug)] 30 | struct Report { 31 | flags: Vec, 32 | verbose: bool, 33 | json: bool, 34 | versions: usize, 35 | keywords: bool, 36 | } 37 | 38 | impl Report { 39 | pub fn new(args: &Args) -> Self { 40 | let mut flags: Vec = vec![]; 41 | if args.repository { 42 | flags.push(Flag::Repository); 43 | } 44 | if args.documentation { 45 | flags.push(Flag::Documentation); 46 | } 47 | if args.downloads { 48 | flags.push(Flag::Downloads); 49 | } 50 | if args.homepage { 51 | flags.push(Flag::Homepage); 52 | } 53 | 54 | if flags.is_empty() { 55 | flags.push(Flag::Default); 56 | } 57 | let versions = match args.versions { 58 | 0 => 0, 59 | 1 => 5, 60 | _ => usize::max_value(), 61 | }; 62 | 63 | Report { 64 | flags, 65 | verbose: args.verbose, 66 | json: args.json, 67 | versions, 68 | keywords: args.keywords, 69 | } 70 | } 71 | 72 | pub fn report(&self, name: &str) -> Result { 73 | let krate_detail = get_crate(name)?; 74 | let krate_json = json::parse(&krate_detail).expect("get crate parse json error"); 75 | 76 | if self.json { 77 | return Ok(krate_json.pretty(2)); 78 | } 79 | 80 | let mut output = String::new(); 81 | let krate = crates::Crate::new(&krate_json); 82 | if self.versions > 0 { 83 | output = output + &self.report_versions(&krate, self.versions); 84 | } else if self.keywords { 85 | output = output + &self.report_keywords(&krate); 86 | } else { 87 | output = output + &self.report_crate(&krate); 88 | } 89 | Ok(output) 90 | } 91 | 92 | pub fn report_crate(&self, krate: &crates::Crate) -> String { 93 | let mut output = String::new(); 94 | for flag in &self.flags { 95 | output = output 96 | + &match *flag { 97 | Flag::Repository => krate.print_repository(self.verbose), 98 | Flag::Documentation => krate.print_documentation(self.verbose), 99 | Flag::Downloads => krate.print_downloads(self.verbose), 100 | Flag::Homepage => krate.print_homepage(self.verbose), 101 | Flag::Default => reportv(krate, self.verbose), 102 | } 103 | } 104 | output 105 | } 106 | 107 | pub fn report_versions(&self, krate: &crates::Crate, limit: usize) -> String { 108 | if limit > 0 { 109 | krate.print_last_versions(limit, self.verbose) 110 | } else { 111 | String::new() 112 | } 113 | } 114 | 115 | pub fn report_keywords(&self, krate: &crates::Crate) -> String { 116 | krate.print_keywords(self.verbose) 117 | } 118 | } 119 | 120 | fn reportv(krate: &crates::Crate, verbose: bool) -> String { 121 | if verbose { 122 | format!("{krate:#}") 123 | } else { 124 | format!("{krate}") 125 | } 126 | } 127 | 128 | fn get_crate(krate: &str) -> Result { 129 | let body = ureq::get(&format!("https://crates.io/api/v1/crates/{krate}")) 130 | .set("User-Agent", USER_AGENT) 131 | .call()? 132 | .into_string()?; 133 | 134 | Ok(body) 135 | } 136 | 137 | fn print_report(r: Result) 138 | where 139 | T: fmt::Display, 140 | { 141 | match r { 142 | Ok(text) => println!("\n{text}\n"), 143 | Err(err) => eprintln!("\n{err}\n"), 144 | } 145 | } 146 | 147 | fn main() -> Result<()> { 148 | color_eyre::install()?; 149 | 150 | let args: Command = Command::parse(); 151 | let Command::Info(args) = args; 152 | 153 | let rep = Report::new(&args); 154 | for krate in args.crates { 155 | print_report(rep.report(&krate)); 156 | } 157 | 158 | Ok(()) 159 | } 160 | --------------------------------------------------------------------------------