rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 heartwood2dfe90755d20b4a4d02494c7e42478aadf284443
{
"request": "trigger",
"version": 1,
"event_type": "patch",
"repository": {
"id": "rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5",
"name": "heartwood",
"description": "Radicle Heartwood Protocol & Stack",
"private": false,
"default_branch": "master",
"delegates": [
"did:key:z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT",
"did:key:z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM",
"did:key:z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz"
]
},
"action": "Created",
"patch": {
"id": "1e96844aef957e27206a8e3d87fbd4706890b174",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"title": "cli: use git config's `core.abbrev` for SHA-1 abbrevs",
"state": {
"status": "archived",
"conflicts": []
},
"before": "ee1c867800eacea37d489d966622d0aff0af0b70",
"after": "2dfe90755d20b4a4d02494c7e42478aadf284443",
"commits": [
"2dfe90755d20b4a4d02494c7e42478aadf284443",
"b2c7d87a1c90e826e415bdced04d9136e343151d"
],
"target": "7e1cb406bb935c3de008d2171e8961f57b4336ea",
"labels": [],
"assignees": [],
"revisions": [
{
"id": "1e96844aef957e27206a8e3d87fbd4706890b174",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "Implements `radicle_cli::git::get_abbrev()`, which will\nget git's `core.abbrev`, which can be applied to COB IDs\nand git OIDs (or any SHA1 abbreviation.)\n\nThis also respects special cases where `core.abbrev` can \nbe legally set to \"auto\" or \"no\", where \"auto\" gets an appropriate\nlength based on a loose count of objects in the current repo, and \n\"no\" which doesn't abbreviate the SHA1 at all.",
"base": "bb5355fcb1a47e6a6ac3e441e2b807906d7ef135",
"oid": "1c20d56d3a963ea1a195b84fd50ad53926a995fe",
"timestamp": 1714434648
},
{
"id": "7a9bd356c9e701a609c7172f86a8b7141579c75e",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "Default to \"auto\" on config/entry failure\nchange CONFIG_ABBRED_DEFAULT to 10",
"base": "bb5355fcb1a47e6a6ac3e441e2b807906d7ef135",
"oid": "f82e6a8024315c79af9229ab0a3c97ad6c3edffa",
"timestamp": 1715213525
},
{
"id": "bdfee1ca83de7ad9160f5133cfe6c94c20ec9b6a",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "forgot to squash commits. whoops.",
"base": "bb5355fcb1a47e6a6ac3e441e2b807906d7ef135",
"oid": "24a3fffbe7ef815efb1f7248dd402765466daa25",
"timestamp": 1715213734
},
{
"id": "cac8ecbdd90c78faf7e8e148ead87e49ad8fe683",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "Updates this patch to do the following:\n\n - Use `std::sync::OnceLock` as a replacement for `static mut`\n - its actually in the std lib for rust as of 1.70.0, \n see `https://github.com/rust-lang/rust/pull/105587`\n - the `once_cell` crate could prolly be removed as a dep in favor of this but im not\n sure if there are other uses of this dep that aren't covered in the std impl\n\n - `CONFIG_ABBREV_DEFAULT` is now set to 10\n - Will use the local config first (if it can be found) and uses the global config otherwise\n should the local config not be found\n - Upon failing to obtain the local config, global config, or just the `core.abbrev` value,\n will simply default to \"auto\". If that also fails: `CONFIG_ABBREV_DEFAULT`.",
"base": "bb5355fcb1a47e6a6ac3e441e2b807906d7ef135",
"oid": "8e8c98e387e1a8da671f955b4fb197f4c52bc61b",
"timestamp": 1715791662
},
{
"id": "bab1f829df649df9cfb8589e1b0be8167f3589c4",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "Changes:\n- Introduce Abbreviation type to make code clearer\n- Use `CONFIG_ABBREV_DEFAULT` for default cases where any values are missing\n- Make `7` the default value to ensure tests still pass",
"base": "bb5355fcb1a47e6a6ac3e441e2b807906d7ef135",
"oid": "46ae3ae4fe035fffb3847f5c220d43ed2658ac40",
"timestamp": 1718632624
},
{
"id": "189de2faa8fcd9bbaff1aaac48459b905c544e57",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "Changes:\n- Improve `Config` search\n- Add more constants to use\n- Improve commit message",
"base": "bb5355fcb1a47e6a6ac3e441e2b807906d7ef135",
"oid": "13d8a81ee74bf71c653146762875775335573ce8",
"timestamp": 1718643204
},
{
"id": "276bf662680bff506d6c2a8001358447c940a9ef",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "Rebase",
"base": "765fc48c8496b35717a53405d745b154fc655955",
"oid": "a1d5825f4f08a9973c88b76472eb0a65f7b559f6",
"timestamp": 1719245165
},
{
"id": "38b88d52303469c7cd192e7af42762c5b932df27",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "- Privatized and Added documentation for `CONFIG_ABBREV` and `CONFIG_ABBREV_DEFAULT`\n - Use `OnceLock::get_or_init()` for `get_abbrev()` rather than a `match`",
"base": "765fc48c8496b35717a53405d745b154fc655955",
"oid": "ec048f417a2c28cde57061af3a8c7846ca512786",
"timestamp": 1720528633
},
{
"id": "6e2a988f903233417a4e2e49b5a9ad99b6e7d748",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "- partially implement per-repo abbreviating\n\nMeant to address a key point in review in its respective zulip topic.\nI want to focus on the implementation of `get_abbrev_rid()` and whatnot\nbefore I can go ahead with replacing the old (cwd) implementation with\nthe new one and make it work with all usages of `format::cob()/oid()`.",
"base": "765fc48c8496b35717a53405d745b154fc655955",
"oid": "b5dff552c64cabde688d24b20a8bb9047c27fe62",
"timestamp": 1721933028
},
{
"id": "13d597c8c12a09e6f76dd3a03239d3ab63a1e03f",
"author": {
"id": "did:key:z6Mktnv1oLyUHMHm7j3p5D119V2yRWPrfMXAn3W42irs8DHL",
"alias": "radsammyt"
},
"description": "Rebase.",
"base": "ee1c867800eacea37d489d966622d0aff0af0b70",
"oid": "2dfe90755d20b4a4d02494c7e42478aadf284443",
"timestamp": 1722258773
}
]
}
}
{
"response": "triggered",
"run_id": {
"id": "b3690268-d99a-4139-b36a-b90a737ecce1"
},
"info_url": "https://cci.rad.levitte.org//b3690268-d99a-4139-b36a-b90a737ecce1.html"
}
Started at: 2026-09-09 01:44:23.837896+02:00
Commands:
$ rad clone rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5 .
✓ Creating checkout in ./...
✓ Remote cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT added
✓ Remote-tracking branch cloudhead@z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT/master created for z6MksFqXN3Yhqk8pTJdUGLwATkRfQvwZXPqR2qMEhbS9wzpT
✓ Remote fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM added
✓ Remote-tracking branch fintohaps@z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM/master created for z6MkireRatUThvd3qzfKht1S44wpm4FEWSSa4PRMTSQZ3voM
✓ Remote lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz added
✓ Remote-tracking branch lorenz@z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz/master created for z6MkkPvBfjP4bQmco5Dm7UGsX2ruDBieEHi8n9DVJWX5sTEz
✓ Repository successfully cloned under /opt/radcis/ci.rad.levitte.org/cci/state/b3690268-d99a-4139-b36a-b90a737ecce1/w/
╭────────────────────────────────────╮
│ heartwood │
│ Radicle Heartwood Protocol & Stack │
│ 189 issues · 39 patches │
╰────────────────────────────────────╯
Run `cd ./.` to go to the repository directory.
Exit code: 0
$ rad patch checkout 1e96844aef957e27206a8e3d87fbd4706890b174
✓ Switched to branch patch/1e96844 at revision 13d597c
✓ Branch patch/1e96844 setup to track rad/patches/1e96844aef957e27206a8e3d87fbd4706890b174
Exit code: 0
$ git config advice.detachedHead false
Exit code: 0
$ git checkout 2dfe90755d20b4a4d02494c7e42478aadf284443
HEAD is now at 2dfe9075 implement per-repo abbreviating
Exit code: 0
$ rad patch show 1e96844aef957e27206a8e3d87fbd4706890b174 -p
╭────────────────────────────────────────────────────────────────────────────────╮
│ Title cli: use git config's `core.abbrev` for SHA-1 abbrevs │
│ Patch 1e96844aef957e27206a8e3d87fbd4706890b174 │
│ Author radsammyt z6Mktnv…irs8DHL │
│ Head 2dfe90755d20b4a4d02494c7e42478aadf284443 │
│ Base ee1c867800eacea37d489d966622d0aff0af0b70 │
│ Target master │
│ Branches patch/1e96844 │
│ Commits ahead 2, behind 1237 │
│ Status archived │
│ │
│ Implements `radicle_cli::git::get_abbrev()`, which will │
│ get git's `core.abbrev`, which can be applied to COB IDs │
│ and git OIDs (or any SHA1 abbreviation.) │
│ │
│ This also respects special cases where `core.abbrev` can │
│ be legally set to "auto" or "no", where "auto" gets an appropriate │
│ length based on a loose count of objects in the current repo, and │
│ "no" which doesn't abbreviate the SHA1 at all. │
├────────────────────────────────────────────────────────────────────────────────┤
│ 2dfe907 implement per-repo abbreviating │
│ b2c7d87 cli: use git config's `core.abbrev` for SHA-1 abbreviations │
├────────────────────────────────────────────────────────────────────────────────┤
│ ● Revision 1e96844 @ bb5355f..1c20d56 by radsammyt z6Mktnv…irs8DHL 2 years ago │
│ ↑ Revision 7a9bd35 @ bb5355f..f82e6a8 by radsammyt z6Mktnv…irs8DHL 2 years ago │
│ ↑ Revision bdfee1c @ bb5355f..24a3fff by radsammyt z6Mktnv…irs8DHL 2 years ago │
│ └─ ⋄ reviewed by fintohaps z6Mkire…SQZ3voM 2 years ago │
│ ↑ Revision cac8ecb @ bb5355f..8e8c98e by radsammyt z6Mktnv…irs8DHL 2 years ago │
│ ↑ Revision bab1f82 @ bb5355f..46ae3ae by fintohaps z6Mkire…SQZ3voM 2 years ago │
│ ↑ Revision 189de2f @ bb5355f..13d8a81 by fintohaps z6Mkire…SQZ3voM 2 years ago │
│ ↑ Revision 276bf66 @ 765fc48..a1d5825 by radsammyt z6Mktnv…irs8DHL 2 years ago │
│ ↑ Revision 38b88d5 @ 765fc48..ec048f4 by radsammyt z6Mktnv…irs8DHL 2 years ago │
│ ↑ Revision 6e2a988 @ 765fc48..b5dff55 by radsammyt z6Mktnv…irs8DHL 2 years ago │
│ ↑ Revision 13d597c @ ee1c867..2dfe907 by radsammyt z6Mktnv…irs8DHL 2 years ago │
╰────────────────────────────────────────────────────────────────────────────────╯
commit 2dfe90755d20b4a4d02494c7e42478aadf284443
Author: RadsammyT <radsammyt@gmail.com>
Date: Thu Jul 25 14:34:16 2024 -0400
implement per-repo abbreviating
Meant to address a key point in review.
I want to focus on the implementation of `get_abbrev_rid()` and whatnot
before I can go ahead with replacing the old (cwd) implementation with
the new one and make it work with all usages of `format::cob()/oid()`
diff --git a/radicle-cli/src/git.rs b/radicle-cli/src/git.rs
index a93d0d9c18..13431a78c1 100644
--- a/radicle-cli/src/git.rs
+++ b/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());
diff --git a/radicle-cli/src/terminal/format.rs b/radicle-cli/src/terminal/format.rs
index 1bacb17baf..8f2101523b 100644
--- a/radicle-cli/src/terminal/format.rs
+++ b/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)
))
}
commit b2c7d87a1c90e826e415bdced04d9136e343151d
Author: RadsammyT <radsammyt@gmail.com>
Date: Thu Apr 25 20:28:28 2024 -0400
cli: use git config's `core.abbrev` for SHA-1 abbreviations
Attempt to determine how to abbreviate SHA-1 values in the CLI by checking the
`core.abbrev` value in Git configuration.
If this is not set then a default of 7 is used as a fallback. Note that a value
of 10 is a better recommendation, however, due to testing values, 7 was chosen
to minimise the changes made in this commit. It should be considered, in the
future, to use `auto` as a default, and then 10 as a final fallback value (or
pehaps 40 -- the max).
Co-authored-by: Fintan Halpenny <fintan.halpenny@gmail.com>
diff --git a/radicle-cli/src/git.rs b/radicle-cli/src/git.rs
index ab0f5c6a93..a93d0d9c18 100644
--- a/radicle-cli/src/git.rs
+++ b/radicle-cli/src/git.rs
@@ -9,10 +9,12 @@ use std::fmt::Display;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::Write;
+use std::num::ParseIntError;
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
+use std::sync::OnceLock;
use anyhow::anyhow;
use anyhow::Context as _;
@@ -36,6 +38,14 @@ pub const CONFIG_GPG_FORMAT: &str = "gpg.format";
pub const CONFIG_GPG_SSH_PROGRAM: &str = "gpg.ssh.program";
pub const CONFIG_GPG_SSH_ALLOWED_SIGNERS: &str = "gpg.ssh.allowedSignersFile";
+/// The default abbreviation length to fall back to should [`get_abbrev()`] fail
+/// to get its value.
+const CONFIG_ABBREV_DEFAULT: usize = 7;
+
+/// The abbreviation length to format all SHA-1 hashes to be this long.
+/// [`get_abbrev()`] should be called to get (or initialize) this value.
+static CONFIG_ABBREV: OnceLock<usize> = OnceLock::new();
+
/// Git revision parameter. Supports extended SHA-1 syntax.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Rev(String);
@@ -331,6 +341,123 @@ pub fn check_version() -> Result<Version, anyhow::Error> {
Ok(git_version)
}
+/// Values that match the possible values of [`core.abbrev`][coreabbrev].
+///
+/// `Abbreviation::default` gives a default value of [`CONFIG_ABBREV_DEFAULT`]
+/// characters.
+///
+/// [coreabbrev]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreabbrev
+#[derive(Clone, Copy, Debug)]
+pub enum Abbreviation {
+ /// Automatically decide the length by using `git` to find the shortest
+ /// abbreviation to uniquely identify any SHA in this repository.
+ Auto,
+ /// Use the maximum abbreviation, i.e. 40 characters.
+ No,
+ /// Use the defined length found at `core.abbrev`.
+ ///
+ /// Note that the value must be between 4 and 40. If a smaller or larger
+ /// value is used, it is clamped.
+ Length(usize),
+}
+
+impl FromStr for Abbreviation {
+ type Err = ParseIntError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ match s {
+ "auto" => Ok(Self::Auto),
+ "no" => Ok(Self::No),
+ n => n
+ .parse::<usize>()
+ .map(|n| Self::Length(n.clamp(Self::MIN, Self::MAX))),
+ }
+ }
+}
+
+impl Default for Abbreviation {
+ fn default() -> Self {
+ Self::Length(CONFIG_ABBREV_DEFAULT)
+ }
+}
+
+impl Abbreviation {
+ /// The minimum number of characters to abbreviate a SHA to.
+ const MIN: usize = 4;
+ /// The maximum number of characters of SHA1.
+ const MAX: usize = 40;
+ /// The Git config key for the abbreviation.
+ const KEY: &'static str = "core.abbrev";
+ /// The Git value for automatically getting the abbreviation length.
+ const AUTO: &'static str = "auto";
+
+ /// Construct the `Abbreviation`.
+ ///
+ /// The `Abbreviation` is constructed by:
+ /// 1. First check the local Git configuration.
+ /// 2. If it could not determine the value in 1., then check the global
+ /// Git configuration.
+ /// 3. Otherwise, default to [`CONFIG_ABBREV_DEFAULT`].
+ pub fn new() -> Result<Self, git2::Error> {
+ match repository().and_then(|repo| Ok(repo.config()?)) {
+ Ok(local) => Self::from_config(&local).or_else(|_| Self::from_global()),
+ Err(_) => Self::from_global(),
+ }
+ }
+
+ fn from_global() -> Result<Self, git2::Error> {
+ git2::Config::open_default()
+ .and_then(|cfg| Self::from_config(&cfg))
+ .or(Ok(Self::default()))
+ }
+
+ fn from_config(config: &git2::Config) -> Result<Self, git2::Error> {
+ let entry = config.get_entry(Self::KEY)?;
+ entry
+ .value()
+ .unwrap_or(Self::AUTO)
+ .trim()
+ .parse::<Self>()
+ .map_err(|e| {
+ git2::Error::new(
+ git2::ErrorCode::User,
+ git2::ErrorClass::Config,
+ e.to_string(),
+ )
+ })
+ }
+
+ /// Get the abbreviation length.
+ ///
+ /// 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 {
+ match self {
+ Abbreviation::Auto => git(Path::new("."), ["rev-parse", "--short", "HEAD"])
+ .unwrap_or("a".repeat(CONFIG_ABBREV_DEFAULT))
+ .trim()
+ .len(),
+ Abbreviation::No => Self::MAX,
+ Abbreviation::Length(n) => *n,
+ }
+ }
+}
+
+/// Get the abbreviation length to use for Git SHA formatting.
+///
+/// The Git config is used to lookup [`core.abbrev`][coreabbrev] to determine
+/// the strategy for how many characters to abbreviate to (see [`Abbreviation`]
+/// for more details).
+///
+/// [coreabbrev]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreabbrev
+pub fn get_abbrev() -> usize {
+ *OnceLock::get_or_init(&CONFIG_ABBREV, || {
+ let abbrev = Abbreviation::new().unwrap_or_default();
+ abbrev.length()
+ })
+}
+
/// Parse a remote refspec into a peer id and ref.
pub fn parse_remote(refspec: &str) -> Option<(NodeId, &str)> {
refspec
@@ -348,9 +475,9 @@ pub fn view_diff(
let workdir = repo
.workdir()
.ok_or_else(|| anyhow!("Could not get workdir current repository."))?;
-
- let left = format!("{:.7}", left.to_string());
- let right = format!("{:.7}", right.to_string());
+ let abbrev = get_abbrev();
+ let left = format!("{:.abbrev$}", left.to_string());
+ let right = format!("{:.abbrev$}", right.to_string());
let mut git = Command::new("git")
.current_dir(workdir)
diff --git a/radicle-cli/src/terminal/format.rs b/radicle-cli/src/terminal/format.rs
index a8bf169051..1bacb17baf 100644
--- a/radicle-cli/src/terminal/format.rs
+++ b/radicle-cli/src/terminal/format.rs
@@ -14,6 +14,7 @@ use radicle::profile::{env, Profile};
use radicle::storage::RefUpdate;
use radicle_term::element::Line;
+use crate::git;
use crate::terminal as term;
/// Format a node id to be more compact.
@@ -27,7 +28,11 @@ pub fn node(node: &NodeId) -> Paint<String> {
/// Format a git Oid.
pub fn oid(oid: impl Into<radicle::git::Oid>) -> Paint<String> {
- Paint::new(format!("{:.7}", oid.into()))
+ Paint::new(format!(
+ "{:.abbrev$}",
+ oid.into(),
+ abbrev = git::get_abbrev()
+ ))
}
/// Wrap parenthesis around styled input, eg. `"input"` -> `"(input)"`.
@@ -47,7 +52,11 @@ pub fn command<D: fmt::Display>(cmd: D) -> Paint<String> {
/// Format a COB id.
pub fn cob(id: &ObjectId) -> Paint<String> {
- Paint::new(format!("{:.7}", id.to_string()))
+ Paint::new(format!(
+ "{:.abbrev$}",
+ id.to_string(),
+ abbrev = git::get_abbrev()
+ ))
}
/// Format a DID.
Exit code: 0
shell: 'cargo --version rustc --version cargo fmt --check cargo clippy --all-targets --workspace -- --deny clippy::all cargo build --all-targets --workspace cargo doc --workspace cargo test --workspace --no-fail-fast '
Commands:
$ podman run --name b3690268-d99a-4139-b36a-b90a737ecce1 -v /opt/radcis/ci.rad.levitte.org/cci/state/b3690268-d99a-4139-b36a-b90a737ecce1/s:/b3690268-d99a-4139-b36a-b90a737ecce1/s:ro -v /opt/radcis/ci.rad.levitte.org/cci/state/b3690268-d99a-4139-b36a-b90a737ecce1/w:/b3690268-d99a-4139-b36a-b90a737ecce1/w -w /b3690268-d99a-4139-b36a-b90a737ecce1/w -v /opt/radcis/ci.rad.levitte.org/.radicle:/${id}/.radicle:ro -e RAD_HOME=/${id}/.radicle rust:trixie bash /b3690268-d99a-4139-b36a-b90a737ecce1/s/script.sh
+ cargo --version
info: syncing channel updates for '1.77-x86_64-unknown-linux-gnu'
info: latest update on 2024-04-09, rust version 1.77.2 (25ef9e3d8 2024-04-09)
info: downloading component 'cargo'
info: downloading component 'rust-std'
info: downloading component 'rustc'
info: installing component 'cargo'
info: installing component 'rust-std'
info: installing component 'rustc'
cargo 1.77.2 (e52e36006 2024-03-26)
+ rustc --version
rustc 1.77.2 (25ef9e3d8 2024-04-09)
+ cargo fmt --check
error: 'cargo-fmt' is not installed for the toolchain '1.77-x86_64-unknown-linux-gnu'.
To install, run `rustup component add --toolchain 1.77-x86_64-unknown-linux-gnu rustfmt`
Exit code: 1
{
"response": "finished",
"result": "failure"
}