Merge pull request #4689 from Byron/missing-project

better handling of missing projects
This commit is contained in:
Sebastian Thiel 2024-08-15 11:28:15 +02:00 committed by GitHub
commit 00e3094795
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 3 deletions

View File

@ -133,6 +133,7 @@ pub enum Code {
CommitSigningFailed, CommitSigningFailed,
CommitHookFailed, CommitHookFailed,
CommitMergeConflictFailure, CommitMergeConflictFailure,
ProjectMissing,
AuthorMissing, AuthorMissing,
} }
@ -147,6 +148,7 @@ impl std::fmt::Display for Code {
Code::CommitHookFailed => "errors.commit.hook_failed", Code::CommitHookFailed => "errors.commit.hook_failed",
Code::CommitMergeConflictFailure => "errors.commit.merge_conflict_failure", Code::CommitMergeConflictFailure => "errors.commit.merge_conflict_failure",
Code::AuthorMissing => "errors.git.author_missing", Code::AuthorMissing => "errors.git.author_missing",
Code::ProjectMissing => "errors.projects.missing",
}; };
f.write_str(code) f.write_str(code)
} }

View File

@ -1,6 +1,6 @@
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use anyhow::{bail, Context, Result}; use anyhow::{anyhow, bail, Context, Result};
use gitbutler_error::error; use gitbutler_error::error;
use super::{storage, storage::UpdateRequest, Project, ProjectId}; use super::{storage, storage::UpdateRequest, Project, ProjectId};
@ -120,8 +120,33 @@ impl Controller {
} }
pub fn get(&self, id: ProjectId) -> Result<Project> { pub fn get(&self, id: ProjectId) -> Result<Project> {
self.get_inner(id, false)
}
/// Like [`Self::get()`], but will assure the project still exists and is valid by
/// opening a git repository. This should only be done for critical points in time.
pub fn get_validated(&self, id: ProjectId) -> Result<Project> {
self.get_inner(id, true)
}
fn get_inner(&self, id: ProjectId, validate: bool) -> Result<Project> {
#[cfg_attr(not(windows), allow(unused_mut))] #[cfg_attr(not(windows), allow(unused_mut))]
let mut project = self.projects_storage.get(id)?; let mut project = self.projects_storage.get(id)?;
if validate {
let worktree_dir = &project.path;
if gix::open_opts(worktree_dir, gix::open::Options::isolated()).is_err() {
let suffix = if !worktree_dir.exists() {
" as it does not exist"
} else {
""
};
return Err(anyhow!(
"Could not open repository at '{}'{suffix}",
worktree_dir.display()
)
.context(error::Code::ProjectMissing));
}
}
if !project.gb_dir().exists() { if !project.gb_dir().exists() {
if let Err(error) = std::fs::create_dir_all(project.gb_dir()) { if let Err(error) = std::fs::create_dir_all(project.gb_dir()) {
tracing::error!(project_id = %project.id, ?error, "failed to create \"{}\" on project get", project.gb_dir().display()); tracing::error!(project_id = %project.id, ?error, "failed to create \"{}\" on project get", project.gb_dir().display());

View File

@ -34,7 +34,7 @@ pub mod commands {
projects: State<'_, Controller>, projects: State<'_, Controller>,
id: ProjectId, id: ProjectId,
) -> Result<projects::Project, Error> { ) -> Result<projects::Project, Error> {
Ok(projects.get(id)?) Ok(projects.get_validated(id)?)
} }
#[tauri::command(async)] #[tauri::command(async)]
@ -66,7 +66,7 @@ pub mod commands {
window: Window, window: Window,
id: ProjectId, id: ProjectId,
) -> Result<(), Error> { ) -> Result<(), Error> {
let project = projects.get(id).context("project not found")?; let project = projects.get_validated(id).context("project not found")?;
Ok(window_state.set_project_to_window(window.label(), &project)?) Ok(window_state.set_project_to_window(window.label(), &project)?)
} }