Skip to main content

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}