#graphql #graphql-schema #cargo #search #dependencies #cli

app cargo-indicate

Crate for running GraphQL queries on Rust dependency trees

2 unstable releases

0.2.1 Oct 8, 2023
0.1.0 Apr 8, 2023

#317 in Cargo plugins

MIT/Apache

180KB
4K SLoC

Rust 3K SLoC // 0.0% comments Rusty Object Notation 429 SLoC // 0.0% comments GraphQL 186 SLoC // 0.2% comments

cargo-indicate

This is the cargo add-on for indicate, providing a user-friendly interface to its schema and functionality.

Installation

To be able to query the unsafety of a package and its dependencies, you need to install cargo-geiger. To do this, simply run:

cargo install cargo-geiger

Due to a known problem with the cargo-geiger --features flag, it may not always work as intended. See the issue on rust-secure-code/cargo-geiger.

You can install the custom command using from source using

cargo install --path . --locked

in this directory, or from crates.io using

cargo install cargo-indicate

which allows you to call the command using cargo indicate.

Note: For some data sources, you currently need to set some environment variables. For GitHub and crates.io, you need to set USER_AGENT. For GitHub you also need to provide GITHUB_API_TOKEN.

Run the following for help

cargo indicate --help # or -h

The indicate library comes with some test queries and can be used with any package. For example

$ cargo indicate 
> -Q ../indicate/test_data/queries/count_dependencies.in.ron
> --cached-advisory-db # Useful when running concurrent requests, like in tests
> -- ../indicate/test_data/fake_crates/simple_deps
[
  {
    "dep_name": [],
    "name": "libc",
    "number": 0
  },
  {
    "dep_name": [
      "proc-macro2",
      "unicode-ident",
      "quote",
      "proc-macro2",
      "unicode-ident",
      "unicode-ident"
    ],
    "name": "syn",
    "number": 6
  }
]

Running Queries

There are currently two ways of running queries, with different pros and cons. The simlest way is to pass a GraphQL matching the cargo-indicate schema (use --show-schema to see it), and then pass eventual arguments in a JSON format. For example,

$ cargo indicate
> --query '{ RootPackage { name @output @filter(op: "=", value: ["$target"]) } }'
> --args '{ "target": "cargo-indicate" }'
> -- .
[
  {
    "name": "cargo-indicate",
  }
]

Both the -q/--query and -a/--args also take file paths. You can pass multiple queries and sets of args, and they will be paired.

If you instead want predefined query/arguments pairs, you can use the -Q/ --query-with-args and d/--query-dir flags to pass files in a supported file format (.ron files are recommended, see [the test queries](/indicate/ indicate/test_data/queries) for examples).

Targeting Workspaces

There are two ways to handle workspaces when using cargo-indicate:

  1. Pass the direct path to a member package directory/Cargo.toml-file
  2. Use the --package flag to specify the name of the package you are interested in

The first option is generally preferable, but the second option is useful when analyzing a lot of packages automatically, and it is unknown if the target dir is a workspace, but you know the desired package name.

Selecting sources

Some arguments change the source of data for some signals. For example, both --cached-advisory-db and --advisory-db-dir attempts to use a local dir.

Using the local directory (containing no advisories) would succeed, but always return an empty list

$ cargo indicate
> --advisory-db-dir .
> -Q ../indicate/test_data/queries/advisory_db_simple.in.ron
> -- ../indicate/test_data/fake_crates/known_advisory_deps
[]

Testing

Both cargo-indicate and the underlying library indicate are tested against queries and dummy crates. Tests here in cargo-indicate ensure the CLI is working as intended.

It uses trycmd. For more info, see the trycmd docs, but the general idea is that tests compare input and output. Directories <test-name>.in are the root of a command defined in <test-name>.toml, and when a <test-name>.out directory is present trycmd ensures that after the command in <test-name>.toml is run <test-name>.in and <test-name.out> is the same (after which they are reset).

This is done using /tmp files, so relative files will not work as if actually being called in <test-name>.in.

Dependencies

~42–60MB
~1M SLoC