mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-02 07:53:55 +03:00
merged upstream
This commit is contained in:
commit
44a032f492
3
.github/workflows/push.yaml
vendored
3
.github/workflows/push.yaml
vendored
@ -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
|
||||
|
77
Cargo.toml
77
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 }
|
||||
|
78
Cranky.toml
78
Cranky.toml
@ -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",
|
||||
]
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use anyhow::Context;
|
||||
use tauri::{generate_context, Manager};
|
||||
|
||||
|
@ -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}")]
|
||||
|
@ -1,6 +1,7 @@
|
||||
mod error;
|
||||
mod local;
|
||||
mod remote;
|
||||
mod tag;
|
||||
mod r#virtual;
|
||||
|
||||
use std::{fmt, str::FromStr};
|
||||
@ -11,12 +12,15 @@ 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,
|
||||
STASH,
|
||||
Tag(TagRefname),
|
||||
Remote(RemoteRefname),
|
||||
Local(LocalRefname),
|
||||
Virtual(VirtualRefname),
|
||||
@ -59,12 +63,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(_) | Self::STASH => None,
|
||||
Self::Remote(remote) => Some(remote.branch()),
|
||||
Self::Local(local) => Some(local.branch()),
|
||||
Self::Virtual(r#virtual) => Some(r#virtual.branch()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -73,20 +77,14 @@ impl FromStr for Refname {
|
||||
type Err = Error;
|
||||
|
||||
fn from_str(value: &str) -> Result<Self, Self::Err> {
|
||||
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())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -107,6 +105,8 @@ 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),
|
||||
Self::Virtual(r#virtual) => r#virtual.fmt(f),
|
||||
@ -117,7 +117,9 @@ impl fmt::Display for Refname {
|
||||
impl Serialize for Refname {
|
||||
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
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),
|
||||
Self::Local(local) => local.serialize(serializer),
|
||||
Self::Virtual(r#virtual) => r#virtual.serialize(serializer),
|
||||
|
53
packages/tauri/src/git/reference/refname/tag.rs
Normal file
53
packages/tauri/src/git/reference/refname/tag.rs
Normal file
@ -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<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> Deserialize<'d> for Refname {
|
||||
fn deserialize<D: serde::Deserializer<'d>>(deserializer: D) -> Result<Self, D::Error> {
|
||||
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<Self, Self::Err> {
|
||||
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()))
|
||||
}
|
||||
}
|
||||
}
|
@ -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<Self, Self::Error> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -330,6 +330,8 @@ 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(),
|
||||
Refname::Remote(remote) => {
|
||||
@ -337,9 +339,11 @@ impl Repository {
|
||||
}
|
||||
},
|
||||
match name {
|
||||
Refname::HEAD | Refname::Virtual(_) | Refname::Local(_) => {
|
||||
git2::BranchType::Local
|
||||
}
|
||||
Refname::STASH
|
||||
| Refname::HEAD
|
||||
| Refname::Virtual(_)
|
||||
| Refname::Local(_)
|
||||
| Refname::Tag(_) => git2::BranchType::Local,
|
||||
Refname::Remote(_) => git2::BranchType::Remote,
|
||||
},
|
||||
)
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
pub mod analytics;
|
||||
pub mod app;
|
||||
pub mod assets;
|
||||
|
@ -580,6 +580,12 @@ pub fn create_virtual_branch_from_branch(
|
||||
applied: Option<bool>,
|
||||
user: Option<&users::User>,
|
||||
) -> Result<branch::Branch, CreateVirtualBranchFromBranchError> {
|
||||
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,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 => {
|
||||
// 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(),
|
||||
));
|
||||
@ -639,7 +648,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,
|
||||
|
@ -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::<Vec<_>>();
|
||||
|
||||
Ok(remote_branches)
|
||||
|
@ -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::<Vec<_>>();
|
||||
|
||||
@ -169,11 +175,13 @@ impl HandlerInner {
|
||||
}
|
||||
}
|
||||
|
||||
fn gb_refs(project_repository: &project_repository::Repository) -> anyhow::Result<Vec<String>> {
|
||||
fn gb_refs(
|
||||
project_repository: &project_repository::Repository,
|
||||
) -> anyhow::Result<Vec<git::Refname>> {
|
||||
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::<Vec<_>>())
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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<any>(undefined);
|
||||
projects$ = this.reload$.pipe(
|
||||
switchMap(() => from(invoke<Project[]>('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<Project>('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<Project>('update_project', { project: params });
|
||||
await invoke<Project>('update_project', { project: params });
|
||||
this.reload();
|
||||
}
|
||||
|
||||
async add(path: string) {
|
||||
return await invoke<Project>('add_project', { path });
|
||||
const project = await invoke<Project>('add_project', { path });
|
||||
this.reload();
|
||||
return project;
|
||||
}
|
||||
|
||||
async deleteProject(id: string) {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user