diff --git a/app/src/lib/branch/BranchIcon.svelte b/app/src/lib/branch/BranchIcon.svelte
index fbc1ffd07..1681de135 100644
--- a/app/src/lib/branch/BranchIcon.svelte
+++ b/app/src/lib/branch/BranchIcon.svelte
@@ -1,12 +1,19 @@
+
+{#if remoteBranch || localBranch}
+
+
+
+
+
+ {#if pr}
+
+
{pr.title}
+ {#if pr.body}
+
+ {@html marked.parse(pr.body, { renderer })}
+
+ {/if}
+
+ {/if}
+
+ {#if remoteCommits}
+ {#each remoteCommits as commit, index (commit.id)}
+
+ {#snippet lines(topHeightPx)}
+
+ {/snippet}
+
+ {/each}
+ {/if}
+ {#if localCommits}
+ {#each localCommits as commit, index (commit.id)}
+
+ {#snippet lines(topHeightPx)}
+
+ {/snippet}
+
+ {/each}
+ {/if}
+ {#if localAndRemoteCommits}
+ {#each localAndRemoteCommits as commit, index (commit.id)}
+
+ {#snippet lines(topHeightPx)}
+
+ {/snippet}
+
+ {/each}
+ {/if}
+
+
+
+
{
+ laneWidth = e.detail / (16 * $userSettings.zoom);
+ lscache.set(laneWidthKey, laneWidth, 7 * 1440); // 7 day ttl
+ }}
+ />
+
+
+ {#await $selectedFile then selected}
+ {#if selected}
+ {
+ fileIdSelection.clear();
+ }}
+ />
+ {/if}
+ {/await}
+
+
+{:else}
+ No local or remote branch found
+{/if}
+
+
diff --git a/app/src/lib/components/RemoteBranchPreview.svelte b/app/src/lib/components/RemoteBranchPreview.svelte
deleted file mode 100644
index 6e0a6f04b..000000000
--- a/app/src/lib/components/RemoteBranchPreview.svelte
+++ /dev/null
@@ -1,141 +0,0 @@
-
-
-
-
-
-
-
- {#if pr}
-
-
{pr.title}
- {#if pr.body}
-
- {@html marked.parse(pr.body, { renderer })}
-
- {/if}
-
- {/if}
- {#await remoteBranchService.getRemoteBranchData(branch.name) then branchData}
- {#if branchData.commits && branchData.commits.length > 0}
-
- {#each branchData.commits as commit, index (commit.id)}
-
- {/each}
-
- {/if}
- {/await}
-
-
-
{
- laneWidth = e.detail / (16 * $userSettings.zoom);
- lscache.set(laneWidthKey, laneWidth, 7 * 1440); // 7 day ttl
- }}
- />
-
-
- {#await $selectedFile then selected}
- {#if selected}
- {
- fileIdSelection.clear();
- }}
- />
- {/if}
- {/await}
-
-
-
-
diff --git a/app/src/lib/navigation/BranchItem.svelte b/app/src/lib/navigation/BranchItem.svelte
index ed2925bf9..ca75eb113 100644
--- a/app/src/lib/navigation/BranchItem.svelte
+++ b/app/src/lib/navigation/BranchItem.svelte
@@ -10,7 +10,10 @@
function getBranchLink(b: CombinedBranch): string | undefined {
if (b.vbranch) return `/${projectId}/board/`;
- if (b.remoteBranch) return `/${projectId}/remote/${branch?.remoteBranch?.displayName}`;
+ // Here we specifically want to prefer looking at the remote branch as
+ // the there may be multiple remotes that share the same local branch.
+ if (b.branch)
+ return `/${projectId}/branch/${branch?.remoteBranch?.name || branch?.localBranch?.name}`;
if (b.pr) return `/${projectId}/pull/${b.pr.number}`;
}
diff --git a/app/src/lib/navigation/Branches.svelte b/app/src/lib/navigation/Branches.svelte
index 450a21559..4156ad203 100644
--- a/app/src/lib/navigation/Branches.svelte
+++ b/app/src/lib/navigation/Branches.svelte
@@ -67,7 +67,7 @@
if (b.pr) return false;
}
- if (params.includeRemote && b.remoteBranch) return true;
+ if (params.includeRemote && b.branch) return true;
return false;
});
}
diff --git a/app/src/lib/vbranches/branchController.ts b/app/src/lib/vbranches/branchController.ts
index 3a6c65492..118d15873 100644
--- a/app/src/lib/vbranches/branchController.ts
+++ b/app/src/lib/vbranches/branchController.ts
@@ -276,11 +276,18 @@ You can find them in the 'Branches' sidebar in order to resolve conflicts.`;
}
}
- async createvBranchFromBranch(branch: string) {
+ /**
+ *
+ * @param branch The branch you want to create a virtual branch for. If you
+ * have a local branch, this should be the branch.
+ * @param remote Optionally sets another branch as the upstream.
+ */
+ async createvBranchFromBranch(branch: string, remote: string | undefined = undefined) {
try {
await invoke('create_virtual_branch_from_branch', {
projectId: this.projectId,
- branch
+ branch,
+ remote
});
} catch (err) {
showError('Failed to create virtual branch', err);
diff --git a/app/src/lib/vbranches/types.ts b/app/src/lib/vbranches/types.ts
index f3ecfa69f..cf39f0a5a 100644
--- a/app/src/lib/vbranches/types.ts
+++ b/app/src/lib/vbranches/types.ts
@@ -315,14 +315,11 @@ export class Branch {
lastCommitTimestampMs?: number | undefined;
lastCommitAuthor?: string | undefined;
givenName!: string;
+ isRemote!: boolean;
get displayName(): string {
return this.name.replace('refs/remotes/', '').replace('refs/heads/', '');
}
-
- get isRemote() {
- return !!this.upstream;
- }
}
export class BranchData {
diff --git a/app/src/routes/[projectId]/+layout.svelte b/app/src/routes/[projectId]/+layout.svelte
index 6c3eba5ad..7946a3ecb 100644
--- a/app/src/routes/[projectId]/+layout.svelte
+++ b/app/src/routes/[projectId]/+layout.svelte
@@ -4,6 +4,7 @@
import { BaseBranch, NoDefaultTarget } from '$lib/baseBranch/baseBranch';
import { BaseBranchService } from '$lib/baseBranch/baseBranchService';
import { BranchDragActionsFactory } from '$lib/branches/dragActions';
+ import { getNameNormalizationServiceContext } from '$lib/branches/nameNormalizationService';
import { BranchService, createBranchServiceStore } from '$lib/branches/service';
import { CommitDragActionsFactory } from '$lib/commits/dragActions';
import NoBaseBranch from '$lib/components/NoBaseBranch.svelte';
@@ -33,6 +34,8 @@
const { data, children }: { data: LayoutData; children: Snippet } = $props();
+ const nameNormalizationService = getNameNormalizationServiceContext();
+
const {
vbranchService,
project,
@@ -104,7 +107,14 @@
listServiceStore.set(ghListService);
githubRepoServiceStore.set(gitHost);
- branchServiceStore.set(new BranchService(vbranchService, remoteBranchService, ghListService));
+ branchServiceStore.set(
+ new BranchService(
+ vbranchService,
+ remoteBranchService,
+ ghListService,
+ nameNormalizationService
+ )
+ );
});
// Once on load and every time the project id changes
diff --git a/app/src/routes/[projectId]/remote/[...name]/+page.svelte b/app/src/routes/[projectId]/branch/[...name]/+page.svelte
similarity index 60%
rename from app/src/routes/[projectId]/remote/[...name]/+page.svelte
rename to app/src/routes/[projectId]/branch/[...name]/+page.svelte
index c3d113baf..71db1a810 100644
--- a/app/src/routes/[projectId]/remote/[...name]/+page.svelte
+++ b/app/src/routes/[projectId]/branch/[...name]/+page.svelte
@@ -4,15 +4,18 @@
// - And it does NOT have a cooresponding vbranch
// It may also display details about a cooresponding pr if they exist
import { getBranchServiceStore } from '$lib/branches/service';
+ import RemoteBranchPreview from '$lib/components/BranchPreview.svelte';
import FullviewLoading from '$lib/components/FullviewLoading.svelte';
- import RemoteBranchPreview from '$lib/components/RemoteBranchPreview.svelte';
import { page } from '$app/stores';
const branchService = getBranchServiceStore();
const branches = $derived($branchService?.branches);
const error = $derived($branchService?.error);
+ // Search for remote branch first as there may be multiple combined branches
+ // which have the same local branch
const branch = $derived(
- $branches?.find((cb) => cb.remoteBranch?.displayName === $page.params.name)
+ $branches?.find((cb) => cb.remoteBranch?.name === $page.params.name) ||
+ $branches?.find((cb) => cb.localBranch?.name === $page.params.name)
);
// $: branch = $branches?.find((b) => b.displayName === $page.params.name);
@@ -21,8 +24,12 @@
Error...
{:else if !$branches}
-{:else if branch?.remoteBranch}
-
+{:else if branch?.remoteBranch || branch?.localBranch}
+
{:else}
Branch doesn't seem to exist
{/if}
diff --git a/crates/gitbutler-branch-actions/src/actions.rs b/crates/gitbutler-branch-actions/src/actions.rs
index ff1e0bc25..9669e7954 100644
--- a/crates/gitbutler-branch-actions/src/actions.rs
+++ b/crates/gitbutler-branch-actions/src/actions.rs
@@ -470,12 +470,13 @@ impl VirtualBranchActions {
&self,
project: &Project,
branch: &Refname,
+ remote: Option,
) -> Result {
let project_repository = open_with_verify(project)?;
let branch_manager = project_repository.branch_manager();
let mut guard = project.exclusive_worktree_access();
branch_manager
- .create_virtual_branch_from_branch(branch, guard.write_permission())
+ .create_virtual_branch_from_branch(branch, remote, guard.write_permission())
.map_err(Into::into)
}
}
diff --git a/crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs b/crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs
index e8e27495e..7e68cd82d 100644
--- a/crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs
+++ b/crates/gitbutler-branch-actions/src/branch_manager/branch_creation.rs
@@ -14,7 +14,7 @@ use gitbutler_commit::commit_headers::HasCommitHeaders;
use gitbutler_error::error::Marker;
use gitbutler_oplog::SnapshotExt;
use gitbutler_project::access::WorktreeWritePermission;
-use gitbutler_reference::Refname;
+use gitbutler_reference::{Refname, RemoteRefname};
use gitbutler_repo::{rebase::cherry_rebase, RepoActionsExt, RepositoryExt};
use gitbutler_time::time::now_since_unix_epoch_ms;
use std::borrow::Cow;
@@ -36,7 +36,7 @@ impl BranchManager<'_> {
let tree = commit
.tree()
- .context("failed to find defaut target commit tree")?;
+ .context("failed to find default target commit tree")?;
let mut all_virtual_branches = vb_state
.list_branches_in_workspace()
@@ -126,20 +126,26 @@ impl BranchManager<'_> {
pub fn create_virtual_branch_from_branch(
&self,
- upstream: &Refname,
+ target: &Refname,
+ upstream_branch: Option,
perm: &mut WorktreeWritePermission,
) -> Result {
// only set upstream if it's not the default target
- let upstream_branch = match upstream {
- Refname::Other(_) | Refname::Virtual(_) => {
- // we only support local or remote branches
- bail!("branch {upstream} must be a local or remote branch");
+ let upstream_branch = match upstream_branch {
+ Some(upstream_branch) => Some(upstream_branch),
+ None => {
+ match target {
+ Refname::Other(_) | Refname::Virtual(_) => {
+ // we only support local or remote branches
+ bail!("branch {target} must be a local or remote branch");
+ }
+ Refname::Remote(remote) => Some(remote.clone()),
+ Refname::Local(local) => local.remote().cloned(),
+ }
}
- Refname::Remote(remote) => Some(remote.clone()),
- Refname::Local(local) => local.remote().cloned(),
};
- let branch_name = upstream
+ let branch_name = target
.branch()
.expect("always a branch reference")
.to_string();
@@ -153,21 +159,21 @@ impl BranchManager<'_> {
let default_target = vb_state.get_default_target()?;
- if let Refname::Remote(remote_upstream) = upstream {
+ if let Refname::Remote(remote_upstream) = target {
if default_target.branch == *remote_upstream {
bail!("cannot create a branch from default target")
}
}
let repo = self.project_repository.repo();
- let head_reference =
- repo.find_reference(&upstream.to_string())
- .map_err(|err| match err {
- err if err.code() == git2::ErrorCode::NotFound => {
- anyhow!("branch {upstream} was not found")
- }
- err => err.into(),
- })?;
+ let head_reference = repo
+ .find_reference(&target.to_string())
+ .map_err(|err| match err {
+ err if err.code() == git2::ErrorCode::NotFound => {
+ anyhow!("branch {target} was not found")
+ }
+ err => err.into(),
+ })?;
let head_commit = head_reference
.peel_to_commit()
.context("failed to peel to commit")?;
@@ -220,7 +226,7 @@ impl BranchManager<'_> {
);
let branch = if let Ok(Some(mut branch)) =
- vb_state.find_by_source_refname_where_not_in_workspace(upstream)
+ vb_state.find_by_source_refname_where_not_in_workspace(target)
{
branch.upstream_head = upstream_branch.is_some().then_some(head_commit.id());
branch.upstream = upstream_branch;
@@ -239,7 +245,7 @@ impl BranchManager<'_> {
id: BranchId::generate(),
name: branch_name.clone(),
notes: String::new(),
- source_refname: Some(upstream.clone()),
+ source_refname: Some(target.clone()),
upstream_head: upstream_branch.is_some().then_some(head_commit.id()),
upstream: upstream_branch,
tree: head_commit_tree.id(),
diff --git a/crates/gitbutler-branch-actions/src/remote.rs b/crates/gitbutler-branch-actions/src/remote.rs
index 23ab226a1..924a10c3d 100644
--- a/crates/gitbutler-branch-actions/src/remote.rs
+++ b/crates/gitbutler-branch-actions/src/remote.rs
@@ -30,6 +30,7 @@ pub struct RemoteBranch {
pub given_name: String,
pub last_commit_timestamp_ms: Option,
pub last_commit_author: Option,
+ pub is_remote: bool,
}
#[derive(Debug, Clone, Serialize, PartialEq)]
@@ -139,6 +140,7 @@ pub(crate) fn branch_to_remote_branch(
.map(|t: u128| t * 1000)
.ok(),
last_commit_author: commit.author().name().map(std::string::ToString::to_string),
+ is_remote: branch.get().is_remote(),
})
}
diff --git a/crates/gitbutler-branch-actions/tests/extra/mod.rs b/crates/gitbutler-branch-actions/tests/extra/mod.rs
index cc4d80515..5e9ac6a8c 100644
--- a/crates/gitbutler-branch-actions/tests/extra/mod.rs
+++ b/crates/gitbutler-branch-actions/tests/extra/mod.rs
@@ -1177,6 +1177,7 @@ fn unapply_branch() -> Result<()> {
let branch_manager = project_repository.branch_manager();
let branch1_id = branch_manager.create_virtual_branch_from_branch(
&Refname::from_str(&real_branch)?,
+ None,
guard.write_permission(),
)?;
let contents = std::fs::read(Path::new(&project.path).join(file_path))?;
@@ -1271,6 +1272,7 @@ fn apply_unapply_added_deleted_files() -> Result<()> {
branch_manager
.create_virtual_branch_from_branch(
&Refname::from_str(&real_branch_2).unwrap(),
+ None,
guard.write_permission(),
)
.unwrap();
@@ -1281,6 +1283,7 @@ fn apply_unapply_added_deleted_files() -> Result<()> {
branch_manager
.create_virtual_branch_from_branch(
&Refname::from_str(&real_branch_3).unwrap(),
+ None,
guard.write_permission(),
)
.unwrap();
diff --git a/crates/gitbutler-branch-actions/tests/virtual_branches/apply_virtual_branch.rs b/crates/gitbutler-branch-actions/tests/virtual_branches/apply_virtual_branch.rs
index 50dff5c3d..2c2dec127 100644
--- a/crates/gitbutler-branch-actions/tests/virtual_branches/apply_virtual_branch.rs
+++ b/crates/gitbutler-branch-actions/tests/virtual_branches/apply_virtual_branch.rs
@@ -94,7 +94,7 @@ async fn rebase_commit() {
{
// apply first vbranch again
branch1_id = controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
@@ -192,7 +192,7 @@ async fn rebase_work() {
{
// apply first vbranch again
branch1_id = controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
diff --git a/crates/gitbutler-branch-actions/tests/virtual_branches/convert_to_real_branch.rs b/crates/gitbutler-branch-actions/tests/virtual_branches/convert_to_real_branch.rs
index 1b7988a92..fcc8f596c 100644
--- a/crates/gitbutler-branch-actions/tests/virtual_branches/convert_to_real_branch.rs
+++ b/crates/gitbutler-branch-actions/tests/virtual_branches/convert_to_real_branch.rs
@@ -92,7 +92,7 @@ async fn conflicting() {
let branch_id = {
// apply branch, it should conflict
let branch_id = controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
diff --git a/crates/gitbutler-branch-actions/tests/virtual_branches/create_virtual_branch_from_branch.rs b/crates/gitbutler-branch-actions/tests/virtual_branches/create_virtual_branch_from_branch.rs
index ac2fb9f4c..ea9039e1e 100644
--- a/crates/gitbutler-branch-actions/tests/virtual_branches/create_virtual_branch_from_branch.rs
+++ b/crates/gitbutler-branch-actions/tests/virtual_branches/create_virtual_branch_from_branch.rs
@@ -56,7 +56,7 @@ async fn integration() {
// checkout a existing remote branch
let branch_id = controller
- .create_virtual_branch_from_branch(project, &branch_name)
+ .create_virtual_branch_from_branch(project, &branch_name, None)
.await
.unwrap();
@@ -151,7 +151,11 @@ async fn no_conflicts() {
assert!(branches.is_empty());
let branch_id = controller
- .create_virtual_branch_from_branch(project, &"refs/remotes/origin/branch".parse().unwrap())
+ .create_virtual_branch_from_branch(
+ project,
+ &"refs/remotes/origin/branch".parse().unwrap(),
+ None,
+ )
.await
.unwrap();
@@ -197,7 +201,11 @@ async fn conflicts_with_uncommited() {
// branch should be created unapplied, because of the conflict
let new_branch_id = controller
- .create_virtual_branch_from_branch(project, &"refs/remotes/origin/branch".parse().unwrap())
+ .create_virtual_branch_from_branch(
+ project,
+ &"refs/remotes/origin/branch".parse().unwrap(),
+ None,
+ )
.await
.unwrap();
let new_branch = controller
@@ -253,7 +261,11 @@ async fn conflicts_with_commited() {
// branch should be created unapplied, because of the conflict
let new_branch_id = controller
- .create_virtual_branch_from_branch(project, &"refs/remotes/origin/branch".parse().unwrap())
+ .create_virtual_branch_from_branch(
+ project,
+ &"refs/remotes/origin/branch".parse().unwrap(),
+ None,
+ )
.await
.unwrap();
let new_branch = controller
@@ -289,6 +301,7 @@ async fn from_default_target() {
.create_virtual_branch_from_branch(
project,
&"refs/remotes/origin/master".parse().unwrap(),
+ None
)
.await
.unwrap_err()
@@ -317,6 +330,7 @@ async fn from_non_existent_branch() {
.create_virtual_branch_from_branch(
project,
&"refs/remotes/origin/branch".parse().unwrap(),
+ None
)
.await
.unwrap_err()
@@ -355,7 +369,11 @@ async fn from_state_remote_branch() {
.unwrap();
let branch_id = controller
- .create_virtual_branch_from_branch(project, &"refs/remotes/origin/branch".parse().unwrap())
+ .create_virtual_branch_from_branch(
+ project,
+ &"refs/remotes/origin/branch".parse().unwrap(),
+ None,
+ )
.await
.unwrap();
diff --git a/crates/gitbutler-branch-actions/tests/virtual_branches/mod.rs b/crates/gitbutler-branch-actions/tests/virtual_branches/mod.rs
index e624f2886..cc98f1157 100644
--- a/crates/gitbutler-branch-actions/tests/virtual_branches/mod.rs
+++ b/crates/gitbutler-branch-actions/tests/virtual_branches/mod.rs
@@ -136,7 +136,7 @@ async fn resolve_conflict_flow() {
let branch1_id = {
// when we apply conflicted branch, it has conflict
let branch1_id = controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
diff --git a/crates/gitbutler-branch-actions/tests/virtual_branches/selected_for_changes.rs b/crates/gitbutler-branch-actions/tests/virtual_branches/selected_for_changes.rs
index 15e7d9391..7f0db5f03 100644
--- a/crates/gitbutler-branch-actions/tests/virtual_branches/selected_for_changes.rs
+++ b/crates/gitbutler-branch-actions/tests/virtual_branches/selected_for_changes.rs
@@ -376,7 +376,7 @@ async fn applying_first_branch() {
.unwrap();
let unapplied_branch = Refname::from_str(&unapplied_branch).unwrap();
controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
diff --git a/crates/gitbutler-branch-actions/tests/virtual_branches/update_base_branch.rs b/crates/gitbutler-branch-actions/tests/virtual_branches/update_base_branch.rs
index 3e77620e2..0c958fb39 100644
--- a/crates/gitbutler-branch-actions/tests/virtual_branches/update_base_branch.rs
+++ b/crates/gitbutler-branch-actions/tests/virtual_branches/update_base_branch.rs
@@ -54,7 +54,7 @@ mod applied_branch {
{
// applying the branch should produce conflict markers
controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).await.unwrap();
@@ -124,7 +124,7 @@ mod applied_branch {
{
// applying the branch should produce conflict markers
controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).await.unwrap();
@@ -200,7 +200,7 @@ mod applied_branch {
{
// applying the branch should produce conflict markers
controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).await.unwrap();
@@ -273,7 +273,7 @@ mod applied_branch {
{
// applying the branch should produce conflict markers
controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).await.unwrap();
@@ -346,7 +346,7 @@ mod applied_branch {
{
// applying the branch should produce conflict markers
controller
- .create_virtual_branch_from_branch(project, &unapplied_branch)
+ .create_virtual_branch_from_branch(project, &unapplied_branch, None)
.await
.unwrap();
let (branches, _) = controller.list_virtual_branches(project).await.unwrap();
@@ -767,6 +767,7 @@ mod applied_branch {
.create_virtual_branch_from_branch(
project,
&Refname::from_str(unapplied_refname.as_str()).unwrap(),
+ None,
)
.await
.unwrap();
diff --git a/crates/gitbutler-tauri/src/virtual_branches.rs b/crates/gitbutler-tauri/src/virtual_branches.rs
index 60009bb0c..9ff49a462 100644
--- a/crates/gitbutler-tauri/src/virtual_branches.rs
+++ b/crates/gitbutler-tauri/src/virtual_branches.rs
@@ -83,10 +83,11 @@ pub mod commands {
projects: State<'_, projects::Controller>,
project_id: ProjectId,
branch: Refname,
+ remote: Option,
) -> Result {
let project = projects.get(project_id)?;
let branch_id = VirtualBranchActions
- .create_virtual_branch_from_branch(&project, &branch)
+ .create_virtual_branch_from_branch(&project, &branch, remote)
.await?;
emit_vbranches(&windows, project_id).await;
Ok(branch_id)