1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//! Get the Xvc root directory for the current project
use crate::error::Result;
use crate::types::xvcroot::XvcRoot;
use clap::Parser;
use crossbeam_channel::Sender;
use relative_path::RelativePath;
use xvc_logging::{watch, XvcOutputLine};

#[derive(Debug, Parser)]
#[command(name = "root")]
/// Get the XVC root directory for the current project
pub struct RootCLI {
    #[arg(long)]
    /// Show absolute path instead of relative
    absolute: bool,
}

/// Entry point for xvc root
///
/// # Arguments
///
/// - `output`: Buffer to write the result
/// - `xvc_root`: The root of the current project
/// - `opts`: [CLI options][RootCLI]
///
/// # Errors and Panics
///
/// - It returns an error when `output` can't be written by `writeln!`
///   This probably leads to panic! in caller.
/// - It returns an error when `xvc_root` cannot be converted to absolute path
///   This should never happen if `xvc_root` properly constructed.
pub fn run(output_snd: &Sender<XvcOutputLine>, xvc_root: &XvcRoot, opts: RootCLI) -> Result<()> {
    if opts.absolute {
        output_snd.send(XvcOutputLine::Output(format!(
            "{}",
            xvc_root.absolute_path().to_string_lossy()
        )))?;
    } else {
        let current_dir = xvc_root.config().current_dir.option.to_path_buf();

        let rel_dir = RelativePath::new(&current_dir.to_string_lossy()).relative(
            RelativePath::new(&xvc_root.absolute_path().to_string_lossy()),
        );
        watch!(rel_dir);
        if rel_dir == "" {
            output_snd.send(XvcOutputLine::Output(".".into()))?;
        } else {
            output_snd.send(XvcOutputLine::Output(format!("{}", rel_dir)))?;
        }
    }
    Ok(())
}