mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-22 00:51:38 +03:00
Merge branch 'master' into ian/visual-changes-2023-07-11-1
This commit is contained in:
commit
b9c9b18aff
@ -84,7 +84,7 @@
|
||||
"svelte-check": "^3.0.1",
|
||||
"svelte-floating-ui": "^1.5.2",
|
||||
"svelte-french-toast": "^1.0.3",
|
||||
"svelte-loadable-store": "^1.2.3",
|
||||
"svelte-loadable-store": "^2.0.0",
|
||||
"svelte-outclick": "^3.5.0",
|
||||
"svelte-resize-observer": "^2.0.0",
|
||||
"tailwindcss": "^3.1.5",
|
||||
|
@ -200,8 +200,8 @@ devDependencies:
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3(svelte@3.55.1)
|
||||
svelte-loadable-store:
|
||||
specifier: ^1.2.3
|
||||
version: 1.2.3(svelte@3.55.1)
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0(svelte@3.55.1)
|
||||
svelte-outclick:
|
||||
specifier: ^3.5.0
|
||||
version: 3.5.0(svelte@3.55.1)
|
||||
@ -213,10 +213,10 @@ devDependencies:
|
||||
version: 3.2.4(postcss@8.4.21)
|
||||
tauri-plugin-log-api:
|
||||
specifier: github:tauri-apps/tauri-plugin-log
|
||||
version: github.com/tauri-apps/tauri-plugin-log/21921031d74f871180381317a338559f588ad8e9
|
||||
version: github.com/tauri-apps/tauri-plugin-log/fbbb126e6d7fba7a7e6772d33f99c0fb689f32b6
|
||||
tauri-plugin-websocket-api:
|
||||
specifier: github:tauri-apps/tauri-plugin-websocket
|
||||
version: github.com/tauri-apps/tauri-plugin-websocket/7832cb121d2ecaf6b52c9bdee77df18fddaac5d9
|
||||
version: github.com/tauri-apps/tauri-plugin-websocket/39b7ba2c0c27a9b0093b00120830ed23774f5403
|
||||
tinykeys:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
@ -4717,8 +4717,8 @@ packages:
|
||||
svelte: 3.55.1
|
||||
dev: true
|
||||
|
||||
/svelte-loadable-store@1.2.3(svelte@3.55.1):
|
||||
resolution: {integrity: sha512-efoCRCGLxzU+RE1D09cpnKKBO2CVXAzjUY0/RatOtPXSNPbb0/HeGcV/baH5davabwiDm7iWf2rqI9ogIRQ1Pw==}
|
||||
/svelte-loadable-store@2.0.0(svelte@3.55.1):
|
||||
resolution: {integrity: sha512-2mnbj99fnbQg4WwXW3WZWUqAbcaXkHacFFulb7r+VdSic9PkkKq/117V94lVeCrC9BxMR7KaOdESE7+JZTsWxg==}
|
||||
peerDependencies:
|
||||
svelte: ^3.0.0
|
||||
dependencies:
|
||||
@ -5459,16 +5459,16 @@ packages:
|
||||
engines: {node: '>=12.20'}
|
||||
dev: true
|
||||
|
||||
github.com/tauri-apps/tauri-plugin-log/21921031d74f871180381317a338559f588ad8e9:
|
||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-log/tar.gz/21921031d74f871180381317a338559f588ad8e9}
|
||||
github.com/tauri-apps/tauri-plugin-log/fbbb126e6d7fba7a7e6772d33f99c0fb689f32b6:
|
||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-log/tar.gz/fbbb126e6d7fba7a7e6772d33f99c0fb689f32b6}
|
||||
name: tauri-plugin-log-api
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@tauri-apps/api': 1.4.0
|
||||
dev: true
|
||||
|
||||
github.com/tauri-apps/tauri-plugin-websocket/7832cb121d2ecaf6b52c9bdee77df18fddaac5d9:
|
||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-websocket/tar.gz/7832cb121d2ecaf6b52c9bdee77df18fddaac5d9}
|
||||
github.com/tauri-apps/tauri-plugin-websocket/39b7ba2c0c27a9b0093b00120830ed23774f5403:
|
||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-websocket/tar.gz/39b7ba2c0c27a9b0093b00120830ed23774f5403}
|
||||
name: tauri-plugin-websocket-api
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
|
@ -563,9 +563,9 @@ impl Repository {
|
||||
// lookup a branch by name
|
||||
let branch = repo.find_branch(target_branch, git2::BranchType::Remote)?;
|
||||
|
||||
let remote = repo.branch_remote_name(branch.get().name().unwrap())?;
|
||||
let remote_url = repo.find_remote(remote.as_str().unwrap())?;
|
||||
let remote_url_str = remote_url.url().unwrap();
|
||||
let remote_name = repo.branch_remote_name(branch.get().name().unwrap())?;
|
||||
let remote = repo.find_remote(remote_name.as_str().unwrap())?;
|
||||
let remote_url = remote.url().unwrap();
|
||||
|
||||
// get a list of currently active virtual branches
|
||||
|
||||
@ -604,8 +604,9 @@ impl Repository {
|
||||
}
|
||||
|
||||
let target = virtual_branches::target::Target {
|
||||
name: branch.name().unwrap().unwrap().to_string(),
|
||||
remote: remote_url_str.to_string(),
|
||||
branch_name: branch.name()?.unwrap().to_string(),
|
||||
remote_name: remote.name().unwrap().to_string(),
|
||||
remote_url: remote_url.to_string(),
|
||||
sha: commit_oid,
|
||||
behind: 0,
|
||||
};
|
||||
|
@ -101,8 +101,9 @@ mod tests {
|
||||
|
||||
fn test_target() -> target::Target {
|
||||
target::Target {
|
||||
name: format!("target_name_{}", unsafe { TEST_TARGET_INDEX }),
|
||||
remote: format!("remote_{}", unsafe { TEST_TARGET_INDEX }),
|
||||
branch_name: format!("branch name{}", unsafe { TEST_TARGET_INDEX }),
|
||||
remote_name: format!("remote name {}", unsafe { TEST_TARGET_INDEX }),
|
||||
remote_url: format!("remote url {}", unsafe { TEST_TARGET_INDEX }),
|
||||
sha: git2::Oid::from_str(&format!(
|
||||
"0123456789abcdef0123456789abcdef0123456{}",
|
||||
unsafe { TEST_TARGET_INDEX }
|
||||
|
@ -752,7 +752,6 @@ pub fn list_virtual_branches(
|
||||
let mut upstream_commit = None;
|
||||
if !branch.upstream.is_empty() {
|
||||
// get the target remote
|
||||
let remote_url = &default_target.remote;
|
||||
let remotes = repo.remotes()?;
|
||||
let mut upstream_remote = None;
|
||||
for remote_name in remotes.iter() {
|
||||
@ -767,7 +766,7 @@ pub fn list_virtual_branches(
|
||||
None => continue,
|
||||
};
|
||||
|
||||
if url == remote_url {
|
||||
if url == default_target.remote_url {
|
||||
upstream_remote = Some(remote);
|
||||
break;
|
||||
}
|
||||
@ -1564,12 +1563,12 @@ pub fn update_branch_target(
|
||||
|
||||
let repo = &project_repository.git_repository;
|
||||
let branch = repo
|
||||
.find_branch(&target.name, git2::BranchType::Remote)
|
||||
.context(format!("failed to find branch {}", target.name))?;
|
||||
let new_target_commit = branch
|
||||
.get()
|
||||
.peel_to_commit()
|
||||
.context(format!("failed to peel branch {} to commit", target.name))?;
|
||||
.find_branch(&target.branch_name, git2::BranchType::Remote)
|
||||
.context(format!("failed to find branch {}", target.branch_name))?;
|
||||
let new_target_commit = branch.get().peel_to_commit().context(format!(
|
||||
"failed to peel branch {} to commit",
|
||||
target.branch_name
|
||||
))?;
|
||||
let new_target_oid = new_target_commit.id();
|
||||
//
|
||||
// if the target has not changed, do nothing
|
||||
@ -1938,13 +1937,13 @@ pub fn get_target_data(
|
||||
Some(mut target) => {
|
||||
let repo = &project_repository.git_repository;
|
||||
let branch = repo
|
||||
.find_branch(&target.name, git2::BranchType::Remote)
|
||||
.find_branch(&target.branch_name, git2::BranchType::Remote)
|
||||
.unwrap();
|
||||
let commit = branch.get().peel_to_commit().unwrap();
|
||||
let oid = commit.id();
|
||||
target.behind = project_repository
|
||||
.behind(oid, target.sha)
|
||||
.context(format!("failed to get behind for {}", target.name))?;
|
||||
.context(format!("failed to get behind for {}", target.branch_name))?;
|
||||
Ok(Some(target))
|
||||
}
|
||||
}
|
||||
@ -2026,8 +2025,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2093,8 +2093,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2153,8 +2154,9 @@ mod tests {
|
||||
gb_repository::Repository::open(gb_repo_path, project.id, project_store, user_store)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2200,8 +2202,9 @@ mod tests {
|
||||
gb_repository::Repository::open(gb_repo_path, project.id, project_store, user_store)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2242,8 +2245,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2329,8 +2333,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2388,8 +2393,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2509,8 +2515,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2624,8 +2631,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2719,8 +2727,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2784,8 +2793,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin/master".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "origin/master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2891,8 +2901,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin/master".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "origin/master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -2970,8 +2981,9 @@ mod tests {
|
||||
let project_repository = project_repository::Repository::open(&project)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin/master".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "origin/master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -3055,8 +3067,9 @@ mod tests {
|
||||
commit_all(&repository)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin/master".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "origin/master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -3160,8 +3173,9 @@ mod tests {
|
||||
commit_all(&repository)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin/master".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -3249,8 +3263,9 @@ mod tests {
|
||||
commit_all(&repository)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin/master".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -3419,8 +3434,9 @@ mod tests {
|
||||
commit_all(&repository)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin/master".to_string(),
|
||||
remote: "http://origin.com/project".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "http://origin.com/project".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -3529,8 +3545,9 @@ mod tests {
|
||||
commit_all(&repository)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin/master".to_string(),
|
||||
remote: "http://origin.com/project".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "http://origin.com/project".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -3681,8 +3698,9 @@ mod tests {
|
||||
)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin/master".to_string(),
|
||||
remote: "http://origin.com/project".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_url: "http://origin.com/project".to_string(),
|
||||
sha: upstream_commit,
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -3785,8 +3803,9 @@ mod tests {
|
||||
commit_all(&repository)?;
|
||||
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "origin".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: repository.head().unwrap().target().unwrap(),
|
||||
behind: 0,
|
||||
})?;
|
||||
@ -3941,8 +3960,9 @@ mod tests {
|
||||
let commit1_oid = repository.head().unwrap().target().unwrap();
|
||||
let commit1 = repository.find_commit(commit1_oid).unwrap();
|
||||
target::Writer::new(&gb_repo).write_default(&target::Target {
|
||||
name: "origin".to_string(),
|
||||
remote: "origin".to_string(),
|
||||
branch_name: "master".to_string(),
|
||||
remote_name: "origin".to_string(),
|
||||
remote_url: "origin".to_string(),
|
||||
sha: commit1_oid,
|
||||
behind: 0,
|
||||
})?;
|
||||
|
@ -8,8 +8,9 @@ pub use writer::TargetWriter as Writer;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Target {
|
||||
pub name: String,
|
||||
pub remote: String,
|
||||
pub branch_name: String,
|
||||
pub remote_name: String,
|
||||
pub remote_url: String,
|
||||
pub sha: git2::Oid,
|
||||
pub behind: u32,
|
||||
}
|
||||
@ -19,26 +20,56 @@ impl Serialize for Target {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("Target", 3)?;
|
||||
state.serialize_field("name", &self.name)?;
|
||||
state.serialize_field("remote", &self.remote)?;
|
||||
let mut state = serializer.serialize_struct("Target", 5)?;
|
||||
state.serialize_field("branchName", &self.branch_name)?;
|
||||
state.serialize_field("remoteName", &self.remote_name)?;
|
||||
state.serialize_field("remoteUrl", &self.remote_url)?;
|
||||
state.serialize_field("behind", &self.behind)?;
|
||||
state.serialize_field("sha", &self.sha.to_string())?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
// this is a backwards compatibile with the old format
|
||||
fn read_remote_url(reader: &dyn crate::reader::Reader) -> Result<String, crate::reader::Error> {
|
||||
match reader.read_string("remote_url") {
|
||||
Ok(url) => Ok(url),
|
||||
// fallback to the old format
|
||||
Err(crate::reader::Error::NotFound) => reader.read_string("remote"),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
// returns (remote_name, branch_name)
|
||||
fn read_remote_name_branch_name(
|
||||
reader: &dyn crate::reader::Reader,
|
||||
) -> Result<(String, String), crate::reader::Error> {
|
||||
match reader.read_string("name") {
|
||||
Ok(branch) => {
|
||||
let parts = branch.split('/').collect::<Vec<_>>();
|
||||
Ok((parts[0].to_string(), branch))
|
||||
}
|
||||
Err(crate::reader::Error::NotFound) => {
|
||||
// fallback to the old format
|
||||
let remote_name = reader.read_string("remote_name")?;
|
||||
let branch_name = reader.read_string("branch_name")?;
|
||||
Ok((remote_name, branch_name))
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&dyn crate::reader::Reader> for Target {
|
||||
type Error = crate::reader::Error;
|
||||
|
||||
fn try_from(reader: &dyn crate::reader::Reader) -> Result<Self, Self::Error> {
|
||||
let name = reader.read_string("name").map_err(|e| {
|
||||
let (remote_name, branch_name) = read_remote_name_branch_name(reader).map_err(|e| {
|
||||
crate::reader::Error::IOError(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("name: {}", e),
|
||||
format!("branch: {}", e),
|
||||
))
|
||||
})?;
|
||||
let remote = reader.read_string("remote").map_err(|e| {
|
||||
let remote_url = read_remote_url(reader).map_err(|e| {
|
||||
crate::reader::Error::IOError(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("remote: {}", e),
|
||||
@ -61,8 +92,9 @@ impl TryFrom<&dyn crate::reader::Reader> for Target {
|
||||
})?;
|
||||
|
||||
Ok(Self {
|
||||
name,
|
||||
remote,
|
||||
branch_name,
|
||||
remote_name,
|
||||
remote_url,
|
||||
sha,
|
||||
behind: 0,
|
||||
})
|
||||
|
@ -33,6 +33,7 @@ impl<'reader> TargetReader<'reader> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::writer::Writer;
|
||||
use anyhow::Result;
|
||||
use tempfile::tempdir;
|
||||
|
||||
@ -116,6 +117,54 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_deprecated_format() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
let project = projects::Project::try_from(&repository)?;
|
||||
let gb_repo_path = tempdir()?.path().to_str().unwrap().to_string();
|
||||
let storage = storage::Storage::from_path(tempdir()?.path());
|
||||
let user_store = users::Storage::new(storage.clone());
|
||||
let project_store = projects::Storage::new(storage);
|
||||
project_store.add_project(&project)?;
|
||||
let gb_repo =
|
||||
gb_repository::Repository::open(gb_repo_path, project.id, project_store, user_store)?;
|
||||
|
||||
let writer = crate::writer::DirWriter::open(gb_repo.root());
|
||||
writer
|
||||
.write_string("branches/target/name", "origin/master")
|
||||
.unwrap();
|
||||
writer
|
||||
.write_string(
|
||||
"branches/target/remote",
|
||||
"git@github.com:gitbutlerapp/gitbutler-client.git",
|
||||
)
|
||||
.unwrap();
|
||||
writer
|
||||
.write_string(
|
||||
"branches/target/sha",
|
||||
"dd945831869e9593448aa622fa4342bbfb84813d",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let session = gb_repo.get_or_create_current_session()?;
|
||||
let session_reader = sessions::Reader::open(&gb_repo, &session)?;
|
||||
let reader = TargetReader::new(&session_reader);
|
||||
|
||||
let read = reader.read_default().unwrap();
|
||||
assert_eq!(read.branch_name, "origin/master");
|
||||
assert_eq!(read.remote_name, "origin");
|
||||
assert_eq!(
|
||||
read.remote_url,
|
||||
"git@github.com:gitbutlerapp/gitbutler-client.git"
|
||||
);
|
||||
assert_eq!(
|
||||
read.sha,
|
||||
git2::Oid::from_str("dd945831869e9593448aa622fa4342bbfb84813d").unwrap()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_read_override_target() -> Result<()> {
|
||||
let repository = test_repository()?;
|
||||
@ -131,15 +180,17 @@ mod tests {
|
||||
let branch = test_branch();
|
||||
|
||||
let target = Target {
|
||||
name: "target".to_string(),
|
||||
remote: "remote".to_string(),
|
||||
remote_name: "remote".to_string(),
|
||||
branch_name: "branch".to_string(),
|
||||
remote_url: "remote url".to_string(),
|
||||
sha: git2::Oid::from_str("fedcba9876543210fedcba9876543210fedcba98").unwrap(),
|
||||
behind: 0,
|
||||
};
|
||||
|
||||
let default_target = Target {
|
||||
name: "default_target".to_string(),
|
||||
remote: "default_remote".to_string(),
|
||||
remote_name: "default remote".to_string(),
|
||||
branch_name: "default branch".to_string(),
|
||||
remote_url: "default remote url".to_string(),
|
||||
sha: git2::Oid::from_str("0123456789abcdef0123456789abcdef01234567").unwrap(),
|
||||
behind: 0,
|
||||
};
|
||||
|
@ -31,11 +31,14 @@ impl<'writer> TargetWriter<'writer> {
|
||||
}
|
||||
|
||||
self.writer
|
||||
.write_string("branches/target/name", &target.name)
|
||||
.context("Failed to write default target name")?;
|
||||
.write_string("branches/target/branch_name", &target.branch_name)
|
||||
.context("Failed to write default target branch name")?;
|
||||
self.writer
|
||||
.write_string("branches/target/remote", &target.remote)
|
||||
.context("Failed to write default target remote")?;
|
||||
.write_string("branches/target/remote_name", &target.remote_name)
|
||||
.context("Failed to write default target remote name ")?;
|
||||
self.writer
|
||||
.write_string("branches/target/remote_url", &target.remote_url)
|
||||
.context("Failed to write default target remote name ")?;
|
||||
self.writer
|
||||
.write_string("branches/target/sha", &target.sha.to_string())
|
||||
.context("Failed to write default target sha")?;
|
||||
@ -53,10 +56,22 @@ impl<'writer> TargetWriter<'writer> {
|
||||
}
|
||||
|
||||
self.writer
|
||||
.write_string(&format!("branches/{}/target/name", id), &target.name)
|
||||
.context("Failed to write branch target name")?;
|
||||
.write_string(
|
||||
&format!("branches/{}/target/branch_name", id),
|
||||
&target.branch_name,
|
||||
)
|
||||
.context("Failed to write branch target branch name")?;
|
||||
self.writer
|
||||
.write_string(&format!("branches/{}/target/remote", id), &target.remote)
|
||||
.write_string(
|
||||
&format!("branches/{}/target/remote_name", id),
|
||||
&target.remote_name,
|
||||
)
|
||||
.context("Failed to write branch target remote")?;
|
||||
self.writer
|
||||
.write_string(
|
||||
&format!("branches/{}/target/remote_url", id),
|
||||
&target.remote_url,
|
||||
)
|
||||
.context("Failed to write branch target remote")?;
|
||||
self.writer
|
||||
.write_string(
|
||||
@ -143,8 +158,9 @@ mod tests {
|
||||
|
||||
let branch = test_branch();
|
||||
let target = Target {
|
||||
name: "target_name".to_string(),
|
||||
remote: "target_remote".to_string(),
|
||||
branch_name: "branch name".to_string(),
|
||||
remote_name: "remote name".to_string(),
|
||||
remote_url: "remote url".to_string(),
|
||||
sha: git2::Oid::from_str("0123456789abcdef0123456789abcdef01234567").unwrap(),
|
||||
behind: 0,
|
||||
};
|
||||
@ -163,14 +179,19 @@ mod tests {
|
||||
branch.name
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("target").join("name").to_str().unwrap())
|
||||
fs::read_to_string(root.join("target").join("branch_name").to_str().unwrap())
|
||||
.context("Failed to read branch target name")?,
|
||||
target.name
|
||||
target.branch_name
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("target").join("remote").to_str().unwrap())
|
||||
.context("Failed to read branch target remote")?,
|
||||
target.remote
|
||||
fs::read_to_string(root.join("target").join("remote_name").to_str().unwrap())
|
||||
.context("Failed to read branch target name name")?,
|
||||
target.remote_name
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("target").join("remote_url").to_str().unwrap())
|
||||
.context("Failed to read branch target remote url")?,
|
||||
target.remote_url
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("target").join("sha").to_str().unwrap())
|
||||
@ -230,8 +251,9 @@ mod tests {
|
||||
|
||||
let branch = test_branch();
|
||||
let target = Target {
|
||||
name: "target_name".to_string(),
|
||||
remote: "target_remote".to_string(),
|
||||
remote_name: "remote name".to_string(),
|
||||
branch_name: "branch name".to_string(),
|
||||
remote_url: "remote url".to_string(),
|
||||
sha: git2::Oid::from_str("0123456789abcdef0123456789abcdef01234567").unwrap(),
|
||||
behind: 0,
|
||||
};
|
||||
@ -242,8 +264,9 @@ mod tests {
|
||||
target_writer.write(&branch.id, &target)?;
|
||||
|
||||
let updated_target = Target {
|
||||
name: "updated_target_name".to_string(),
|
||||
remote: "updated_target_remote".to_string(),
|
||||
remote_name: "updated remote name".to_string(),
|
||||
branch_name: "updated branch name".to_string(),
|
||||
remote_url: "updated remote url".to_string(),
|
||||
sha: git2::Oid::from_str("fedcba9876543210fedcba9876543210fedcba98").unwrap(),
|
||||
behind: 0,
|
||||
};
|
||||
@ -253,14 +276,20 @@ mod tests {
|
||||
let root = gb_repo.root().join("branches").join(&branch.id);
|
||||
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("target").join("name").to_str().unwrap())
|
||||
.context("Failed to read branch target name")?,
|
||||
updated_target.name
|
||||
fs::read_to_string(root.join("target").join("branch_name").to_str().unwrap())
|
||||
.context("Failed to read branch target branch name")?,
|
||||
updated_target.branch_name
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("target").join("remote_name").to_str().unwrap())
|
||||
.context("Failed to read branch target remote name")?,
|
||||
updated_target.remote_name
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("target").join("remote").to_str().unwrap())
|
||||
.context("Failed to read branch target remote")?,
|
||||
updated_target.remote
|
||||
fs::read_to_string(root.join("target").join("remote_url").to_str().unwrap())
|
||||
.context("Failed to read branch target remote url")?,
|
||||
updated_target.remote_url
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("target").join("sha").to_str().unwrap())
|
||||
|
@ -12,8 +12,9 @@ static mut TEST_TARGET_INDEX: usize = 0;
|
||||
|
||||
fn test_target() -> virtual_branches::target::Target {
|
||||
virtual_branches::target::Target {
|
||||
name: format!("target_name_{}", unsafe { TEST_TARGET_INDEX }),
|
||||
remote: format!("remote_{}", unsafe { TEST_TARGET_INDEX }),
|
||||
branch_name: format!("branch name {}", unsafe { TEST_TARGET_INDEX }),
|
||||
remote_name: format!("remote name {}", unsafe { TEST_TARGET_INDEX }),
|
||||
remote_url: format!("remote url {}", unsafe { TEST_TARGET_INDEX }),
|
||||
sha: git2::Oid::from_str(&format!(
|
||||
"0123456789abcdef0123456789abcdef0123456{}",
|
||||
unsafe { TEST_TARGET_INDEX }
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { handleErrorWithSentry, init } from '@sentry/sveltekit';
|
||||
import type { NavigationEvent } from '@sveltejs/kit';
|
||||
import { dev } from '$app/environment';
|
||||
import { log } from '$lib';
|
||||
|
||||
init({
|
||||
enabled: !dev,
|
||||
@ -10,7 +9,7 @@ init({
|
||||
tracesSampleRate: 1.0
|
||||
});
|
||||
|
||||
log.info(`sentry init`);
|
||||
console.log(`sentry init`);
|
||||
|
||||
function myErrorHandler({ error, event }: { error: any; event: NavigationEvent }) {
|
||||
console.error('An error occurred on the client side:', error, event);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { PUBLIC_API_BASE_URL } from '$env/static/public';
|
||||
import { PUBLIC_CHAIN_API } from '$env/static/public';
|
||||
import * as log from '$lib/log';
|
||||
import { nanoid } from 'nanoid';
|
||||
|
||||
const apiUrl = new URL('/api/', new URL(PUBLIC_API_BASE_URL));
|
||||
@ -72,13 +71,13 @@ const withRequestId: FetchMiddleware = (fetch) => async (url, options) => {
|
||||
};
|
||||
|
||||
const withLog: FetchMiddleware = (fetch) => async (url, options) => {
|
||||
log.info('fetch', url, options);
|
||||
console.log('fetch', url, options);
|
||||
try {
|
||||
const resp = await fetch(url, options);
|
||||
log.info(resp);
|
||||
console.log(resp);
|
||||
return resp;
|
||||
} catch (e: any) {
|
||||
log.error('fetch', e);
|
||||
console.error('fetch', e);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { type LoginToken, CloudApi } from '$lib/api';
|
||||
import { toasts, log, stores } from '$lib';
|
||||
import { toasts, stores } from '$lib';
|
||||
import { derived, writable } from '@square/svelte-store';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
import Button from './Button';
|
||||
@ -31,7 +31,7 @@
|
||||
.then(cloud.login.token.create)
|
||||
.then(token.set)
|
||||
.catch((e) => {
|
||||
log.error(e);
|
||||
console.error(e);
|
||||
toasts.error('Something went wrong');
|
||||
})
|
||||
.finally(() => (signUpOrLoginLoading = false));
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { building } from '$app/environment';
|
||||
import { events } from '$lib';
|
||||
|
||||
export async function on(combo: string, callback: (event: KeyboardEvent) => void) {
|
||||
if (building) return () => {};
|
||||
|
||||
const comboContainsControlKeys =
|
||||
combo.includes('Meta') || combo.includes('Alt') || combo.includes('Ctrl');
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
export * as api from './api';
|
||||
export * as log from './log';
|
||||
export * as toasts from './toasts';
|
||||
export { Toaster } from './toasts';
|
||||
export * as week from './week';
|
||||
|
@ -1,14 +1,11 @@
|
||||
import { building } from '$app/environment';
|
||||
import type { EventCallback, EventName } from '@tauri-apps/api/event';
|
||||
import { invoke as invokeTauri } from '@tauri-apps/api/tauri';
|
||||
import { listen as listenTauri } from '@tauri-apps/api/event';
|
||||
|
||||
export async function invoke<T>(command: string, params: Record<string, unknown> = {}): Promise<T> {
|
||||
return building
|
||||
? Promise.reject('cannot invoke ipc command while building')
|
||||
: import('@tauri-apps/api').then(({ invoke }) => invoke<T>(command, params));
|
||||
return invokeTauri<T>(command, params);
|
||||
}
|
||||
|
||||
export function listen<T>(event: EventName, handle: EventCallback<T>) {
|
||||
return building
|
||||
? Promise.reject('cannot listen to ipc events while building')
|
||||
: import('@tauri-apps/api/event').then(({ listen }) => listen(event, handle));
|
||||
return listenTauri(event, handle);
|
||||
}
|
||||
|
@ -1,42 +0,0 @@
|
||||
import { building } from '$app/environment';
|
||||
|
||||
export async function setup() {
|
||||
if (!building) {
|
||||
await (await import('tauri-plugin-log-api')).attachConsole();
|
||||
}
|
||||
}
|
||||
|
||||
const logger = async () =>
|
||||
building
|
||||
? {
|
||||
debug: () => {},
|
||||
info: () => {},
|
||||
error: () => {}
|
||||
}
|
||||
: import('tauri-plugin-log-api').then((tauri) => ({
|
||||
debug: tauri.debug,
|
||||
info: tauri.info,
|
||||
error: tauri.error
|
||||
}));
|
||||
|
||||
const toString = (value: any) => {
|
||||
if (value instanceof Error) {
|
||||
return value.message;
|
||||
} else if (typeof value === 'object') {
|
||||
return JSON.stringify(value);
|
||||
} else {
|
||||
return value.toString();
|
||||
}
|
||||
};
|
||||
|
||||
export async function debug(...args: any[]) {
|
||||
return (await logger()).debug(args.map(toString).join(' '));
|
||||
}
|
||||
|
||||
export async function info(...args: any[]) {
|
||||
return (await logger()).info(args.map(toString).join(' '));
|
||||
}
|
||||
|
||||
export async function error(...args: any[]) {
|
||||
(await logger()).error(args.map(toString).join(' '));
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { writable, type Loadable, derived, Value } from 'svelte-loadable-store';
|
||||
import { writable, type Loadable, derived, Loaded } from 'svelte-loadable-store';
|
||||
import { bookmarks, type Bookmark } from '$lib/api';
|
||||
import { get as getValue, type Readable } from '@square/svelte-store';
|
||||
|
||||
@ -12,7 +12,7 @@ export function list(params: { projectId: string }) {
|
||||
const oldValue = getValue(store);
|
||||
if (oldValue.isLoading) {
|
||||
bookmarks.list(params).then(set);
|
||||
} else if (Value.isError(oldValue.value)) {
|
||||
} else if (Loaded.isError(oldValue)) {
|
||||
bookmarks.list(params).then(set);
|
||||
} else {
|
||||
set(oldValue.value.filter((b) => b.timestampMs !== bookmark.timestampMs).concat(bookmark));
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { writable, type Loadable, Value } from 'svelte-loadable-store';
|
||||
import { writable, type Loadable, Loaded } from 'svelte-loadable-store';
|
||||
import { deltas, type Delta } from '$lib/api';
|
||||
import { get, type Readable } from '@square/svelte-store';
|
||||
|
||||
@ -13,7 +13,7 @@ export default (params: { projectId: string; sessionId: string }) => {
|
||||
const oldValue = get(store);
|
||||
if (oldValue.isLoading) {
|
||||
deltas.list(params).then(set);
|
||||
} else if (Value.isError(oldValue.value)) {
|
||||
} else if (Loaded.isError(oldValue)) {
|
||||
deltas.list(params).then(set);
|
||||
} else {
|
||||
set({
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { writable, type Loadable, Value } from 'svelte-loadable-store';
|
||||
import { writable, type Loadable, Loaded } from 'svelte-loadable-store';
|
||||
import { files } from '$lib/api';
|
||||
import { get, type Readable } from '@square/svelte-store';
|
||||
|
||||
@ -13,7 +13,7 @@ export default (params: { projectId: string; sessionId: string }) => {
|
||||
const oldValue = get(store);
|
||||
if (oldValue.isLoading) {
|
||||
files.list(params).then(set);
|
||||
} else if (Value.isError(oldValue.value)) {
|
||||
} else if (Loaded.isError(oldValue)) {
|
||||
files.list(params).then(set);
|
||||
} else {
|
||||
set({
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { derived, writable, type Loadable, Value } from 'svelte-loadable-store';
|
||||
import { derived, writable, type Loadable, Loaded } from 'svelte-loadable-store';
|
||||
import { sessions, type Session } from '$lib/api';
|
||||
import { get, type Readable } from '@square/svelte-store';
|
||||
|
||||
@ -13,7 +13,7 @@ export default (params: { projectId: string }) => {
|
||||
const oldValue = get(store);
|
||||
if (oldValue.isLoading) {
|
||||
sessions.list(params).then(set);
|
||||
} else if (Value.isError(oldValue.value)) {
|
||||
} else if (Loaded.isError(oldValue)) {
|
||||
sessions.list(params).then(set);
|
||||
} else {
|
||||
set(
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { building } from '$app/environment';
|
||||
import { writable, type Writable } from '@square/svelte-store';
|
||||
import { appWindow, type Theme } from '@tauri-apps/api/window';
|
||||
import type { SettingsStore } from './userSettings';
|
||||
@ -9,7 +8,6 @@ let systemTheme: string | null;
|
||||
let selectedTheme: string | undefined;
|
||||
|
||||
export function initTheme(userSettings: SettingsStore) {
|
||||
if (building) return;
|
||||
appWindow.theme().then((value: Theme | null) => {
|
||||
systemTheme = value;
|
||||
updateDom();
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { writable, type Loadable, Value } from 'svelte-loadable-store';
|
||||
import { writable, type Loadable, Loaded } from 'svelte-loadable-store';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { git } from '$lib/api/ipc';
|
||||
import { stores } from '$lib';
|
||||
@ -19,10 +19,11 @@ export class BranchStoresCache {
|
||||
if (cachedStore) {
|
||||
return cachedStore;
|
||||
}
|
||||
|
||||
const writableStore = writable(ipc.listVirtualBranches({ projectId }), (set) => {
|
||||
stores.sessions({ projectId }).subscribe((sessions) => {
|
||||
if (sessions.isLoading) return;
|
||||
if (Value.isError(sessions.value)) return;
|
||||
if (Loaded.isError(sessions)) return;
|
||||
const lastSession = sessions.value.at(-1);
|
||||
if (!lastSession) return;
|
||||
return stores.deltas({ projectId, sessionId: lastSession.id }).subscribe(() => {
|
||||
|
@ -63,7 +63,8 @@ export class BranchData {
|
||||
|
||||
export class Target {
|
||||
sha!: string;
|
||||
name!: string;
|
||||
remote!: string;
|
||||
branchName!: string;
|
||||
remoteName!: string;
|
||||
remoteUrl!: string;
|
||||
behind!: number;
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { log } from '$lib';
|
||||
|
||||
$: if ($page.error) {
|
||||
log.error($page.url, $page.error);
|
||||
console.error($page.url, $page.error);
|
||||
} else {
|
||||
log.error($page.url, $page.status);
|
||||
console.log($page.url, $page.status);
|
||||
}
|
||||
|
||||
$: message = $page.error
|
||||
|
@ -1,5 +1,5 @@
|
||||
import type { LayoutLoad } from './$types';
|
||||
import { api, log } from '$lib';
|
||||
import { api } from '$lib';
|
||||
import Posthog from '$lib/posthog';
|
||||
import Sentry from '$lib/sentry';
|
||||
import { BranchStoresCache } from '$lib/vbranches';
|
||||
@ -7,7 +7,7 @@ import { wrapLoadWithSentry } from '@sentry/sveltekit';
|
||||
import { loadUserSettings } from '$lib/userSettings';
|
||||
|
||||
export const ssr = false;
|
||||
export const prerender = true;
|
||||
export const prerender = false;
|
||||
export const csr = true;
|
||||
|
||||
import { dev } from '$app/environment';
|
||||
@ -17,7 +17,6 @@ import { dev } from '$app/environment';
|
||||
// I examined the call stack and found a section suggesting it might not happen in prod.
|
||||
// TODO(mattias): Investigate and decide what to do
|
||||
function loadFn({ fetch: realFetch }: { fetch: typeof fetch }) {
|
||||
log.setup();
|
||||
return {
|
||||
projects: api.projects.Projects(),
|
||||
cloud: api.CloudApi({ fetch: realFetch }),
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { format, startOfDay } from 'date-fns';
|
||||
import type { Delta } from '$lib/api';
|
||||
import { generateBuckets } from './histogram';
|
||||
import { derived, Value } from 'svelte-loadable-store';
|
||||
import { derived, Loaded } from 'svelte-loadable-store';
|
||||
import FileActivity from './FileActivity.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { Link } from '$lib/components';
|
||||
@ -44,7 +44,7 @@
|
||||
<h2 class="text-2xl font-bold text-zinc-400">Loading file changes...</h2>
|
||||
</div>
|
||||
</li>
|
||||
{:else if Value.isError($deltasByDate.value) || Value.isError($buckets.value)}
|
||||
{:else if Loaded.isError($deltasByDate) || Loaded.isError($buckets)}
|
||||
<li class="flex flex-1 space-y-4 rounded-lg border border-dashed border-zinc-400">
|
||||
<div class="flex flex-1 flex-col items-center justify-center gap-4">
|
||||
<IconSparkle class="h-16 w-16 text-zinc-400 " />
|
||||
|
@ -9,7 +9,7 @@
|
||||
import { error, success } from '$lib/toasts';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { Modal } from '$lib/components';
|
||||
import { log, hotkeys, stores } from '$lib';
|
||||
import { hotkeys, stores } from '$lib';
|
||||
import { IconChevronDown, IconChevronUp } from '$lib/icons';
|
||||
import { onMount } from 'svelte';
|
||||
import { unsubscribe } from '$lib/utils';
|
||||
@ -193,7 +193,7 @@
|
||||
await project.update({ api: { ...$project.api, sync: true } });
|
||||
}
|
||||
} catch (e) {
|
||||
log.error(`Failed to update project sync status: ${e}`);
|
||||
console.error(`Failed to update project sync status: ${e}`);
|
||||
error('Failed to update project sync status');
|
||||
}
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { page } from '$app/stores';
|
||||
import { stores, api } from '$lib';
|
||||
import { format } from 'date-fns';
|
||||
import { derived, Value } from 'svelte-loadable-store';
|
||||
import { derived, Loaded } from 'svelte-loadable-store';
|
||||
|
||||
const sessions = stores.sessions({ projectId: $page.params.projectId });
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
</script>
|
||||
|
||||
<div id="player-page" class="flex h-full w-full flex-col">
|
||||
{#if !$dates.isLoading && Value.isValue($dates.value)}
|
||||
{#if !$dates.isLoading && Loaded.isValue($dates)}
|
||||
{#if $dates.value.length === 0}
|
||||
<div class="text-center">
|
||||
<h2 class="text-2xl">I haven't seen any changes yet</h2>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { LayoutData } from './$types';
|
||||
import { page } from '$app/stores';
|
||||
import { derived, Value } from 'svelte-loadable-store';
|
||||
import { derived, Loaded } from 'svelte-loadable-store';
|
||||
import { format } from 'date-fns';
|
||||
import { onMount } from 'svelte';
|
||||
import { api, events, hotkeys, stores } from '$lib';
|
||||
@ -85,7 +85,7 @@
|
||||
<IconLoading class="mb-4 h-12 w-12 animate-spin ease-linear" />
|
||||
<h2 class="text-center text-2xl font-medium text-gray-500">Loading...</h2>
|
||||
</div>
|
||||
{:else if Value.isError($richSessions.value) || Value.isError($currentSession.value)}
|
||||
{:else if Loaded.isError($richSessions) || Loaded.isError($currentSession)}
|
||||
<div class="flex h-full flex-col items-center justify-center">
|
||||
<h2 class="text-center text-2xl font-medium text-gray-500">Error</h2>
|
||||
</div>
|
||||
@ -102,10 +102,10 @@
|
||||
<header class="flex items-center gap-3 bg-card-active px-3 py-2">
|
||||
{#if $currentSession.isLoading || $richSessions.isLoading}
|
||||
<span>Loading...</span>
|
||||
{:else if Loaded.isError($currentSession) || Loaded.isError($richSessions)}
|
||||
<span>Error</span>
|
||||
{:else if !$currentSession.value}
|
||||
<span>No session found</span>
|
||||
{:else if Value.isError($currentSession.value) || Value.isError($richSessions.value)}
|
||||
<span>Error</span>
|
||||
{:else}
|
||||
<SessionNavigations currentSession={$currentSession.value} sessions={$richSessions.value} />
|
||||
{/if}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { log, toasts, api } from '$lib';
|
||||
import { toasts, api } from '$lib';
|
||||
import { Button, Modal } from '$lib/components';
|
||||
import { IconBookmarkFilled } from '$lib/icons';
|
||||
|
||||
@ -47,7 +47,7 @@
|
||||
modal.close();
|
||||
})
|
||||
.catch((err) => {
|
||||
log.error(err);
|
||||
console.error(err);
|
||||
toasts.error('Failed to create bookmark');
|
||||
})
|
||||
.finally(() => (isCreating = false));
|
||||
|
@ -5,9 +5,9 @@
|
||||
import { derived } from '@square/svelte-store';
|
||||
import { stores } from '$lib';
|
||||
import { IconBookmarkFilled } from '$lib/icons';
|
||||
import { Value } from 'svelte-loadable-store';
|
||||
import { line } from '$lib/diff';
|
||||
import { Stats } from '$lib/components';
|
||||
import { Loaded } from 'svelte-loadable-store';
|
||||
|
||||
export let isCurrent: boolean;
|
||||
export let session: Session;
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||
$: bookmarks = derived(stores.bookmarks.list({ projectId: session.projectId }), (bookmarks) => {
|
||||
if (bookmarks.isLoading) return [];
|
||||
if (Value.isError(bookmarks.value)) return [];
|
||||
if (Loaded.isError(bookmarks)) return [];
|
||||
const timestamps = Object.values(deltas ?? {}).flatMap((deltas) =>
|
||||
deltas.map((d) => d.timestampMs)
|
||||
);
|
||||
|
@ -8,7 +8,7 @@
|
||||
import { unsubscribe } from '$lib/utils';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { onMount } from 'svelte';
|
||||
import { Value, type Loadable } from 'svelte-loadable-store';
|
||||
import { Loaded, type Loadable } from 'svelte-loadable-store';
|
||||
import { derived } from 'svelte-loadable-store';
|
||||
import { format } from 'date-fns';
|
||||
|
||||
@ -57,19 +57,11 @@
|
||||
onMount(() =>
|
||||
unsubscribe(
|
||||
hotkeys.on('Shift+ArrowRight', () => {
|
||||
if (
|
||||
!$nextSessionId.isLoading &&
|
||||
Value.isValue($nextSessionId.value) &&
|
||||
$nextSessionId.value
|
||||
)
|
||||
if (!$nextSessionId.isLoading && Loaded.isValue($nextSessionId) && $nextSessionId.value)
|
||||
goto(getSessionURI($nextSessionId.value));
|
||||
}),
|
||||
hotkeys.on('Shift+ArrowLeft', () => {
|
||||
if (
|
||||
!$prevSessionId.isLoading &&
|
||||
Value.isValue($prevSessionId.value) &&
|
||||
$prevSessionId.value
|
||||
)
|
||||
if (!$prevSessionId.isLoading && Loaded.isValue($prevSessionId) && $prevSessionId.value)
|
||||
goto(getSessionURI($prevSessionId.value));
|
||||
})
|
||||
)
|
||||
@ -83,7 +75,7 @@
|
||||
</span>
|
||||
|
||||
<div class="flex items-center gap-1">
|
||||
{#if !$prevSessionId.isLoading && !$nextSessionId.isLoading && Value.isValue($prevSessionId.value) && Value.isValue($nextSessionId.value)}
|
||||
{#if !$prevSessionId.isLoading && !$nextSessionId.isLoading && Loaded.isValue($prevSessionId) && Loaded.isValue($nextSessionId)}
|
||||
<a
|
||||
href={$prevSessionId.value && getSessionURI($prevSessionId.value)}
|
||||
class="rounded border border-zinc-500 bg-zinc-600 p-0.5"
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import type { Delta, Session } from '$lib/api';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { Value, type Loadable } from 'svelte-loadable-store';
|
||||
import { Loaded, type Loadable } from 'svelte-loadable-store';
|
||||
import { derived } from 'svelte-loadable-store';
|
||||
import SessionCard from './SessionCard.svelte';
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
...session,
|
||||
visible:
|
||||
!$visibleDeltas.isLoading &&
|
||||
!Value.isError($visibleDeltas.value) &&
|
||||
!Loaded.isError($visibleDeltas) &&
|
||||
Object.keys($visibleDeltas.value[i]).length > 0
|
||||
}));
|
||||
</script>
|
||||
@ -48,7 +48,7 @@
|
||||
>
|
||||
{#each visibleSessions as session, i}
|
||||
{@const isCurrent = session.id === currentSession?.id}
|
||||
{#if session.visible && !$visibleDeltas.isLoading && !Value.isError($visibleDeltas.value) && !$visibleFiles.isLoading && !Value.isError($visibleFiles.value)}
|
||||
{#if session.visible && !$visibleDeltas.isLoading && !Loaded.isError($visibleDeltas) && !$visibleFiles.isLoading && !Loaded.isError($visibleFiles)}
|
||||
<SessionCard
|
||||
{isCurrent}
|
||||
{session}
|
||||
|
@ -3,7 +3,7 @@
|
||||
import type { PageData } from './$types';
|
||||
import { page } from '$app/stores';
|
||||
import { get, writable } from '@square/svelte-store';
|
||||
import { derived, Value } from 'svelte-loadable-store';
|
||||
import { derived, Loaded } from 'svelte-loadable-store';
|
||||
import { format } from 'date-fns';
|
||||
import { stores } from '$lib';
|
||||
import Playback from './Playback.svelte';
|
||||
@ -55,7 +55,7 @@
|
||||
|
||||
richSessions?.subscribe((sessions) => {
|
||||
if (sessions.isLoading) return;
|
||||
if (Value.isError(sessions.value)) return;
|
||||
if (Loaded.isError(sessions)) return;
|
||||
if (sessions.value.length === 0) return;
|
||||
if (!sessions.value.some((s) => s.id === $currentSessionId)) {
|
||||
$currentSessionId = sessions.value[0].id;
|
||||
@ -74,7 +74,7 @@
|
||||
|
||||
$: {
|
||||
// this hook updates player value if current page url has changed
|
||||
if (!$richSessions.isLoading && Value.isValue($richSessions.value)) {
|
||||
if (!$richSessions.isLoading && Loaded.isValue($richSessions)) {
|
||||
const currentSessionIndex = $richSessions.value.findIndex(
|
||||
(s) => s.id === $page.params.sessionId
|
||||
);
|
||||
@ -83,7 +83,7 @@
|
||||
.filter((_, index) => index < currentSessionIndex)
|
||||
.reduce((acc, s) => {
|
||||
const deltas = get(s.deltas);
|
||||
if (!deltas.isLoading && Value.isValue(deltas.value)) {
|
||||
if (!deltas.isLoading && Loaded.isValue(deltas)) {
|
||||
return acc + deltas.value.length;
|
||||
} else {
|
||||
return acc;
|
||||
@ -100,7 +100,7 @@
|
||||
/>
|
||||
<h2 class="text-center text-2xl font-medium text-gray-500">Loading...</h2>
|
||||
</div>
|
||||
{:else if Value.isError($richSessions.value)}
|
||||
{:else if Loaded.isError($richSessions)}
|
||||
<div class="flex h-full flex-col items-center justify-center">
|
||||
<h2 class="text-center text-2xl font-medium text-gray-500">Something went wrong</h2>
|
||||
</div>
|
||||
|
@ -3,7 +3,7 @@
|
||||
import type { Frame } from './frame';
|
||||
import { DeltasViewer } from '$lib/components';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { Value, type Loadable } from 'svelte-loadable-store';
|
||||
import { Loaded, type Loadable } from 'svelte-loadable-store';
|
||||
|
||||
export let context: number;
|
||||
export let fullContext: boolean;
|
||||
@ -17,8 +17,8 @@
|
||||
if (
|
||||
!$deltas.isLoading &&
|
||||
!$files.isLoading &&
|
||||
Value.isValue($deltas.value) &&
|
||||
Value.isValue($files.value)
|
||||
Loaded.isValue($deltas) &&
|
||||
Loaded.isValue($files)
|
||||
) {
|
||||
let i = value;
|
||||
for (const j in $deltas.value) {
|
||||
|
@ -3,8 +3,8 @@
|
||||
import { collapse } from '$lib/paths';
|
||||
import { IconBookmark, IconBookmarkFilled } from '$lib/icons';
|
||||
import { format } from 'date-fns';
|
||||
import { Value } from 'svelte-loadable-store';
|
||||
import { page } from '$app/stores';
|
||||
import { Loaded } from 'svelte-loadable-store';
|
||||
|
||||
export let timestampMs: number;
|
||||
export let filename: string;
|
||||
@ -13,7 +13,7 @@
|
||||
|
||||
const toggleBookmark = () => {
|
||||
if ($bookmark.isLoading) return;
|
||||
if (Value.isError($bookmark.value)) return;
|
||||
if (Loaded.isError($bookmark)) return;
|
||||
api.bookmarks.upsert(
|
||||
!$bookmark.value
|
||||
? {
|
||||
@ -30,7 +30,7 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if !$bookmark.isLoading && !Value.isError($bookmark.value)}
|
||||
{#if !$bookmark.isLoading && !Loaded.isError($bookmark)}
|
||||
<div
|
||||
class="flex max-w-[357px] flex-col gap-2 rounded-[18px] py-2 px-4 shadow"
|
||||
style="border: 0.5px solid rgba(63, 63, 70, 0.5);
|
||||
|
@ -6,7 +6,7 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { hotkeys } from '$lib';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { type Loadable, derived, Value } from 'svelte-loadable-store';
|
||||
import { type Loadable, derived, Loaded } from 'svelte-loadable-store';
|
||||
|
||||
export let value: number;
|
||||
export let context: number;
|
||||
@ -39,7 +39,7 @@
|
||||
|
||||
const gotoNextDelta = () => {
|
||||
if ($maxDeltaIndex.isLoading) return;
|
||||
if (Value.isError($maxDeltaIndex.value)) return;
|
||||
if (Loaded.isError($maxDeltaIndex)) return;
|
||||
if (value < $maxDeltaIndex.value) {
|
||||
value += 1;
|
||||
} else {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Bookmark, Delta } from '$lib/api';
|
||||
import { derived, Value, type Loadable } from 'svelte-loadable-store';
|
||||
import { derived, Loaded, type Loadable } from 'svelte-loadable-store';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { ModuleChapters, ModuleMarkers, type Marker } from './slider';
|
||||
import { JSR, ModuleSlider } from 'mm-jsr';
|
||||
@ -89,7 +89,7 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
{#if !$totalDeltas.isLoading && Value.isValue($totalDeltas.value) && !$chapters.isLoading && Value.isValue($chapters.value) && !$markers.isLoading && Value.isValue($markers.value)}
|
||||
{#if !$totalDeltas.isLoading && Loaded.isValue($totalDeltas) && !$chapters.isLoading && Loaded.isValue($chapters) && !$markers.isLoading && Loaded.isValue($markers)}
|
||||
<div
|
||||
use:jsrSlider={{
|
||||
min: 0,
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { Button, Modal } from '$lib/components';
|
||||
import type { PageData } from './$types';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
import { log, toasts, api, stores, events } from '$lib';
|
||||
import { toasts, api, stores, events } from '$lib';
|
||||
import { goto } from '$app/navigation';
|
||||
import CloudForm from './CloudForm.svelte';
|
||||
import DetailsForm from './DetailsForm.svelte';
|
||||
@ -22,7 +22,7 @@
|
||||
.then(() => api.projects.del({ id: $project?.id }))
|
||||
.then(() => deleteConfirmationModal.close())
|
||||
.catch((e) => {
|
||||
log.error(e);
|
||||
console.error(e);
|
||||
toasts.error('Failed to delete project');
|
||||
})
|
||||
.then(() => goto('/'))
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { stores, log, toasts } from '$lib';
|
||||
import { stores, toasts } from '$lib';
|
||||
import { CloudApi, type Project } from '$lib/api';
|
||||
import { Login, Checkbox } from '$lib/components';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
@ -37,7 +37,7 @@
|
||||
}));
|
||||
dispatch('updated', { ...project, api: { ...cloudProject, sync } });
|
||||
} catch (error) {
|
||||
log.error(`Failed to update project sync status: ${error}`);
|
||||
console.error(`Failed to update project sync status: ${error}`);
|
||||
toasts.error('Failed to update project sync status');
|
||||
}
|
||||
};
|
||||
|
@ -5,7 +5,6 @@ import { WebglAddon } from 'xterm-addon-webgl';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { Unicode11Addon } from 'xterm-addon-unicode11';
|
||||
import WebSocket, { type Message } from 'tauri-plugin-websocket-api';
|
||||
import { log } from '$lib';
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
const isWebgl2Supported = (() => {
|
||||
@ -48,7 +47,7 @@ const newSession = async (params: { project: Project }) => {
|
||||
return WebSocket.connect(`ws://localhost:${port}/${project.id}`).then((conn) => {
|
||||
const sendMessage = (message: Message) => {
|
||||
conn.send(message).catch((e: any) => {
|
||||
log.error(`failed to send message to terminal: ${e}`);
|
||||
console.error(`failed to send message to terminal: ${e}`);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -2,9 +2,9 @@
|
||||
import Board from './Board.svelte';
|
||||
import Tray from './Tray.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { Value } from 'svelte-loadable-store';
|
||||
import { Button } from '$lib/components';
|
||||
import { BranchController } from '$lib/vbranches';
|
||||
import { Loaded } from 'svelte-loadable-store';
|
||||
|
||||
export let data: PageData;
|
||||
let {
|
||||
@ -25,15 +25,15 @@
|
||||
);
|
||||
|
||||
$: remoteBranches =
|
||||
!$remoteBranchStore.isLoading && !Value.isError($remoteBranchStore.value)
|
||||
!$remoteBranchStore.isLoading && !Loaded.isError($remoteBranchStore)
|
||||
? $remoteBranchStore.value
|
||||
: [];
|
||||
$: target =
|
||||
!$targetBranchStore.isLoading && !Value.isError($targetBranchStore.value)
|
||||
!$targetBranchStore.isLoading && !Loaded.isError($targetBranchStore)
|
||||
? $targetBranchStore.value
|
||||
: undefined;
|
||||
$: branches =
|
||||
!$vbranchStore.isLoading && !Value.isError($vbranchStore.value) ? $vbranchStore.value : [];
|
||||
!$vbranchStore.isLoading && !Loaded.isError($vbranchStore) ? $vbranchStore.value : [];
|
||||
let targetChoice: string | undefined;
|
||||
|
||||
function onSetTargetClick() {
|
||||
|
@ -69,7 +69,7 @@
|
||||
<div
|
||||
class="flex w-full flex-row items-center justify-between border-b border-light-400 pb-1 pl-2 pr-1 text-light-900 dark:border-dark-500 dark:bg-dark-700 dark:text-dark-100"
|
||||
>
|
||||
<div class="flex-grow pb-1 font-bold" title={behindMessage}>{target.name}</div>
|
||||
<div class="flex-grow pb-1 font-bold" title={behindMessage}>{target.branchName}</div>
|
||||
<div class="flex items-center gap-1">
|
||||
<div class="pb-1">{target.behind > 0 ? `behind ${target.behind}` : 'up-to-date'}</div>
|
||||
<div class="flex-shrink-0 text-light-700 dark:text-dark-100" title={behindMessage}>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Button, Modal, Login } from '$lib/components';
|
||||
import type { PageData } from './$types';
|
||||
import { log, stores, toasts } from '$lib';
|
||||
import { stores, toasts } from '$lib';
|
||||
import { deleteAllData } from '$lib/api';
|
||||
import { goto } from '$app/navigation';
|
||||
import Logo from '$lib/assets/logo-310x310.png';
|
||||
@ -59,7 +59,7 @@
|
||||
});
|
||||
toasts.success('Profile updated');
|
||||
} catch (e) {
|
||||
log.error(e);
|
||||
console.error(e);
|
||||
toasts.error('Failed to update user');
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@
|
||||
.then(() => user.set(null))
|
||||
.then(() => toasts.success('All data deleted'))
|
||||
.catch((e) => {
|
||||
log.error(e);
|
||||
console.error(e);
|
||||
toasts.error('Failed to delete project');
|
||||
})
|
||||
.then(() => deleteConfirmationModal.close())
|
||||
|
Loading…
Reference in New Issue
Block a user