git_lfs/args.rs
1//! Clap CLI surface (struct `Cli` + subcommands).
2//!
3//! Extracted from `main.rs` so xtask (and any future tool) can
4//! reuse the command tree for man-page generation, completion
5//! scripts, etc. Keep this file focused on the clap derive — all
6//! dispatch / business logic stays in main.rs and the per-command
7//! modules.
8//!
9//! Each subcommand is a tuple variant on [`Command`] delegating to
10//! a `*Args` struct. The struct is the home for the rustdoc that
11//! drives clap's `about` / `long_about` (first paragraph → about,
12//! rest → long_about) and for `#[command(...)]` extras such as
13//! `after_help`, aliases, and arg-group headings. Keep the variants
14//! themselves bare — putting a doc comment on the variant would
15//! shadow the struct's docs.
16
17use std::path::PathBuf;
18
19use clap::{Args, Parser, Subcommand};
20
21#[derive(Parser)]
22#[command(
23 name = "git-lfs",
24 about = "Git LFS — large file storage for git",
25 // We want `git lfs --version` to print the same banner as
26 // `git lfs version`. clap's auto-derived `--version` would
27 // emit `git-lfs <version>` (one token, no `/` separator),
28 // which doesn't match the user-agent style upstream uses.
29 // Suppress clap's flag and handle --version ourselves.
30 disable_version_flag = true,
31 max_term_width = 100,
32)]
33pub struct Cli {
34 /// Print the version banner and exit.
35 #[arg(long, short = 'V', global = true)]
36 pub version: bool,
37
38 #[command(subcommand)]
39 pub command: Option<Command>,
40}
41
42// note: don't add rustdoc comments here, they will shadow the struct's docs
43// in the clap-generated help output
44#[derive(Subcommand)]
45pub enum Command {
46 Clean(CleanArgs),
47 Smudge(SmudgeArgs),
48 Install(InstallArgs),
49 Uninstall(UninstallArgs),
50 Track(TrackArgs),
51 Untrack(UntrackArgs),
52 FilterProcess(FilterProcessArgs),
53 Fetch(FetchArgs),
54 Pull(PullArgs),
55 Push(PushArgs),
56 Clone(CloneArgs),
57 PostCheckout(PostCheckoutArgs),
58 PostCommit(PostCommitArgs),
59 PostMerge(PostMergeArgs),
60 PrePush(PrePushArgs),
61 Version(VersionArgs),
62 Pointer(PointerArgs),
63 Env(EnvArgs),
64 Ext(ExtArgs),
65 Update(UpdateArgs),
66 Migrate(MigrateArgs),
67 Checkout(CheckoutArgs),
68 Prune(PruneArgs),
69 Fsck(FsckArgs),
70 Status(StatusArgs),
71 Lock(LockArgs),
72 Locks(LocksArgs),
73 Unlock(UnlockArgs),
74 LsFiles(LsFilesArgs),
75}
76
77/// Git clean filter that converts large files to pointers
78///
79/// Read the contents of a large file from standard input, and write a
80/// Git LFS pointer file for that file to standard output.
81///
82/// Clean is typically run by Git’s clean filter, configured by the
83/// repository’s Git attributes.
84///
85/// Clean is not part of the user-facing Git plumbing commands.
86/// To preview the pointer of a large file as it would be generated,
87/// see the git-lfs-pointer(1) command.
88#[derive(Args)]
89pub struct CleanArgs {
90 /// Working-tree path of the file being cleaned.
91 ///
92 /// Substituted for `%f` in any configured `lfs.extension.<name>.clean` command.
93 pub path: Option<PathBuf>,
94}
95
96/// Git smudge filter that converts pointer in blobs to the actual content
97///
98/// Read a Git LFS pointer file from standard input and write the contents of the
99/// corresponding large file to standard output. If needed, download the file’s
100/// contents from the Git LFS endpoint. The argument, if provided, is only used
101/// for a progress bar.
102///
103/// Smudge is typically run by Git’s smudge filter, configured by the repository’s
104/// Git attributes.
105///
106/// In your Git configuration or in a .lfsconfig file, you may set either or both
107/// of `lfs.fetchinclude` and `lfs.fetchexclude` to comma-separated lists of paths.
108/// If `lfs.fetchinclude` is defined, Git LFS pointer files will only be replaced
109/// with the contents of the corresponding Git LFS object file if their path
110/// matches one in that list, and if `lfs.fetchexclude` is defined, Git LFS pointer
111/// files will only be replaced with the contents of the corresponding Git LFS
112/// object file if their path does not match one in that list. Paths are matched
113/// using wildcard matching as per gitignore(5). Git LFS pointer files that are
114/// not replaced with the contents of their corresponding object files are simply
115/// copied to standard output without change.
116///
117/// Without any options, git lfs smudge outputs the raw Git LFS content to standard
118/// output.
119#[derive(Args)]
120pub struct SmudgeArgs {
121 /// Working-tree path of the file being smudged (currently unused).
122 pub path: Option<PathBuf>,
123 /// Skip automatic downloading of objects on clone or pull.
124 ///
125 /// Equivalent to `GIT_LFS_SKIP_SMUDGE=1`. Wired up by `git lfs install --skip-smudge`.
126 #[arg(long)]
127 pub skip: bool,
128}
129
130/// Install Git LFS configuration
131///
132/// Set up the `lfs` smudge and clean filters under the name `lfs` in
133/// the global Git config, and (when run from inside a repository)
134/// install a pre-push hook to run git-lfs-pre-push(1). If
135/// `core.hooksPath` is configured in any Git configuration (supported
136/// on Git v2.9.0 or later), the pre-push hook is installed to that
137/// directory instead.
138///
139/// Without any options, only sets up the `lfs` smudge and clean filters
140/// if they are not already set.
141#[derive(Args)]
142pub struct InstallArgs {
143 // TODO(post-1.0): replace the --local/--system/--worktree/--file mutex
144 // with a clap ArgGroup (multiple = false). Validation lives in
145 // resolve_install_scope (cli/src/main.rs); kept manual because
146 // tests/t-install.sh:329 (and the t-install-worktree / t-uninstall /
147 // t-uninstall-worktree variants) assert upstream's exact wording
148 // ("Only one of the --local, --system, --worktree, and --file
149 // options can be specified."). Worth taking once we're free to
150 // update those assertions.
151 /// Set the `lfs` smudge and clean filters, overwriting existing
152 /// values.
153 #[arg(short, long)]
154 pub force: bool,
155
156 /// Set the `lfs` smudge and clean filters in the local repository's
157 /// git config, instead of the global git config (`~/.gitconfig`).
158 #[arg(short, long)]
159 pub local: bool,
160
161 /// Set the `lfs` smudge and clean filters in the current working
162 /// tree's git config, instead of the global git config
163 /// (`~/.gitconfig`) or local repository's git config
164 /// (`$GIT_DIR/config`).
165 ///
166 /// If multiple working trees are in use, the Git config extension
167 /// `worktreeConfig` must be enabled to use this option. If only one
168 /// working tree is in use, `--worktree` has the same effect as
169 /// `--local`. Available only on Git v2.20.0 or later.
170 #[arg(short, long)]
171 pub worktree: bool,
172
173 /// Set the `lfs` smudge and clean filters in the system git config,
174 /// e.g. `/etc/gitconfig` instead of the global git config
175 /// (`~/.gitconfig`).
176 #[arg(long)]
177 pub system: bool,
178
179 /// Set the `lfs` smudge and clean filters in the Git configuration
180 /// file specified by `<PATH>`.
181 #[arg(long, value_name = "PATH")]
182 pub file: Option<PathBuf>,
183
184 /// Skip automatic downloading of objects on clone or pull.
185 ///
186 /// Requires a manual `git lfs pull` every time a new commit is
187 /// checked out on the repository.
188 #[arg(short, long)]
189 pub skip_smudge: bool,
190
191 /// Skip installation of hooks into the local repository.
192 ///
193 /// Use if you want to install the LFS filters but not make changes
194 /// to the hooks. Valid alongside `--local`, `--worktree`, `--system`,
195 /// or `--file`.
196 #[arg(long)]
197 pub skip_repo: bool,
198}
199
200/// Remove Git LFS configuration
201///
202/// Remove the `lfs` clean and smudge filters from the global Git config,
203/// and (when run from inside a Git repository) uninstall the Git LFS
204/// pre-push hook. Hooks that don't match what we would write are left
205/// untouched.
206#[derive(Args)]
207pub struct UninstallArgs {
208 // TODO(post-1.0): same --local/--system/--worktree/--file mutex as
209 // InstallArgs — share a clap ArgGroup. See InstallArgs's TODO for
210 // the rationale and test references.
211 /// Optional mode. With `hooks`, removes only the LFS git hooks and
212 /// leaves the filter config alone (the inverse of `--skip-repo`).
213 pub mode: Option<String>,
214
215 /// Remove the `lfs` smudge and clean filters from the local
216 /// repository's git config, instead of the global git config
217 /// (`~/.gitconfig`).
218 #[arg(short, long)]
219 pub local: bool,
220
221 /// Remove the `lfs` smudge and clean filters from the current
222 /// working tree's git config, instead of the global git config
223 /// (`~/.gitconfig`) or local repository's git config
224 /// (`$GIT_DIR/config`).
225 ///
226 /// If multiple working trees are in use, the Git config extension
227 /// `worktreeConfig` must be enabled to use this option. If only one
228 /// working tree is in use, `--worktree` has the same effect as
229 /// `--local`. Available only on Git v2.20.0 or later.
230 #[arg(short, long)]
231 pub worktree: bool,
232
233 /// Remove the `lfs` smudge and clean filters from the system git
234 /// config, instead of the global git config (`~/.gitconfig`).
235 #[arg(long)]
236 pub system: bool,
237
238 /// Remove the `lfs` smudge and clean filters from the Git
239 /// configuration file specified by `<PATH>`.
240 #[arg(long, value_name = "PATH")]
241 pub file: Option<PathBuf>,
242
243 /// Skip cleanup of the local repo.
244 ///
245 /// Use if you want to uninstall the global LFS filters but not
246 /// make changes to the current repo.
247 #[arg(long)]
248 pub skip_repo: bool,
249}
250
251/// View or add Git LFS paths to Git attributes
252///
253/// Start tracking the given pattern(s) through Git LFS. The argument is
254/// written to `.gitattributes`. If no paths are provided, list the
255/// currently-tracked paths.
256///
257/// Per gitattributes(5), patterns use the gitignore(5) pattern rules to
258/// match paths. This means that patterns containing asterisk (`*`),
259/// question mark (`?`), and the bracket characters (`[` and `]`) are
260/// treated specially; to disable this behavior and treat them literally
261/// instead, use `--filename` or escape the character with a backslash.
262#[derive(Args)]
263pub struct TrackArgs {
264 /// File patterns to track (e.g. `*.jpg`, `data/*.bin`).
265 pub patterns: Vec<String>,
266
267 /// Log files which `git lfs track` will touch. Disabled by default.
268 #[arg(short, long)]
269 pub verbose: bool,
270
271 /// Log all actions that would normally take place (adding entries
272 /// to `.gitattributes`, touching files on disk, etc.) without
273 /// performing any mutative operations.
274 ///
275 /// Implicitly mocks the behavior of `--verbose`, logging in greater
276 /// detail what it is doing. Disabled by default.
277 #[arg(short, long)]
278 pub dry_run: bool,
279
280 /// Write the currently tracked patterns as JSON to standard output.
281 ///
282 /// Intended for interoperation with external tools. Cannot be
283 /// combined with any pattern arguments. If `--no-excluded` is also
284 /// provided, that option will have no effect.
285 #[arg(short, long)]
286 pub json: bool,
287
288 /// Treat the arguments as literal filenames, not as patterns.
289 ///
290 /// Any special glob characters in the filename will be escaped
291 /// when writing the `.gitattributes` file.
292 #[arg(long)]
293 pub filename: bool,
294
295 /// Make the paths "lockable" — they should be locked to edit them,
296 /// and will be made read-only in the working copy when not locked.
297 #[arg(short, long)]
298 pub lockable: bool,
299
300 /// Remove the lockable flag from the paths so they are no longer
301 /// read-only unless locked.
302 #[arg(long)]
303 pub not_lockable: bool,
304
305 /// Don't list patterns that are excluded in the output; only list
306 /// patterns that are tracked.
307 #[arg(long)]
308 pub no_excluded: bool,
309
310 /// Make matched entries stat-dirty so that Git can re-index files
311 /// you wish to convert to LFS.
312 ///
313 /// Does not modify any `.gitattributes` file.
314 #[arg(long)]
315 pub no_modify_attrs: bool,
316}
317
318/// Remove Git LFS paths from Git attributes
319///
320/// Stop tracking the given path(s) through Git LFS. The argument can
321/// be a glob pattern or a file path. The matching pointer files in
322/// history (and the objects in the local store) are left in place.
323#[derive(Args)]
324pub struct UntrackArgs {
325 /// Paths or glob patterns to stop tracking.
326 pub patterns: Vec<String>,
327}
328
329/// Git filter process that converts between pointer and actual content
330///
331/// Implement the Git process filter API, exchanging handshake messages
332/// and then accepting and responding to requests to either clean or
333/// smudge a file.
334///
335/// `filter-process` is always run by Git's filter process, and is
336/// configured by the repository's Git attributes.
337///
338/// In your Git configuration or in a `.lfsconfig` file, you may set
339/// either or both of `lfs.fetchinclude` and `lfs.fetchexclude` to
340/// comma-separated lists of paths. If `lfs.fetchinclude` is defined,
341/// Git LFS pointer files will only be replaced with the contents of
342/// the corresponding object file if their path matches one in that
343/// list, and if `lfs.fetchexclude` is defined, pointer files will
344/// only be replaced if their path does not match one in that list.
345/// Paths are matched using wildcard matching as per gitignore(5).
346/// Pointer files that are not replaced are simply copied to standard
347/// output without change.
348///
349/// The filter process uses Git's pkt-line protocol to communicate, and
350/// is documented in detail in gitattributes(5).
351#[derive(Args)]
352pub struct FilterProcessArgs {
353 /// Skip automatic downloading of objects on clone or pull.
354 ///
355 /// Equivalent to `GIT_LFS_SKIP_SMUDGE=1`. Wired up by
356 /// `git lfs install --skip-smudge`.
357 #[arg(short, long)]
358 pub skip: bool,
359}
360
361/// Download all Git LFS files for a given ref
362///
363/// Download Git LFS objects at the given refs from the specified remote.
364/// See DEFAULT REMOTE and DEFAULT REFS for what happens if you don't
365/// specify.
366///
367/// This does not update the working copy; use git-lfs-pull(1) to
368/// download and replace pointer text with object content, or
369/// git-lfs-checkout(1) to materialize already-downloaded objects.
370#[derive(Args)]
371pub struct FetchArgs {
372 /// Optional remote name followed by refs. The first positional
373 /// argument is treated as a remote name when it resolves; any
374 /// following arguments are refs to fetch.
375 pub args: Vec<String>,
376
377 /// Specify `lfs.fetchinclude` just for this invocation; see
378 /// INCLUDE AND EXCLUDE.
379 #[arg(short = 'I', long, help_heading = FILTER)]
380 pub include: Vec<String>,
381
382 /// Specify `lfs.fetchexclude` just for this invocation; see
383 /// INCLUDE AND EXCLUDE.
384 #[arg(short = 'X', long, help_heading = FILTER)]
385 pub exclude: Vec<String>,
386
387 /// Download all objects that are referenced by any commit
388 /// reachable from the refs provided as arguments.
389 ///
390 /// If no refs are provided, then all refs are fetched. This is
391 /// primarily for backup and migration purposes. Cannot be
392 /// combined with `--include`/`--exclude`. Ignores any globally
393 /// configured include and exclude paths to ensure that all
394 /// objects are downloaded.
395 #[arg(short, long)]
396 pub all: bool,
397
398 /// Read a list of newline-delimited refs from standard input
399 /// instead of the command line.
400 #[arg(long)]
401 pub stdin: bool,
402
403 /// Prune old and unreferenced objects after fetching, equivalent
404 /// to running `git lfs prune` afterwards. See git-lfs-prune(1)
405 /// for more details.
406 #[arg(short, long)]
407 pub prune: bool,
408
409 /// Also fetch objects that are already present locally.
410 ///
411 /// Useful for recovery from a corrupt local store.
412 #[arg(long)]
413 pub refetch: bool,
414
415 /// Print what would be fetched, without actually fetching anything.
416 #[arg(short, long)]
417 pub dry_run: bool,
418
419 /// Write the details of all object transfer requests as JSON to
420 /// standard output.
421 ///
422 /// Intended for interoperation with external tools. When
423 /// `--dry-run` is also specified, writes the details of the
424 /// transfers that would occur if the objects were fetched.
425 #[arg(short, long)]
426 pub json: bool,
427}
428
429const FILTER: &str = "Filter options";
430
431/// Download all Git LFS files for current ref and checkout
432///
433/// Download Git LFS objects for the currently checked out ref, and
434/// update the working copy with the downloaded content if required.
435///
436/// This is generally equivalent to running `git lfs fetch [options]
437/// [<remote>]` followed by `git lfs checkout`. See git-lfs-checkout(1)
438/// for partial-clone, sparse-checkout, and bare-repository behavior
439/// (governed by the installed Git version and `GIT_ATTR_SOURCE`).
440///
441/// Requires `git lfs install` to have wired up the smudge filter. If
442/// the filter is missing, the fetch step still runs but the
443/// working-tree update is skipped with a hint to install.
444#[derive(Args)]
445pub struct PullArgs {
446 /// Optional remote name followed by refs.
447 ///
448 /// The first positional argument is treated as a remote name when
449 /// it resolves; any following arguments are refs to fetch. With
450 /// no arguments, the default remote is used.
451 pub args: Vec<String>,
452
453 /// Specify `lfs.fetchinclude` just for this invocation.
454 #[arg(short = 'I', long, help_heading = FILTER)]
455 pub include: Vec<String>,
456
457 /// Specify `lfs.fetchexclude` just for this invocation.
458 #[arg(short = 'X', long, help_heading = FILTER)]
459 pub exclude: Vec<String>,
460}
461
462/// Push queued large files to the Git LFS endpoint
463///
464/// Upload Git LFS files to the configured endpoint for the current Git
465/// remote. By default, filters out objects that are already referenced
466/// by the local clone of the remote (approximated via
467/// `refs/remotes/<remote>/*`); the server's batch API dedupes again,
468/// so a missing local tracking ref doesn't waste bandwidth.
469#[derive(Args)]
470pub struct PushArgs {
471 /// Remote to push to (e.g. `origin`). The remote's tracking refs
472 /// are excluded from the upload set so already-pushed objects
473 /// aren't sent again.
474 pub remote: String,
475
476 /// Refs (or, with `--object-id`, raw OIDs) to push. With `--all`,
477 /// restricts the all-refs walk to these; with `--stdin`, ignored
478 /// (a warning is emitted).
479 pub args: Vec<String>,
480
481 /// Print the files that would be pushed, without actually pushing
482 /// them.
483 #[arg(short, long)]
484 pub dry_run: bool,
485
486 /// Push all objects reachable from the refs given as arguments.
487 ///
488 /// If no refs are provided, all local refs are pushed. Note this
489 /// behavior differs from `git lfs fetch --all`, which fetches
490 /// every ref including refs outside `refs/heads` / `refs/tags`. If
491 /// you're migrating a repository, run `git lfs push` for any
492 /// additional remote refs that contain LFS objects not reachable
493 /// from your local refs.
494 #[arg(short, long)]
495 pub all: bool,
496
497 /// Push only the object OIDs listed on the command line (or read
498 /// from stdin with `--stdin`), separated by spaces.
499 #[arg(short, long)]
500 pub object_id: bool,
501
502 /// Read newline-delimited refs (or object IDs when using
503 /// `--object-id`) from standard input instead of the command
504 /// line.
505 #[arg(long)]
506 pub stdin: bool,
507}
508
509/// Efficiently clone a LFS-enabled repository
510///
511/// Clone an LFS-enabled Git repository by disabling LFS during the
512/// `git clone`, then running `git lfs pull` directly afterwards.
513/// Also installs the repo-level hooks (`.git/hooks`) that LFS requires
514/// to operate; if `--separate-git-dir` is given to `git clone`, the
515/// hooks are installed there.
516///
517/// Historically faster than a regular `git clone` because that would
518/// download LFS content via the smudge filter one file at a time.
519/// Modern `git clone` parallelizes the smudge filter, so this command
520/// no longer offers a meaningful speedup over plain `git clone`. You
521/// should prefer plain `git clone`.
522///
523/// In addition to the options accepted by `git clone`, the LFS-only
524/// flags `--include` / `-I <paths>`, `--exclude` / `-X <paths>`, and
525/// `--skip-repo` (skip installing the repo-level hooks) are accepted
526/// — see git-lfs-fetch(1) for the include/exclude semantics. They're
527/// parsed from the trailing argument list rather than declared as
528/// clap flags, so they don't appear in this command's `--help`.
529#[derive(Args)]
530pub struct CloneArgs {
531 /// `git clone` arguments plus the LFS pass-through flags
532 /// (`-I`/`--include`, `-X`/`--exclude`, `--skip-repo`). The
533 /// repository URL is required; an optional target directory
534 /// follows.
535 #[arg(trailing_var_arg = true, allow_hyphen_values = true)]
536 pub args: Vec<String>,
537}
538
539/// Git post-checkout hook implementation
540///
541/// Respond to Git post-checkout events. Git invokes this hook with
542/// `<rev-before> <ref-after> <is-branch-checkout>`. We make sure that
543/// any files which are marked as lockable by `git lfs track` are
544/// read-only in the working copy, if not currently locked by the
545/// local user.
546#[derive(Args)]
547pub struct PostCheckoutArgs {
548 /// Positional arguments passed by git. Not normally invoked by
549 /// hand.
550 pub args: Vec<String>,
551}
552
553/// Git post-commit hook implementation
554///
555/// Respond to Git post-commit events. Like `git lfs post-merge`, we
556/// make sure that any files which are marked as lockable by
557/// `git lfs track` are read-only in the working copy, if not
558/// currently locked by the local user.
559///
560/// Upstream optimizes by only checking files changed in HEAD; we
561/// currently scan the full work tree on every commit. The result is
562/// the same, but slower on large repositories.
563#[derive(Args)]
564pub struct PostCommitArgs {
565 /// Positional arguments passed by git. Not normally invoked by
566 /// hand.
567 pub args: Vec<String>,
568}
569
570/// Git post-merge hook implementation
571///
572/// Respond to Git post-merge events. Git invokes this hook with
573/// `<is-squash>`. We make sure that any files which are marked as
574/// lockable by `git lfs track` are read-only in the working copy, if
575/// not currently locked by the local user.
576#[derive(Args)]
577pub struct PostMergeArgs {
578 /// Positional arguments passed by git. Not normally invoked by
579 /// hand.
580 pub args: Vec<String>,
581}
582
583/// Git pre-push hook implementation
584///
585/// Respond to Git pre-push events. Reads the range of commits from
586/// stdin in the form `<local-ref> <local-sha1> <remote-ref>
587/// <remote-sha1>`, takes the remote name and URL as arguments, and
588/// uploads any Git LFS objects associated with those commits to the
589/// Git LFS API.
590///
591/// When pushing a new branch, the list of Git objects considered is
592/// every object reachable from the new branch. When deleting a
593/// branch, no LFS objects are pushed.
594#[derive(Args)]
595pub struct PrePushArgs {
596 /// Name of the remote being pushed to.
597 pub remote: String,
598
599 /// URL of the remote (informational; we use the `lfs.url`
600 /// config).
601 pub url: Option<String>,
602
603 /// Print the files that would be pushed, without actually
604 /// pushing them.
605 #[arg(short, long)]
606 pub dry_run: bool,
607}
608
609/// Print the git-lfs version banner and exit
610#[derive(Args)]
611pub struct VersionArgs;
612
613/// Build, compare, and check pointers
614///
615/// Build and optionally compare generated pointer files to ensure
616/// consistency between different Git LFS implementations.
617#[derive(Args)]
618pub struct PointerArgs {
619 // TODO(post-1.0): replace the --strict/--no-strict, --check/--pointer,
620 // and --check/--file/--stdin manual checks (cli/src/pointer_cmd.rs:108,
621 // 218, 223, 230, 241) with clap arg_group/conflicts_with/requires.
622 // No shell test asserts this wording, so the constraint here is
623 // softer than for the other commands — the deferral is purely about
624 // upstream parity. Worth taking whenever.
625 /// A local file to build the pointer from.
626 #[arg(short, long)]
627 pub file: Option<PathBuf>,
628
629 /// A local file containing a pointer generated from another
630 /// implementation.
631 ///
632 /// Compared to the pointer generated from `--file`.
633 #[arg(short, long)]
634 pub pointer: Option<PathBuf>,
635
636 /// Read the pointer from standard input to compare with the
637 /// pointer generated from `--file`.
638 #[arg(long)]
639 pub stdin: bool,
640
641 /// Read the pointer from standard input (with `--stdin`) or the
642 /// filepath (with `--file`).
643 ///
644 /// If neither or both of `--stdin` and `--file` are given, the
645 /// invocation is invalid. Exits 0 if the data read is a valid Git
646 /// LFS pointer, 1 otherwise. With `--strict`, exits 2 if the
647 /// pointer is not byte-canonical.
648 #[arg(long)]
649 pub check: bool,
650
651 /// With `--check`, verify that the pointer is canonical (the one
652 /// Git LFS would create).
653 ///
654 /// If it isn't, exits 2. The default — for backwards compatibility
655 /// — is `--no-strict`.
656 #[arg(long)]
657 pub strict: bool,
658
659 /// Disable strict mode (paired with `--strict`).
660 #[arg(long)]
661 pub no_strict: bool,
662}
663
664/// Display the Git LFS environment
665///
666/// Display the current Git LFS environment: version, endpoints,
667/// on-disk paths, and the three `filter.lfs.*` config values.
668#[derive(Args)]
669pub struct EnvArgs;
670
671/// List the configured LFS pointer extensions
672///
673/// Print each `lfs.extension.<name>.*` entry resolved to its final
674/// configuration in priority order. Extensions chain external
675/// clean / smudge programs around each LFS object — see
676/// git-lfs-config(5) for how to configure them.
677#[derive(Args)]
678pub struct ExtArgs;
679
680/// Update Git hooks
681///
682/// Update the Git hooks used by Git LFS. Silently upgrades known hook
683/// contents. If you have your own custom hooks you may need to use
684/// one of the extended options below.
685#[derive(Args)]
686pub struct UpdateArgs {
687 /// Forcibly overwrite any existing hooks with git-lfs hooks.
688 ///
689 /// Use this option if `git lfs update` fails because of existing
690 /// hooks but you don't care about their current contents.
691 #[arg(short, long)]
692 pub force: bool,
693
694 /// Print instructions for manually updating your hooks to
695 /// include git-lfs functionality.
696 ///
697 /// Use this option if `git lfs update` fails because of existing
698 /// hooks and you want to retain their functionality.
699 #[arg(short, long)]
700 pub manual: bool,
701}
702
703/// Migrate history to or from Git LFS
704///
705/// Convert files in a Git repository to or from Git LFS pointers, or
706/// summarize Git file sizes by file type. The `import` mode converts
707/// Git files (i.e. blobs) to Git LFS, the `export` mode does the
708/// reverse, and the `info` mode provides an informational summary
709/// useful for deciding which files to import or export.
710///
711/// In all modes, by default `git lfs migrate` operates only on the
712/// currently checked-out branch, and only on files added in commits
713/// which do not exist on any remote. Multiple options are available
714/// to override these defaults — see INCLUDE AND EXCLUDE REFERENCES.
715///
716/// When converting files to or from Git LFS, this command only
717/// changes your local repository and working copy, never any remotes.
718/// `import` and `export` are generally DESTRUCTIVE — they rewrite Git
719/// history, changing commits and generating new commit SHAs. (The
720/// exception is the `--no-rewrite` `import` sub-mode.) Always commit
721/// or stash any uncommitted work first, validate the result before
722/// pushing, and force-push the new history once you're satisfied.
723///
724/// For `info` and `import`, all file types are considered by default.
725/// In `import` you'll usually want filename patterns or `--fixup`;
726/// `export` requires at least one `--include` pattern. See INCLUDE
727/// AND EXCLUDE.
728///
729/// `git lfs migrate` will examine, create, and modify `.gitattributes`
730/// files as necessary. They are always assigned the default
731/// read/write permissions mode; symbolic links with that name halt
732/// the migration.
733#[derive(Args)]
734pub struct MigrateArgs {
735 #[command(subcommand)]
736 pub cmd: MigrateCmd,
737}
738
739#[derive(Subcommand)]
740pub enum MigrateCmd {
741 Import(MigrateImportArgs),
742 Export(MigrateExportArgs),
743 Info(MigrateInfoArgs),
744}
745
746/// Convert Git objects to Git LFS pointers
747///
748/// Migrate objects present in the Git history to pointer files
749/// tracked and stored with Git LFS. Adds entries for the converted
750/// file types to `.gitattributes`, creating those files if they
751/// don't exist — as if `git lfs track` had been run at the points
752/// in history where each type first appears.
753///
754/// With `--fixup`, examine existing `.gitattributes` files and
755/// convert only Git objects that should be tracked by Git LFS
756/// according to those rules but aren't yet.
757///
758/// With `--no-rewrite`, migrate objects to pointers in a single new
759/// commit on top of HEAD without rewriting history. The base
760/// `migrate` options (`--include-ref`, `--everything`, etc.) are
761/// ignored in this sub-mode, and the positional argument list
762/// changes from branches to a list of files. Files must be tracked
763/// by patterns already in `.gitattributes`.
764#[derive(Args)]
765pub struct MigrateImportArgs {
766 // TODO(post-1.0): replace the manual --no-rewrite/--fixup/--above/
767 // --include/--exclude/--everything cross-flag validation
768 // (cli/src/migrate/import.rs:53-77, plus the shared
769 // --everything/positional check in migrate/mod.rs::resolve_refs)
770 // with clap arg_group/conflicts_with. Currently kept as-is because
771 // tests/t-migrate-fixup.sh:94,112,130 and t-migrate-import.sh:814,
772 // 825,836 assert upstream's exact wording (e.g. "--no-rewrite and
773 // --fixup cannot be combined", "Cannot use --everything with
774 // --include-ref or --exclude-ref"). Worth taking once we're free
775 // to update those assertions.
776 /// Branches to rewrite (default: the currently checked-out
777 /// branch). With `--no-rewrite`, instead a list of working-tree
778 /// files to convert. References prefixed with `^` are excluded.
779 pub args: Vec<String>,
780
781 /// Convert paths matching this glob (repeatable, comma-delimited).
782 /// Required unless `--above` is set or `--no-rewrite` is given.
783 #[arg(short = 'I', long = "include")]
784 pub include: Vec<String>,
785
786 /// Exclude paths matching this glob (repeatable, comma-delimited).
787 #[arg(short = 'X', long = "exclude")]
788 pub exclude: Vec<String>,
789
790 /// Restrict the rewrite to commits reachable from these refs.
791 /// Repeatable.
792 #[arg(long = "include-ref")]
793 pub include_ref: Vec<String>,
794
795 /// Exclude commits reachable from these refs. Repeatable.
796 #[arg(long = "exclude-ref")]
797 pub exclude_ref: Vec<String>,
798
799 /// Consider all commits reachable from any local or remote ref.
800 ///
801 /// Only local refs are updated even with `--everything`; remote
802 /// refs stay synchronized with their remote.
803 #[arg(long)]
804 pub everything: bool,
805
806 /// Only migrate files whose individual filesize is above the
807 /// given size (e.g. `1b`, `20 MB`, `3 TiB`).
808 ///
809 /// Cannot be used with `--include`, `--exclude`, or `--fixup`.
810 #[arg(long, default_value = "")]
811 pub above: String,
812
813 /// Migrate objects in a new commit on top of HEAD without
814 /// rewriting Git history.
815 ///
816 /// Switches to a different argument list (positional args become
817 /// files, not branches) and ignores the core `migrate` options
818 /// (`--include-ref`, `--everything`, etc.).
819 #[arg(long)]
820 pub no_rewrite: bool,
821
822 /// Commit message for the `--no-rewrite` commit.
823 ///
824 /// If omitted, a message is generated from the file arguments.
825 #[arg(short, long)]
826 pub message: Option<String>,
827
828 /// Infer `--include` and `--exclude` filters per-commit from the
829 /// repository's `.gitattributes` files.
830 ///
831 /// Imports filepaths that should be tracked by Git LFS but
832 /// aren't yet pointers. Incompatible with explicitly given
833 /// `--include` / `--exclude` filters.
834 #[arg(long)]
835 pub fixup: bool,
836
837 /// Write a CSV of `<OLD-SHA>,<NEW-SHA>` for every rewritten
838 /// commit to the named file.
839 #[arg(long = "object-map")]
840 pub object_map: Option<PathBuf>,
841
842 /// Print the commit OID and filename of migrated files to
843 /// standard output.
844 #[arg(long)]
845 pub verbose: bool,
846
847 /// Remote to consult when fetching missing LFS objects (default
848 /// `origin`).
849 #[arg(long)]
850 pub remote: Option<String>,
851
852 /// Don't refresh the known set of remote references before
853 /// determining the set of "un-pushed" commits to migrate.
854 ///
855 /// Has no effect when combined with `--include-ref` or
856 /// `--exclude-ref`.
857 #[arg(long)]
858 pub skip_fetch: bool,
859
860 /// Assume a yes answer to any prompts, permitting noninteractive
861 /// use.
862 ///
863 /// Currently we don't prompt for any reason, so this is accepted
864 /// as a no-op for upstream parity.
865 #[arg(long)]
866 pub yes: bool,
867}
868
869/// Convert Git LFS pointers to Git objects
870///
871/// Migrate Git LFS pointer files present in the Git history out of
872/// Git LFS, converting them back into their corresponding object
873/// files. Files matching the `--include` patterns are removed from
874/// Git LFS; files matching `--exclude` retain their LFS status.
875/// Modifies `.gitattributes` to set/unset the relevant filepath
876/// patterns.
877///
878/// At least one `--include` pattern is required. Objects not present
879/// in the local LFS store are downloaded from the `--remote`
880/// (defaults to `origin`). Pointers whose objects can't be fetched
881/// are left as-is.
882#[derive(Args)]
883pub struct MigrateExportArgs {
884 // TODO(post-1.0): make --include a required clap arg (it is required
885 // in practice — cli/src/migrate/export.rs:53). Currently kept as a
886 // runtime check because tests/t-migrate-export.sh:208 asserts
887 // upstream's exact wording ("One or more files must be specified
888 // with --include"); clap's "the following required arguments were
889 // not provided: --include <INCLUDE>" would be a strict UX win but
890 // a behavioral diff. Also see the shared --everything/positional
891 // check in migrate/mod.rs::resolve_refs.
892 /// Branches to rewrite (default: the currently checked-out
893 /// branch). References prefixed with `^` are excluded.
894 pub branches: Vec<String>,
895
896 /// Convert pointers at paths matching this glob (repeatable,
897 /// comma-delimited). Required — at least one must be given.
898 #[arg(short = 'I', long = "include")]
899 pub include: Vec<String>,
900
901 /// Don't convert pointers at paths matching this glob
902 /// (repeatable, comma-delimited).
903 #[arg(short = 'X', long = "exclude")]
904 pub exclude: Vec<String>,
905
906 /// Restrict the rewrite to commits reachable from these refs.
907 /// Repeatable.
908 #[arg(long = "include-ref")]
909 pub include_ref: Vec<String>,
910
911 /// Exclude commits reachable from these refs. Repeatable.
912 #[arg(long = "exclude-ref")]
913 pub exclude_ref: Vec<String>,
914
915 /// Consider all commits reachable from any local or remote ref.
916 ///
917 /// Only local refs are updated even with `--everything`; remote
918 /// refs stay synchronized with their remote.
919 #[arg(long)]
920 pub everything: bool,
921
922 /// Write a CSV of `<OLD-SHA>,<NEW-SHA>` for every rewritten
923 /// commit to the named file.
924 ///
925 /// Useful as input to `git filter-repo` or other downstream
926 /// tools.
927 #[arg(long = "object-map")]
928 pub object_map: Option<PathBuf>,
929
930 /// Print the commit OID and filename of migrated files to
931 /// standard output.
932 #[arg(long)]
933 pub verbose: bool,
934
935 /// Download LFS objects from this remote during the export.
936 /// Defaults to `origin`.
937 #[arg(long)]
938 pub remote: Option<String>,
939
940 /// Don't refresh the known set of remote references before the
941 /// rewrite.
942 #[arg(long)]
943 pub skip_fetch: bool,
944
945 /// Assume a yes answer to any prompts, permitting noninteractive
946 /// use.
947 ///
948 /// Currently we don't prompt for any reason, so this is accepted
949 /// as a no-op for upstream parity.
950 #[arg(long)]
951 pub yes: bool,
952}
953
954/// Show information about repository size
955///
956/// Summarize the sizes of file objects present in the Git history,
957/// grouped by filename extension. Read-only — no objects or history
958/// change.
959///
960/// Existing Git LFS pointers are followed by default (the size of
961/// the referenced objects is totaled in a separate "LFS Objects"
962/// line). Use `--pointers=ignore` to skip pointers entirely, or
963/// `--pointers=no-follow` to count the pointer-text size as if the
964/// pointers were regular files (the older Git LFS behavior).
965#[derive(Args)]
966pub struct MigrateInfoArgs {
967 // TODO(post-1.0): replace the manual --everything/--include-ref/
968 // --exclude-ref/--fixup/--pointers/--include/--exclude cross-flag
969 // validation (cli/src/migrate/info.rs:59-83, plus the shared
970 // --everything/positional check in migrate/mod.rs::resolve_refs)
971 // with clap arg_group/conflicts_with. Currently kept as-is because
972 // tests/t-migrate-info.sh:903,922,941,977,995,1013,1031 assert
973 // upstream's exact wording (e.g. "Cannot use --fixup with
974 // --pointers=follow"). The value-conditional --pointers checks
975 // ("=follow" / "=no-follow") may not all collapse cleanly to
976 // declarative clap rules.
977 /// Branches to scan (default: the currently checked-out branch).
978 /// References prefixed with `^` are excluded.
979 pub branches: Vec<String>,
980
981 /// Only include paths matching this glob (repeatable,
982 /// comma-delimited).
983 #[arg(short = 'I', long = "include")]
984 pub include: Vec<String>,
985
986 /// Exclude paths matching this glob (repeatable, comma-delimited).
987 #[arg(short = 'X', long = "exclude")]
988 pub exclude: Vec<String>,
989
990 /// Restrict the scan to commits reachable from these refs.
991 /// Repeatable.
992 #[arg(long = "include-ref")]
993 pub include_ref: Vec<String>,
994
995 /// Exclude commits reachable from these refs. Repeatable.
996 #[arg(long = "exclude-ref")]
997 pub exclude_ref: Vec<String>,
998
999 /// Consider all commits reachable from any local or remote ref.
1000 #[arg(long)]
1001 pub everything: bool,
1002
1003 /// Only count files whose individual filesize is above the given
1004 /// size (e.g. `1b`, `20 MB`, `3 TiB`).
1005 ///
1006 /// File-extension groups whose largest file is below `--above`
1007 /// don't appear in the output.
1008 #[arg(long, default_value = "")]
1009 pub above: String,
1010
1011 /// Display the top N entries, ordered by total file count.
1012 ///
1013 /// Default 5. When existing Git LFS objects are found, an extra
1014 /// "LFS Objects" line is output in addition to the top N
1015 /// entries (unless `--pointers` changes this).
1016 #[arg(long, default_value_t = 5)]
1017 pub top: usize,
1018
1019 /// How to handle existing LFS pointer blobs.
1020 ///
1021 /// `follow` (default): summarize referenced objects in a separate
1022 /// "LFS Objects" line. `ignore`: skip pointers entirely.
1023 /// `no-follow`: count pointer-text size as if pointers were
1024 /// regular files (the older Git LFS behavior). When `--fixup` is
1025 /// given, defaults to `ignore`.
1026 #[arg(long)]
1027 pub pointers: Option<String>,
1028
1029 /// Format byte quantities in this unit.
1030 ///
1031 /// Valid units: `b, kib, mib, gib, tib, pib` (IEC) or
1032 /// `b, kb, mb, gb, tb, pb` (SI). Auto-scaled when omitted.
1033 #[arg(long)]
1034 pub unit: Option<String>,
1035
1036 /// Infer `--include` and `--exclude` filters per-commit from the
1037 /// repository's `.gitattributes` files.
1038 ///
1039 /// Counts filepaths that should be tracked by Git LFS but aren't
1040 /// yet pointers. Incompatible with explicit `--include` /
1041 /// `--exclude` filters and with `--pointers` settings other than
1042 /// `ignore`. Implies `--pointers=ignore` if not set.
1043 #[arg(long)]
1044 pub fixup: bool,
1045
1046 /// Don't refresh the known set of remote references before the
1047 /// scan.
1048 #[arg(long)]
1049 pub skip_fetch: bool,
1050
1051 /// Remote to consult (currently a no-op; reserved for the
1052 /// auto-fetch path).
1053 #[arg(long)]
1054 pub remote: Option<String>,
1055}
1056
1057/// Populate working copy with real content from Git LFS files.
1058///
1059/// Try to ensure that the working copy contains file content for Git LFS
1060/// objects for the current ref, if the object data is available. Does not
1061/// download any content; see git-lfs-fetch(1) for that.
1062///
1063/// Checkout scans the current ref for all LFS objects that would be
1064/// required, then where a file is either missing in the working copy, or
1065/// contains placeholder pointer content with the same SHA, the real file
1066/// content is written, provided we have it in the local store. Modified
1067/// files are never overwritten.
1068///
1069/// One or more may be provided as arguments to restrict the set of files
1070/// that are updated. Glob patterns are matched as per the format described
1071/// in gitignore(5).
1072///
1073/// When used with `--to` and the working tree is in a conflicted state due
1074/// to a merge, this option checks out one of the three stages a conflicting
1075/// Git LFS object into a separate file (which can be outside of the work
1076/// tree). This can make using diff tools to inspect and resolve merges
1077/// easier. A single Git LFS object's file path must be provided in
1078/// `PATHS`. If `FILE` already exists, whether as a regular
1079/// file, symbolic link, or directory, it will be removed and replaced, unless
1080/// it is a non-empty directory or otherwise cannot be deleted.
1081///
1082/// If the installed Git version is at least 2.42.0,
1083/// this command will by default check out Git LFS objects for files
1084/// only if they are present in the Git index and if they match a Git LFS
1085/// filter attribute from a `.gitattributes` file that is present in either
1086/// the index or the current working tree (or, as is always the case, if
1087/// they match a Git LFS filter attribute in a local gitattributes file
1088/// such as `$GIT_DIR/info/attributes`). These constraints do not apply
1089/// with prior versions of Git.
1090///
1091/// In a repository with a partial clone or sparse checkout, it is therefore
1092/// advisable to check out all `.gitattributes` files from HEAD before
1093/// using this command, if Git v2.42.0 or later is installed. Alternatively,
1094/// the `GIT_ATTR_SOURCE` environment variable may be set to HEAD, which
1095/// will cause Git to only read attributes from `.gitattributes` files in
1096/// HEAD and ignore those in the index or working tree.
1097///
1098/// In a bare repository, this command prints an informational message and
1099/// exits without modifying anything. In a future version, it may exit with
1100/// an error.
1101#[derive(Args)]
1102pub struct CheckoutArgs {
1103 // TODO(post-1.0): replace this manual stage/--to validation with
1104 // clap arg_group/requires/conflicts_with. Currently kept as-is
1105 // because tests/t-checkout.sh:897-909 assert upstream's exact error
1106 // wording; clap's wording would be a strict UX improvement but a
1107 // behavioral diff. Worth taking once we're free to update those
1108 // assertions.
1109 /// Check out the merge base of the specified file
1110 #[arg(long)]
1111 pub base: bool,
1112
1113 /// Check out our side (that of the current branch) of the
1114 /// conflict for the specified file
1115 #[arg(long)]
1116 pub ours: bool,
1117
1118 /// Check out their side (that of the other branch) of the
1119 /// conflict for the specified file
1120 #[arg(long)]
1121 pub theirs: bool,
1122
1123 /// If the working tree is in a conflicted state, check out the
1124 /// portion of the conflict specified by `--base`, `--ours`, or
1125 /// `--theirs` to the given path. Exactly one of these options
1126 /// is required.
1127 #[arg(long, value_name = "FILE")]
1128 pub to: Option<String>,
1129
1130 /// Paths to check out.
1131 ///
1132 /// When empty, everything in HEAD's tree is checked out. In
1133 /// conflict mode (`--to <path>` together with one of `--base`,
1134 /// `--ours`, or `--theirs`), exactly one path is required.
1135 pub paths: Vec<String>,
1136}
1137
1138/// Delete old LFS files from local storage
1139///
1140/// Delete locally stored LFS objects that aren't reachable from HEAD
1141/// or any unpushed commit, freeing up disk space.
1142///
1143/// Note: many of upstream's prune options aren't yet supported —
1144/// `--force`, `--recent`, `--verify-remote` (and the `--no-...`
1145/// variants), `--verify-unreachable`, `--when-unverified`, the
1146/// recent-refs / recent-commits retention windows, and the
1147/// stash / worktree retention rules. The basic
1148/// reachable-from-HEAD-or-unpushed walk is implemented and matches
1149/// upstream's default semantics.
1150#[derive(Args)]
1151pub struct PruneArgs {
1152 /// Don't actually delete anything; just report what would have
1153 /// been done.
1154 #[arg(short, long)]
1155 pub dry_run: bool,
1156
1157 /// Report the full detail of what is/would be deleted.
1158 #[arg(short, long)]
1159 pub verbose: bool,
1160}
1161
1162/// Check Git LFS files for consistency
1163///
1164/// Check all Git LFS files in the current HEAD for consistency.
1165/// Corrupted files are moved to `.git/lfs/bad`.
1166///
1167/// A single committish may be given to inspect that commit instead of
1168/// HEAD. The `<a>..<b>` range form from upstream is not yet supported
1169/// — only a single ref is accepted. With no argument, HEAD is
1170/// examined.
1171///
1172/// The default is to perform all checks. `lfs.fetchexclude` is also
1173/// not yet honored on this command; objects whose paths match the
1174/// exclude list will still be checked.
1175#[derive(Args)]
1176pub struct FsckArgs {
1177 /// Ref to scan. Defaults to HEAD.
1178 pub refspec: Option<String>,
1179
1180 /// Check that each object in HEAD matches its expected hash and
1181 /// that each object exists on disk.
1182 #[arg(long)]
1183 pub objects: bool,
1184
1185 /// Check that each pointer is canonical and that each file which
1186 /// should be stored as a Git LFS file is so stored.
1187 #[arg(long)]
1188 pub pointers: bool,
1189
1190 /// Perform checks, but do not move any corrupted files to
1191 /// `.git/lfs/bad`.
1192 #[arg(short, long)]
1193 pub dry_run: bool,
1194}
1195
1196/// Show the status of Git LFS files in the working tree
1197///
1198/// Display paths of Git LFS objects that have not been pushed to the
1199/// Git LFS server (large files that would be uploaded by `git push`),
1200/// that have differences between the index file and the current HEAD
1201/// commit (large files that would be committed by `git commit`), or
1202/// that have differences between the working tree and the index file
1203/// (files that could be staged with `git add`).
1204///
1205/// Must be run in a non-bare repository.
1206#[derive(Args)]
1207pub struct StatusArgs {
1208 /// Give the output in an easy-to-parse format for scripts.
1209 #[arg(short, long)]
1210 pub porcelain: bool,
1211
1212 /// Write Git LFS file status information as JSON to standard
1213 /// output if the command exits successfully.
1214 ///
1215 /// Intended for interoperation with external tools. If
1216 /// `--porcelain` is also provided, that option takes precedence.
1217 #[arg(short, long)]
1218 pub json: bool,
1219}
1220
1221/// Set a file as "locked" on the Git LFS server
1222///
1223/// Sets the given file path as "locked" against the Git LFS server,
1224/// with the intention of blocking attempts by other users to update
1225/// the given path. Locking a file requires the file to exist in the
1226/// working copy.
1227///
1228/// Once locked, LFS will verify that Git pushes do not modify files
1229/// locked by other users. See the description of the
1230/// `lfs.<url>.locksverify` config key in git-lfs-config(5) for
1231/// details.
1232#[derive(Args)]
1233pub struct LockArgs {
1234 /// Paths to lock. Repo-relative or absolute; must resolve inside
1235 /// the working tree. Upstream's CLI accepts a single path; ours
1236 /// accepts multiple (additive extension).
1237 pub paths: Vec<String>,
1238
1239 /// Specify the Git LFS server to use. Ignored if the `lfs.url`
1240 /// config key is set.
1241 #[arg(short, long)]
1242 pub remote: Option<String>,
1243
1244 /// Write lock info as JSON to standard output if the command
1245 /// exits successfully.
1246 ///
1247 /// Intended for interoperation with external tools. If the command
1248 /// returns with a non-zero exit code, plain text messages are sent
1249 /// to standard error.
1250 #[arg(short, long)]
1251 pub json: bool,
1252
1253 /// Refspec to associate the lock with (extension over upstream).
1254 ///
1255 /// Defaults to the current branch's tracked upstream
1256 /// (`branch.<current>.merge`) or the current branch's full ref
1257 /// (`refs/heads/<branch>`).
1258 #[arg(long = "ref")]
1259 pub refspec: Option<String>,
1260}
1261
1262/// Lists currently locked files from the Git LFS server
1263///
1264/// Lists current locks from the Git LFS server. Without filters, all
1265/// locks visible to the configured remote are returned.
1266#[derive(Args)]
1267pub struct LocksArgs {
1268 /// Specify the Git LFS server to use. Ignored if the `lfs.url`
1269 /// config key is set.
1270 #[arg(short, long)]
1271 pub remote: Option<String>,
1272
1273 /// Specify a lock by its ID. Returns a single result.
1274 #[arg(short, long)]
1275 pub id: Option<String>,
1276
1277 /// Specify a lock by its path. Returns a single result.
1278 #[arg(short, long)]
1279 pub path: Option<String>,
1280
1281 /// List only our own locks which are cached locally. Skips a
1282 /// remote call.
1283 ///
1284 /// Useful when offline or to confirm what `git lfs lock` recorded
1285 /// locally. Combine with `--path` / `--id` / `--limit` to filter;
1286 /// `--verify` is rejected.
1287 #[arg(long)]
1288 pub local: bool,
1289
1290 /// Verify the lock owner on the server and mark our own locks
1291 /// with `O`.
1292 ///
1293 /// Own locks are held by us and the corresponding files can be
1294 /// updated for the next push. All other locks are held by someone
1295 /// else. Contrary to `--local`, this also detects locks held by us
1296 /// despite no local lock information being available (e.g. because
1297 /// the file had been locked from a different clone) and detects
1298 /// "broken" locks (e.g. someone else forcibly unlocked our files).
1299 #[arg(long)]
1300 pub verify: bool,
1301
1302 /// Maximum number of results to return.
1303 #[arg(short, long)]
1304 pub limit: Option<u32>,
1305
1306 /// Write lock info as JSON to standard output if the command
1307 /// exits successfully.
1308 ///
1309 /// Intended for interoperation with external tools. If the command
1310 /// returns with a non-zero exit code, plain text messages are sent
1311 /// to standard error.
1312 #[arg(short, long)]
1313 pub json: bool,
1314
1315 /// Refspec to filter locks by (extension over upstream).
1316 ///
1317 /// Defaults to the current branch's tracked upstream — same
1318 /// auto-resolution as `git lfs lock`.
1319 #[arg(long = "ref")]
1320 pub refspec: Option<String>,
1321}
1322
1323/// Remove "locked" setting for a file on the Git LFS server
1324///
1325/// Removes the given file path as "locked" on the Git LFS server.
1326/// Files must exist and have a clean git status before they can be
1327/// unlocked. The `--force` flag will skip these checks.
1328#[derive(Args)]
1329pub struct UnlockArgs {
1330 // TODO(post-1.0): replace the manual --id-xor-paths check
1331 // (cli/src/lock.rs:301-306) with a clap ArgGroup
1332 // (required = true, multiple = false) covering --id and the
1333 // positional paths arg. Currently kept as-is because
1334 // tests/t-unlock.sh:228,431,482 assert upstream's exact wording
1335 // ("Exactly one of --id or a set of paths must be provided").
1336 // Worth taking once we're free to update those assertions.
1337 /// Paths to unlock. Upstream's CLI accepts a single path; ours
1338 /// accepts multiple (additive extension). Mutually exclusive
1339 /// with `--id`.
1340 pub paths: Vec<String>,
1341
1342 /// Specify the Git LFS server to use. Ignored if the `lfs.url`
1343 /// config key is set.
1344 #[arg(short, long)]
1345 pub remote: Option<String>,
1346
1347 /// Tell the server to remove the lock, even if it's owned by
1348 /// another user.
1349 #[arg(short, long)]
1350 pub force: bool,
1351
1352 /// Specify a lock by its ID instead of path. Mutually exclusive
1353 /// with the positional paths.
1354 #[arg(short, long)]
1355 pub id: Option<String>,
1356
1357 /// Write lock info as JSON to standard output if the command
1358 /// exits successfully.
1359 ///
1360 /// Intended for interoperation with external tools. If the command
1361 /// returns with a non-zero exit code, plain text messages are sent
1362 /// to standard error.
1363 #[arg(short, long)]
1364 pub json: bool,
1365
1366 /// Refspec to send with the unlock request (extension over
1367 /// upstream).
1368 ///
1369 /// Defaults to the current branch's tracked upstream — same
1370 /// auto-resolution as `git lfs lock`.
1371 #[arg(long = "ref")]
1372 pub refspec: Option<String>,
1373}
1374
1375/// Show information about Git LFS files in the index and working tree
1376///
1377/// Display paths of Git LFS files that are found in the tree at the
1378/// given reference. If no reference is given, scan the currently
1379/// checked-out branch.
1380///
1381/// An asterisk (`*`) after the OID indicates a full object, a minus
1382/// (`-`) indicates an LFS pointer.
1383///
1384/// Note: upstream's `--include` / `--exclude` path filters and the
1385/// `--deleted` flag (which shows the full history of the given
1386/// reference, including objects that have been deleted) aren't yet
1387/// supported. The two-references form (`git lfs ls-files <a> <b>`,
1388/// to show files modified between two refs) is also not yet
1389/// supported.
1390#[derive(Args)]
1391pub struct LsFilesArgs {
1392 /// Ref to list. Defaults to HEAD.
1393 pub refspec: Option<String>,
1394
1395 /// Show the entire 64-character OID, instead of just the first
1396 /// 10.
1397 #[arg(short, long)]
1398 pub long: bool,
1399
1400 /// Show the size of the LFS object in parentheses at the end of
1401 /// each line.
1402 #[arg(short, long)]
1403 pub size: bool,
1404
1405 /// Show only the LFS-tracked file names.
1406 #[arg(short, long)]
1407 pub name_only: bool,
1408
1409 /// Inspect the full history of the repository, not the current
1410 /// HEAD (or other provided reference).
1411 ///
1412 /// Includes previous versions of LFS objects that are no longer
1413 /// found in the current tree.
1414 #[arg(short, long)]
1415 pub all: bool,
1416
1417 /// Show as much information as possible about an LFS file.
1418 ///
1419 /// Intended for manual inspection; the exact format may change
1420 /// at any time.
1421 #[arg(short, long)]
1422 pub debug: bool,
1423
1424 /// Write Git LFS file information as JSON to standard output if
1425 /// the command exits successfully.
1426 ///
1427 /// Intended for interoperation with external tools. If `--debug`
1428 /// is also provided, that option takes precedence. If any of
1429 /// `--long`, `--size`, or `--name-only` are provided, those
1430 /// options will have no effect.
1431 #[arg(short, long)]
1432 pub json: bool,
1433}