Skip to content

Commit ae737b6

Browse files
committed
enhance: better indication and context-commands for worktree-linked branch (#1761)
- For worktree-linked branch, `Checkout xyz` will be replaced with `Switch to xyz (worktree)` - Show worktree path in tooltip of worktree-linked branch - Add context menu entry `Open` for selected worktree Signed-off-by: leo <[email protected]>
1 parent db9b13c commit ae737b6

File tree

8 files changed

+46
-18
lines changed

8 files changed

+46
-18
lines changed

src/Commands/QueryBranches.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public QueryBranches(string repo)
1515
{
1616
WorkingDirectory = repo;
1717
Context = repo;
18-
Args = "branch -l --all -v --format=\"%(refname)%00%(committerdate:unix)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)\"";
18+
Args = "branch -l --all -v --format=\"%(refname)%00%(committerdate:unix)%00%(objectname)%00%(HEAD)%00%(upstream)%00%(upstream:trackshort)%00%(worktreepath)\"";
1919
}
2020

2121
public async Task<List<Models.Branch>> GetResultAsync()
@@ -61,7 +61,7 @@ public QueryBranches(string repo)
6161
private Models.Branch ParseLine(string line)
6262
{
6363
var parts = line.Split('\0');
64-
if (parts.Length != 6)
64+
if (parts.Length != 7)
6565
return null;
6666

6767
var branch = new Models.Branch();
@@ -109,6 +109,7 @@ private Models.Branch ParseLine(string line)
109109
parts[5].Equals("=", StringComparison.Ordinal))
110110
branch.TrackStatus = new Models.BranchTrackStatus();
111111

112+
branch.WorktreePath = parts[6];
112113
return branch;
113114
}
114115
}

src/Models/Branch.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public class Branch
4242
public BranchTrackStatus TrackStatus { get; set; }
4343
public string Remote { get; set; }
4444
public bool IsUpstreamGone { get; set; }
45+
public string WorktreePath { get; set; }
4546

4647
public string FriendlyName => IsLocal ? Name : $"{Remote}/{Name}";
4748
}

src/Resources/Locales/en_US.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">Rebase ${0}$ on ${1}$...</x:String>
7171
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rename ${0}$...</x:String>
7272
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">Reset ${0}$ to ${1}$...</x:String>
73+
<x:String x:Key="Text.BranchCM.SwitchToWorktree" xml:space="preserve">Switch to ${0}$ (worktree)</x:String>
7374
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Set Tracking Branch...</x:String>
7475
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Compare</x:String>
7576
<x:String x:Key="Text.BranchTree.InvalidUpstream" xml:space="preserve">Invalid</x:String>
@@ -874,6 +875,7 @@
874875
<x:String x:Key="Text.Worktree" xml:space="preserve">WORKTREE</x:String>
875876
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">Copy Path</x:String>
876877
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">Lock</x:String>
878+
<x:String x:Key="Text.Worktree.Open" xml:space="preserve">Open</x:String>
877879
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">Remove</x:String>
878880
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">Unlock</x:String>
879881
</ResourceDictionary>

src/Resources/Locales/zh_CN.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">变基(rebase) ${0}$ 至 ${1}$...</x:String>
7575
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重命名 ${0}$...</x:String>
7676
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">重置 ${0}$ 到 ${1}$...</x:String>
77+
<x:String x:Key="Text.BranchCM.SwitchToWorktree" xml:space="preserve">切换到 ${0}$ (工作树)</x:String>
7778
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切换上游分支 ...</x:String>
7879
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比较</x:String>
7980
<x:String x:Key="Text.BranchTree.InvalidUpstream" xml:space="preserve">不存在</x:String>
@@ -878,6 +879,7 @@
878879
<x:String x:Key="Text.Worktree" xml:space="preserve">本地工作树</x:String>
879880
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">复制工作树路径</x:String>
880881
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">锁定工作树</x:String>
882+
<x:String x:Key="Text.Worktree.Open" xml:space="preserve">打开工作树</x:String>
881883
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">移除工作树</x:String>
882884
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">解除工作树锁定</x:String>
883885
</ResourceDictionary>

src/Resources/Locales/zh_TW.axaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
<x:String x:Key="Text.BranchCM.Rebase" xml:space="preserve">重定基底 (rebase) ${0}$ 分支至 ${1}$...</x:String>
7575
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重新命名 ${0}$...</x:String>
7676
<x:String x:Key="Text.BranchCM.ResetToSelectedCommit" xml:space="preserve">重設 ${0}$ 至 ${1}$...</x:String>
77+
<x:String x:Key="Text.BranchCM.SwitchToWorktree" xml:space="preserve">切換到 ${0}$ (工作區)</x:String>
7778
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切換上游分支...</x:String>
7879
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比較</x:String>
7980
<x:String x:Key="Text.BranchTree.InvalidUpstream" xml:space="preserve">無效</x:String>
@@ -878,6 +879,7 @@
878879
<x:String x:Key="Text.Worktree" xml:space="preserve">本機工作區</x:String>
879880
<x:String x:Key="Text.Worktree.CopyPath" xml:space="preserve">複製工作區路徑</x:String>
880881
<x:String x:Key="Text.Worktree.Lock" xml:space="preserve">鎖定工作區</x:String>
882+
<x:String x:Key="Text.Worktree.Open" xml:space="preserve">開啟工作區</x:String>
881883
<x:String x:Key="Text.Worktree.Remove" xml:space="preserve">移除工作區</x:String>
882884
<x:String x:Key="Text.Worktree.Unlock" xml:space="preserve">解除鎖定工作區</x:String>
883885
</ResourceDictionary>

src/Views/BranchTree.axaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,17 @@
4545
<Path Width="12" Height="12" Data="{StaticResource Icons.Branch}"/>
4646
<TextBlock FontWeight="Bold" VerticalAlignment="Center" Margin="8,0,0,0" Text="{Binding FriendlyName}"/>
4747
<Border Background="Green" Margin="4,0,0,0" CornerRadius="4" VerticalAlignment="Center" IsVisible="{Binding !IsLocal}">
48-
<TextBlock Text="{DynamicResource Text.BranchTree.Remote}" FontSize="12" Classes="primary" Margin="4,1" Foreground="White" VerticalAlignment="Center"/>
48+
<TextBlock Text="{DynamicResource Text.BranchTree.Remote}" FontSize="12" Classes="primary" Margin="4,0" Foreground="White" VerticalAlignment="Center"/>
49+
</Border>
50+
<Border Background="Gray" Margin="4,0,0,0" CornerRadius="4" VerticalAlignment="Center">
51+
<Border.IsVisible>
52+
<MultiBinding Converter="{x:Static BoolConverters.And}">
53+
<Binding Path="IsCurrent" Converter="{x:Static BoolConverters.Not}"/>
54+
<Binding Path="WorktreePath" Converter="{x:Static StringConverters.IsNotNullOrEmpty}"/>
55+
</MultiBinding>
56+
</Border.IsVisible>
57+
58+
<TextBlock Text="{Binding WorktreePath, Mode=OneWay}" FontSize="12" Classes="primary" Margin="4,0" Foreground="White" VerticalAlignment="Center"/>
4959
</Border>
5060
</StackPanel>
5161

src/Views/BranchTree.axaml.cs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -633,22 +633,21 @@ private ContextMenu CreateContextMenuForLocalBranch(ViewModels.Repository repo,
633633
}
634634
else
635635
{
636-
if (!repo.IsBare)
636+
var hasNoWorktree = string.IsNullOrEmpty(branch.WorktreePath);
637+
638+
var checkout = new MenuItem();
639+
checkout.Header = App.Text(hasNoWorktree ? "BranchCM.Checkout" : "BranchCM.SwitchToWorktree", branch.Name);
640+
checkout.Icon = App.CreateMenuIcon("Icons.Check");
641+
checkout.IsEnabled = !repo.IsBare || !hasNoWorktree;
642+
checkout.Click += async (_, e) =>
637643
{
638-
var checkout = new MenuItem();
639-
checkout.Header = App.Text("BranchCM.Checkout", branch.Name);
640-
checkout.Icon = App.CreateMenuIcon("Icons.Check");
641-
checkout.Click += async (_, e) =>
642-
{
643-
await repo.CheckoutBranchAsync(branch);
644-
e.Handled = true;
645-
};
646-
menu.Items.Add(checkout);
647-
menu.Items.Add(new MenuItem() { Header = "-" });
648-
}
644+
await repo.CheckoutBranchAsync(branch);
645+
e.Handled = true;
646+
};
647+
menu.Items.Add(checkout);
648+
menu.Items.Add(new MenuItem() { Header = "-" });
649649

650-
var worktree = repo.Worktrees.Find(x => x.Branch == branch.FullName);
651-
if (upstream != null && worktree == null)
650+
if (upstream != null && hasNoWorktree)
652651
{
653652
var fastForward = new MenuItem();
654653
fastForward.Header = App.Text("BranchCM.FastForward", upstream.FriendlyName);
@@ -705,7 +704,7 @@ private ContextMenu CreateContextMenuForLocalBranch(ViewModels.Repository repo,
705704
menu.Items.Add(rebase);
706705
}
707706

708-
if (worktree == null)
707+
if (hasNoWorktree)
709708
{
710709
var selectedCommit = repo.GetSelectedCommitInHistory();
711710
if (selectedCommit != null && !selectedCommit.SHA.Equals(branch.Head, StringComparison.Ordinal))

src/Views/Repository.axaml.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,17 @@ private void OnWorktreeContextRequested(object sender, ContextRequestedEventArgs
190190
{
191191
var menu = new ContextMenu();
192192

193+
var switchTo = new MenuItem();
194+
switchTo.Header = App.Text("Worktree.Open");
195+
switchTo.Icon = App.CreateMenuIcon("Icons.Folder.Open");
196+
switchTo.Click += (_, ev) =>
197+
{
198+
repo.OpenWorktree(worktree);
199+
ev.Handled = true;
200+
};
201+
menu.Items.Add(switchTo);
202+
menu.Items.Add(new MenuItem() { Header = "-" });
203+
193204
if (worktree.IsLocked)
194205
{
195206
var unlock = new MenuItem();

0 commit comments

Comments
 (0)