diff --git a/src/ViewModels/CommitDetail.cs b/src/ViewModels/CommitDetail.cs index 01f39b35..d90e97d6 100644 --- a/src/ViewModels/CommitDetail.cs +++ b/src/ViewModels/CommitDetail.cs @@ -420,34 +420,37 @@ namespace SourceGit.ViewModels menu.Items.Add(patch); menu.Items.Add(new MenuItem { Header = "-" }); - var resetToThisRevision = new MenuItem(); - resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision"); - resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout"); - resetToThisRevision.Click += (_, ev) => + if (!_repo.IsBare) { - new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}"); - ev.Handled = true; - }; + var resetToThisRevision = new MenuItem(); + resetToThisRevision.Header = App.Text("ChangeCM.CheckoutThisRevision"); + resetToThisRevision.Icon = App.CreateMenuIcon("Icons.File.Checkout"); + resetToThisRevision.Click += (_, ev) => + { + new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}"); + ev.Handled = true; + }; - var resetToFirstParent = new MenuItem(); - resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision"); - resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout"); - resetToFirstParent.IsEnabled = _commit.Parents.Count > 0; - resetToFirstParent.Click += (_, ev) => - { - if (change.Index == Models.ChangeState.Renamed) - new Commands.Checkout(_repo.FullPath).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1"); + var resetToFirstParent = new MenuItem(); + resetToFirstParent.Header = App.Text("ChangeCM.CheckoutFirstParentRevision"); + resetToFirstParent.Icon = App.CreateMenuIcon("Icons.File.Checkout"); + resetToFirstParent.IsEnabled = _commit.Parents.Count > 0; + resetToFirstParent.Click += (_, ev) => + { + if (change.Index == Models.ChangeState.Renamed) + new Commands.Checkout(_repo.FullPath).FileWithRevision(change.OriginalPath, $"{_commit.SHA}~1"); - new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}~1"); - ev.Handled = true; - }; + new Commands.Checkout(_repo.FullPath).FileWithRevision(change.Path, $"{_commit.SHA}~1"); + ev.Handled = true; + }; - menu.Items.Add(resetToThisRevision); - menu.Items.Add(resetToFirstParent); - menu.Items.Add(new MenuItem { Header = "-" }); + menu.Items.Add(resetToThisRevision); + menu.Items.Add(resetToFirstParent); + menu.Items.Add(new MenuItem { Header = "-" }); - if (File.Exists(Path.Combine(fullPath))) - TryToAddContextMenuItemsForGitLFS(menu, change.Path); + if (File.Exists(Path.Combine(fullPath))) + TryToAddContextMenuItemsForGitLFS(menu, change.Path); + } var copyPath = new MenuItem(); copyPath.Header = App.Text("CopyPath"); diff --git a/src/ViewModels/CreateBranch.cs b/src/ViewModels/CreateBranch.cs index 64806a49..b67a453a 100644 --- a/src/ViewModels/CreateBranch.cs +++ b/src/ViewModels/CreateBranch.cs @@ -31,6 +31,11 @@ namespace SourceGit.ViewModels set => _repo.Settings.CheckoutBranchOnCreateBranch = value; } + public bool IsBareRepository + { + get => _repo.IsBare; + } + public CreateBranch(Repository repo, Models.Branch branch) { _repo = repo; @@ -84,7 +89,7 @@ namespace SourceGit.ViewModels return Task.Run(() => { var succ = false; - if (CheckoutAfterCreated) + if (CheckoutAfterCreated && !_repo.IsBare) { var changes = new Commands.CountLocalChangesWithoutUntracked(_repo.FullPath).Result(); var needPopStash = false; diff --git a/src/ViewModels/Histories.cs b/src/ViewModels/Histories.cs index b890b76e..b5754d33 100644 --- a/src/ViewModels/Histories.cs +++ b/src/ViewModels/Histories.cs @@ -213,7 +213,7 @@ namespace SourceGit.ViewModels { if (firstRemoteBranch != null) _repo.ShowPopup(new CreateBranch(_repo, firstRemoteBranch)); - else + else if (!_repo.IsBare) _repo.ShowPopup(new CheckoutCommit(_repo, commit)); } } @@ -253,36 +253,39 @@ namespace SourceGit.ViewModels var multipleMenu = new ContextMenu(); - if (canCherryPick) + if (!_repo.IsBare) { - var cherryPickMultiple = new MenuItem(); - cherryPickMultiple.Header = App.Text("CommitCM.CherryPickMultiple"); - cherryPickMultiple.Icon = App.CreateMenuIcon("Icons.CherryPick"); - cherryPickMultiple.Click += (_, e) => + if (canCherryPick) { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new CherryPick(_repo, selected)); - e.Handled = true; - }; - multipleMenu.Items.Add(cherryPickMultiple); - } + var cherryPickMultiple = new MenuItem(); + cherryPickMultiple.Header = App.Text("CommitCM.CherryPickMultiple"); + cherryPickMultiple.Icon = App.CreateMenuIcon("Icons.CherryPick"); + cherryPickMultiple.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new CherryPick(_repo, selected)); + e.Handled = true; + }; + multipleMenu.Items.Add(cherryPickMultiple); + } - if (canMerge) - { - var mergeMultiple = new MenuItem(); - mergeMultiple.Header = App.Text("CommitCM.MergeMultiple"); - mergeMultiple.Icon = App.CreateMenuIcon("Icons.Merge"); - mergeMultiple.Click += (_, e) => + if (canMerge) { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new MergeMultiple(_repo, selected)); - e.Handled = true; - }; - multipleMenu.Items.Add(mergeMultiple); - } + var mergeMultiple = new MenuItem(); + mergeMultiple.Header = App.Text("CommitCM.MergeMultiple"); + mergeMultiple.Icon = App.CreateMenuIcon("Icons.Merge"); + mergeMultiple.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new MergeMultiple(_repo, selected)); + e.Handled = true; + }; + multipleMenu.Items.Add(mergeMultiple); + } - if (canCherryPick || canMerge) - multipleMenu.Items.Add(new MenuItem() { Header = "-" }); + if (canCherryPick || canMerge) + multipleMenu.Items.Add(new MenuItem() { Header = "-" }); + } var saveToPatchMultiple = new MenuItem(); saveToPatchMultiple.Icon = App.CreateMenuIcon("Icons.Diff"); @@ -394,25 +397,48 @@ namespace SourceGit.ViewModels menu.Items.Add(new MenuItem() { Header = "-" }); } - if (current.Head != commit.SHA) + if (!_repo.IsBare) { - var reset = new MenuItem(); - reset.Header = new Views.NameHighlightedTextBlock("CommitCM.Reset", current.Name); - reset.Icon = App.CreateMenuIcon("Icons.Reset"); - reset.Click += (_, e) => + if (current.Head != commit.SHA) { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Reset(_repo, current, commit)); - e.Handled = true; - }; - menu.Items.Add(reset); + var reset = new MenuItem(); + reset.Header = new Views.NameHighlightedTextBlock("CommitCM.Reset", current.Name); + reset.Icon = App.CreateMenuIcon("Icons.Reset"); + reset.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new Reset(_repo, current, commit)); + e.Handled = true; + }; + menu.Items.Add(reset); - if (commit.IsMerged) + if (commit.IsMerged) + { + var squash = new MenuItem(); + squash.Header = App.Text("CommitCM.SquashCommitsSinceThis"); + squash.Icon = App.CreateMenuIcon("Icons.SquashIntoParent"); + squash.Click += (_, e) => + { + if (_repo.LocalChangesCount > 0) + { + App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); + return; + } + + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new Squash(_repo, commit, commit.SHA)); + + e.Handled = true; + }; + menu.Items.Add(squash); + } + } + else { - var squash = new MenuItem(); - squash.Header = App.Text("CommitCM.SquashCommitsSinceThis"); - squash.Icon = App.CreateMenuIcon("Icons.SquashIntoParent"); - squash.Click += (_, e) => + var reword = new MenuItem(); + reword.Header = App.Text("CommitCM.Reword"); + reword.Icon = App.CreateMenuIcon("Icons.Edit"); + reword.Click += (_, e) => { if (_repo.LocalChangesCount > 0) { @@ -421,169 +447,149 @@ namespace SourceGit.ViewModels } if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Squash(_repo, commit, commit.SHA)); + _repo.ShowPopup(new Reword(_repo, commit)); + e.Handled = true; + }; + menu.Items.Add(reword); + + var squash = new MenuItem(); + squash.Header = App.Text("CommitCM.Squash"); + squash.Icon = App.CreateMenuIcon("Icons.SquashIntoParent"); + squash.IsEnabled = commit.Parents.Count == 1; + squash.Click += (_, e) => + { + if (_repo.LocalChangesCount > 0) + { + App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); + return; + } + + if (commit.Parents.Count == 1) + { + var parent = _commits.Find(x => x.SHA == commit.Parents[0]); + if (parent != null && _repo.CanCreatePopup()) + _repo.ShowPopup(new Squash(_repo, parent, commit.SHA)); + } e.Handled = true; }; menu.Items.Add(squash); } - } - else - { - var reword = new MenuItem(); - reword.Header = App.Text("CommitCM.Reword"); - reword.Icon = App.CreateMenuIcon("Icons.Edit"); - reword.Click += (_, e) => + + if (!commit.IsMerged) { - if (_repo.LocalChangesCount > 0) - { - App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); - return; - } - - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Reword(_repo, commit)); - e.Handled = true; - }; - menu.Items.Add(reword); - - var squash = new MenuItem(); - squash.Header = App.Text("CommitCM.Squash"); - squash.Icon = App.CreateMenuIcon("Icons.SquashIntoParent"); - squash.IsEnabled = commit.Parents.Count == 1; - squash.Click += (_, e) => - { - if (_repo.LocalChangesCount > 0) - { - App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); - return; - } - - if (commit.Parents.Count == 1) - { - var parent = _commits.Find(x => x.SHA == commit.Parents[0]); - if (parent != null && _repo.CanCreatePopup()) - _repo.ShowPopup(new Squash(_repo, parent, commit.SHA)); - } - - e.Handled = true; - }; - menu.Items.Add(squash); - } - - if (!commit.IsMerged) - { - var rebase = new MenuItem(); - rebase.Header = new Views.NameHighlightedTextBlock("CommitCM.Rebase", current.Name); - rebase.Icon = App.CreateMenuIcon("Icons.Rebase"); - rebase.Click += (_, e) => - { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Rebase(_repo, current, commit)); - e.Handled = true; - }; - menu.Items.Add(rebase); - - if (!commit.HasDecorators) - { - var merge = new MenuItem(); - merge.Header = new Views.NameHighlightedTextBlock("CommitCM.Merge", current.Name); - merge.Icon = App.CreateMenuIcon("Icons.Merge"); - merge.Click += (_, e) => + var rebase = new MenuItem(); + rebase.Header = new Views.NameHighlightedTextBlock("CommitCM.Rebase", current.Name); + rebase.Icon = App.CreateMenuIcon("Icons.Rebase"); + rebase.Click += (_, e) => { if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Merge(_repo, commit, current.Name)); + _repo.ShowPopup(new Rebase(_repo, current, commit)); + e.Handled = true; + }; + menu.Items.Add(rebase); + + if (!commit.HasDecorators) + { + var merge = new MenuItem(); + merge.Header = new Views.NameHighlightedTextBlock("CommitCM.Merge", current.Name); + merge.Icon = App.CreateMenuIcon("Icons.Merge"); + merge.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new Merge(_repo, commit, current.Name)); + + e.Handled = true; + }; + menu.Items.Add(merge); + } + + var cherryPick = new MenuItem(); + cherryPick.Header = App.Text("CommitCM.CherryPick"); + cherryPick.Icon = App.CreateMenuIcon("Icons.CherryPick"); + cherryPick.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + { + if (commit.Parents.Count <= 1) + { + _repo.ShowPopup(new CherryPick(_repo, [commit])); + } + else + { + var parents = new List(); + foreach (var sha in commit.Parents) + { + var parent = _commits.Find(x => x.SHA == sha); + if (parent == null) + parent = new Commands.QuerySingleCommit(_repo.FullPath, sha).Result(); + + if (parent != null) + parents.Add(parent); + } + + _repo.ShowPopup(new CherryPick(_repo, commit, parents)); + } + } e.Handled = true; }; - menu.Items.Add(merge); + menu.Items.Add(cherryPick); + } + else + { + var revert = new MenuItem(); + revert.Header = App.Text("CommitCM.Revert"); + revert.Icon = App.CreateMenuIcon("Icons.Undo"); + revert.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new Revert(_repo, commit)); + e.Handled = true; + }; + menu.Items.Add(revert); } - var cherryPick = new MenuItem(); - cherryPick.Header = App.Text("CommitCM.CherryPick"); - cherryPick.Icon = App.CreateMenuIcon("Icons.CherryPick"); - cherryPick.Click += (_, e) => + if (current.Head != commit.SHA) { - if (_repo.CanCreatePopup()) + var checkoutCommit = new MenuItem(); + checkoutCommit.Header = App.Text("CommitCM.Checkout"); + checkoutCommit.Icon = App.CreateMenuIcon("Icons.Detached"); + checkoutCommit.Click += (_, e) => { - if (commit.Parents.Count <= 1) - { - _repo.ShowPopup(new CherryPick(_repo, [commit])); - } - else - { - var parents = new List(); - foreach (var sha in commit.Parents) - { - var parent = _commits.Find(x => x.SHA == sha); - if (parent == null) - parent = new Commands.QuerySingleCommit(_repo.FullPath, sha).Result(); + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new CheckoutCommit(_repo, commit)); + e.Handled = true; + }; + menu.Items.Add(checkoutCommit); + } - if (parent != null) - parents.Add(parent); - } - - _repo.ShowPopup(new CherryPick(_repo, commit, parents)); - } - } - - e.Handled = true; - }; - menu.Items.Add(cherryPick); - } - else - { - var revert = new MenuItem(); - revert.Header = App.Text("CommitCM.Revert"); - revert.Icon = App.CreateMenuIcon("Icons.Undo"); - revert.Click += (_, e) => - { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Revert(_repo, commit)); - e.Handled = true; - }; - menu.Items.Add(revert); - } - - if (current.Head != commit.SHA) - { - var checkoutCommit = new MenuItem(); - checkoutCommit.Header = App.Text("CommitCM.Checkout"); - checkoutCommit.Icon = App.CreateMenuIcon("Icons.Detached"); - checkoutCommit.Click += (_, e) => - { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new CheckoutCommit(_repo, commit)); - e.Handled = true; - }; - menu.Items.Add(checkoutCommit); - } - - menu.Items.Add(new MenuItem() { Header = "-" }); - - if (commit.IsMerged && current.Head != commit.SHA) - { - var interactiveRebase = new MenuItem(); - interactiveRebase.Header = new Views.NameHighlightedTextBlock("CommitCM.InteractiveRebase", current.Name); - interactiveRebase.Icon = App.CreateMenuIcon("Icons.InteractiveRebase"); - interactiveRebase.Click += (_, e) => - { - if (_repo.LocalChangesCount > 0) - { - App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); - return; - } - - App.OpenDialog(new Views.InteractiveRebase() - { - DataContext = new InteractiveRebase(_repo, current, commit) - }); - - e.Handled = true; - }; - menu.Items.Add(interactiveRebase); menu.Items.Add(new MenuItem() { Header = "-" }); - } + + if (commit.IsMerged && current.Head != commit.SHA) + { + var interactiveRebase = new MenuItem(); + interactiveRebase.Header = new Views.NameHighlightedTextBlock("CommitCM.InteractiveRebase", current.Name); + interactiveRebase.Icon = App.CreateMenuIcon("Icons.InteractiveRebase"); + interactiveRebase.Click += (_, e) => + { + if (_repo.LocalChangesCount > 0) + { + App.RaiseException(_repo.FullPath, "You have local changes. Please run stash or discard first."); + return; + } + + App.OpenDialog(new Views.InteractiveRebase() + { + DataContext = new InteractiveRebase(_repo, current, commit) + }); + + e.Handled = true; + }; + menu.Items.Add(interactiveRebase); + menu.Items.Add(new MenuItem() { Header = "-" }); + } + } if (current.Head != commit.SHA) { @@ -914,21 +920,24 @@ namespace SourceGit.ViewModels submenu.Items.Add(rename); submenu.Items.Add(new MenuItem() { Header = "-" }); - var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, current.Name); - if (detect.IsGitFlowBranch) + if (!_repo.IsBare) { - var finish = new MenuItem(); - finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", current.Name); - finish.Icon = App.CreateMenuIcon("Icons.GitFlow"); - finish.Click += (_, e) => + var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, current.Name); + if (detect.IsGitFlowBranch) { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new GitFlowFinish(_repo, current, detect.Type, detect.Prefix)); - e.Handled = true; - }; - submenu.Items.Add(finish); - submenu.Items.Add(new MenuItem() { Header = "-" }); - } + var finish = new MenuItem(); + finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", current.Name); + finish.Icon = App.CreateMenuIcon("Icons.GitFlow"); + finish.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new GitFlowFinish(_repo, current, detect.Type, detect.Prefix)); + e.Handled = true; + }; + submenu.Items.Add(finish); + submenu.Items.Add(new MenuItem() { Header = "-" }); + } + } var copy = new MenuItem(); copy.Header = App.Text("BranchCM.CopyName"); @@ -951,27 +960,30 @@ namespace SourceGit.ViewModels FillBranchVisibilityMenu(submenu, branch); - var checkout = new MenuItem(); - checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", branch.Name); - checkout.Icon = App.CreateMenuIcon("Icons.Check"); - checkout.Click += (_, e) => + if (!_repo.IsBare) { - _repo.CheckoutBranch(branch); - e.Handled = true; - }; - submenu.Items.Add(checkout); + var checkout = new MenuItem(); + checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", branch.Name); + checkout.Icon = App.CreateMenuIcon("Icons.Check"); + checkout.Click += (_, e) => + { + _repo.CheckoutBranch(branch); + e.Handled = true; + }; + submenu.Items.Add(checkout); - var merge = new MenuItem(); - merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", branch.Name, current.Name); - merge.Icon = App.CreateMenuIcon("Icons.Merge"); - merge.IsEnabled = !merged; - merge.Click += (_, e) => - { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Merge(_repo, branch, current.Name)); - e.Handled = true; - }; - submenu.Items.Add(merge); + var merge = new MenuItem(); + merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", branch.Name, current.Name); + merge.Icon = App.CreateMenuIcon("Icons.Merge"); + merge.IsEnabled = !merged; + merge.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new Merge(_repo, branch, current.Name)); + e.Handled = true; + }; + submenu.Items.Add(merge); + } var rename = new MenuItem(); rename.Header = new Views.NameHighlightedTextBlock("BranchCM.Rename", branch.Name); @@ -996,21 +1008,24 @@ namespace SourceGit.ViewModels submenu.Items.Add(delete); submenu.Items.Add(new MenuItem() { Header = "-" }); - var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, branch.Name); - if (detect.IsGitFlowBranch) + if (!_repo.IsBare) { - var finish = new MenuItem(); - finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name); - finish.Icon = App.CreateMenuIcon("Icons.GitFlow"); - finish.Click += (_, e) => + var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, branch.Name); + if (detect.IsGitFlowBranch) { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new GitFlowFinish(_repo, branch, detect.Type, detect.Prefix)); - e.Handled = true; - }; - submenu.Items.Add(finish); - submenu.Items.Add(new MenuItem() { Header = "-" }); - } + var finish = new MenuItem(); + finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name); + finish.Icon = App.CreateMenuIcon("Icons.GitFlow"); + finish.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new GitFlowFinish(_repo, branch, detect.Type, detect.Prefix)); + e.Handled = true; + }; + submenu.Items.Add(finish); + submenu.Items.Add(new MenuItem() { Header = "-" }); + } + } var copy = new MenuItem(); copy.Header = App.Text("BranchCM.CopyName"); @@ -1104,17 +1119,19 @@ namespace SourceGit.ViewModels }; submenu.Items.Add(push); - var merge = new MenuItem(); - merge.Header = new Views.NameHighlightedTextBlock("TagCM.Merge", tag.Name, current.Name); - merge.Icon = App.CreateMenuIcon("Icons.Merge"); - merge.IsEnabled = !merged; - merge.Click += (_, e) => + if (!_repo.IsBare && !merged) { - if (_repo.CanCreatePopup()) - _repo.ShowPopup(new Merge(_repo, tag, current.Name)); - e.Handled = true; - }; - submenu.Items.Add(merge); + var merge = new MenuItem(); + merge.Header = new Views.NameHighlightedTextBlock("TagCM.Merge", tag.Name, current.Name); + merge.Icon = App.CreateMenuIcon("Icons.Merge"); + merge.Click += (_, e) => + { + if (_repo.CanCreatePopup()) + _repo.ShowPopup(new Merge(_repo, tag, current.Name)); + e.Handled = true; + }; + submenu.Items.Add(merge); + } var delete = new MenuItem(); delete.Header = new Views.NameHighlightedTextBlock("TagCM.Delete", tag.Name); diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 57a1c404..6761eccf 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -280,19 +280,20 @@ namespace SourceGit.ViewModels return; } - var gitDir = new Commands.QueryGitDir(node.Id).Result(); - if (string.IsNullOrEmpty(gitDir)) + var isBare = new Commands.IsBareRepository(node.Id).Result(); + var gitDir = node.Id; + if (!isBare) { - var ctx = page == null ? ActivePage.Node.Id : page.Node.Id; - App.RaiseException(ctx, "Given path is not a valid git repository!"); - return; + gitDir = new Commands.QueryGitDir(node.Id).Result(); + if (string.IsNullOrEmpty(gitDir)) + { + var ctx = page == null ? ActivePage.Node.Id : page.Node.Id; + App.RaiseException(ctx, "Given path is not a valid git repository!"); + return; + } } - var repo = new Repository() - { - FullPath = node.Id, - GitDir = gitDir, - }; + var repo = new Repository(isBare, node.Id, gitDir); repo.Open(); if (page == null) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index b747556c..28f32da5 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -18,6 +18,11 @@ namespace SourceGit.ViewModels { public class Repository : ObservableObject, Models.IRepository { + public bool IsBare + { + get; + } + public string FullPath { get => _fullpath; @@ -448,6 +453,13 @@ namespace SourceGit.ViewModels private set => SetProperty(ref _isAutoFetching, value); } + public Repository(bool isBare, string path, string gitDir) + { + IsBare = isBare; + FullPath = path; + GitDir = gitDir; + } + public void Open() { var settingsFile = Path.Combine(_gitDir, "sourcegit.settings"); @@ -995,6 +1007,9 @@ namespace SourceGit.ViewModels public void RefreshWorkingCopyChanges() { + if (IsBare) + return; + var changes = new Commands.QueryLocalChanges(_fullpath, _settings.IncludeUntrackedInLocalChanges).Result(); if (_workingCopy == null) return; @@ -1010,6 +1025,9 @@ namespace SourceGit.ViewModels public void RefreshStashes() { + if (IsBare) + return; + var stashes = new Commands.QueryStashes(_fullpath).Result(); Dispatcher.UIThread.Invoke(() => { @@ -1044,6 +1062,9 @@ namespace SourceGit.ViewModels } } + if (IsBare) + return; + if (!CanCreatePopup()) return; @@ -1416,66 +1437,72 @@ namespace SourceGit.ViewModels if (branch.IsCurrent) { - var discard = new MenuItem(); - discard.Header = App.Text("BranchCM.DiscardAll"); - discard.Icon = App.CreateMenuIcon("Icons.Undo"); - discard.Click += (_, e) => + if (!IsBare) { - if (CanCreatePopup()) - ShowPopup(new Discard(this)); - e.Handled = true; - }; - - menu.Items.Add(discard); - menu.Items.Add(new MenuItem() { Header = "-" }); - - if (!string.IsNullOrEmpty(branch.Upstream)) - { - var upstream = branch.Upstream.Substring(13); - var fastForward = new MenuItem(); - fastForward.Header = new Views.NameHighlightedTextBlock("BranchCM.FastForward", upstream); - fastForward.Icon = App.CreateMenuIcon("Icons.FastForward"); - fastForward.IsEnabled = branch.TrackStatus.Ahead.Count == 0; - fastForward.Click += (_, e) => + var discard = new MenuItem(); + discard.Header = App.Text("BranchCM.DiscardAll"); + discard.Icon = App.CreateMenuIcon("Icons.Undo"); + discard.Click += (_, e) => { - var b = _branches.Find(x => x.FriendlyName == upstream); - if (b == null) - return; - if (CanCreatePopup()) - ShowAndStartPopup(new Merge(this, b, branch.Name)); - + ShowPopup(new Discard(this)); e.Handled = true; }; - var pull = new MenuItem(); - pull.Header = new Views.NameHighlightedTextBlock("BranchCM.Pull", upstream); - pull.Icon = App.CreateMenuIcon("Icons.Pull"); - pull.Click += (_, e) => - { - if (CanCreatePopup()) - ShowPopup(new Pull(this, null)); - e.Handled = true; - }; + menu.Items.Add(discard); + menu.Items.Add(new MenuItem() { Header = "-" }); - menu.Items.Add(fastForward); - menu.Items.Add(pull); - } + if (!string.IsNullOrEmpty(branch.Upstream)) + { + var upstream = branch.Upstream.Substring(13); + var fastForward = new MenuItem(); + fastForward.Header = new Views.NameHighlightedTextBlock("BranchCM.FastForward", upstream); + fastForward.Icon = App.CreateMenuIcon("Icons.FastForward"); + fastForward.IsEnabled = branch.TrackStatus.Ahead.Count == 0; + fastForward.Click += (_, e) => + { + var b = _branches.Find(x => x.FriendlyName == upstream); + if (b == null) + return; + + if (CanCreatePopup()) + ShowAndStartPopup(new Merge(this, b, branch.Name)); + + e.Handled = true; + }; + + var pull = new MenuItem(); + pull.Header = new Views.NameHighlightedTextBlock("BranchCM.Pull", upstream); + pull.Icon = App.CreateMenuIcon("Icons.Pull"); + pull.Click += (_, e) => + { + if (CanCreatePopup()) + ShowPopup(new Pull(this, null)); + e.Handled = true; + }; + + menu.Items.Add(fastForward); + menu.Items.Add(pull); + } + } menu.Items.Add(push); } else { - var checkout = new MenuItem(); - checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", branch.Name); - checkout.Icon = App.CreateMenuIcon("Icons.Check"); - checkout.Click += (_, e) => + if (!IsBare) { - CheckoutBranch(branch); - e.Handled = true; - }; - menu.Items.Add(checkout); - menu.Items.Add(new MenuItem() { Header = "-" }); + var checkout = new MenuItem(); + checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", branch.Name); + checkout.Icon = App.CreateMenuIcon("Icons.Check"); + checkout.Click += (_, e) => + { + CheckoutBranch(branch); + e.Handled = true; + }; + menu.Items.Add(checkout); + menu.Items.Add(new MenuItem() { Header = "-" }); + } var worktree = _worktrees.Find(x => x.Branch == branch.FullName); var upstream = _branches.Find(x => x.FullName == branch.Upstream); @@ -1510,28 +1537,31 @@ namespace SourceGit.ViewModels menu.Items.Add(push); - var merge = new MenuItem(); - merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", branch.Name, _currentBranch.Name); - merge.Icon = App.CreateMenuIcon("Icons.Merge"); - merge.Click += (_, e) => + if (!IsBare) { - if (CanCreatePopup()) - ShowPopup(new Merge(this, branch, _currentBranch.Name)); - e.Handled = true; - }; + var merge = new MenuItem(); + merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", branch.Name, _currentBranch.Name); + merge.Icon = App.CreateMenuIcon("Icons.Merge"); + merge.Click += (_, e) => + { + if (CanCreatePopup()) + ShowPopup(new Merge(this, branch, _currentBranch.Name)); + e.Handled = true; + }; - var rebase = new MenuItem(); - rebase.Header = new Views.NameHighlightedTextBlock("BranchCM.Rebase", _currentBranch.Name, branch.Name); - rebase.Icon = App.CreateMenuIcon("Icons.Rebase"); - rebase.Click += (_, e) => - { - if (CanCreatePopup()) - ShowPopup(new Rebase(this, _currentBranch, branch)); - e.Handled = true; - }; + var rebase = new MenuItem(); + rebase.Header = new Views.NameHighlightedTextBlock("BranchCM.Rebase", _currentBranch.Name, branch.Name); + rebase.Icon = App.CreateMenuIcon("Icons.Rebase"); + rebase.Click += (_, e) => + { + if (CanCreatePopup()) + ShowPopup(new Rebase(this, _currentBranch, branch)); + e.Handled = true; + }; - menu.Items.Add(merge); - menu.Items.Add(rebase); + menu.Items.Add(merge); + menu.Items.Add(rebase); + } var compareWithHead = new MenuItem(); compareWithHead.Header = App.Text("BranchCM.CompareWithHead"); @@ -1566,21 +1596,24 @@ namespace SourceGit.ViewModels } } - var detect = Commands.GitFlow.DetectType(_fullpath, _branches, branch.Name); - if (detect.IsGitFlowBranch) + if (!IsBare) { - var finish = new MenuItem(); - finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name); - finish.Icon = App.CreateMenuIcon("Icons.GitFlow"); - finish.Click += (_, e) => + var detect = Commands.GitFlow.DetectType(_fullpath, _branches, branch.Name); + if (detect.IsGitFlowBranch) { - if (CanCreatePopup()) - ShowPopup(new GitFlowFinish(this, branch, detect.Type, detect.Prefix)); - e.Handled = true; - }; - menu.Items.Add(new MenuItem() { Header = "-" }); - menu.Items.Add(finish); - } + var finish = new MenuItem(); + finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name); + finish.Icon = App.CreateMenuIcon("Icons.GitFlow"); + finish.Click += (_, e) => + { + if (CanCreatePopup()) + ShowPopup(new GitFlowFinish(this, branch, detect.Type, detect.Prefix)); + e.Handled = true; + }; + menu.Items.Add(new MenuItem() { Header = "-" }); + menu.Items.Add(finish); + } + } var rename = new MenuItem(); rename.Header = new Views.NameHighlightedTextBlock("BranchCM.Rename", branch.Name); @@ -1631,26 +1664,29 @@ namespace SourceGit.ViewModels menu.Items.Add(createTag); menu.Items.Add(new MenuItem() { Header = "-" }); - var remoteBranches = new List(); - foreach (var b in _branches) + if (!IsBare) { - if (!b.IsLocal) - remoteBranches.Add(b); - } - - if (remoteBranches.Count > 0) - { - var tracking = new MenuItem(); - tracking.Header = App.Text("BranchCM.Tracking"); - tracking.Icon = App.CreateMenuIcon("Icons.Track"); - tracking.Click += (_, e) => + var remoteBranches = new List(); + foreach (var b in _branches) { - if (CanCreatePopup()) - ShowPopup(new SetUpstream(this, branch, remoteBranches)); - e.Handled = true; - }; - menu.Items.Add(tracking); - } + if (!b.IsLocal) + remoteBranches.Add(b); + } + + if (remoteBranches.Count > 0) + { + var tracking = new MenuItem(); + tracking.Header = App.Text("BranchCM.Tracking"); + tracking.Icon = App.CreateMenuIcon("Icons.Track"); + tracking.Click += (_, e) => + { + if (CanCreatePopup()) + ShowPopup(new SetUpstream(this, branch, remoteBranches)); + e.Handled = true; + }; + menu.Items.Add(tracking); + } + } var archive = new MenuItem(); archive.Icon = App.CreateMenuIcon("Icons.Archive"); diff --git a/src/ViewModels/ScanRepositories.cs b/src/ViewModels/ScanRepositories.cs index 5c023587..8d14e36e 100644 --- a/src/ViewModels/ScanRepositories.cs +++ b/src/ViewModels/ScanRepositories.cs @@ -34,7 +34,7 @@ namespace SourceGit.ViewModels watch.Start(); var rootDir = new DirectoryInfo(RootDir); - var founded = new List(); + var founded = new List(); GetUnmanagedRepositories(rootDir, founded, new EnumerationOptions() { AttributesToSkip = FileAttributes.Hidden | FileAttributes.System, @@ -47,16 +47,16 @@ namespace SourceGit.ViewModels foreach (var f in founded) { - var parent = new DirectoryInfo(f).Parent!.FullName.Replace("\\", "/"); + var parent = new DirectoryInfo(f.Path).Parent!.FullName.Replace("\\", "/"); if (parent.Equals(normalizedRoot, StringComparison.Ordinal)) { - Preferences.Instance.FindOrAddNodeByRepositoryPath(f, null, false); + Preferences.Instance.FindOrAddNodeByRepositoryPath(f.Path, null, false); } else if (parent.StartsWith(normalizedRoot, StringComparison.Ordinal)) { var relative = parent.Substring(normalizedRoot.Length).TrimStart('/'); var group = FindOrCreateGroupRecursive(Preferences.Instance.RepositoryNodes, relative); - Preferences.Instance.FindOrAddNodeByRepositoryPath(f, group, false); + Preferences.Instance.FindOrAddNodeByRepositoryPath(f.Path, group, false); } } @@ -85,7 +85,7 @@ namespace SourceGit.ViewModels } } - private void GetUnmanagedRepositories(DirectoryInfo dir, List outs, EnumerationOptions opts, int depth = 0) + private void GetUnmanagedRepositories(DirectoryInfo dir, List outs, EnumerationOptions opts, int depth = 0) { var subdirs = dir.GetDirectories("*", opts); foreach (var subdir in subdirs) @@ -111,12 +111,19 @@ namespace SourceGit.ViewModels { var normalized = test.StdOut.Trim().Replace("\\", "/"); if (!_managed.Contains(normalized)) - outs.Add(normalized); + outs.Add(new FoundRepository(normalized, false)); } continue; } + var isBare = new Commands.IsBareRepository(subdir.FullName).Result(); + if (isBare) + { + outs.Add(new FoundRepository(normalizedSelf, true)); + continue; + } + if (depth < 5) GetUnmanagedRepositories(subdir, outs, opts, depth + 1); } @@ -161,6 +168,12 @@ namespace SourceGit.ViewModels return added; } + private record FoundRepository(string path, bool isBare) + { + public string Path { get; set; } = path; + public bool IsBare { get; set; } = isBare; + } + private HashSet _managed = new HashSet(); } } diff --git a/src/ViewModels/Welcome.cs b/src/ViewModels/Welcome.cs index 5c9c9380..95f7f010 100644 --- a/src/ViewModels/Welcome.cs +++ b/src/ViewModels/Welcome.cs @@ -94,20 +94,20 @@ namespace SourceGit.ViewModels } var isBare = new Commands.IsBareRepository(path).Result(); - if (isBare) + var repoRoot = path; + if (!isBare) { - App.RaiseException(string.Empty, $"'{path}' is a bare repository, which is not supported by SourceGit!"); - return; + var test = new Commands.QueryRepositoryRootPath(path).ReadToEnd(); + if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut)) + { + InitRepository(path, parent, test.StdErr); + return; + } + + repoRoot = test.StdOut.Trim(); } - var test = new Commands.QueryRepositoryRootPath(path).ReadToEnd(); - if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut)) - { - InitRepository(path, parent, test.StdErr); - return; - } - - var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(test.StdOut.Trim(), parent, bMoveExistedNode); + var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(repoRoot, parent, bMoveExistedNode); Refresh(); var launcher = App.GetLauncer(); diff --git a/src/Views/CreateBranch.axaml b/src/Views/CreateBranch.axaml index 43f4e50c..49bfda8d 100644 --- a/src/Views/CreateBranch.axaml +++ b/src/Views/CreateBranch.axaml @@ -18,8 +18,8 @@ - - + + - - - - - + Text="{DynamicResource Text.CreateBranch.LocalChanges}" + IsVisible="{Binding !IsBareRepository}"/> + + + + + + + + IsChecked="{Binding CheckoutAfterCreated, Mode=TwoWay}" + IsVisible="{Binding !IsBareRepository}"/> diff --git a/src/Views/Repository.axaml b/src/Views/Repository.axaml index d935d754..00f9f6ce 100644 --- a/src/Views/Repository.axaml +++ b/src/Views/Repository.axaml @@ -40,7 +40,7 @@ - +