Created
April 3, 2019 17:06
-
-
Save ExpHP/4bc95908166fddb624d87fa30c2f78ef to your computer and use it in GitHub Desktop.
cargo-unused
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import pytoml as toml | |
| import argparse | |
| import subprocess | |
| import sys | |
| def main(): | |
| p = argparse.ArgumentParser('cargo-unused') | |
| # TODO: Should have an --all flag that detects unused deps on all crates in a workspace | |
| p.add_argument('--manifest-path', default='Cargo.toml', help='Path to Cargo.toml') | |
| # TODO: it would be better to search just the rs files that belong to the crate. | |
| # Not sure how to properly do this though; Cargo.toml can tell us the crate root, | |
| # but only rustc knows how to find the other modules from that. | |
| # TODO: Maybe support a glob option with globstars? | |
| p.add_argument('--search-path', default='src', help='source directory') | |
| # FIXME: how are you supposed to properly handle the fact that the first arg of a cargo | |
| # subcommand is the subcommand name itself? | |
| argv = sys.argv | |
| if argv[0] == 'unused': | |
| del argv[0] | |
| args = p.parse_args(argv) | |
| with open(args.manifest_path) as f: | |
| cargo_toml = toml.load(f) | |
| # TODO: build-dependencies, which should only search rs files that belong to the build script | |
| found_unused = False | |
| for deps_key in ('dependencies', 'dev-dependencies'): | |
| for dep_package in cargo_toml[deps_key]: | |
| # TODO: support renamed dependencies | |
| dep_crate = dep_package.replace('-', '_') | |
| result = check_rg_match( | |
| pattern=rf'\b{dep_crate}\b', | |
| search_paths=[args.search_path], | |
| ) | |
| if not result: | |
| print(f'Unused package: {dep_package}') | |
| found_unused = True | |
| sys.exit(int(found_unused)) | |
| def check_rg_installed(): | |
| try: subprocess.check_output(['rg', '--version']) | |
| except FileNotFoundError: die('Please install ripgrep: cargo install rg') | |
| except subprocess.CalledProcessError: die('Error calling rg --version') | |
| def check_rg_match(pattern, search_paths): | |
| try: subprocess.check_output(['rg', '--', pattern] + search_paths) | |
| except subprocess.CalledProcessError: return False | |
| return True | |
| def die(*args): | |
| print(*args, file=sys.stderr) | |
| sys.exit(1) | |
| if __name__ == '__main__': | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment