diff --git a/src/Commands/InitGit.cs b/src/Commands/InitGit.cs new file mode 100644 index 000000000..58df0db78 --- /dev/null +++ b/src/Commands/InitGit.cs @@ -0,0 +1,28 @@ +using System.Text; + +namespace SourceGit.Commands +{ + public class InitGit : Command + { + public InitGit(string ctx, string path, string localName, string branchName, bool bareRepo) + { + Context = ctx; + WorkingDirectory = path; + + var builder = new StringBuilder(1024); + builder.Append("init "); + + if (bareRepo) + builder.Append("--bare "); + else + { + if (!string.IsNullOrEmpty(branchName)) + builder.Append("-b " + branchName + " "); + } + + builder.Append(localName.Quoted()); + + Args = builder.ToString(); + } + } +} diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index d5843d79f..9f2217db5 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -540,6 +540,15 @@ Do you want to run `git init` command under this path? Open repository failed. Reason: Path: + Initialize Git Repository + Create Bare Repository + Bookmark: + Group: + Initial Branch Name + main + Parent Folder + Project Name + new_git_project Cherry-Pick in progress. Processing commit Merge in progress. @@ -945,6 +954,7 @@ Delete DRAG & DROP FOLDER SUPPORTED. CUSTOM GROUPING SUPPORTED. Edit + Initialize Git Repository Move to Another Group Open All Repositories Open Repository diff --git a/src/ViewModels/InitGit.cs b/src/ViewModels/InitGit.cs new file mode 100644 index 000000000..b3ad5d257 --- /dev/null +++ b/src/ViewModels/InitGit.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Threading.Tasks; +using System.Globalization; + +namespace SourceGit.ViewModels +{ + public class InitGit : Popup + { + [Required(ErrorMessage = "Parent folder is required")] + [CustomValidation(typeof(InitGit), nameof(ValidateParentFolder))] + public string ParentFolder + { + get => _parentFolder; + set => SetProperty(ref _parentFolder, value, true); + } + + public string ProjectName + { + get => null; + set => SetProperty(ref _projectName, value); + } + + public List Groups + { + get; + } + + public RepositoryNode SelectedGroup + { + get => _selectedGroup; + set => SetProperty(ref _selectedGroup, value); + } + + public List Bookmarks + { + get; + } + + public int Bookmark + { + get => _bookmark; + set => SetProperty(ref _bookmark, value); + } + + public string InitialBranch + { + get => null; + set => SetProperty(ref _initialBranch, value); + } + + public bool BareRepo + { + get; + set; + } = false; + + public InitGit(string pageId) + { + _pageId = pageId; + + Groups = new List(); + Groups.Add(new RepositoryNode { Name = "No Group (Uncategorized)", Id = string.Empty }); + SelectedGroup = Groups[0]; + CollectGroups(Groups, Preferences.Instance.RepositoryNodes); + + Bookmarks = new List(); + for (var i = 0; i < Models.Bookmarks.Brushes.Length; i++) + Bookmarks.Add(i); + + var activeWorkspace = Preferences.Instance.GetActiveWorkspace(); + _parentFolder = activeWorkspace?.DefaultCloneDir; + if (string.IsNullOrEmpty(ParentFolder)) + _parentFolder = Preferences.Instance.GitDefaultCloneDir; + } + + public static ValidationResult ValidateParentFolder(string folder, ValidationContext _) + { + if (!Directory.Exists(folder)) + return new ValidationResult("Given path can NOT be found"); + return ValidationResult.Success; + } + + public override async Task Sure() + { + ProgressDescription = "Init ..."; + + var log = new CommandLog("Init"); + Use(log); + + var succ = await new Commands.InitGit(_pageId, _parentFolder, _projectName, _initialBranch, BareRepo) + .Use(log) + .ExecAsync(); + if (!succ) + return false; + + var path = _parentFolder; + if (!string.IsNullOrEmpty(_projectName)) + { + path = Path.GetFullPath(Path.Combine(path, _projectName)); + } + else + { + path = Path.GetFullPath(Path.Combine(path, "new_git_project")); + } + + if (!Directory.Exists(path)) + { + Models.Notification.Send(_pageId, $"Folder '{path}' can NOT be found", true); + return false; + } + + log.Complete(); + + var parent = _selectedGroup is { Id: not "" } ? _selectedGroup : null; + var node = Preferences.Instance.FindOrAddNodeByRepositoryPath(path, parent, true); + node.Bookmark = _bookmark; + await node.UpdateStatusAsync(false, null); + + var launcher = App.GetLauncher(); + LauncherPage page = null; + foreach (var one in launcher.Pages) + { + if (one.Node.Id == _pageId) + { + page = one; + break; + } + } + + Welcome.Instance.Refresh(); + launcher.OpenRepositoryInTab(node, page); + return true; + } + + private void CollectGroups(List outs, List collections) + { + foreach (var node in collections) + { + if (!node.IsRepository) + { + outs.Add(node); + CollectGroups(outs, node.SubNodes); + } + } + } + + private string _pageId = string.Empty; + private string _parentFolder = string.Empty; + private string _projectName = App.Text("InitGit.ProjectName.Placeholder"); + private string _initialBranch = App.Text("InitGit.InitialBranch.Placeholder"); + private RepositoryNode _selectedGroup = null; + private int _bookmark = 0; + } +} diff --git a/src/ViewModels/Welcome.cs b/src/ViewModels/Welcome.cs index 49539292d..2d052d314 100644 --- a/src/ViewModels/Welcome.cs +++ b/src/ViewModels/Welcome.cs @@ -171,6 +171,19 @@ public void OpenTerminal() Native.OS.OpenTerminal(null); } + public void InitGit() + { + if (!Preferences.Instance.IsGitConfigured()) + { + Models.Notification.Send(null, App.Text("NotConfigured"), true); + return; + } + + var activePage = App.GetLauncher().ActivePage; + if (activePage != null && activePage.CanCreatePopup()) + activePage.Popup = new InitGit(activePage.Node.Id); + } + public void ScanDefaultCloneDir() { if (!Preferences.Instance.IsGitConfigured()) diff --git a/src/Views/InitGit.axaml b/src/Views/InitGit.axaml new file mode 100644 index 000000000..e0262ba4a --- /dev/null +++ b/src/Views/InitGit.axaml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Views/InitGit.axaml.cs b/src/Views/InitGit.axaml.cs new file mode 100644 index 000000000..21e3ce84a --- /dev/null +++ b/src/Views/InitGit.axaml.cs @@ -0,0 +1,46 @@ +using System; +using Avalonia.Controls; +using Avalonia.Input.Platform; +using Avalonia.Interactivity; +using Avalonia.Platform.Storage; + +namespace SourceGit.Views +{ + public partial class InitGit : UserControl + { + public InitGit() + { + InitializeComponent(); + } + + protected override async void OnLoaded(RoutedEventArgs e) + { + base.OnLoaded(e); + } + + private async void SelectParentFolder(object _, RoutedEventArgs e) + { + var options = new FolderPickerOpenOptions() { AllowMultiple = false }; + var toplevel = TopLevel.GetTopLevel(this); + if (toplevel == null) + return; + + try + { + var selected = await toplevel.StorageProvider.OpenFolderPickerAsync(options); + if (selected.Count == 1) + { + var folder = selected[0]; + var folderPath = folder is { Path: { IsAbsoluteUri: true } path } ? path.LocalPath : folder?.Path.ToString(); + TxtParentFolder.Text = folderPath; + } + } + catch (Exception exception) + { + Models.Notification.Send(null, $"Failed to select parent folder: {exception.Message}", true); + } + + e.Handled = true; + } + } +} diff --git a/src/Views/WelcomeToolbar.axaml b/src/Views/WelcomeToolbar.axaml index 91f2064fa..ef662fa1b 100644 --- a/src/Views/WelcomeToolbar.axaml +++ b/src/Views/WelcomeToolbar.axaml @@ -33,6 +33,10 @@ + +