Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
implement per-repo abbreviating
✗ CI failure RadsammyT committed 1 year ago
commit 2dfe90755d20b4a4d02494c7e42478aadf284443
parent b2c7d87a1c90e826e415bdced04d9136e343151d
1 failed (1 total) View logs
2 files changed +71 -10
modified radicle-cli/src/git.rs
@@ -4,9 +4,11 @@ pub mod ddiff;
pub mod pretty_diff;
pub mod unified_diff;

-
use std::collections::HashSet;
+
use std::cell::RefCell;
+
use std::collections::{HashMap, HashSet};
use std::fmt::Display;
use std::fs::{File, OpenOptions};
+

use std::io;
use std::io::Write;
use std::num::ParseIntError;
@@ -18,14 +20,15 @@ use std::sync::OnceLock;

use anyhow::anyhow;
use anyhow::Context as _;
+
use radicle::storage::{ReadRepository, ReadStorage};
use thiserror::Error;

use radicle::crypto::ssh;
-
use radicle::git;
use radicle::git::raw as git2;
use radicle::git::{Version, VERSION_REQUIRED};
use radicle::prelude::{NodeId, RepoId};
use radicle::storage::git::transport;
+
use radicle::{git, Profile};

pub use radicle::git::raw::{
    build::CheckoutBuilder, AnnotatedCommit, Commit, Direction, ErrorCode, MergeAnalysis,
@@ -46,6 +49,10 @@ const CONFIG_ABBREV_DEFAULT: usize = 7;
/// [`get_abbrev()`] should be called to get (or initialize) this value.
static CONFIG_ABBREV: OnceLock<usize> = OnceLock::new();

+
thread_local! {
+
    /// Stores the Abbreviation size per RID for caching purposes
+
    static REPO_ABBREVS: RefCell<HashMap<RepoId, usize>> = RefCell::default();
+
}
/// Git revision parameter. Supports extended SHA-1 syntax.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Rev(String);
@@ -432,9 +439,9 @@ impl Abbreviation {
    /// In the case of `Abbreviation::Auto`, the `git` CLI is used to determine
    /// the shortest abbreviation length to use, if this fails a default of
    /// [`CONFIG_ABBREV_DEFAULT`] is returned.
-
    pub fn length(&self) -> usize {
+
    pub fn length(&self, path: &Path) -> usize {
        match self {
-
            Abbreviation::Auto => git(Path::new("."), ["rev-parse", "--short", "HEAD"])
+
            Abbreviation::Auto => git(Path::new(path), ["rev-parse", "--short", "HEAD"])
                .unwrap_or("a".repeat(CONFIG_ABBREV_DEFAULT))
                .trim()
                .len(),
@@ -451,10 +458,46 @@ impl Abbreviation {
/// for more details).
///
/// [coreabbrev]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreabbrev
-
pub fn get_abbrev() -> usize {
+
pub fn get_abbrev_cwd() -> usize {
    *OnceLock::get_or_init(&CONFIG_ABBREV, || {
        let abbrev = Abbreviation::new().unwrap_or_default();
-
        abbrev.length()
+
        abbrev.length(Path::new("."))
+
    })
+
}
+

+
/// Get the path to the stored repo based off of the provided RID.
+
fn get_storage_repo(rid: &RepoId) -> anyhow::Result<PathBuf> {
+
    let storage = Profile::load()?.storage;
+
    let candidate = storage
+
        .repositories()?
+
        .into_iter()
+
        .find(|x| x.rid == *rid)
+
        .ok_or_else(|| anyhow!("Repo not found"))?;
+
    let repo = storage.repository(candidate.rid)?;
+
    Ok(repo.path().to_path_buf())
+
}
+

+
/// Get the abbreviation length to use for a specific repository (based off an RID)
+
/// for Git SHA formatting.
+
///
+
/// Only the global Git config is used to lookup [`core.abbrev`][coreabbrev], as this uses
+
/// the repositories in storage to determine the amount of characters to abbreviate to.
+
///
+
/// [coreabbrev]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreabbrev
+
pub fn get_abbrev_rid(rid: &RepoId) -> usize {
+
    REPO_ABBREVS.with_borrow_mut(|map| {
+
        if let Some(abbrev) = map.get(rid) {
+
            return *abbrev;
+
        }
+
        let path = match get_storage_repo(rid) {
+
            Ok(pb) => pb,
+
            Err(_) => return CONFIG_ABBREV_DEFAULT,
+
        };
+
        let abbrev = Abbreviation::from_global()
+
            .unwrap_or_default()
+
            .length(&path);
+
        map.insert(*rid, abbrev);
+
        abbrev
    })
}

@@ -475,7 +518,7 @@ pub fn view_diff(
    let workdir = repo
        .workdir()
        .ok_or_else(|| anyhow!("Could not get workdir current repository."))?;
-
    let abbrev = get_abbrev();
+
    let abbrev = get_abbrev_cwd();
    let left = format!("{:.abbrev$}", left.to_string());
    let right = format!("{:.abbrev$}", right.to_string());

modified radicle-cli/src/terminal/format.rs
@@ -6,7 +6,7 @@ pub use radicle_term::format::*;
pub use radicle_term::{style, Paint};

use radicle::cob::ObjectId;
-
use radicle::identity::Visibility;
+
use radicle::identity::{RepoId, Visibility};
use radicle::node::policy::Policy;
use radicle::node::{Alias, AliasStore, NodeId};
use radicle::prelude::Did;
@@ -31,7 +31,16 @@ pub fn oid(oid: impl Into<radicle::git::Oid>) -> Paint<String> {
    Paint::new(format!(
        "{:.abbrev$}",
        oid.into(),
-
        abbrev = git::get_abbrev()
+
        abbrev = git::get_abbrev_cwd()
+
    ))
+
}
+

+
/// Format a git Oid based on its belonging RID.
+
pub fn oid_rid(oid: impl Into<radicle::git::Oid>, rid: &RepoId) -> Paint<String> {
+
    Paint::new(format!(
+
        "{:.abbrev$}",
+
        oid.into(),
+
        abbrev = git::get_abbrev_rid(rid)
    ))
}

@@ -55,7 +64,16 @@ pub fn cob(id: &ObjectId) -> Paint<String> {
    Paint::new(format!(
        "{:.abbrev$}",
        id.to_string(),
-
        abbrev = git::get_abbrev()
+
        abbrev = git::get_abbrev_cwd()
+
    ))
+
}
+

+
/// Format a COB id based on its belonging RID.
+
pub fn cob_rid(id: &ObjectId, rid: &RepoId) -> Paint<String> {
+
    Paint::new(format!(
+
        "{:.abbrev$}",
+
        id.to_string(),
+
        abbrev = git::get_abbrev_rid(rid)
    ))
}