1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
// Copyright (c) The cargo-guppy Contributors
// SPDX-License-Identifier: MIT OR Apache-2.0

//! `cargo hakari` is a command-line application to manage workspace-hack crates. Use it to speed up
//! local `cargo build` and `cargo check` commands by **15-95%**, and cumulatively by **20-25% or
//! more**.
//!
//! For an explanation of what workspace-hack packages are and how they make your builds faster, see
//! the [`about` module](https://docs.rs/cargo-hakari/latest/cargo_hakari/about).
//!
//! # Examples
//!
//! The `cargo-guppy` repository uses a workspace-hack crate managed by `cargo hakari`. [See the
//! generated `Cargo.toml`.](https://github.com/guppy-rs/guppy/blob/main/workspace-hack/Cargo.toml)
//!
//! # Platform support
//!
//! * **Unix platforms**: Hakari works and is supported.
//! * **Windows**: Hakari works and outputs file paths with forward slashes for consistency with
//!   Unix. CRLF line endings are not supported in the workspace-hack's `Cargo.toml`. Within Git
//!   repositories, `cargo hakari init` automatically does this for you. [Here's how to do it
//!   manually.](https://stackoverflow.com/a/10017566) (Pull requests to improve this are welcome.)
//!
//! # Installation
//!
//! ## Release binaries
//!
//! Release binaries are available on [GitHub
//! Releases](https://github.com/guppy-rs/guppy/releases?q=cargo-hakari&expanded=true), via [`cargo
//! binstall`](https://github.com/cargo-bins/cargo-binstall):
//!
//! ```sh
//! cargo binstall cargo-hakari
//! ```
//!
//! In GitHub Actions CI, use [`taiki-e/install-action`](https://github.com/taiki-e/install-action),
//! which uses `cargo binstall` under the hood:
//!
//! ```yml
//! - name: Install cargo-hakari
//!   uses: taiki-e/install-action@v2
//!    with:
//!      tool: cargo-hakari
//! ```
//!
//! ## Installing from source
//!
//! To install or update `cargo-hakari`, run:
//!
//! ```sh
//! cargo install cargo-hakari --locked
//! ```
//!
//! If `$HOME/.cargo/bin` is in your `PATH`, the `cargo hakari` command will be available.
//!
//! # Usage
//!
//! ## Getting started
//!
//! There are four steps you *must* take for `cargo hakari` to work properly.
//!
//! ### 1. Check in your `Cargo.lock`
//!
//! For hakari to work correctly, you *must* [add your `Cargo.lock` to version
//! control](https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries),
//! even if you don't have any binary crates. This is because patch version bumps in dependencies
//! can add or remove features or even entire transitive dependencies.
//!
//! ### 2. Initialize the workspace-hack
//!
//! Initialize a workspace-hack crate for a workspace at path `my-workspace-hack`:
//!
//! ```sh
//! cargo hakari init my-workspace-hack
//! ```
//!
//! <p align="center">
//! <img src="https://user-images.githubusercontent.com/180618/135726175-dc00dd0c-68a1-455f-a13d-0dd24f545ca6.png">
//! </p>
//!
//! ### 3. Generate the `Cargo.toml`
//!
//! Generate or update the contents of a workspace-hack crate:
//!
//! ```sh
//! cargo hakari generate
//! ```
//!
//! ### 4. Add dependencies to the workspace-hack
//!
//! Add the workspace-hack crate as a dependency to all other workspace crates:
//!
//! ```sh
//! cargo hakari manage-deps
//! ```
//!
//! <p align="center">
//! <img src="https://user-images.githubusercontent.com/180618/135725773-c71fc4cd-8b7d-4a8e-b97c-d84a2b3b3662.png">
//! </p>
//!
//! ## Making hakari work well
//!
//! These are things that are not absolutely necessary to do, but will make `cargo hakari` work
//! better.
//!
//! ### 1. Update the hakari config
//!
//! Open up `.config/hakari.toml`, then:
//!
//! * uncomment or add commonly-used developer platforms
//! * read the note about the resolver, and strongly consider [setting `resolver =
//!   "2"`](https://blog.rust-lang.org/2021/03/25/Rust-1.51.0.html#cargos-new-feature-resolver) in
//!   your workspace's `Cargo.toml`.
//!
//! Remember to run `cargo hakari generate` after changing the config.
//!
//! ### 2. Keep the workspace-hack up-to-date in CI
//!
//! Run the following commands in CI:
//!
//! ```sh
//! cargo hakari generate --diff  # workspace-hack Cargo.toml is up-to-date
//! cargo hakari manage-deps --dry-run  # all workspace crates depend on workspace-hack
//! ```
//!
//! If either of these commands exits with a non-zero status, you can choose to fail CI or produce a
//! warning message.
//!
//! For an example, see [this GitHub action used by
//! `cargo-guppy`](https://github.com/guppy-rs/guppy/blob/main/.github/workflows/hakari.yml).
//!
//! All `cargo hakari` commands take a `--quiet` option to suppress output, though showing diff
//! output in CI is often useful.
//!
//! ### 3. Consider a `[patch]` directive
//!
//! If your workspace is depended on as a Git or path dependency, it is **strongly recommended**
//! that you follow the instructions in the [`[patch]` directive
//! section](https://docs.rs/cargo-hakari/latest/cargo_hakari/patch_directive).
//!
//! ## Information about the workspace-hack
//!
//! The commands in this section provide information about components in the workspace-hack.
//!
//! ### Why is a dependency in the workspace-hack?
//!
//! Print out information about why a dependency is present in the workspace-hack:
//!
//! ```sh
//! cargo hakari explain <dependency-name>
//! ```
//!
//! <p align="center">
//! <img src="https://user-images.githubusercontent.com/180618/144933657-c45cf719-ecaf-49e0-b2c7-c8d12adf11c0.png" width=550>
//! </p>
//!
//! ### Does the workspace-hack ensure that each dependency is built with exactly one feature set?
//!
//! ```sh
//! cargo hakari verify
//! ```
//!
//! If some dependencies are built with more than one feature set, this command will print out
//! details about them. **This is always a bug**---if you encounter it, [a bug
//! report](https://github.com/guppy-rs/guppy/issues/new) with more information would be greatly
//! appreciated!
//!
//! ###
//! ## Publishing a crate
//!
//! If you publish crates to `crates.io` or other registries, see the [`publishing`
//! module](https://docs.rs/cargo-hakari/latest/cargo_hakari/publishing).
//!
//! ## Disabling and uninstalling
//!
//! Disable the workspace-hack crate temporarily by removing generated lines from `Cargo.toml`.
//! (Re-enable by running `cargo hakari generate`.)
//!
//! ```sh
//! cargo hakari disable
//! ```
//!
//! Remove the workspace-hack crate as a dependency from all other workspace crates:
//!
//! ```sh
//! cargo hakari remove-deps
//! ```
//!
//! <p align="center">
//! <img src="https://user-images.githubusercontent.com/180618/135726181-9fe86782-6471-4a1d-a511-a6c55dffbbd7.png">
//! </p>
//!
//! # Configuration
//!
//! `cargo hakari` is configured through `.config/hakari.toml` at the root of the workspace. Running
//! `cargo hakari init` causes a new file to be created at this location.
//!
//! Example configuration:
//!
//! ```toml
//! ## The name of the package used for workspace-hack unification.
//! hakari-package = "workspace-hack"
//! ## Cargo resolver version in use -- version 2 is highly recommended.
//! resolver = "2"
//!
//! ## Format for `workspace-hack = ...` lines in other Cargo.tomls. Version 2 requires cargo-hakari
//! ## 0.9.8 or above.
//! dep-format-version = "2"
//!
//! ## Add triples corresponding to platforms commonly used by developers here.
//! ## https://doc.rust-lang.org/rustc/platform-support.html
//! platforms = [
//!     ## "x86_64-unknown-linux-gnu",
//!     ## "x86_64-apple-darwin",
//!     ## "x86_64-pc-windows-msvc",
//! ]
//!
//! ## Write out exact versions rather than specifications. Set this to true if version numbers in
//! ## `Cargo.toml` and `Cargo.lock` files are kept in sync, e.g. in some configurations of
//! ## https://dependabot.com/.
//! ## exact-versions = false
//! ```
//!
//! For more options, including how to exclude crates from the output, see the [`config`
//! module](https://docs.rs/cargo-hakari/latest/cargo_hakari/config).
//!
//! # Stability guarantees
//!
//! `cargo-hakari` follows semantic versioning, where the public API is the command-line interface.
//!
//! Within a given series, the command-line interface will be treated as append-only.
//!
//! The generated `Cargo.toml` will also be kept the same unless:
//!
//! * a new config option is added, in which case the different output will be gated on the new
//!   option, or
//! * there is a bugfix involved.

mod cargo_cli;
mod command;
mod docs;
mod helpers;
mod output;
mod publish;

pub use docs::*;

// Not part of the stable API.
#[doc(hidden)]
pub use command::Args;