From ee53b09a6158ebb034b579ff124362131d93eb7b Mon Sep 17 00:00:00 2001 From: Nikita Galaiko Date: Fri, 24 Nov 2023 09:03:04 +0100 Subject: [PATCH 1/5] replace cranky with new clippy --- .github/workflows/push.yaml | 3 +- Cargo.toml | 77 ++++++++++++++++++++++++++++++++++++ Cranky.toml | 78 ------------------------------------- packages/butler/Cargo.toml | 3 ++ packages/tauri/Cargo.toml | 3 ++ packages/tauri/src/bin.rs | 2 - packages/tauri/src/lib.rs | 2 - scripts/check.sh | 2 +- 8 files changed, 85 insertions(+), 85 deletions(-) delete mode 100644 Cranky.toml diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml index 6a42ccd7f..0e5f0506f 100644 --- a/.github/workflows/push.yaml +++ b/.github/workflows/push.yaml @@ -77,5 +77,4 @@ jobs: steps: - uses: actions/checkout@v4 - uses: ./.github/actions/init-env-rust - - run: cargo install cargo-cranky - - run: cargo cranky --all-targets --all-features + - run: cargo clippy --all-targets --all-features --tests diff --git a/Cargo.toml b/Cargo.toml index fc2c9b640..d355a0426 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,3 +10,80 @@ codegen-units = 1 # Compile crates one after another so the compiler can optimiz lto = true # Enables link to optimizations opt-level = "s" # Optimize for binary size debug = true # Enable debug symbols, for sentry + +[workspace.lints.rust] +unsafe_code = "forbid" + +[workspace.lints.clippy] +all = "deny" +perf = "deny" +correctness = "deny" +complexity = "deny" +style = "deny" +pedantic = "deny" + +# selection from clippy::restriction (see https://rust-lang.github.io/rust-clippy/master/index.html#/?groups=restriction) +as_underscore = "deny" +assertions_on_result_states = "deny" +clone_on_ref_ptr = "deny" +create_dir = "deny" +dbg_macro = "deny" +decimal_literal_representation = "deny" +default_numeric_fallback = "deny" +empty_drop = "deny" +empty_structs_with_brackets = "deny" +exit = "deny" +filetype_is_file = "deny" +float_cmp_const = "deny" +fn_to_numeric_cast_any = "deny" +format_push_string = "deny" +get_unwrap = "deny" +integer_division = "deny" +lossy_float_literal = "deny" +mem_forget = "deny" +mixed_read_write_in_expression = "deny" +mutex_atomic = "deny" +needless_raw_strings = "deny" +non_ascii_literal = "deny" +panic = "deny" +print_stderr = "deny" +pub_without_shorthand = "deny" +rc_buffer = "deny" +rc_mutex = "deny" +redundant_type_annotations = "deny" +ref_patterns = "deny" +rest_pat_in_fully_bound_structs = "deny" +same_name_method = "deny" +string_add = "deny" +string_lit_chars_any = "deny" +string_slice = "deny" +string_to_string = "deny" +suspicious_xor_used_as_pow = "deny" +todo = "deny" +try_err = "deny" +unimplemented = "deny" +unnecessary_self_imports = "deny" +unneeded_field_pattern = "deny" +unseparated_literal_suffix = "deny" +if_then_some_else_none = "deny" +use_debug = "deny" +# TODO +# partial_pub_fields = "deny" +# print_stdout = "deny" +# unwrap_used = "deny" +# unwrap_in_result = "deny" + +# noise and or false-positives +missing_errors_doc = { level = "allow", priority = 1 } +used_underscore_binding = { level = "allow", priority = 1 } +must_use_candidate = { level = "allow", priority = 1 } +module_name_repetitions = { level = "allow", priority = 1 } +missing_panics_doc = { level = "allow", priority = 1 } +too_many_lines = { level = "allow", priority = 1 } +implicit_hasher = { level = "allow", priority = 1 } +if_not_else = { level = "allow", priority = 1 } +return_self_not_must_use = { level = "allow", priority = 1 } +inconsistent_struct_constructor = { level = "allow", priority = 1 } +match_wildcard_for_single_variants = { level = "allow", priority = 1 } +unnested_or_patterns = { level = "allow", priority = 1 } +similar_names = { level = "allow", priority = 1 } diff --git a/Cranky.toml b/Cranky.toml deleted file mode 100644 index 62ac4f5e7..000000000 --- a/Cranky.toml +++ /dev/null @@ -1,78 +0,0 @@ -# https://github.com/ericseppanen/cargo-cranky -# cargo install cargo-cranky && cargo cranky - -deny = [ - "clippy::all", - "clippy::perf", - "clippy::correctness", - "clippy::complexity", - "clippy::style", - "clippy::pedantic", - # selection from clippy::restriction (see https://rust-lang.github.io/rust-clippy/master/index.html#/?groups=restriction) - "clippy::as_underscore", - "clippy::assertions_on_result_states", - "clippy::clone_on_ref_ptr", - "clippy::create_dir", - "clippy::dbg_macro", - "clippy::decimal_literal_representation", - "clippy::default_numeric_fallback", - "clippy::empty_drop", - "clippy::empty_structs_with_brackets", - "clippy::exit", - "clippy::filetype_is_file", - "clippy::float_cmp_const", - "clippy::fn_to_numeric_cast_any", - "clippy::format_push_string", - "clippy::get_unwrap", - "clippy::integer_division", - "clippy::lossy_float_literal", - "clippy::mem_forget", - "clippy::mixed_read_write_in_expression", - "clippy::mutex_atomic", - "clippy::needless_raw_strings", - "clippy::non_ascii_literal", - "clippy::panic", - "clippy::print_stderr", - "clippy::pub_without_shorthand", - "clippy::rc_buffer", - "clippy::rc_mutex", - "clippy::redundant_type_annotations", - "clippy::ref_patterns", - "clippy::rest_pat_in_fully_bound_structs", - "clippy::same_name_method", - "clippy::string_add", - "clippy::string_lit_chars_any", - "clippy::string_slice", - "clippy::string_to_string", - "clippy::suspicious_xor_used_as_pow", - "clippy::todo", - "clippy::try_err", - "clippy::unimplemented", - "clippy::unnecessary_self_imports", - "clippy::unneeded_field_pattern", - "clippy::unseparated_literal_suffix", - "clippy::if_then_some_else_none", - "clippy::use_debug", - #TODO: - # "clippy::partial_pub_fields" - # "clippy::print_stdout" - # "clippy::unwrap_used" - # "clippy::unwrap_in_result" -] - -allow = [ - # reason = "noise and or false-positives" - "clippy::missing_errors_doc", - "clippy::used_underscore_binding", - "clippy::must_use_candidate", - "clippy::module_name_repetitions", - "clippy::missing_panics_doc", - "clippy::too_many_lines", - "clippy::implicit_hasher", - "clippy::if_not_else", - "clippy::return_self_not_must_use", - "clippy::inconsistent_struct_constructor", - "clippy::match_wildcard_for_single_variants", - "clippy::unnested_or_patterns", - "clippy::similar_names", -] diff --git a/packages/butler/Cargo.toml b/packages/butler/Cargo.toml index 863618806..083c763d0 100644 --- a/packages/butler/Cargo.toml +++ b/packages/butler/Cargo.toml @@ -16,3 +16,6 @@ dialoguer = "0.11.0" dirs = "5.0.1" git2 = { version = "0.18.1", features = ["vendored-openssl", "vendored-libgit2"] } gitbutler = { path = "../tauri" } + +[lints] +workspace = true diff --git a/packages/tauri/Cargo.toml b/packages/tauri/Cargo.toml index e6c073e01..c8c17a2e3 100644 --- a/packages/tauri/Cargo.toml +++ b/packages/tauri/Cargo.toml @@ -84,3 +84,6 @@ devtools = ["tauri/devtools"] # this feature is used used for production builds where `devPath` points to the filesystem # DO NOT remove this custom-protocol = ["tauri/custom-protocol"] + +[lints] +workspace = true diff --git a/packages/tauri/src/bin.rs b/packages/tauri/src/bin.rs index 9ed90b6ac..d5dbfe472 100644 --- a/packages/tauri/src/bin.rs +++ b/packages/tauri/src/bin.rs @@ -1,5 +1,3 @@ -#![forbid(unsafe_code)] - use anyhow::Context; use tauri::{generate_context, Manager}; diff --git a/packages/tauri/src/lib.rs b/packages/tauri/src/lib.rs index 388de383e..bfe7701e9 100644 --- a/packages/tauri/src/lib.rs +++ b/packages/tauri/src/lib.rs @@ -1,5 +1,3 @@ -#![forbid(unsafe_code)] - pub mod analytics; pub mod app; pub mod assets; diff --git a/scripts/check.sh b/scripts/check.sh index d182a034f..f5a2a26bb 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -7,7 +7,7 @@ set -o pipefail function rust() { cargo fmt --check cargo sort -c -w - cargo cranky --all-targets --all-features + cargo clippy --all-targets --all-features --tests cargo test } From 8defd6e42ba1e54d613559bb23f280e65155ab04 Mon Sep 17 00:00:00 2001 From: Nikita Galaiko Date: Fri, 24 Nov 2023 09:38:50 +0100 Subject: [PATCH 2/5] support tag refnames --- .../tauri/src/git/reference/refname/error.rs | 2 + .../tauri/src/git/reference/refname/mod.rs | 15 ++++-- .../tauri/src/git/reference/refname/tag.rs | 53 +++++++++++++++++++ .../src/git/reference/refname/virtual.rs | 15 +----- packages/tauri/src/git/repository.rs | 3 +- packages/tauri/src/virtual_branches/base.rs | 13 ++++- packages/tauri/src/virtual_branches/remote.rs | 2 +- packages/tauri/tests/common.rs | 10 ++-- 8 files changed, 87 insertions(+), 26 deletions(-) create mode 100644 packages/tauri/src/git/reference/refname/tag.rs diff --git a/packages/tauri/src/git/reference/refname/error.rs b/packages/tauri/src/git/reference/refname/error.rs index cd17f13f9..a964fe399 100644 --- a/packages/tauri/src/git/reference/refname/error.rs +++ b/packages/tauri/src/git/reference/refname/error.rs @@ -4,6 +4,8 @@ use crate::git; pub enum Error { #[error("branch name is invalid: {0}")] InvalidName(String), + #[error("reference is not a tag: {0}")] + NotTag(String), #[error("branch is not local: {0}")] NotLocal(String), #[error("branch is not remote: {0}")] diff --git a/packages/tauri/src/git/reference/refname/mod.rs b/packages/tauri/src/git/reference/refname/mod.rs index 16f94912a..f9169d0f5 100644 --- a/packages/tauri/src/git/reference/refname/mod.rs +++ b/packages/tauri/src/git/reference/refname/mod.rs @@ -1,6 +1,7 @@ mod error; mod local; mod remote; +mod tag; mod r#virtual; use std::{fmt, str::FromStr}; @@ -11,12 +12,14 @@ pub use error::Error; pub use local::Refname as LocalRefname; pub use r#virtual::Refname as VirtualRefname; pub use remote::Refname as RemoteRefname; +pub use tag::Refname as TagRefname; use crate::git; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Refname { HEAD, + Tag(TagRefname), Remote(RemoteRefname), Local(LocalRefname), Virtual(VirtualRefname), @@ -59,12 +62,12 @@ impl From<&LocalRefname> for Refname { } impl Refname { - pub fn branch(&self) -> &str { + pub fn branch(&self) -> Option<&str> { match self { - Self::HEAD => "HEAD", - Self::Remote(remote) => remote.branch(), - Self::Local(local) => local.branch(), - Self::Virtual(r#virtual) => r#virtual.branch(), + Self::HEAD | Self::Tag(_) => None, + Self::Remote(remote) => Some(remote.branch()), + Self::Local(local) => Some(local.branch()), + Self::Virtual(r#virtual) => Some(r#virtual.branch()), } } } @@ -107,6 +110,7 @@ impl fmt::Display for Refname { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::HEAD => write!(f, "HEAD"), + Self::Tag(tag) => tag.fmt(f), Self::Remote(remote) => remote.fmt(f), Self::Local(local) => local.fmt(f), Self::Virtual(r#virtual) => r#virtual.fmt(f), @@ -118,6 +122,7 @@ impl Serialize for Refname { fn serialize(&self, serializer: S) -> Result { match self { Self::HEAD => serializer.serialize_str("HEAD"), + Self::Tag(tag) => tag.serialize(serializer), Self::Remote(remote) => remote.serialize(serializer), Self::Local(local) => local.serialize(serializer), Self::Virtual(r#virtual) => r#virtual.serialize(serializer), diff --git a/packages/tauri/src/git/reference/refname/tag.rs b/packages/tauri/src/git/reference/refname/tag.rs new file mode 100644 index 000000000..a20494737 --- /dev/null +++ b/packages/tauri/src/git/reference/refname/tag.rs @@ -0,0 +1,53 @@ +use std::{fmt, str::FromStr}; + +use serde::{Deserialize, Serialize}; + +use super::error::Error; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct Refname { + tag: String, +} + +impl Refname { + pub fn tag(&self) -> &str { + &self.tag + } +} + +impl Serialize for Refname { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(&self.to_string()) + } +} + +impl<'d> Deserialize<'d> for Refname { + fn deserialize>(deserializer: D) -> Result { + let name = String::deserialize(deserializer)?; + name.as_str().parse().map_err(serde::de::Error::custom) + } +} + +impl fmt::Display for Refname { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "refs/tags/{}", self.tag) + } +} + +impl FromStr for Refname { + type Err = Error; + + fn from_str(value: &str) -> Result { + if !value.starts_with("refs/tags/") { + return Err(Error::NotTag(value.to_string())); + } + + if let Some(tag) = value.strip_prefix("refs/tags/") { + Ok(Self { + tag: tag.to_string(), + }) + } else { + Err(Error::InvalidName(value.to_string())) + } + } +} diff --git a/packages/tauri/src/git/reference/refname/virtual.rs b/packages/tauri/src/git/reference/refname/virtual.rs index 0d29ea0cc..3a1d994f5 100644 --- a/packages/tauri/src/git/reference/refname/virtual.rs +++ b/packages/tauri/src/git/reference/refname/virtual.rs @@ -2,7 +2,7 @@ use std::{fmt, str::FromStr}; use serde::{Deserialize, Serialize}; -use crate::{git, virtual_branches::Branch}; +use crate::virtual_branches::Branch; use super::error::Error; @@ -62,16 +62,3 @@ impl FromStr for Refname { } } } - -impl TryFrom<&git::Branch<'_>> for Refname { - type Error = Error; - - fn try_from(value: &git::Branch<'_>) -> std::result::Result { - let branch_name = String::from_utf8(value.refname_bytes().to_vec()).map_err(Error::Utf8)?; - if value.is_remote() { - Err(Error::NotLocal(branch_name)) - } else { - branch_name.parse() - } - } -} diff --git a/packages/tauri/src/git/repository.rs b/packages/tauri/src/git/repository.rs index 0b236d68a..fea3693a6 100644 --- a/packages/tauri/src/git/repository.rs +++ b/packages/tauri/src/git/repository.rs @@ -330,6 +330,7 @@ impl Repository { .find_branch( &match name { Refname::HEAD => "HEAD".to_string(), + Refname::Tag(tag) => tag.tag().to_string(), Refname::Virtual(virtual_refname) => virtual_refname.branch().to_string(), Refname::Local(local) => local.branch().to_string(), Refname::Remote(remote) => { @@ -337,7 +338,7 @@ impl Repository { } }, match name { - Refname::HEAD | Refname::Virtual(_) | Refname::Local(_) => { + Refname::HEAD | Refname::Virtual(_) | Refname::Local(_) | Refname::Tag(_) => { git2::BranchType::Local } Refname::Remote(_) => git2::BranchType::Remote, diff --git a/packages/tauri/src/virtual_branches/base.rs b/packages/tauri/src/virtual_branches/base.rs index 735aacc43..798822ea1 100644 --- a/packages/tauri/src/virtual_branches/base.rs +++ b/packages/tauri/src/virtual_branches/base.rs @@ -580,6 +580,12 @@ pub fn create_virtual_branch_from_branch( applied: Option, user: Option<&users::User>, ) -> Result { + if !matches!(upstream, git::Refname::Local(_) | git::Refname::Remote(_)) { + return Err(errors::CreateVirtualBranchFromBranchError::BranchNotFound( + upstream.clone(), + )); + } + let current_session = gb_repository .get_or_create_current_session() .context("failed to get or create current session")?; @@ -623,7 +629,7 @@ pub fn create_virtual_branch_from_branch( // only set upstream if it's not the default target let upstream_branch = match upstream { - git::Refname::Virtual(_) | git::Refname::HEAD => { + git::Refname::Virtual(_) | git::Refname::HEAD | git::Refname::Tag(_) => { // we don't support creating virtual branches from virtual branches return Err(errors::CreateVirtualBranchFromBranchError::BranchNotFound( upstream.clone(), @@ -639,7 +645,10 @@ pub fn create_virtual_branch_from_branch( let mut branch = branch::Branch { id: BranchId::generate(), - name: upstream.branch().to_string(), + name: upstream + .branch() + .expect("always a branch reference") + .to_string(), notes: String::new(), applied: applied.unwrap_or(false), upstream: upstream_branch, diff --git a/packages/tauri/src/virtual_branches/remote.rs b/packages/tauri/src/virtual_branches/remote.rs index 7075e19f1..d748c8133 100644 --- a/packages/tauri/src/virtual_branches/remote.rs +++ b/packages/tauri/src/virtual_branches/remote.rs @@ -66,7 +66,7 @@ pub fn list_remote_branches( .context("failed to convert branches")? .into_iter() .flatten() - .filter(|branch| branch.name.branch() != default_target.branch.branch()) + .filter(|branch| branch.name.branch() != Some(default_target.branch.branch())) .collect::>(); Ok(remote_branches) diff --git a/packages/tauri/tests/common.rs b/packages/tauri/tests/common.rs index 613fcdb9b..502f70531 100644 --- a/packages/tauri/tests/common.rs +++ b/packages/tauri/tests/common.rs @@ -109,9 +109,13 @@ impl TestProject { /// works like if we'd open and merge a PR on github. does not update local. pub fn merge(&self, branch_name: &git::Refname) { - let branch_name: git::Refname = format!("refs/heads/{}", branch_name.branch()) - .parse() - .unwrap(); + let branch_name: git::Refname = match branch_name { + git::Refname::Local(local) => format!("refs/heads/{}", local.branch()).parse().unwrap(), + git::Refname::Remote(remote) => { + format!("refs/heads/{}", remote.branch()).parse().unwrap() + } + _ => "INVALID".parse().unwrap(), // todo + }; let branch = self.remote_repository.find_branch(&branch_name).unwrap(); let branch_commit = branch.peel_to_commit().unwrap(); From c58298f48f66e48900716349730f654111ea1d62 Mon Sep 17 00:00:00 2001 From: Nikita Galaiko Date: Fri, 24 Nov 2023 09:56:42 +0100 Subject: [PATCH 3/5] support stash ref --- .../tauri/src/git/reference/refname/mod.rs | 27 +++++++++---------- packages/tauri/src/git/repository.rs | 9 ++++--- packages/tauri/src/virtual_branches/base.rs | 7 +++-- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/packages/tauri/src/git/reference/refname/mod.rs b/packages/tauri/src/git/reference/refname/mod.rs index f9169d0f5..e02718176 100644 --- a/packages/tauri/src/git/reference/refname/mod.rs +++ b/packages/tauri/src/git/reference/refname/mod.rs @@ -19,6 +19,7 @@ use crate::git; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Refname { HEAD, + STASH, Tag(TagRefname), Remote(RemoteRefname), Local(LocalRefname), @@ -64,7 +65,7 @@ impl From<&LocalRefname> for Refname { impl Refname { pub fn branch(&self) -> Option<&str> { match self { - Self::HEAD | Self::Tag(_) => None, + Self::HEAD | Self::Tag(_) | Self::STASH => None, Self::Remote(remote) => Some(remote.branch()), Self::Local(local) => Some(local.branch()), Self::Virtual(r#virtual) => Some(r#virtual.branch()), @@ -76,20 +77,14 @@ impl FromStr for Refname { type Err = Error; fn from_str(value: &str) -> Result { - if value == "HEAD" { - Ok(Self::HEAD) - } else if value.starts_with("refs") { - if value.starts_with("refs/remotes/") { - Ok(Self::Remote(value.parse()?)) - } else if value.starts_with("refs/heads/") { - Ok(Self::Local(value.parse()?)) - } else if value.starts_with("refs/gitbutler/") { - Ok(Self::Virtual(value.parse()?)) - } else { - Err(Error::InvalidName(value.to_string())) - } - } else { - Ok(Self::Local(value.parse()?)) + match value { + "HEAD" => Ok(Self::HEAD), + "refs/stash" => Ok(Self::STASH), + value if value.starts_with("refs/tags/") => Ok(Self::Tag(value.parse()?)), + value if value.starts_with("refs/remotes/") => Ok(Self::Remote(value.parse()?)), + value if value.starts_with("refs/heads/") => Ok(Self::Local(value.parse()?)), + value if value.starts_with("refs/gitbutler/") => Ok(Self::Virtual(value.parse()?)), + _ => Err(Error::InvalidName(value.to_string())), } } } @@ -110,6 +105,7 @@ impl fmt::Display for Refname { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::HEAD => write!(f, "HEAD"), + Self::STASH => write!(f, "refs/stash"), Self::Tag(tag) => tag.fmt(f), Self::Remote(remote) => remote.fmt(f), Self::Local(local) => local.fmt(f), @@ -121,6 +117,7 @@ impl fmt::Display for Refname { impl Serialize for Refname { fn serialize(&self, serializer: S) -> Result { match self { + Self::STASH => serializer.serialize_str("refs/stash"), Self::HEAD => serializer.serialize_str("HEAD"), Self::Tag(tag) => tag.serialize(serializer), Self::Remote(remote) => remote.serialize(serializer), diff --git a/packages/tauri/src/git/repository.rs b/packages/tauri/src/git/repository.rs index fea3693a6..81e3a4f8d 100644 --- a/packages/tauri/src/git/repository.rs +++ b/packages/tauri/src/git/repository.rs @@ -330,6 +330,7 @@ impl Repository { .find_branch( &match name { Refname::HEAD => "HEAD".to_string(), + Refname::STASH => "stash".to_string(), Refname::Tag(tag) => tag.tag().to_string(), Refname::Virtual(virtual_refname) => virtual_refname.branch().to_string(), Refname::Local(local) => local.branch().to_string(), @@ -338,9 +339,11 @@ impl Repository { } }, match name { - Refname::HEAD | Refname::Virtual(_) | Refname::Local(_) | Refname::Tag(_) => { - git2::BranchType::Local - } + Refname::STASH + | Refname::HEAD + | Refname::Virtual(_) + | Refname::Local(_) + | Refname::Tag(_) => git2::BranchType::Local, Refname::Remote(_) => git2::BranchType::Remote, }, ) diff --git a/packages/tauri/src/virtual_branches/base.rs b/packages/tauri/src/virtual_branches/base.rs index 798822ea1..9eb4a0119 100644 --- a/packages/tauri/src/virtual_branches/base.rs +++ b/packages/tauri/src/virtual_branches/base.rs @@ -629,8 +629,11 @@ pub fn create_virtual_branch_from_branch( // only set upstream if it's not the default target let upstream_branch = match upstream { - git::Refname::Virtual(_) | git::Refname::HEAD | git::Refname::Tag(_) => { - // we don't support creating virtual branches from virtual branches + git::Refname::STASH + | git::Refname::Virtual(_) + | git::Refname::HEAD + | git::Refname::Tag(_) => { + // we only support local or remote branches return Err(errors::CreateVirtualBranchFromBranchError::BranchNotFound( upstream.clone(), )); From 07a2d01e837f58645b3d88c9fad8b8922e8d18bb Mon Sep 17 00:00:00 2001 From: Nikita Galaiko Date: Fri, 24 Nov 2023 10:03:04 +0100 Subject: [PATCH 4/5] filter pushable references by type --- .../handlers/push_project_to_gitbutler.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/tauri/src/watcher/handlers/push_project_to_gitbutler.rs b/packages/tauri/src/watcher/handlers/push_project_to_gitbutler.rs index 90896a208..a8561a1e7 100644 --- a/packages/tauri/src/watcher/handlers/push_project_to_gitbutler.rs +++ b/packages/tauri/src/watcher/handlers/push_project_to_gitbutler.rs @@ -5,7 +5,7 @@ use tauri::AppHandle; use tokio::sync::Mutex; use crate::{ - gb_repository, + gb_repository, git, paths::DataDir, project_repository, projects::{self, CodePushState, ProjectId}, @@ -144,10 +144,16 @@ impl HandlerInner { Err(err) => return Err(err).context("failed to push"), }; - let refs = gb_refs(&project_repository)?; + let refnames = gb_refs(&project_repository)?; - let all_refs = refs + let all_refs = refnames .iter() + .filter(|r| { + matches!( + r, + git::Refname::Remote(_) | git::Refname::Virtual(_) | git::Refname::Local(_) + ) + }) .map(|r| format!("+{}:{}", r, r)) .collect::>(); @@ -169,11 +175,13 @@ impl HandlerInner { } } -fn gb_refs(project_repository: &project_repository::Repository) -> anyhow::Result> { +fn gb_refs( + project_repository: &project_repository::Repository, +) -> anyhow::Result> { Ok(project_repository .git_repository .references_glob("refs/*")? .flatten() - .filter_map(|r| r.name().map(|name| name.to_string())) + .filter_map(|r| r.name()) .collect::>()) } From d477c269304e1c8e7afa57d25336f695bfcfa8b8 Mon Sep 17 00:00:00 2001 From: Mattias Granlund Date: Fri, 24 Nov 2023 10:08:28 +0100 Subject: [PATCH 5/5] Fix issue with saving project settings --- packages/ui/src/lib/backend/projects.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/ui/src/lib/backend/projects.ts b/packages/ui/src/lib/backend/projects.ts index f635740c1..0bc6fb37d 100644 --- a/packages/ui/src/lib/backend/projects.ts +++ b/packages/ui/src/lib/backend/projects.ts @@ -1,6 +1,6 @@ import { invoke } from '$lib/backend/ipc'; import type { Project as CloudProject } from '$lib/backend/cloud'; -import { BehaviorSubject, catchError, from, switchMap } from 'rxjs'; +import { BehaviorSubject, Observable, catchError, from, map, shareReplay, switchMap } from 'rxjs'; export type Key = | 'generated' @@ -22,6 +22,7 @@ export class ProjectService { error$ = new BehaviorSubject(undefined); projects$ = this.reload$.pipe( switchMap(() => from(invoke('list_projects'))), + shareReplay(1), catchError((e) => { this.error$.next(e); return []; @@ -31,20 +32,33 @@ export class ProjectService { constructor() {} getProject(projectId: string) { - return from(invoke('get_project', { id: projectId })); + return this.projects$.pipe( + map((projects) => { + const project = projects.find((p) => (p.id = projectId)); + if (!project) { + // We need to abort loading of /[projectId]/ if no project exists, such + // that the type here is of Project rather than Project | undefined. + throw 'Project not found'; + } + return project; + }) + ); } - updateProject(params: { + async updateProject(params: { id: string; title?: string; api?: CloudProject & { sync: boolean }; preferred_key?: Key; }) { - return invoke('update_project', { project: params }); + await invoke('update_project', { project: params }); + this.reload(); } async add(path: string) { - return await invoke('add_project', { path }); + const project = await invoke('add_project', { path }); + this.reload(); + return project; } async deleteProject(id: string) {