cli/cli/cli_args/commands_git_projection.rs
1// SPDX-License-Identifier: Apache-2.0
2//! Git projection command definitions.
3
4use std::path::PathBuf;
5
6use clap::Subcommand;
7
8/// Source for a git import: either a local filesystem path or a URL that
9/// sley can fetch from.
10///
11/// We discriminate by inspecting the input string: anything containing
12/// `://` (https/ssh/git/file URLs) or starting with `git@` (ssh shorthand)
13/// is treated as a URL; everything else is a local path. This keeps the
14/// rules predictable — `/tmp/foo` always means a path, and a stray
15/// `git@host:path` shorthand never gets misread as a relative path.
16#[derive(Debug, Clone)]
17pub enum GitSource {
18 Path(PathBuf),
19 Url(String),
20}
21
22impl GitSource {
23 pub fn parse(s: &str) -> Result<Self, String> {
24 if s.contains("://") || s.starts_with("git@") {
25 Ok(GitSource::Url(s.to_string()))
26 } else {
27 Ok(GitSource::Path(PathBuf::from(s)))
28 }
29 }
30
31 pub fn display(&self) -> String {
32 match self {
33 GitSource::Path(p) => p.display().to_string(),
34 GitSource::Url(u) => u.clone(),
35 }
36 }
37}
38
39pub(crate) fn parse_git_source(s: &str) -> Result<GitSource, String> {
40 GitSource::parse(s)
41}
42
43#[derive(Subcommand, Clone)]
44pub enum ImportCommands {
45 /// Import Git commits to Heddle.
46 ///
47 /// Walks local branches and tags by default. To import remote-tracking
48 /// refs (`refs/remotes/*`), name them explicitly with `--ref`.
49 Git {
50 /// Local path or git URL to import from.
51 #[arg(short, long, value_parser = parse_git_source)]
52 path: Option<GitSource>,
53
54 /// Ref names to import (repeatable). Scopes the import to the
55 /// listed branches, tags, or remote-tracking refs; omit to
56 /// import all branches and tags.
57 #[arg(long = "ref", value_name = "REF")]
58 refs: Vec<String>,
59
60 /// Accept git tree entries Heddle cannot represent losslessly.
61 #[arg(long)]
62 lossy: bool,
63 },
64}
65
66#[derive(Subcommand, Clone)]
67pub enum ExportCommands {
68 /// Export Heddle states to Git.
69 ///
70 /// Writes a complete bare Git repository at `--destination` containing
71 /// every reachable Heddle state as a Git commit, with branches and tags
72 /// mirroring Heddle's threads and markers.
73 Git {
74 /// Destination path for the exported Git repository. Must be writable;
75 /// will be initialized as a bare repo if it does not already exist.
76 #[arg(short, long)]
77 destination: Option<std::path::PathBuf>,
78 },
79}
80
81#[derive(Subcommand, Clone, Debug)]
82pub enum SyncCommands {
83 /// Bidirectional sync with Git (export + import).
84 Git {
85 /// Local path or git URL to sync with.
86 #[arg(short, long, value_parser = parse_git_source)]
87 path: Option<GitSource>,
88 },
89}