feat(config): 在加密导出/导入中包含个人访问令牌

This commit is contained in:
2026-03-23 17:59:23 +08:00
parent 0c7d2ad518
commit 8dd9e85b77
7 changed files with 787 additions and 48 deletions

View File

@@ -1042,6 +1042,102 @@ impl<'a> GitConfigHelper<'a> {
}
}
/// Configuration source indicator
#[derive(Debug, Clone, PartialEq)]
pub enum ConfigSource {
Local,
Global,
NotSet,
}
impl std::fmt::Display for ConfigSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConfigSource::Local => write!(f, "local"),
ConfigSource::Global => write!(f, "global"),
ConfigSource::NotSet => write!(f, "not set"),
}
}
}
/// Single configuration entry with source information
#[derive(Debug, Clone)]
pub struct ConfigEntry {
pub value: Option<String>,
pub source: ConfigSource,
pub local_value: Option<String>,
pub global_value: Option<String>,
}
impl ConfigEntry {
pub fn new(local: Option<String>, global: Option<String>) -> Self {
let (value, source) = match (&local, &global) {
(Some(_), _) => (local.clone(), ConfigSource::Local),
(None, Some(_)) => (global.clone(), ConfigSource::Global),
(None, None) => (None, ConfigSource::NotSet),
};
Self {
value,
source,
local_value: local,
global_value: global,
}
}
pub fn is_set(&self) -> bool {
self.value.is_some()
}
pub fn is_local(&self) -> bool {
self.source == ConfigSource::Local
}
pub fn is_global(&self) -> bool {
self.source == ConfigSource::Global
}
}
/// Merged user configuration with local/global source tracking
#[derive(Debug, Clone)]
pub struct MergedUserConfig {
pub name: ConfigEntry,
pub email: ConfigEntry,
pub signing_key: ConfigEntry,
pub ssh_command: ConfigEntry,
pub commit_gpgsign: ConfigEntry,
pub tag_gpgsign: ConfigEntry,
}
impl MergedUserConfig {
pub fn from_repo(repo: &Repository) -> Result<Self> {
let local_config = repo.config().ok();
let global_config = git2::Config::open_default().ok();
let get_entry = |key: &str| -> ConfigEntry {
let local = local_config.as_ref().and_then(|c| c.get_string(key).ok());
let global = global_config.as_ref().and_then(|c| c.get_string(key).ok());
ConfigEntry::new(local, global)
};
Ok(Self {
name: get_entry("user.name"),
email: get_entry("user.email"),
signing_key: get_entry("user.signingkey"),
ssh_command: get_entry("core.sshCommand"),
commit_gpgsign: get_entry("commit.gpgsign"),
tag_gpgsign: get_entry("tag.gpgsign"),
})
}
pub fn is_complete(&self) -> bool {
self.name.is_set() && self.email.is_set()
}
pub fn has_local_overrides(&self) -> bool {
self.name.is_local() || self.email.is_local() || self.signing_key.is_local() || self.ssh_command.is_local()
}
}
/// User configuration for git
#[derive(Debug, Clone)]
pub struct UserConfig {