From 40cfc55309dd298b3a9d5594e0d5f8ee86614c41 Mon Sep 17 00:00:00 2001 From: Kiril Videlov Date: Mon, 3 Jun 2024 17:00:14 +0200 Subject: [PATCH] support setting signCommits git config --- app/src/lib/ai/service.test.ts | 6 ++++ app/src/lib/backend/gitConfigService.ts | 11 ++++++ app/src/lib/components/PreferencesForm.svelte | 27 ++++++++++++++ crates/gitbutler-core/src/config/git.rs | 35 +++++++++++++++++++ crates/gitbutler-core/src/config/mod.rs | 1 + crates/gitbutler-core/src/lib.rs | 1 + crates/gitbutler-tauri/src/config.rs | 34 ++++++++++++++++++ crates/gitbutler-tauri/src/lib.rs | 1 + crates/gitbutler-tauri/src/main.rs | 4 ++- 9 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 crates/gitbutler-core/src/config/git.rs create mode 100644 crates/gitbutler-core/src/config/mod.rs create mode 100644 crates/gitbutler-tauri/src/config.rs diff --git a/app/src/lib/ai/service.test.ts b/app/src/lib/ai/service.test.ts index c1849e554..4550f7082 100644 --- a/app/src/lib/ai/service.test.ts +++ b/app/src/lib/ai/service.test.ts @@ -29,6 +29,12 @@ const defaultGitConfig = Object.freeze({ class DummyGitConfigService implements GitConfigService { constructor(private config: { [index: string]: string | undefined }) {} + async getSignCommitsConfig(_projectId: string): Promise { + throw new Error('Method not implemented.'); + } + async setSignCommitsConfig(_projectId: string, _value: boolean): Promise { + throw new Error('Method not implemented.'); + } async get(key: string): Promise { return (this.config[key] || undefined) as T | undefined; diff --git a/app/src/lib/backend/gitConfigService.ts b/app/src/lib/backend/gitConfigService.ts index dce50fd73..223efb4ac 100644 --- a/app/src/lib/backend/gitConfigService.ts +++ b/app/src/lib/backend/gitConfigService.ts @@ -13,4 +13,15 @@ export class GitConfigService { async set(key: string, value: T) { return await invoke('git_set_global_config', { key, value }); } + + // Gets the value of `gitbutler.signCommits` + // Determines if the app should attempt to sign commits using per the git configuration. + async getSignCommitsConfig(projectId: string): Promise { + return await invoke('get_sign_commits_config', { projectId }); + } + + // Sets the value of `gitbutler.signCommits` + async setSignCommitsConfig(projectId: string, value: boolean) { + return await invoke('set_sign_commits_config', { projectId, value }); + } } diff --git a/app/src/lib/components/PreferencesForm.svelte b/app/src/lib/components/PreferencesForm.svelte index 769d9fbd6..9fda2b63b 100644 --- a/app/src/lib/components/PreferencesForm.svelte +++ b/app/src/lib/components/PreferencesForm.svelte @@ -2,10 +2,12 @@ import SectionCard from './SectionCard.svelte'; import Spacer from './Spacer.svelte'; import TextBox from './TextBox.svelte'; + import { GitConfigService } from '$lib/backend/gitConfigService'; import { Project, ProjectService } from '$lib/backend/projects'; import Toggle from '$lib/components/Toggle.svelte'; import { projectRunCommitHooks } from '$lib/config/config'; import { getContext } from '$lib/utils/context'; + import { onMount } from 'svelte'; const projectService = getContext(ProjectService); const project = getContext(Project); @@ -14,6 +16,7 @@ let allowForcePushing = project?.ok_with_force_push; let omitCertificateCheck = project?.omit_certificate_check; + const gitConfig = getContext(GitConfigService); const runCommitHooks = projectRunCommitHooks(project.id); async function setWithForcePush(value: boolean) { @@ -30,6 +33,16 @@ project.snapshot_lines_threshold = value; await projectService.updateProject(project); } + + let signCommits = false; + async function setSignCommits(value: boolean) { + signCommits = value; + await gitConfig.setSignCommitsConfig(project.id, value); + } + + onMount(async () => { + signCommits = (await gitConfig.getSignCommitsConfig(project.id)) || false; + });
@@ -48,6 +61,20 @@ + + Sign commits + + GitButler will sign commits as per your git configuration. + + + await setSignCommits(signCommits)} + /> + + + Ignore host certificate checks diff --git a/crates/gitbutler-core/src/config/git.rs b/crates/gitbutler-core/src/config/git.rs new file mode 100644 index 000000000..715dc8d18 --- /dev/null +++ b/crates/gitbutler-core/src/config/git.rs @@ -0,0 +1,35 @@ +use crate::projects::Project; +use anyhow::Result; +use git2::ConfigLevel; + +const CFG_SIGN_COMMITS: &str = "gitbutler.signCommits"; + +impl Project { + pub fn set_sign_commits(&self, val: bool) -> Result<()> { + self.set_local_bool(CFG_SIGN_COMMITS, val) + } + pub fn sign_commits(&self) -> Result> { + self.get_bool(CFG_SIGN_COMMITS) + } + + fn set_local_bool(&self, key: &str, val: bool) -> Result<()> { + let repo = git2::Repository::open(&self.path)?; + let config = repo.config()?; + match config.open_level(ConfigLevel::Local) { + Ok(mut local) => local.set_bool(key, val).map_err(Into::into), + Err(err) => Err(err.into()), + } + } + + fn get_bool(&self, key: &str) -> Result> { + let repo = git2::Repository::open(&self.path)?; + let config = repo.config()?; + match config.get_bool(key) { + Ok(value) => Ok(Some(value)), + Err(err) => match err.code() { + git2::ErrorCode::NotFound => Ok(None), + _ => Err(err.into()), + }, + } + } +} diff --git a/crates/gitbutler-core/src/config/mod.rs b/crates/gitbutler-core/src/config/mod.rs new file mode 100644 index 000000000..c2bf1c3ee --- /dev/null +++ b/crates/gitbutler-core/src/config/mod.rs @@ -0,0 +1 @@ +pub mod git; diff --git a/crates/gitbutler-core/src/lib.rs b/crates/gitbutler-core/src/lib.rs index 8d7441d19..079323f1f 100644 --- a/crates/gitbutler-core/src/lib.rs +++ b/crates/gitbutler-core/src/lib.rs @@ -15,6 +15,7 @@ pub mod askpass; pub mod assets; +pub mod config; pub mod dedup; pub mod error; pub mod fs; diff --git a/crates/gitbutler-tauri/src/config.rs b/crates/gitbutler-tauri/src/config.rs new file mode 100644 index 000000000..25f99594c --- /dev/null +++ b/crates/gitbutler-tauri/src/config.rs @@ -0,0 +1,34 @@ +use crate::error::Error; +use anyhow::Context; +use gitbutler_core::projects::{self, ProjectId}; +use tauri::Manager; +use tracing::instrument; + +#[tauri::command(async)] +#[instrument(skip(handle), err(Debug))] +pub async fn get_sign_commits_config( + handle: tauri::AppHandle, + project_id: ProjectId, +) -> Result, Error> { + handle + .state::() + .get(project_id) + .context("failed to get project")? + .sign_commits() + .map_err(Into::into) +} + +#[tauri::command(async)] +#[instrument(skip(handle), err(Debug))] +pub async fn set_sign_commits_config( + handle: tauri::AppHandle, + project_id: ProjectId, + value: bool, +) -> Result<(), Error> { + handle + .state::() + .get(project_id) + .context("failed to get project")? + .set_sign_commits(value) + .map_err(Into::into) +} diff --git a/crates/gitbutler-tauri/src/lib.rs b/crates/gitbutler-tauri/src/lib.rs index 4845906f4..6b0034b3a 100644 --- a/crates/gitbutler-tauri/src/lib.rs +++ b/crates/gitbutler-tauri/src/lib.rs @@ -21,6 +21,7 @@ pub mod menu; pub mod watcher; pub mod askpass; +pub mod config; pub mod error; pub mod github; pub mod keys; diff --git a/crates/gitbutler-tauri/src/main.rs b/crates/gitbutler-tauri/src/main.rs index d5bcb5fd1..8c520770d 100644 --- a/crates/gitbutler-tauri/src/main.rs +++ b/crates/gitbutler-tauri/src/main.rs @@ -15,7 +15,7 @@ use gitbutler_core::{assets, git, storage}; use gitbutler_tauri::{ - app, askpass, commands, github, keys, logs, menu, projects, remotes, undo, users, + app, askpass, commands, config, github, keys, logs, menu, projects, remotes, undo, users, virtual_branches, watcher, zip, }; use tauri::{generate_context, Manager}; @@ -209,6 +209,8 @@ fn main() { undo::list_snapshots, undo::restore_snapshot, undo::snapshot_diff, + config::get_sign_commits_config, + config::set_sign_commits_config, menu::menu_item_set_enabled, keys::commands::get_public_key, github::commands::init_device_oauth,