Unified · Split
| @@ -1835,6 +1835,7 @@ dependencies = [ · 1834 unmodified lines | |||
| 1835 | "git-repository", | 1835 | "git-repository", |
| 1836 | "git-transport", | 1836 | "git-transport", |
| 1837 | "gitoxide-core", | 1837 | "gitoxide-core", |
| 1838 | "owo-colors", | ||
| 1838 | "prodash", | 1839 | "prodash", |
| 1839 | ] | 1840 | ] |
| 1840 | 1841 | ||
| @@ -2380,6 +2381,12 @@ dependencies = [ · 539 unmodified lines | |||
| 2380 | "winapi", | 2381 | "winapi", |
| 2381 | ] | 2382 | ] |
| 2382 | 2383 | ||
| 2384 | [[package]] | ||
| 2385 | name = "owo-colors" | ||
| 2386 | version = "3.5.0" | ||
| 2387 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
| 2388 | checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" | ||
| 2389 | |||
| 2383 | [[package]] | 2390 | [[package]] |
| 2384 | name = "parking" | 2391 | name = "parking" |
| 2385 | version = "2.0.0" | 2392 | version = "2.0.0" |
| @@ -92,6 +92,9 @@ env_logger = { version = "0.9.0", default-features = false } · 91 unmodified lines | |||
| 92 | crosstermion = { version = "0.10.1", optional = true, default-features = false } | 92 | crosstermion = { version = "0.10.1", optional = true, default-features = false } |
| 93 | futures-lite = { version = "1.12.0", optional = true, default-features = false, features = ["std"] } | 93 | futures-lite = { version = "1.12.0", optional = true, default-features = false, features = ["std"] } |
| 94 | 94 | ||
| 95 | # for show-progress | ||
| 96 | owo-colors = "3.5.0" | ||
| 97 | |||
| 95 | document-features = { version = "0.2.0", optional = true } | 98 | document-features = { version = "0.2.0", optional = true } |
| 96 | 99 | ||
| 97 | [profile.dev.package] | 100 | [profile.dev.package] |
| @@ -27,6 +27,10 @@ Please see _'Development Status'_ for a listing of all crates and their capabili · 26 unmodified lines | |||
| 27 | * Based on the [git-hours] algorithm. | 27 | * Based on the [git-hours] algorithm. |
| 28 | * See the [discussion][git-hours-discussion] for some performance data. | 28 | * See the [discussion][git-hours-discussion] for some performance data. |
| 29 | * **the `gix` program** _(plumbing)_ - lower level commands for use in automation | 29 | * **the `gix` program** _(plumbing)_ - lower level commands for use in automation |
| 30 | * **progress** | ||
| 31 | * [x] **show** - provide an overview of what works and what doesn't from the perspective of the git configuration. | ||
| 32 | This is likely to change a lot over time depending on actual needs, but maybe useful for you to see | ||
| 33 | if particular git-configuration is picked up and where it deviates. | ||
| 30 | * **config** - list the complete git configuration in human-readable form and optionally filter sections by name. | 34 | * **config** - list the complete git configuration in human-readable form and optionally filter sections by name. |
| 31 | * **exclude** | 35 | * **exclude** |
| 32 | * [x] **query** - check if path specs are excluded via gits exclusion rules like `.gitignore`. | 36 | * [x] **query** - check if path specs are excluded via gits exclusion rules like `.gitignore`. |
| @@ -14,8 +14,12 @@ use gitoxide_core as core; · 13 unmodified lines | |||
| 14 | use gitoxide_core::pack::verify; | 14 | use gitoxide_core::pack::verify; |
| 15 | 15 | ||
| 16 | use crate::{ | 16 | use crate::{ |
| 17 | plumbing::options::{ | 17 | plumbing::{ |
| 18 | commit, config, credential, exclude, free, mailmap, odb, remote, revision, tree, Args, Subcommands, | 18 | options::{ |
| 19 | commit, config, credential, exclude, free, mailmap, odb, progress, remote, revision, tree, Args, | ||
| 20 | Subcommands, | ||
| 21 | }, | ||
| 22 | show_progress, | ||
| 19 | }, | 23 | }, |
| 20 | shared::pretty::prepare_and_run, | 24 | shared::pretty::prepare_and_run, |
| 21 | }; | 25 | }; |
| @@ -111,6 +115,7 @@ pub fn main() -> Result<()> { · 89 unmodified lines | |||
| 111 | })?; | 115 | })?; |
| 112 | 116 | ||
| 113 | match cmd { | 117 | match cmd { |
| 118 | Subcommands::Progress(progress::Subcommands::Show) => show_progress(), | ||
| 114 | Subcommands::Credential(cmd) => core::repository::credential( | 119 | Subcommands::Credential(cmd) => core::repository::credential( |
| 115 | repository(Mode::StrictWithGitInstallConfig)?, | 120 | repository(Mode::StrictWithGitInstallConfig)?, |
| 116 | match cmd { | 121 | match cmd { |
| @@ -1,4 +1,8 @@ | |||
| 1 | mod main; | 1 | mod main; |
| 2 | pub use main::main; | 2 | pub use main::main; |
| 3 | 3 | ||
| 4 | #[path = "progress.rs"] | ||
| 5 | mod progress_impl; | ||
| 6 | pub use progress_impl::show_progress; | ||
| 7 | |||
| 4 | mod options; | 8 | mod options; |
| @@ -1,677 +0,0 @@ | |||
| 1 | use std::path::PathBuf; | ||
| 2 | |||
| 3 | use git_repository as git; | ||
| 4 | use git_repository::bstr::BString; | ||
| 5 | use gitoxide_core as core; | ||
| 6 | |||
| 7 | #[derive(Debug, clap::Parser)] | ||
| 8 | #[clap(name = "gix-plumbing", about = "The git underworld", version = clap::crate_version!())] | ||
| 9 | #[clap(subcommand_required = true)] | ||
| 10 | #[clap(arg_required_else_help = true)] | ||
| 11 | pub struct Args { | ||
| 12 | /// The repository to access. | ||
| 13 | #[clap(short = 'r', long, default_value = ".")] | ||
| 14 | pub repository: PathBuf, | ||
| 15 | |||
| 16 | /// Add these values to the configuration in the form of `key=value` or `key`. | ||
| 17 | /// | ||
| 18 | /// For example, if `key` is `core.abbrev`, set configuration like `[core] abbrev = key`, | ||
| 19 | /// or `remote.origin.url = foo` to set `[remote "origin"] url = foo`. | ||
| 20 | #[clap(long, short = 'c', parse(try_from_os_str = git::env::os_str_to_bstring))] | ||
| 21 | pub config: Vec<BString>, | ||
| 22 | |||
| 23 | #[clap(long, short = 't')] | ||
| 24 | /// The amount of threads to use for some operations. | ||
| 25 | /// | ||
| 26 | /// If unset, or the value is 0, there is no limit and all logical cores can be used. | ||
| 27 | pub threads: Option<usize>, | ||
| 28 | |||
| 29 | /// Display verbose messages and progress information | ||
| 30 | #[clap(long, short = 'v')] | ||
| 31 | pub verbose: bool, | ||
| 32 | |||
| 33 | /// Bring up a terminal user interface displaying progress visually | ||
| 34 | #[cfg(feature = "prodash-render-tui")] | ||
| 35 | #[clap(long, conflicts_with("verbose"))] | ||
| 36 | pub progress: bool, | ||
| 37 | |||
| 38 | /// The progress TUI will stay up even though the work is already completed. | ||
| 39 | /// | ||
| 40 | /// Use this to be able to read progress messages or additional information visible in the TUI log pane. | ||
| 41 | #[cfg(feature = "prodash-render-tui")] | ||
| 42 | #[clap(long, conflicts_with("verbose"), requires("progress"))] | ||
| 43 | pub progress_keep_open: bool, | ||
| 44 | |||
| 45 | /// Determine the format to use when outputting statistics. | ||
| 46 | #[clap( | ||
| 47 | long, | ||
| 48 | short = 'f', | ||
| 49 | default_value = "human", | ||
| 50 | possible_values(core::OutputFormat::variants()) | ||
| 51 | )] | ||
| 52 | pub format: core::OutputFormat, | ||
| 53 | |||
| 54 | /// The object format to assume when reading files that don't inherently know about it, or when writing files. | ||
| 55 | #[clap(long, default_value_t = git_repository::hash::Kind::default(), possible_values(&["SHA1"]))] | ||
| 56 | pub object_hash: git_repository::hash::Kind, | ||
| 57 | |||
| 58 | #[clap(subcommand)] | ||
| 59 | pub cmd: Subcommands, | ||
| 60 | } | ||
| 61 | |||
| 62 | #[derive(Debug, clap::Subcommand)] | ||
| 63 | pub enum Subcommands { | ||
| 64 | /// Interact with the object database. | ||
| 65 | #[clap(subcommand)] | ||
| 66 | Odb(odb::Subcommands), | ||
| 67 | /// Interact with tree objects. | ||
| 68 | #[clap(subcommand)] | ||
| 69 | Tree(tree::Subcommands), | ||
| 70 | /// Interact with commit objects. | ||
| 71 | #[clap(subcommand)] | ||
| 72 | Commit(commit::Subcommands), | ||
| 73 | /// Verify the integrity of the entire repository | ||
| 74 | Verify { | ||
| 75 | #[clap(flatten)] | ||
| 76 | args: free::pack::VerifyOptions, | ||
| 77 | }, | ||
| 78 | /// Query and obtain information about revisions. | ||
| 79 | #[clap(subcommand)] | ||
| 80 | Revision(revision::Subcommands), | ||
| 81 | /// A program just like `git credential`. | ||
| 82 | #[clap(subcommand)] | ||
| 83 | Credential(credential::Subcommands), | ||
| 84 | /// Interact with the mailmap. | ||
| 85 | #[clap(subcommand)] | ||
| 86 | Mailmap(mailmap::Subcommands), | ||
| 87 | /// Interact with the remote hosts. | ||
| 88 | Remote(remote::Platform), | ||
| 89 | /// Interact with the exclude files like .gitignore. | ||
| 90 | #[clap(subcommand)] | ||
| 91 | Exclude(exclude::Subcommands), | ||
| 92 | Config(config::Platform), | ||
| 93 | /// Subcommands that need no git repository to run. | ||
| 94 | #[clap(subcommand)] | ||
| 95 | Free(free::Subcommands), | ||
| 96 | } | ||
| 97 | |||
| 98 | pub mod config { | ||
| 99 | /// Print all entries in a configuration file or access other sub-commands | ||
| 100 | #[derive(Debug, clap::Parser)] | ||
| 101 | #[clap(subcommand_required(false))] | ||
| 102 | pub struct Platform { | ||
| 103 | /// The filter terms to limit the output to matching sections and subsections only. | ||
| 104 | /// | ||
| 105 | /// Typical filters are `branch` or `remote.origin` or `remote.or*` - git-style globs are supported | ||
| 106 | /// and comparisons are case-insensitive. | ||
| 107 | pub filter: Vec<String>, | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | pub mod remote { | ||
| 112 | use git_repository as git; | ||
| 113 | |||
| 114 | #[derive(Debug, clap::Parser)] | ||
| 115 | pub struct Platform { | ||
| 116 | /// The name of the remote to connect to. | ||
| 117 | /// | ||
| 118 | /// If unset, the current branch will determine the remote. | ||
| 119 | #[clap(long, short = 'n')] | ||
| 120 | pub name: Option<String>, | ||
| 121 | |||
| 122 | /// Connect directly to the given URL, forgoing any configuration from the repository. | ||
| 123 | #[clap(long, short = 'u', conflicts_with("name"), parse(try_from_os_str = std::convert::TryFrom::try_from))] | ||
| 124 | pub url: Option<git::Url>, | ||
| 125 | |||
| 126 | /// Output additional typically information provided by the server as part of the connection handshake. | ||
| 127 | #[clap(long)] | ||
| 128 | pub handshake_info: bool, | ||
| 129 | |||
| 130 | /// Subcommands | ||
| 131 | #[clap(subcommand)] | ||
| 132 | pub cmd: Subcommands, | ||
| 133 | } | ||
| 134 | |||
| 135 | #[derive(Debug, clap::Subcommand)] | ||
| 136 | #[clap(visible_alias = "remotes")] | ||
| 137 | pub enum Subcommands { | ||
| 138 | /// Print all references available on the remote. | ||
| 139 | #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))] | ||
| 140 | Refs, | ||
| 141 | /// Print all references available on the remote as filtered through ref-specs. | ||
| 142 | #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))] | ||
| 143 | RefMap { | ||
| 144 | /// Override the built-in and configured ref-specs with one or more of the given ones. | ||
| 145 | #[clap(parse(try_from_os_str = git::env::os_str_to_bstring))] | ||
| 146 | ref_spec: Vec<git_repository::bstr::BString>, | ||
| 147 | }, | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | pub mod mailmap { | ||
| 152 | #[derive(Debug, clap::Subcommand)] | ||
| 153 | pub enum Subcommands { | ||
| 154 | /// Print all entries in configured mailmaps, inform about errors as well. | ||
| 155 | Entries, | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | pub mod odb { | ||
| 160 | #[derive(Debug, clap::Subcommand)] | ||
| 161 | pub enum Subcommands { | ||
| 162 | /// Print all object names. | ||
| 163 | Entries, | ||
| 164 | /// Provide general information about the object database. | ||
| 165 | Info, | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | pub mod tree { | ||
| 170 | #[derive(Debug, clap::Subcommand)] | ||
| 171 | pub enum Subcommands { | ||
| 172 | /// Print entries in a given tree | ||
| 173 | Entries { | ||
| 174 | /// Traverse the entire tree and its subtrees respectively, not only this tree. | ||
| 175 | #[clap(long, short = 'r')] | ||
| 176 | recursive: bool, | ||
| 177 | |||
| 178 | /// Provide files size as well. This is expensive as the object is decoded entirely. | ||
| 179 | #[clap(long, short = 'e')] | ||
| 180 | extended: bool, | ||
| 181 | |||
| 182 | /// The tree to traverse, or the tree at `HEAD` if unspecified. | ||
| 183 | treeish: Option<String>, | ||
| 184 | }, | ||
| 185 | /// Provide information about a tree. | ||
| 186 | Info { | ||
| 187 | /// Provide files size as well. This is expensive as the object is decoded entirely. | ||
| 188 | #[clap(long, short = 'e')] | ||
| 189 | extended: bool, | ||
| 190 | /// The tree to traverse, or the tree at `HEAD` if unspecified. | ||
| 191 | treeish: Option<String>, | ||
| 192 | }, | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | pub mod commit { | ||
| 197 | #[derive(Debug, clap::Subcommand)] | ||
| 198 | pub enum Subcommands { | ||
| 199 | /// Describe the current commit or the given one using the name of the closest annotated tag in its ancestry. | ||
| 200 | Describe { | ||
| 201 | /// Use annotated tag references only, not all tags. | ||
| 202 | #[clap(long, short = 't', conflicts_with("all-refs"))] | ||
| 203 | annotated_tags: bool, | ||
| 204 | |||
| 205 | /// Use all references under the `ref/` namespaces, which includes tag references, local and remote branches. | ||
| 206 | #[clap(long, short = 'a', conflicts_with("annotated-tags"))] | ||
| 207 | all_refs: bool, | ||
| 208 | |||
| 209 | /// Only follow the first parent when traversing the commit graph. | ||
| 210 | #[clap(long, short = 'f')] | ||
| 211 | first_parent: bool, | ||
| 212 | |||
| 213 | /// Always display the long format, even if that would not be necessary as the id is located directly on a reference. | ||
| 214 | #[clap(long, short = 'l')] | ||
| 215 | long: bool, | ||
| 216 | |||
| 217 | /// Consider only the given `n` candidates. This can take longer, but potentially produces more accurate results. | ||
| 218 | #[clap(long, short = 'c', default_value = "10")] | ||
| 219 | max_candidates: usize, | ||
| 220 | |||
| 221 | /// Print information on stderr to inform about performance statistics | ||
| 222 | #[clap(long, short = 's')] | ||
| 223 | statistics: bool, | ||
| 224 | |||
| 225 | #[clap(long)] | ||
| 226 | /// If there was no way to describe the commit, fallback to using the abbreviated input revision. | ||
| 227 | always: bool, | ||
| 228 | |||
| 229 | /// A specification of the revision to use, or the current `HEAD` if unset. | ||
| 230 | rev_spec: Option<String>, | ||
| 231 | }, | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | pub mod credential { | ||
| 236 | #[derive(Debug, clap::Subcommand)] | ||
| 237 | pub enum Subcommands { | ||
| 238 | /// Get the credentials fed for `url=<url>` via STDIN. | ||
| 239 | #[clap(visible_alias = "get")] | ||
| 240 | Fill, | ||
| 241 | /// Approve the information piped via STDIN as obtained with last call to `fill` | ||
| 242 | #[clap(visible_alias = "store")] | ||
| 243 | Approve, | ||
| 244 | /// Try to resolve the given revspec and print the object names. | ||
| 245 | #[clap(visible_alias = "erase")] | ||
| 246 | Reject, | ||
| 247 | } | ||
| 248 | } | ||
| 249 | |||
| 250 | pub mod revision { | ||
| 251 | #[derive(Debug, clap::Subcommand)] | ||
| 252 | #[clap(visible_alias = "rev", visible_alias = "r")] | ||
| 253 | pub enum Subcommands { | ||
| 254 | /// List all commits reachable from the given rev-spec. | ||
| 255 | #[clap(visible_alias = "l")] | ||
| 256 | List { spec: std::ffi::OsString }, | ||
| 257 | /// Provide the revision specification like `@~1` to explain. | ||
| 258 | #[clap(visible_alias = "e")] | ||
| 259 | Explain { spec: std::ffi::OsString }, | ||
| 260 | /// Try to resolve the given revspec and print the object names. | ||
| 261 | #[clap(visible_alias = "query", visible_alias = "parse", visible_alias = "p")] | ||
| 262 | Resolve { | ||
| 263 | /// Instead of resolving a rev-spec, explain what would be done for the first spec. | ||
| 264 | /// | ||
| 265 | /// Equivalent to the `explain` subcommand. | ||
| 266 | #[clap(short = 'e', long)] | ||
| 267 | explain: bool, | ||
| 268 | /// Show the first resulting object similar to how `git cat-file` would, but don't show the resolved spec. | ||
| 269 | #[clap(short = 'c', long, conflicts_with = "explain")] | ||
| 270 | cat_file: bool, | ||
| 271 | /// rev-specs like `@`, `@~1` or `HEAD^2`. | ||
| 272 | #[clap(required = true)] | ||
| 273 | specs: Vec<std::ffi::OsString>, | ||
| 274 | }, | ||
| 275 | /// Return the names and hashes of all previously checked-out branches. | ||
| 276 | #[clap(visible_alias = "prev")] | ||
| 277 | PreviousBranches, | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | /// | ||
| 282 | pub mod free { | ||
| 283 | #[derive(Debug, clap::Subcommand)] | ||
| 284 | #[clap(visible_alias = "no-repo")] | ||
| 285 | pub enum Subcommands { | ||
| 286 | /// Subcommands for interacting with commit-graphs | ||
| 287 | #[clap(subcommand)] | ||
| 288 | CommitGraph(commitgraph::Subcommands), | ||
| 289 | /// Subcommands for interacting with mailmaps | ||
| 290 | Mailmap { | ||
| 291 | #[clap(flatten)] | ||
| 292 | cmd: mailmap::Platform, | ||
| 293 | }, | ||
| 294 | /// Subcommands for interacting with pack files and indices | ||
| 295 | #[clap(subcommand)] | ||
| 296 | Pack(pack::Subcommands), | ||
| 297 | /// Subcommands for interacting with a worktree index, typically at .git/index | ||
| 298 | Index(index::Platform), | ||
| 299 | } | ||
| 300 | |||
| 301 | /// | ||
| 302 | pub mod commitgraph { | ||
| 303 | use std::path::PathBuf; | ||
| 304 | |||
| 305 | #[derive(Debug, clap::Subcommand)] | ||
| 306 | pub enum Subcommands { | ||
| 307 | /// Verify the integrity of a commit graph | ||
| 308 | Verify { | ||
| 309 | /// The path to '.git/objects/info/', '.git/objects/info/commit-graphs/', or '.git/objects/info/commit-graph' to validate. | ||
| 310 | path: PathBuf, | ||
| 311 | /// output statistical information about the pack | ||
| 312 | #[clap(long, short = 's')] | ||
| 313 | statistics: bool, | ||
| 314 | }, | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | pub mod index { | ||
| 319 | use std::path::PathBuf; | ||
| 320 | |||
| 321 | #[derive(Debug, clap::Parser)] | ||
| 322 | pub struct Platform { | ||
| 323 | /// The object format to assume when reading files that don't inherently know about it, or when writing files. | ||
| 324 | #[clap(long, default_value_t = git_repository::hash::Kind::default(), possible_values(&["SHA1"]))] | ||
| 325 | pub object_hash: git_repository::hash::Kind, | ||
| 326 | |||
| 327 | /// The path to the index file. | ||
| 328 | #[clap(short = 'i', long, default_value = ".git/index")] | ||
| 329 | pub index_path: PathBuf, | ||
| 330 | |||
| 331 | /// Subcommands | ||
| 332 | #[clap(subcommand)] | ||
| 333 | pub cmd: Subcommands, | ||
| 334 | } | ||
| 335 | |||
| 336 | #[derive(Debug, clap::Subcommand)] | ||
| 337 | pub enum Subcommands { | ||
| 338 | /// Validate constraints and assumptions of an index along with its integrity. | ||
| 339 | Verify, | ||
| 340 | /// Print all entries to standard output | ||
| 341 | Entries, | ||
| 342 | /// Print information about the index structure | ||
| 343 | Info { | ||
| 344 | /// Do not extract specific extension information to gain only a superficial idea of the index's composition. | ||
| 345 | #[clap(long)] | ||
| 346 | no_details: bool, | ||
| 347 | }, | ||
| 348 | /// Checkout the index into a directory with exclusive write access, similar to what would happen during clone. | ||
| 349 | CheckoutExclusive { | ||
| 350 | /// The path to `.git` repository from which objects can be obtained to write the actual files referenced | ||
| 351 | /// in the index. Use this measure the impact on extracting objects on overall performance. | ||
| 352 | #[clap(long, short = 'r')] | ||
| 353 | repository: Option<PathBuf>, | ||
| 354 | /// Ignore errors and keep checking out as many files as possible, and report all errors at the end of the operation. | ||
| 355 | #[clap(long, short = 'k')] | ||
| 356 | keep_going: bool, | ||
| 357 | /// Enable to query the object database yet write only empty files. This is useful to measure the overhead of ODB query | ||
| 358 | /// compared to writing the bytes to disk. | ||
| 359 | #[clap(long, short = 'e', requires = "repository")] | ||
| 360 | empty_files: bool, | ||
| 361 | /// The directory into which to write all index entries. | ||
| 362 | directory: PathBuf, | ||
| 363 | }, | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | /// | ||
| 368 | pub mod pack { | ||
| 369 | use std::{ffi::OsString, path::PathBuf}; | ||
| 370 | |||
| 371 | use gitoxide_core as core; | ||
| 372 | |||
| 373 | #[derive(Debug, clap::Subcommand)] | ||
| 374 | pub enum Subcommands { | ||
| 375 | /// Subcommands for interacting with pack indices (.idx) | ||
| 376 | #[clap(subcommand)] | ||
| 377 | Index(index::Subcommands), | ||
| 378 | /// Subcommands for interacting with multi-pack indices (named "multi-pack-index") | ||
| 379 | MultiIndex(multi_index::Platform), | ||
| 380 | /// Create a new pack with a set of objects. | ||
| 381 | Create { | ||
| 382 | #[clap(long, short = 'r')] | ||
| 383 | /// the directory containing the '.git' repository from which objects should be read. | ||
| 384 | repository: Option<PathBuf>, | ||
| 385 | |||
| 386 | #[clap(long, short = 'e', possible_values(core::pack::create::ObjectExpansion::variants()))] | ||
| 387 | /// the way objects are expanded. They differ in costs. | ||
| 388 | /// | ||
| 389 | /// Possible values are "none" and "tree-traversal". Default is "none". | ||
| 390 | expansion: Option<core::pack::create::ObjectExpansion>, | ||
| 391 | |||
| 392 | #[clap(long, default_value_t = 3, requires = "nondeterministic-count")] | ||
| 393 | /// The amount of threads to use when counting and the `--nondeterminisitc-count` flag is set, defaulting | ||
| 394 | /// to the globally configured threads. | ||
| 395 | /// | ||
| 396 | /// Use it to have different trade-offs between counting performance and cost in terms of CPU, as the scaling | ||
| 397 | /// here is everything but linear. The effectiveness of each core seems to be no more than 30%. | ||
| 398 | counting_threads: usize, | ||
| 399 | |||
| 400 | #[clap(long)] | ||
| 401 | /// if set, the counting phase may be accelerated using multithreading. | ||
| 402 | /// | ||
| 403 | /// On the flip side, however, one will loose deterministic counting results which affects the | ||
| 404 | /// way the resulting pack is structured. | ||
| 405 | nondeterministic_count: bool, | ||
| 406 | |||
| 407 | #[clap(long, short = 's')] | ||
| 408 | /// If set statistical information will be presented to inform about pack creation details. | ||
| 409 | /// It's a form of instrumentation for developers to help improve pack generation. | ||
| 410 | statistics: bool, | ||
| 411 | |||
| 412 | #[clap(long)] | ||
| 413 | /// The size in megabytes for a cache to speed up pack access for packs with long delta chains. | ||
| 414 | /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size. | ||
| 415 | /// | ||
| 416 | /// If unset, no cache will be used. | ||
| 417 | pack_cache_size_mb: Option<usize>, | ||
| 418 | |||
| 419 | #[clap(long)] | ||
| 420 | /// The size in megabytes for a cache to speed up accessing entire objects, bypassing object database access when hit. | ||
| 421 | /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size. | ||
| 422 | /// | ||
| 423 | /// This cache type is currently only effective when using the 'diff-tree' object expansion. | ||
| 424 | /// | ||
| 425 | /// If unset, no cache will be used. | ||
| 426 | object_cache_size_mb: Option<usize>, | ||
| 427 | |||
| 428 | #[clap(long)] | ||
| 429 | /// if set, delta-objects whose base object wouldn't be in the pack will not be recompressed as base object, but instead | ||
| 430 | /// refer to its base object using its object id. | ||
| 431 | /// | ||
| 432 | /// This allows for smaller packs but requires the receiver of the pack to resolve these ids before storing the pack. | ||
| 433 | /// Packs produced with this option enabled are only valid in transit, but not at rest. | ||
| 434 | thin: bool, | ||
| 435 | |||
| 436 | /// The directory into which to write the pack file. | ||
| 437 | #[clap(long, short = 'o')] | ||
| 438 | output_directory: Option<PathBuf>, | ||
| 439 | |||
| 440 | /// The tips from which to start the commit graph iteration, either as fully qualified commit hashes | ||
| 441 | /// or as branch names. | ||
| 442 | /// | ||
| 443 | /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode. | ||
| 444 | /// Otherwise the expansion mode is 'tree-traversal' by default. | ||
| 445 | tips: Vec<OsString>, | ||
| 446 | }, | ||
| 447 | /// Use the git-protocol to receive a pack, emulating a clone. | ||
| 448 | #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))] | ||
| 449 | Receive { | ||
| 450 | /// The protocol version to use. Valid values are 1 and 2 | ||
| 451 | #[clap(long, short = 'p')] | ||
| 452 | protocol: Option<core::net::Protocol>, | ||
| 453 | |||
| 454 | /// the directory into which to write references. Existing files will be overwritten. | ||
| 455 | /// | ||
| 456 | /// Note that the directory will be created if needed. | ||
| 457 | #[clap(long, short = 'd')] | ||
| 458 | refs_directory: Option<PathBuf>, | ||
| 459 | |||
| 460 | /// The URLs or path from which to receive the pack. | ||
| 461 | /// | ||
| 462 | /// See here for a list of supported URLs: <https://www.git-scm.com/docs/git-clone#_git_urls> | ||
| 463 | url: String, | ||
| 464 | |||
| 465 | /// If set once or more times, these references will be fetched instead of all advertised ones. | ||
| 466 | /// | ||
| 467 | /// Note that this requires a reasonably modern git server. | ||
| 468 | #[clap(long = "reference", short = 'r')] | ||
| 469 | refs: Vec<String>, | ||
| 470 | |||
| 471 | /// The directory into which to write the received pack and index. | ||
| 472 | /// | ||
| 473 | /// If unset, they will be discarded. | ||
| 474 | directory: Option<PathBuf>, | ||
| 475 | }, | ||
| 476 | /// Dissolve a pack into its loose objects. | ||
| 477 | /// | ||
| 478 | /// Note that this effectively removes delta compression for an average compression of 2x, creating one file per object in the process. | ||
| 479 | /// Thus this should only be done to dissolve small packs after a fetch. | ||
| 480 | Explode { | ||
| 481 | #[clap(long)] | ||
| 482 | /// Read written objects back and assert they match their source. Fail the operation otherwise. | ||
| 483 | /// | ||
| 484 | /// Only relevant if an object directory is set. | ||
| 485 | verify: bool, | ||
| 486 | |||
| 487 | /// delete the pack and index file after the operation is successful | ||
| 488 | #[clap(long)] | ||
| 489 | delete_pack: bool, | ||
| 490 | |||
| 491 | /// The amount of checks to run | ||
| 492 | #[clap( | ||
| 493 | long, | ||
| 494 | short = 'c', | ||
| 495 | default_value = "all", | ||
| 496 | possible_values(core::pack::explode::SafetyCheck::variants()) | ||
| 497 | )] | ||
| 498 | check: core::pack::explode::SafetyCheck, | ||
| 499 | |||
| 500 | /// Compress bytes even when using the sink, i.e. no object directory is specified | ||
| 501 | /// | ||
| 502 | /// This helps to determine overhead related to compression. If unset, the sink will | ||
| 503 | /// only create hashes from bytes, which is usually limited by the speed at which input | ||
| 504 | /// can be obtained. | ||
| 505 | #[clap(long)] | ||
| 506 | sink_compress: bool, | ||
| 507 | |||
| 508 | /// The '.pack' or '.idx' file to explode into loose objects | ||
| 509 | pack_path: PathBuf, | ||
| 510 | |||
| 511 | /// The path into which all objects should be written. Commonly '.git/objects' | ||
| 512 | object_path: Option<PathBuf>, | ||
| 513 | }, | ||
| 514 | /// Verify the integrity of a pack, index or multi-index file | ||
| 515 | Verify { | ||
| 516 | #[clap(flatten)] | ||
| 517 | args: VerifyOptions, | ||
| 518 | |||
| 519 | /// The '.pack', '.idx' or 'multi-pack-index' file to validate. | ||
| 520 | path: PathBuf, | ||
| 521 | }, | ||
| 522 | } | ||
| 523 | |||
| 524 | #[derive(Debug, clap::Parser)] | ||
| 525 | pub struct VerifyOptions { | ||
| 526 | /// output statistical information | ||
| 527 | #[clap(long, short = 's')] | ||
| 528 | pub statistics: bool, | ||
| 529 | /// The algorithm used to verify packs. They differ in costs. | ||
| 530 | #[clap( | ||
| 531 | long, | ||
| 532 | short = 'a', | ||
| 533 | default_value = "less-time", | ||
| 534 | possible_values(core::pack::verify::Algorithm::variants()) | ||
| 535 | )] | ||
| 536 | pub algorithm: core::pack::verify::Algorithm, | ||
| 537 | |||
| 538 | #[clap(long, conflicts_with("re-encode"))] | ||
| 539 | /// Decode and parse tags, commits and trees to validate their correctness beyond hashing correctly. | ||
| 540 | /// | ||
| 541 | /// Malformed objects should not usually occur, but could be injected on purpose or accident. | ||
| 542 | /// This will reduce overall performance. | ||
| 543 | pub decode: bool, | ||
| 544 | |||
| 545 | #[clap(long)] | ||
| 546 | /// Decode and parse tags, commits and trees to validate their correctness, and re-encode them. | ||
| 547 | /// | ||
| 548 | /// This flag is primarily to test the implementation of encoding, and requires to decode the object first. | ||
| 549 | /// Encoding an object after decoding it should yield exactly the same bytes. | ||
| 550 | /// This will reduce overall performance even more, as re-encoding requires to transform zero-copy objects into | ||
| 551 | /// owned objects, causing plenty of allocation to occur. | ||
| 552 | pub re_encode: bool, | ||
| 553 | } | ||
| 554 | |||
| 555 | /// | ||
| 556 | pub mod multi_index { | ||
| 557 | use std::path::PathBuf; | ||
| 558 | |||
| 559 | #[derive(Debug, clap::Parser)] | ||
| 560 | pub struct Platform { | ||
| 561 | /// The path to the index file. | ||
| 562 | #[clap(short = 'i', long, default_value = ".git/objects/pack/multi-pack-index")] | ||
| 563 | pub multi_index_path: PathBuf, | ||
| 564 | |||
| 565 | /// Subcommands | ||
| 566 | #[clap(subcommand)] | ||
| 567 | pub cmd: Subcommands, | ||
| 568 | } | ||
| 569 | |||
| 570 | #[derive(Debug, clap::Subcommand)] | ||
| 571 | pub enum Subcommands { | ||
| 572 | /// Display all entries of a multi-index: <oid> <pack-id> <pack-offset> | ||
| 573 | Entries, | ||
| 574 | /// Print general information about a multi-index file | ||
| 575 | Info, | ||
| 576 | /// Verify a multi-index quickly without inspecting objects themselves | ||
| 577 | Verify, | ||
| 578 | /// Create a multi-pack index from one or more pack index files, overwriting possibloy existing files. | ||
| 579 | Create { | ||
| 580 | /// Paths to the pack index files to read (with .idx extension). | ||
| 581 | /// | ||
| 582 | /// Note for the multi-index to be useful, it should be side-by-side with the supplied `.idx` files. | ||
| 583 | #[clap(required = true)] | ||
| 584 | index_paths: Vec<PathBuf>, | ||
| 585 | }, | ||
| 586 | } | ||
| 587 | } | ||
| 588 | |||
| 589 | /// | ||
| 590 | pub mod index { | ||
| 591 | use std::path::PathBuf; | ||
| 592 | |||
| 593 | use gitoxide_core as core; | ||
| 594 | |||
| 595 | #[derive(Debug, clap::Subcommand)] | ||
| 596 | pub enum Subcommands { | ||
| 597 | /// create a pack index from a pack data file. | ||
| 598 | Create { | ||
| 599 | /// Specify how to iterate the pack, defaults to 'verify' | ||
| 600 | /// | ||
| 601 | /// Valid values are | ||
| 602 | /// | ||
| 603 | /// **as-is** do not do anything and expect the pack file to be valid as per the trailing hash, | ||
| 604 | /// **verify** the input ourselves and validate that it matches with the hash provided in the pack, | ||
| 605 | /// **restore** hash the input ourselves and ignore failing entries, instead finish the pack with the hash we computed | ||
| 606 | /// to keep as many objects as possible. | ||
| 607 | #[clap( | ||
| 608 | long, | ||
| 609 | short = 'i', | ||
| 610 | default_value = "verify", | ||
| 611 | possible_values(core::pack::index::IterationMode::variants()) | ||
| 612 | )] | ||
| 613 | iteration_mode: core::pack::index::IterationMode, | ||
| 614 | |||
| 615 | /// Path to the pack file to read (with .pack extension). | ||
| 616 | /// | ||
| 617 | /// If unset, the pack file is expected on stdin. | ||
| 618 | #[clap(long, short = 'p')] | ||
| 619 | pack_path: Option<PathBuf>, | ||
| 620 | |||
| 621 | /// The folder into which to place the pack and the generated index file | ||
| 622 | /// | ||
| 623 | /// If unset, only informational output will be provided to standard output. | ||
| 624 | directory: Option<PathBuf>, | ||
| 625 | }, | ||
| 626 | } | ||
| 627 | } | ||
| 628 | } | ||
| 629 | |||
| 630 | /// | ||
| 631 | pub mod mailmap { | ||
| 632 | use std::path::PathBuf; | ||
| 633 | |||
| 634 | #[derive(Debug, clap::Parser)] | ||
| 635 | pub struct Platform { | ||
| 636 | /// The path to the mailmap file. | ||
| 637 | #[clap(short = 'p', long, default_value = ".mailmap")] | ||
| 638 | pub path: PathBuf, | ||
| 639 | |||
| 640 | /// Subcommands | ||
| 641 | #[clap(subcommand)] | ||
| 642 | pub cmd: Subcommands, | ||
| 643 | } | ||
| 644 | |||
| 645 | #[derive(Debug, clap::Subcommand)] | ||
| 646 | pub enum Subcommands { | ||
| 647 | /// Parse all entries in the mailmap and report malformed lines or collisions. | ||
| 648 | Verify, | ||
| 649 | } | ||
| 650 | } | ||
| 651 | } | ||
| 652 | |||
| 653 | pub mod exclude { | ||
| 654 | use std::ffi::OsString; | ||
| 655 | |||
| 656 | use git_repository as git; | ||
| 657 | |||
| 658 | #[derive(Debug, clap::Subcommand)] | ||
| 659 | pub enum Subcommands { | ||
| 660 | /// Check if path-specs are excluded and print the result similar to `git check-ignore`. | ||
| 661 | Query { | ||
| 662 | /// Show actual ignore patterns instead of un-excluding an entry. | ||
| 663 | /// | ||
| 664 | /// That way one can understand why an entry might not be excluded. | ||
| 665 | #[clap(long, short = 'i')] | ||
| 666 | show_ignore_patterns: bool, | ||
| 667 | /// Additional patterns to use for exclusions. They have the highest priority. | ||
| 668 | /// | ||
| 669 | /// Useful for undoing previous patterns using the '!' prefix. | ||
| 670 | #[clap(long, short = 'p')] | ||
| 671 | patterns: Vec<OsString>, | ||
| 672 | /// The git path specifications to check for exclusion, or unset to read from stdin one per line. | ||
| 673 | #[clap(parse(try_from_os_str = std::convert::TryFrom::try_from))] | ||
| 674 | pathspecs: Vec<git::path::Spec>, | ||
| 675 | }, | ||
| 676 | } | ||
| 677 | } | ||
| @@ -0,0 +1,368 @@ | |||
| 1 | #[derive(Debug, clap::Subcommand)] | ||
| 2 | #[clap(visible_alias = "no-repo")] | ||
| 3 | pub enum Subcommands { | ||
| 4 | /// Subcommands for interacting with commit-graphs | ||
| 5 | #[clap(subcommand)] | ||
| 6 | CommitGraph(commitgraph::Subcommands), | ||
| 7 | /// Subcommands for interacting with mailmaps | ||
| 8 | Mailmap { | ||
| 9 | #[clap(flatten)] | ||
| 10 | cmd: mailmap::Platform, | ||
| 11 | }, | ||
| 12 | /// Subcommands for interacting with pack files and indices | ||
| 13 | #[clap(subcommand)] | ||
| 14 | Pack(pack::Subcommands), | ||
| 15 | /// Subcommands for interacting with a worktree index, typically at .git/index | ||
| 16 | Index(index::Platform), | ||
| 17 | } | ||
| 18 | |||
| 19 | /// | ||
| 20 | pub mod commitgraph { | ||
| 21 | use std::path::PathBuf; | ||
| 22 | |||
| 23 | #[derive(Debug, clap::Subcommand)] | ||
| 24 | pub enum Subcommands { | ||
| 25 | /// Verify the integrity of a commit graph | ||
| 26 | Verify { | ||
| 27 | /// The path to '.git/objects/info/', '.git/objects/info/commit-graphs/', or '.git/objects/info/commit-graph' to validate. | ||
| 28 | path: PathBuf, | ||
| 29 | /// output statistical information about the pack | ||
| 30 | #[clap(long, short = 's')] | ||
| 31 | statistics: bool, | ||
| 32 | }, | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | pub mod index { | ||
| 37 | use std::path::PathBuf; | ||
| 38 | |||
| 39 | #[derive(Debug, clap::Parser)] | ||
| 40 | pub struct Platform { | ||
| 41 | /// The object format to assume when reading files that don't inherently know about it, or when writing files. | ||
| 42 | #[clap(long, default_value_t = git_repository::hash::Kind::default(), possible_values(&["SHA1"]))] | ||
| 43 | pub object_hash: git_repository::hash::Kind, | ||
| 44 | |||
| 45 | /// The path to the index file. | ||
| 46 | #[clap(short = 'i', long, default_value = ".git/index")] | ||
| 47 | pub index_path: PathBuf, | ||
| 48 | |||
| 49 | /// Subcommands | ||
| 50 | #[clap(subcommand)] | ||
| 51 | pub cmd: Subcommands, | ||
| 52 | } | ||
| 53 | |||
| 54 | #[derive(Debug, clap::Subcommand)] | ||
| 55 | pub enum Subcommands { | ||
| 56 | /// Validate constraints and assumptions of an index along with its integrity. | ||
| 57 | Verify, | ||
| 58 | /// Print all entries to standard output | ||
| 59 | Entries, | ||
| 60 | /// Print information about the index structure | ||
| 61 | Info { | ||
| 62 | /// Do not extract specific extension information to gain only a superficial idea of the index's composition. | ||
| 63 | #[clap(long)] | ||
| 64 | no_details: bool, | ||
| 65 | }, | ||
| 66 | /// Checkout the index into a directory with exclusive write access, similar to what would happen during clone. | ||
| 67 | CheckoutExclusive { | ||
| 68 | /// The path to `.git` repository from which objects can be obtained to write the actual files referenced | ||
| 69 | /// in the index. Use this measure the impact on extracting objects on overall performance. | ||
| 70 | #[clap(long, short = 'r')] | ||
| 71 | repository: Option<PathBuf>, | ||
| 72 | /// Ignore errors and keep checking out as many files as possible, and report all errors at the end of the operation. | ||
| 73 | #[clap(long, short = 'k')] | ||
| 74 | keep_going: bool, | ||
| 75 | /// Enable to query the object database yet write only empty files. This is useful to measure the overhead of ODB query | ||
| 76 | /// compared to writing the bytes to disk. | ||
| 77 | #[clap(long, short = 'e', requires = "repository")] | ||
| 78 | empty_files: bool, | ||
| 79 | /// The directory into which to write all index entries. | ||
| 80 | directory: PathBuf, | ||
| 81 | }, | ||
| 82 | } | ||
| 83 | } | ||
| 84 | |||
| 85 | /// | ||
| 86 | pub mod pack { | ||
| 87 | use std::{ffi::OsString, path::PathBuf}; | ||
| 88 | |||
| 89 | use gitoxide_core as core; | ||
| 90 | |||
| 91 | #[derive(Debug, clap::Subcommand)] | ||
| 92 | pub enum Subcommands { | ||
| 93 | /// Subcommands for interacting with pack indices (.idx) | ||
| 94 | #[clap(subcommand)] | ||
| 95 | Index(index::Subcommands), | ||
| 96 | /// Subcommands for interacting with multi-pack indices (named "multi-pack-index") | ||
| 97 | MultiIndex(multi_index::Platform), | ||
| 98 | /// Create a new pack with a set of objects. | ||
| 99 | Create { | ||
| 100 | #[clap(long, short = 'r')] | ||
| 101 | /// the directory containing the '.git' repository from which objects should be read. | ||
| 102 | repository: Option<PathBuf>, | ||
| 103 | |||
| 104 | #[clap(long, short = 'e', possible_values(core::pack::create::ObjectExpansion::variants()))] | ||
| 105 | /// the way objects are expanded. They differ in costs. | ||
| 106 | /// | ||
| 107 | /// Possible values are "none" and "tree-traversal". Default is "none". | ||
| 108 | expansion: Option<core::pack::create::ObjectExpansion>, | ||
| 109 | |||
| 110 | #[clap(long, default_value_t = 3, requires = "nondeterministic-count")] | ||
| 111 | /// The amount of threads to use when counting and the `--nondeterminisitc-count` flag is set, defaulting | ||
| 112 | /// to the globally configured threads. | ||
| 113 | /// | ||
| 114 | /// Use it to have different trade-offs between counting performance and cost in terms of CPU, as the scaling | ||
| 115 | /// here is everything but linear. The effectiveness of each core seems to be no more than 30%. | ||
| 116 | counting_threads: usize, | ||
| 117 | |||
| 118 | #[clap(long)] | ||
| 119 | /// if set, the counting phase may be accelerated using multithreading. | ||
| 120 | /// | ||
| 121 | /// On the flip side, however, one will loose deterministic counting results which affects the | ||
| 122 | /// way the resulting pack is structured. | ||
| 123 | nondeterministic_count: bool, | ||
| 124 | |||
| 125 | #[clap(long, short = 's')] | ||
| 126 | /// If set statistical information will be presented to inform about pack creation details. | ||
| 127 | /// It's a form of instrumentation for developers to help improve pack generation. | ||
| 128 | statistics: bool, | ||
| 129 | |||
| 130 | #[clap(long)] | ||
| 131 | /// The size in megabytes for a cache to speed up pack access for packs with long delta chains. | ||
| 132 | /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size. | ||
| 133 | /// | ||
| 134 | /// If unset, no cache will be used. | ||
| 135 | pack_cache_size_mb: Option<usize>, | ||
| 136 | |||
| 137 | #[clap(long)] | ||
| 138 | /// The size in megabytes for a cache to speed up accessing entire objects, bypassing object database access when hit. | ||
| 139 | /// It is shared among all threads, so 4 threads would use their own cache 1/4th of the size. | ||
| 140 | /// | ||
| 141 | /// This cache type is currently only effective when using the 'diff-tree' object expansion. | ||
| 142 | /// | ||
| 143 | /// If unset, no cache will be used. | ||
| 144 | object_cache_size_mb: Option<usize>, | ||
| 145 | |||
| 146 | #[clap(long)] | ||
| 147 | /// if set, delta-objects whose base object wouldn't be in the pack will not be recompressed as base object, but instead | ||
| 148 | /// refer to its base object using its object id. | ||
| 149 | /// | ||
| 150 | /// This allows for smaller packs but requires the receiver of the pack to resolve these ids before storing the pack. | ||
| 151 | /// Packs produced with this option enabled are only valid in transit, but not at rest. | ||
| 152 | thin: bool, | ||
| 153 | |||
| 154 | /// The directory into which to write the pack file. | ||
| 155 | #[clap(long, short = 'o')] | ||
| 156 | output_directory: Option<PathBuf>, | ||
| 157 | |||
| 158 | /// The tips from which to start the commit graph iteration, either as fully qualified commit hashes | ||
| 159 | /// or as branch names. | ||
| 160 | /// | ||
| 161 | /// If empty, we expect to read objects on stdin and default to 'none' as expansion mode. | ||
| 162 | /// Otherwise the expansion mode is 'tree-traversal' by default. | ||
| 163 | tips: Vec<OsString>, | ||
| 164 | }, | ||
| 165 | /// Use the git-protocol to receive a pack, emulating a clone. | ||
| 166 | #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))] | ||
| 167 | Receive { | ||
| 168 | /// The protocol version to use. Valid values are 1 and 2 | ||
| 169 | #[clap(long, short = 'p')] | ||
| 170 | protocol: Option<core::net::Protocol>, | ||
| 171 | |||
| 172 | /// the directory into which to write references. Existing files will be overwritten. | ||
| 173 | /// | ||
| 174 | /// Note that the directory will be created if needed. | ||
| 175 | #[clap(long, short = 'd')] | ||
| 176 | refs_directory: Option<PathBuf>, | ||
| 177 | |||
| 178 | /// The URLs or path from which to receive the pack. | ||
| 179 | /// | ||
| 180 | /// See here for a list of supported URLs: <https://www.git-scm.com/docs/git-clone#_git_urls> | ||
| 181 | url: String, | ||
| 182 | |||
| 183 | /// If set once or more times, these references will be fetched instead of all advertised ones. | ||
| 184 | /// | ||
| 185 | /// Note that this requires a reasonably modern git server. | ||
| 186 | #[clap(long = "reference", short = 'r')] | ||
| 187 | refs: Vec<String>, | ||
| 188 | |||
| 189 | /// The directory into which to write the received pack and index. | ||
| 190 | /// | ||
| 191 | /// If unset, they will be discarded. | ||
| 192 | directory: Option<PathBuf>, | ||
| 193 | }, | ||
| 194 | /// Dissolve a pack into its loose objects. | ||
| 195 | /// | ||
| 196 | /// Note that this effectively removes delta compression for an average compression of 2x, creating one file per object in the process. | ||
| 197 | /// Thus this should only be done to dissolve small packs after a fetch. | ||
| 198 | Explode { | ||
| 199 | #[clap(long)] | ||
| 200 | /// Read written objects back and assert they match their source. Fail the operation otherwise. | ||
| 201 | /// | ||
| 202 | /// Only relevant if an object directory is set. | ||
| 203 | verify: bool, | ||
| 204 | |||
| 205 | /// delete the pack and index file after the operation is successful | ||
| 206 | #[clap(long)] | ||
| 207 | delete_pack: bool, | ||
| 208 | |||
| 209 | /// The amount of checks to run | ||
| 210 | #[clap( | ||
| 211 | long, | ||
| 212 | short = 'c', | ||
| 213 | default_value = "all", | ||
| 214 | possible_values(core::pack::explode::SafetyCheck::variants()) | ||
| 215 | )] | ||
| 216 | check: core::pack::explode::SafetyCheck, | ||
| 217 | |||
| 218 | /// Compress bytes even when using the sink, i.e. no object directory is specified | ||
| 219 | /// | ||
| 220 | /// This helps to determine overhead related to compression. If unset, the sink will | ||
| 221 | /// only create hashes from bytes, which is usually limited by the speed at which input | ||
| 222 | /// can be obtained. | ||
| 223 | #[clap(long)] | ||
| 224 | sink_compress: bool, | ||
| 225 | |||
| 226 | /// The '.pack' or '.idx' file to explode into loose objects | ||
| 227 | pack_path: PathBuf, | ||
| 228 | |||
| 229 | /// The path into which all objects should be written. Commonly '.git/objects' | ||
| 230 | object_path: Option<PathBuf>, | ||
| 231 | }, | ||
| 232 | /// Verify the integrity of a pack, index or multi-index file | ||
| 233 | Verify { | ||
| 234 | #[clap(flatten)] | ||
| 235 | args: VerifyOptions, | ||
| 236 | |||
| 237 | /// The '.pack', '.idx' or 'multi-pack-index' file to validate. | ||
| 238 | path: PathBuf, | ||
| 239 | }, | ||
| 240 | } | ||
| 241 | |||
| 242 | #[derive(Debug, clap::Parser)] | ||
| 243 | pub struct VerifyOptions { | ||
| 244 | /// output statistical information | ||
| 245 | #[clap(long, short = 's')] | ||
| 246 | pub statistics: bool, | ||
| 247 | /// The algorithm used to verify packs. They differ in costs. | ||
| 248 | #[clap( | ||
| 249 | long, | ||
| 250 | short = 'a', | ||
| 251 | default_value = "less-time", | ||
| 252 | possible_values(core::pack::verify::Algorithm::variants()) | ||
| 253 | )] | ||
| 254 | pub algorithm: core::pack::verify::Algorithm, | ||
| 255 | |||
| 256 | #[clap(long, conflicts_with("re-encode"))] | ||
| 257 | /// Decode and parse tags, commits and trees to validate their correctness beyond hashing correctly. | ||
| 258 | /// | ||
| 259 | /// Malformed objects should not usually occur, but could be injected on purpose or accident. | ||
| 260 | /// This will reduce overall performance. | ||
| 261 | pub decode: bool, | ||
| 262 | |||
| 263 | #[clap(long)] | ||
| 264 | /// Decode and parse tags, commits and trees to validate their correctness, and re-encode them. | ||
| 265 | /// | ||
| 266 | /// This flag is primarily to test the implementation of encoding, and requires to decode the object first. | ||
| 267 | /// Encoding an object after decoding it should yield exactly the same bytes. | ||
| 268 | /// This will reduce overall performance even more, as re-encoding requires to transform zero-copy objects into | ||
| 269 | /// owned objects, causing plenty of allocation to occur. | ||
| 270 | pub re_encode: bool, | ||
| 271 | } | ||
| 272 | |||
| 273 | /// | ||
| 274 | pub mod multi_index { | ||
| 275 | use std::path::PathBuf; | ||
| 276 | |||
| 277 | #[derive(Debug, clap::Parser)] | ||
| 278 | pub struct Platform { | ||
| 279 | /// The path to the index file. | ||
| 280 | #[clap(short = 'i', long, default_value = ".git/objects/pack/multi-pack-index")] | ||
| 281 | pub multi_index_path: PathBuf, | ||
| 282 | |||
| 283 | /// Subcommands | ||
| 284 | #[clap(subcommand)] | ||
| 285 | pub cmd: Subcommands, | ||
| 286 | } | ||
| 287 | |||
| 288 | #[derive(Debug, clap::Subcommand)] | ||
| 289 | pub enum Subcommands { | ||
| 290 | /// Display all entries of a multi-index: <oid> <pack-id> <pack-offset> | ||
| 291 | Entries, | ||
| 292 | /// Print general information about a multi-index file | ||
| 293 | Info, | ||
| 294 | /// Verify a multi-index quickly without inspecting objects themselves | ||
| 295 | Verify, | ||
| 296 | /// Create a multi-pack index from one or more pack index files, overwriting possibloy existing files. | ||
| 297 | Create { | ||
| 298 | /// Paths to the pack index files to read (with .idx extension). | ||
| 299 | /// | ||
| 300 | /// Note for the multi-index to be useful, it should be side-by-side with the supplied `.idx` files. | ||
| 301 | #[clap(required = true)] | ||
| 302 | index_paths: Vec<PathBuf>, | ||
| 303 | }, | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /// | ||
| 308 | pub mod index { | ||
| 309 | use std::path::PathBuf; | ||
| 310 | |||
| 311 | use gitoxide_core as core; | ||
| 312 | |||
| 313 | #[derive(Debug, clap::Subcommand)] | ||
| 314 | pub enum Subcommands { | ||
| 315 | /// create a pack index from a pack data file. | ||
| 316 | Create { | ||
| 317 | /// Specify how to iterate the pack, defaults to 'verify' | ||
| 318 | /// | ||
| 319 | /// Valid values are | ||
| 320 | /// | ||
| 321 | /// **as-is** do not do anything and expect the pack file to be valid as per the trailing hash, | ||
| 322 | /// **verify** the input ourselves and validate that it matches with the hash provided in the pack, | ||
| 323 | /// **restore** hash the input ourselves and ignore failing entries, instead finish the pack with the hash we computed | ||
| 324 | /// to keep as many objects as possible. | ||
| 325 | #[clap( | ||
| 326 | long, | ||
| 327 | short = 'i', | ||
| 328 | default_value = "verify", | ||
| 329 | possible_values(core::pack::index::IterationMode::variants()) | ||
| 330 | )] | ||
| 331 | iteration_mode: core::pack::index::IterationMode, | ||
| 332 | |||
| 333 | /// Path to the pack file to read (with .pack extension). | ||
| 334 | /// | ||
| 335 | /// If unset, the pack file is expected on stdin. | ||
| 336 | #[clap(long, short = 'p')] | ||
| 337 | pack_path: Option<PathBuf>, | ||
| 338 | |||
| 339 | /// The folder into which to place the pack and the generated index file | ||
| 340 | /// | ||
| 341 | /// If unset, only informational output will be provided to standard output. | ||
| 342 | directory: Option<PathBuf>, | ||
| 343 | }, | ||
| 344 | } | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | /// | ||
| 349 | pub mod mailmap { | ||
| 350 | use std::path::PathBuf; | ||
| 351 | |||
| 352 | #[derive(Debug, clap::Parser)] | ||
| 353 | pub struct Platform { | ||
| 354 | /// The path to the mailmap file. | ||
| 355 | #[clap(short = 'p', long, default_value = ".mailmap")] | ||
| 356 | pub path: PathBuf, | ||
| 357 | |||
| 358 | /// Subcommands | ||
| 359 | #[clap(subcommand)] | ||
| 360 | pub cmd: Subcommands, | ||
| 361 | } | ||
| 362 | |||
| 363 | #[derive(Debug, clap::Subcommand)] | ||
| 364 | pub enum Subcommands { | ||
| 365 | /// Parse all entries in the mailmap and report malformed lines or collisions. | ||
| 366 | Verify, | ||
| 367 | } | ||
| 368 | } | ||
| @@ -0,0 +1,319 @@ | |||
| 1 | use std::path::PathBuf; | ||
| 2 | |||
| 3 | use git_repository as git; | ||
| 4 | use git_repository::bstr::BString; | ||
| 5 | use gitoxide_core as core; | ||
| 6 | |||
| 7 | #[derive(Debug, clap::Parser)] | ||
| 8 | #[clap(name = "gix-plumbing", about = "The git underworld", version = clap::crate_version!())] | ||
| 9 | #[clap(subcommand_required = true)] | ||
| 10 | #[clap(arg_required_else_help = true)] | ||
| 11 | pub struct Args { | ||
| 12 | /// The repository to access. | ||
| 13 | #[clap(short = 'r', long, default_value = ".")] | ||
| 14 | pub repository: PathBuf, | ||
| 15 | |||
| 16 | /// Add these values to the configuration in the form of `key=value` or `key`. | ||
| 17 | /// | ||
| 18 | /// For example, if `key` is `core.abbrev`, set configuration like `[core] abbrev = key`, | ||
| 19 | /// or `remote.origin.url = foo` to set `[remote "origin"] url = foo`. | ||
| 20 | #[clap(long, short = 'c', parse(try_from_os_str = git::env::os_str_to_bstring))] | ||
| 21 | pub config: Vec<BString>, | ||
| 22 | |||
| 23 | #[clap(long, short = 't')] | ||
| 24 | /// The amount of threads to use for some operations. | ||
| 25 | /// | ||
| 26 | /// If unset, or the value is 0, there is no limit and all logical cores can be used. | ||
| 27 | pub threads: Option<usize>, | ||
| 28 | |||
| 29 | /// Display verbose messages and progress information | ||
| 30 | #[clap(long, short = 'v')] | ||
| 31 | pub verbose: bool, | ||
| 32 | |||
| 33 | /// Bring up a terminal user interface displaying progress visually | ||
| 34 | #[cfg(feature = "prodash-render-tui")] | ||
| 35 | #[clap(long, conflicts_with("verbose"))] | ||
| 36 | pub progress: bool, | ||
| 37 | |||
| 38 | /// The progress TUI will stay up even though the work is already completed. | ||
| 39 | /// | ||
| 40 | /// Use this to be able to read progress messages or additional information visible in the TUI log pane. | ||
| 41 | #[cfg(feature = "prodash-render-tui")] | ||
| 42 | #[clap(long, conflicts_with("verbose"), requires("progress"))] | ||
| 43 | pub progress_keep_open: bool, | ||
| 44 | |||
| 45 | /// Determine the format to use when outputting statistics. | ||
| 46 | #[clap( | ||
| 47 | long, | ||
| 48 | short = 'f', | ||
| 49 | default_value = "human", | ||
| 50 | possible_values(core::OutputFormat::variants()) | ||
| 51 | )] | ||
| 52 | pub format: core::OutputFormat, | ||
| 53 | |||
| 54 | /// The object format to assume when reading files that don't inherently know about it, or when writing files. | ||
| 55 | #[clap(long, default_value_t = git_repository::hash::Kind::default(), possible_values(&["SHA1"]))] | ||
| 56 | pub object_hash: git_repository::hash::Kind, | ||
| 57 | |||
| 58 | #[clap(subcommand)] | ||
| 59 | pub cmd: Subcommands, | ||
| 60 | } | ||
| 61 | |||
| 62 | #[derive(Debug, clap::Subcommand)] | ||
| 63 | pub enum Subcommands { | ||
| 64 | /// Interact with the object database. | ||
| 65 | #[clap(subcommand)] | ||
| 66 | Odb(odb::Subcommands), | ||
| 67 | /// Interact with tree objects. | ||
| 68 | #[clap(subcommand)] | ||
| 69 | Tree(tree::Subcommands), | ||
| 70 | /// Interact with commit objects. | ||
| 71 | #[clap(subcommand)] | ||
| 72 | Commit(commit::Subcommands), | ||
| 73 | /// Verify the integrity of the entire repository | ||
| 74 | Verify { | ||
| 75 | #[clap(flatten)] | ||
| 76 | args: free::pack::VerifyOptions, | ||
| 77 | }, | ||
| 78 | /// Query and obtain information about revisions. | ||
| 79 | #[clap(subcommand)] | ||
| 80 | Revision(revision::Subcommands), | ||
| 81 | /// A program just like `git credential`. | ||
| 82 | #[clap(subcommand)] | ||
| 83 | Credential(credential::Subcommands), | ||
| 84 | /// Interact with the mailmap. | ||
| 85 | #[clap(subcommand)] | ||
| 86 | Mailmap(mailmap::Subcommands), | ||
| 87 | /// Interact with the remote hosts. | ||
| 88 | Remote(remote::Platform), | ||
| 89 | /// Interact with the exclude files like .gitignore. | ||
| 90 | #[clap(subcommand)] | ||
| 91 | Exclude(exclude::Subcommands), | ||
| 92 | #[clap(subcommand)] | ||
| 93 | Progress(progress::Subcommands), | ||
| 94 | Config(config::Platform), | ||
| 95 | /// Subcommands that need no git repository to run. | ||
| 96 | #[clap(subcommand)] | ||
| 97 | Free(free::Subcommands), | ||
| 98 | } | ||
| 99 | |||
| 100 | pub mod progress { | ||
| 101 | |||
| 102 | #[derive(Debug, clap::Subcommand)] | ||
| 103 | pub enum Subcommands { | ||
| 104 | /// Show the implementation progress of gitoxide based on the git configuration that it consumes. | ||
| 105 | Show, | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | pub mod config { | ||
| 110 | /// Print all entries in a configuration file or access other sub-commands | ||
| 111 | #[derive(Debug, clap::Parser)] | ||
| 112 | #[clap(subcommand_required(false))] | ||
| 113 | pub struct Platform { | ||
| 114 | /// The filter terms to limit the output to matching sections and subsections only. | ||
| 115 | /// | ||
| 116 | /// Typical filters are `branch` or `remote.origin` or `remote.or*` - git-style globs are supported | ||
| 117 | /// and comparisons are case-insensitive. | ||
| 118 | pub filter: Vec<String>, | ||
| 119 | } | ||
| 120 | } | ||
| 121 | |||
| 122 | pub mod remote { | ||
| 123 | use git_repository as git; | ||
| 124 | |||
| 125 | #[derive(Debug, clap::Parser)] | ||
| 126 | pub struct Platform { | ||
| 127 | /// The name of the remote to connect to. | ||
| 128 | /// | ||
| 129 | /// If unset, the current branch will determine the remote. | ||
| 130 | #[clap(long, short = 'n')] | ||
| 131 | pub name: Option<String>, | ||
| 132 | |||
| 133 | /// Connect directly to the given URL, forgoing any configuration from the repository. | ||
| 134 | #[clap(long, short = 'u', conflicts_with("name"), parse(try_from_os_str = std::convert::TryFrom::try_from))] | ||
| 135 | pub url: Option<git::Url>, | ||
| 136 | |||
| 137 | /// Output additional typically information provided by the server as part of the connection handshake. | ||
| 138 | #[clap(long)] | ||
| 139 | pub handshake_info: bool, | ||
| 140 | |||
| 141 | /// Subcommands | ||
| 142 | #[clap(subcommand)] | ||
| 143 | pub cmd: Subcommands, | ||
| 144 | } | ||
| 145 | |||
| 146 | #[derive(Debug, clap::Subcommand)] | ||
| 147 | #[clap(visible_alias = "remotes")] | ||
| 148 | pub enum Subcommands { | ||
| 149 | /// Print all references available on the remote. | ||
| 150 | #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))] | ||
| 151 | Refs, | ||
| 152 | /// Print all references available on the remote as filtered through ref-specs. | ||
| 153 | #[cfg(any(feature = "gitoxide-core-async-client", feature = "gitoxide-core-blocking-client"))] | ||
| 154 | RefMap { | ||
| 155 | /// Override the built-in and configured ref-specs with one or more of the given ones. | ||
| 156 | #[clap(parse(try_from_os_str = git::env::os_str_to_bstring))] | ||
| 157 | ref_spec: Vec<git_repository::bstr::BString>, | ||
| 158 | }, | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | pub mod mailmap { | ||
| 163 | #[derive(Debug, clap::Subcommand)] | ||
| 164 | pub enum Subcommands { | ||
| 165 | /// Print all entries in configured mailmaps, inform about errors as well. | ||
| 166 | Entries, | ||
| 167 | } | ||
| 168 | } | ||
| 169 | |||
| 170 | pub mod odb { | ||
| 171 | #[derive(Debug, clap::Subcommand)] | ||
| 172 | pub enum Subcommands { | ||
| 173 | /// Print all object names. | ||
| 174 | Entries, | ||
| 175 | /// Provide general information about the object database. | ||
| 176 | Info, | ||
| 177 | } | ||
| 178 | } | ||
| 179 | |||
| 180 | pub mod tree { | ||
| 181 | #[derive(Debug, clap::Subcommand)] | ||
| 182 | pub enum Subcommands { | ||
| 183 | /// Print entries in a given tree | ||
| 184 | Entries { | ||
| 185 | /// Traverse the entire tree and its subtrees respectively, not only this tree. | ||
| 186 | #[clap(long, short = 'r')] | ||
| 187 | recursive: bool, | ||
| 188 | |||
| 189 | /// Provide files size as well. This is expensive as the object is decoded entirely. | ||
| 190 | #[clap(long, short = 'e')] | ||
| 191 | extended: bool, | ||
| 192 | |||
| 193 | /// The tree to traverse, or the tree at `HEAD` if unspecified. | ||
| 194 | treeish: Option<String>, | ||
| 195 | }, | ||
| 196 | /// Provide information about a tree. | ||
| 197 | Info { | ||
| 198 | /// Provide files size as well. This is expensive as the object is decoded entirely. | ||
| 199 | #[clap(long, short = 'e')] | ||
| 200 | extended: bool, | ||
| 201 | /// The tree to traverse, or the tree at `HEAD` if unspecified. | ||
| 202 | treeish: Option<String>, | ||
| 203 | }, | ||
| 204 | } | ||
| 205 | } | ||
| 206 | |||
| 207 | pub mod commit { | ||
| 208 | #[derive(Debug, clap::Subcommand)] | ||
| 209 | pub enum Subcommands { | ||
| 210 | /// Describe the current commit or the given one using the name of the closest annotated tag in its ancestry. | ||
| 211 | Describe { | ||
| 212 | /// Use annotated tag references only, not all tags. | ||
| 213 | #[clap(long, short = 't', conflicts_with("all-refs"))] | ||
| 214 | annotated_tags: bool, | ||
| 215 | |||
| 216 | /// Use all references under the `ref/` namespaces, which includes tag references, local and remote branches. | ||
| 217 | #[clap(long, short = 'a', conflicts_with("annotated-tags"))] | ||
| 218 | all_refs: bool, | ||
| 219 | |||
| 220 | /// Only follow the first parent when traversing the commit graph. | ||
| 221 | #[clap(long, short = 'f')] | ||
| 222 | first_parent: bool, | ||
| 223 | |||
| 224 | /// Always display the long format, even if that would not be necessary as the id is located directly on a reference. | ||
| 225 | #[clap(long, short = 'l')] | ||
| 226 | long: bool, | ||
| 227 | |||
| 228 | /// Consider only the given `n` candidates. This can take longer, but potentially produces more accurate results. | ||
| 229 | #[clap(long, short = 'c', default_value = "10")] | ||
| 230 | max_candidates: usize, | ||
| 231 | |||
| 232 | /// Print information on stderr to inform about performance statistics | ||
| 233 | #[clap(long, short = 's')] | ||
| 234 | statistics: bool, | ||
| 235 | |||
| 236 | #[clap(long)] | ||
| 237 | /// If there was no way to describe the commit, fallback to using the abbreviated input revision. | ||
| 238 | always: bool, | ||
| 239 | |||
| 240 | /// A specification of the revision to use, or the current `HEAD` if unset. | ||
| 241 | rev_spec: Option<String>, | ||
| 242 | }, | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | pub mod credential { | ||
| 247 | #[derive(Debug, clap::Subcommand)] | ||
| 248 | pub enum Subcommands { | ||
| 249 | /// Get the credentials fed for `url=<url>` via STDIN. | ||
| 250 | #[clap(visible_alias = "get")] | ||
| 251 | Fill, | ||
| 252 | /// Approve the information piped via STDIN as obtained with last call to `fill` | ||
| 253 | #[clap(visible_alias = "store")] | ||
| 254 | Approve, | ||
| 255 | /// Try to resolve the given revspec and print the object names. | ||
| 256 | #[clap(visible_alias = "erase")] | ||
| 257 | Reject, | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | pub mod revision { | ||
| 262 | #[derive(Debug, clap::Subcommand)] | ||
| 263 | #[clap(visible_alias = "rev", visible_alias = "r")] | ||
| 264 | pub enum Subcommands { | ||
| 265 | /// List all commits reachable from the given rev-spec. | ||
| 266 | #[clap(visible_alias = "l")] | ||
| 267 | List { spec: std::ffi::OsString }, | ||
| 268 | /// Provide the revision specification like `@~1` to explain. | ||
| 269 | #[clap(visible_alias = "e")] | ||
| 270 | Explain { spec: std::ffi::OsString }, | ||
| 271 | /// Try to resolve the given revspec and print the object names. | ||
| 272 | #[clap(visible_alias = "query", visible_alias = "parse", visible_alias = "p")] | ||
| 273 | Resolve { | ||
| 274 | /// Instead of resolving a rev-spec, explain what would be done for the first spec. | ||
| 275 | /// | ||
| 276 | /// Equivalent to the `explain` subcommand. | ||
| 277 | #[clap(short = 'e', long)] | ||
| 278 | explain: bool, | ||
| 279 | /// Show the first resulting object similar to how `git cat-file` would, but don't show the resolved spec. | ||
| 280 | #[clap(short = 'c', long, conflicts_with = "explain")] | ||
| 281 | cat_file: bool, | ||
| 282 | /// rev-specs like `@`, `@~1` or `HEAD^2`. | ||
| 283 | #[clap(required = true)] | ||
| 284 | specs: Vec<std::ffi::OsString>, | ||
| 285 | }, | ||
| 286 | /// Return the names and hashes of all previously checked-out branches. | ||
| 287 | #[clap(visible_alias = "prev")] | ||
| 288 | PreviousBranches, | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | pub mod exclude { | ||
| 293 | use std::ffi::OsString; | ||
| 294 | |||
| 295 | use git_repository as git; | ||
| 296 | |||
| 297 | #[derive(Debug, clap::Subcommand)] | ||
| 298 | pub enum Subcommands { | ||
| 299 | /// Check if path-specs are excluded and print the result similar to `git check-ignore`. | ||
| 300 | Query { | ||
| 301 | /// Show actual ignore patterns instead of un-excluding an entry. | ||
| 302 | /// | ||
| 303 | /// That way one can understand why an entry might not be excluded. | ||
| 304 | #[clap(long, short = 'i')] | ||
| 305 | show_ignore_patterns: bool, | ||
| 306 | /// Additional patterns to use for exclusions. They have the highest priority. | ||
| 307 | /// | ||
| 308 | /// Useful for undoing previous patterns using the '!' prefix. | ||
| 309 | #[clap(long, short = 'p')] | ||
| 310 | patterns: Vec<OsString>, | ||
| 311 | /// The git path specifications to check for exclusion, or unset to read from stdin one per line. | ||
| 312 | #[clap(parse(try_from_os_str = std::convert::TryFrom::try_from))] | ||
| 313 | pathspecs: Vec<git::path::Spec>, | ||
| 314 | }, | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | /// | ||
| 319 | pub mod free; | ||
| @@ -0,0 +1,44 @@ | |||
| 1 | use crosstermion::crossterm::style::Stylize; | ||
| 2 | use std::fmt::{Display, Formatter}; | ||
| 3 | |||
| 4 | enum Usage { | ||
| 5 | InModule(&'static str), | ||
| 6 | } | ||
| 7 | use Usage::*; | ||
| 8 | |||
| 9 | impl Display for Usage { | ||
| 10 | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { | ||
| 11 | match self { | ||
| 12 | InModule(m) => write!(f, "mod {m}"), | ||
| 13 | } | ||
| 14 | } | ||
| 15 | } | ||
| 16 | |||
| 17 | struct Record { | ||
| 18 | config: &'static str, | ||
| 19 | usage: Usage, | ||
| 20 | deviation: Option<&'static str>, | ||
| 21 | } | ||
| 22 | |||
| 23 | static GIT_CONFIG: &[Record] = &[Record { | ||
| 24 | config: "pack.threads", | ||
| 25 | usage: InModule("remote::connection::fetch"), | ||
| 26 | deviation: Some("if unset, it uses all threads as opposed to just 1"), | ||
| 27 | }]; | ||
| 28 | |||
| 29 | /// A programmatic way to record and display progress. | ||
| 30 | pub fn show_progress() -> anyhow::Result<()> { | ||
| 31 | for Record { | ||
| 32 | config, | ||
| 33 | usage, | ||
| 34 | deviation, | ||
| 35 | } in GIT_CONFIG | ||
| 36 | { | ||
| 37 | println!( | ||
| 38 | "{}: {usage}{}", | ||
| 39 | config.bold(), | ||
| 40 | deviation.map(|d| format!(" ({d})")).unwrap_or_default().dark_grey() | ||
| 41 | ); | ||
| 42 | } | ||
| 43 | Ok(()) | ||
| 44 | } | ||