OXYGENHUB
# 2b5ee371060e oxygen / src / cli / identity.rs
2.8 KiB · Rust · last changed User config file layered under repo config, user-scoped identities; split the CLI into modules; fix clone remote persistence 1 month ago source blame history raw
1
//! Identity, verification, and configuration commands.
2
3
use super::format::{short_id, signature_line, when};
4
use super::open;
5
use anyhow::Result;
6
use oxy_core::hash::ChangeHash;
7
use oxy_core::repo::{self, IdentityScope};
8
9
pub fn create(name: Option<String>, email: Option<String>, local: bool) -> Result<i32> {
10
    let mut repo = open()?;
11
    let name = name.unwrap_or_else(|| repo.config.author_name.clone());
12
    let email = email.unwrap_or_else(|| repo.config.author_email.clone());
13
    let scope = if local { IdentityScope::Repo } else { IdentityScope::User };
14
    let (key, _) = repo.create_identity(&name, &email, scope)?;
15
    println!("Created identity {name} <{email}>");
16
    println!("KeyId: {key}");
17
    println!("Secret key stored under {}", repo::default_keys_dir().display());
18
    match scope {
19
        IdentityScope::User => println!("Recorded as your default author in {}", repo.user_config_path().display()),
20
        IdentityScope::Repo => println!("Recorded in this repository's .oxy/config only"),
21
    }
22
    if !repo.config.sign_changes {
23
        println!("Changes will carry this author; run `oxy config --user core.sign change` to sign each commit.");
24
    }
25
    Ok(0)
26
}
27
28
pub fn show() -> Result<i32> {
29
    let repo = open()?;
30
    let Some(key) = repo.config.author_key else {
31
        println!("No identity configured; run `oxy identity create`.");
32
        return Ok(0);
33
    };
34
    let id = repo.identity(&key)?;
35
    println!("{} <{}>", id.name, id.email);
36
    println!("KeyId:   {key}");
37
    println!("Created: {}", when(id.created));
38
    println!("Secret:  {}", if repo.secret_key()?.is_some() { "available" } else { "NOT FOUND in key directory" });
39
    println!("Signing: {}", if repo.config.sign_changes { "every change (core.sign = change)" } else { "at push via seals (core.sign = seal)" });
40
    Ok(0)
41
}
42
43
pub fn verify(change: Option<&str>) -> Result<i32> {
44
    let repo = open()?;
45
    let hashes: Vec<ChangeHash> = match change {
46
        Some(c) => vec![repo.resolve_change(c)?],
47
        None => repo.log()?.into_iter().filter(|e| !e.is_working_copy).map(|e| e.hash).collect(),
48
    };
49
    let mut bad = 0;
50
    for h in hashes {
51
        let c = repo.store().get_change(&h)?;
52
        let line = signature_line(&repo, &h)?;
53
        if line.starts_with("INVALID") {
54
            bad += 1;
55
        }
56
        println!("{} #{}  {line}", short_id(&c), h.short(12));
57
    }
58
    Ok(if bad > 0 { 1 } else { 0 })
59
}
60
61
pub fn config(key: &str, value: &str, user: bool) -> Result<i32> {
62
    if user {
63
        let path = repo::default_user_config();
64
        repo::Config::set_user(&path, key, value)?;
65
        println!("{key} = {value} (in {})", path.display());
66
    } else {
67
        let mut repo = open()?;
68
        repo.config.set(key, value)?;
69
        repo.save_config()?;
70
        println!("{key} = {value} (in this repository)");
71
    }
72
    Ok(0)
73
}