Skip to content

Commit 991d560

Browse files
charlieviethth1000s
authored andcommitted
Cache the Git remote URL to speed up rendering hyperlinks
This commit changes the GitConfig struct to cache the GitRemoteRepo, which speeds up the rendering of hyperlinks by ~55x. Fixes #1939
1 parent e95965c commit 991d560

File tree

3 files changed

+34
-20
lines changed

3 files changed

+34
-20
lines changed

src/features/hyperlinks.rs

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use regex::{Match, Matches, Regex};
66

77
use crate::config::Config;
88
use crate::features::OptionValueFunction;
9-
use crate::git_config::{GitConfig, GitRemoteRepo};
9+
10+
#[cfg(test)]
11+
use crate::git_config::GitConfig;
1012

1113
pub fn make_feature() -> Vec<(String, OptionValueFunction)> {
1214
builtin_feature!([
@@ -19,18 +21,6 @@ pub fn make_feature() -> Vec<(String, OptionValueFunction)> {
1921
])
2022
}
2123

22-
#[cfg(test)]
23-
pub fn remote_from_config(_: &Option<&GitConfig>) -> Option<GitRemoteRepo> {
24-
Some(GitRemoteRepo::GitHub {
25-
slug: "dandavison/delta".to_string(),
26-
})
27-
}
28-
29-
#[cfg(not(test))]
30-
pub fn remote_from_config(cfg: &Option<&GitConfig>) -> Option<GitRemoteRepo> {
31-
cfg.and_then(GitConfig::get_remote_url)
32-
}
33-
3424
lazy_static! {
3525
// Commit hashes can be abbreviated to 7 characters, these necessarily become longer
3626
// when more objects are in a repository.
@@ -80,12 +70,14 @@ pub fn format_commit_line_with_osc8_commit_hyperlink<'a>(
8070
.with_input(line, &first_match, &mut matches);
8171
return Cow::from(result);
8272
}
83-
} else if let Some(repo) = remote_from_config(&config.git_config()) {
84-
let mut matches = COMMIT_HASH_REGEX.find_iter(line);
85-
if let Some(first_match) = matches.next() {
86-
let result = HyperlinkCommits(|commit_hash| repo.format_commit_url(commit_hash))
87-
.with_input(line, &first_match, &mut matches);
88-
return Cow::from(result);
73+
} else if let Some(config) = config.git_config() {
74+
if let Some(repo) = config.get_remote_url() {
75+
let mut matches = COMMIT_HASH_REGEX.find_iter(line);
76+
if let Some(first_match) = matches.next() {
77+
let result = HyperlinkCommits(|commit_hash| repo.format_commit_url(commit_hash))
78+
.with_input(line, &first_match, &mut matches);
79+
return Cow::from(result);
80+
}
8981
}
9082
}
9183
Cow::from(line)

src/git_config/mod.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub use remote::GitRemoteRepo;
44

55
use crate::env::DeltaEnv;
66
use regex::Regex;
7+
use std::cell::OnceCell;
78
use std::collections::HashMap;
89
use std::path::Path;
910

@@ -14,6 +15,7 @@ pub struct GitConfig {
1415
config_from_env_var: HashMap<String, String>,
1516
pub enabled: bool,
1617
repo: Option<git2::Repository>,
18+
remote_url: OnceCell<Option<GitRemoteRepo>>,
1719
// To make GitConfig cloneable when testing (in turn to make Config cloneable):
1820
#[cfg(test)]
1921
path: std::path::PathBuf,
@@ -29,6 +31,7 @@ impl Clone for GitConfig {
2931
config_from_env_var: self.config_from_env_var.clone(),
3032
enabled: self.enabled,
3133
repo: None,
34+
remote_url: OnceCell::new(),
3235
path: self.path.clone(),
3336
}
3437
}
@@ -57,6 +60,7 @@ impl GitConfig {
5760
config_from_env_var: parse_config_from_env_var(env),
5861
repo,
5962
enabled: true,
63+
remote_url: OnceCell::new(),
6064
})
6165
}
6266
None => None,
@@ -76,6 +80,7 @@ impl GitConfig {
7680
config_from_env_var: HashMap::new(),
7781
enabled: true,
7882
repo: None,
83+
remote_url: OnceCell::new(),
7984
path: std::path::PathBuf::from("/invalid_null.git"),
8085
})
8186
}
@@ -98,6 +103,7 @@ impl GitConfig {
98103
},
99104
repo: None,
100105
enabled: true,
106+
remote_url: OnceCell::new(),
101107
#[cfg(test)]
102108
path: path.into(),
103109
}
@@ -119,8 +125,13 @@ impl GitConfig {
119125
}
120126
}
121127

128+
#[cfg(test)]
129+
fn get_remote_url_impl(&self) -> Option<GitRemoteRepo> {
130+
GitRemoteRepo::for_testing()
131+
}
132+
122133
#[cfg(not(test))]
123-
pub fn get_remote_url(&self) -> Option<GitRemoteRepo> {
134+
fn get_remote_url_impl(&self) -> Option<GitRemoteRepo> {
124135
use std::str::FromStr;
125136
self.repo
126137
.as_ref()?
@@ -130,6 +141,10 @@ impl GitConfig {
130141
.and_then(|url| GitRemoteRepo::from_str(url).ok())
131142
}
132143

144+
pub fn get_remote_url(&self) -> &Option<GitRemoteRepo> {
145+
self.remote_url.get_or_init(|| self.get_remote_url_impl())
146+
}
147+
133148
pub fn for_each<F>(&self, regex: &str, mut f: F)
134149
where
135150
F: FnMut(&str, Option<&str>),

src/git_config/remote.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ impl GitRemoteRepo {
3131
}
3232
}
3333
}
34+
35+
#[cfg(test)]
36+
pub fn for_testing() -> Option<GitRemoteRepo> {
37+
Some(GitRemoteRepo::GitHub {
38+
slug: "dandavison/delta".to_string(),
39+
})
40+
}
3441
}
3542

3643
lazy_static! {

0 commit comments

Comments
 (0)