diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 44dbc977f..d6b5c0e9a 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -354,7 +354,36 @@ public override void OnFrameworkInitializationCompleted() if (TryLaunchAsAskpass(desktop)) return; - TryLaunchAsNormal(desktop); + _ipcChannel = new Models.IpcChannel(); + if (!_ipcChannel.IsFirstInstance) + { + var argsToSend = new List(); + if (desktop.Args != null) + { + for (int i = 0; i < desktop.Args.Length; i++) + { + var arg = desktop.Args[i].Trim(); + if (i == 0 && !arg.StartsWith("--")) + { + if (arg.StartsWith('"') && arg.EndsWith('"')) + arg = arg.Substring(1, arg.Length - 2).Trim(); + + if (arg.Length > 0 && !Path.IsPathFullyQualified(arg)) + arg = Path.GetFullPath(arg); + } + argsToSend.Add(arg); + } + } + + _ipcChannel.SendToFirstInstance(string.Join("\n", argsToSend)); + Environment.Exit(0); + } + else + { + _ipcChannel.MessageReceived += TryOpenRepository; + desktop.Exit += (_, _) => _ipcChannel.Dispose(); + TryLaunchAsNormal(desktop); + } } } #endregion @@ -542,8 +571,8 @@ private void TryLaunchAsNormal(IClassicDesktopStyleApplicationLifetime desktop) Models.AvatarManager.Instance.Start(); string startupRepo = null; - if (desktop.Args is { Length: 1 } && Directory.Exists(desktop.Args[0])) - startupRepo = desktop.Args[0]; + if (desktop.Args != null) + ParsedArgs = ParseArgs(desktop.Args, out startupRepo); var pref = ViewModels.Preferences.Instance; pref.SetCanModify(); @@ -552,7 +581,21 @@ private void TryLaunchAsNormal(IClassicDesktopStyleApplicationLifetime desktop) desktop.MainWindow = new Views.Launcher() { DataContext = _launcher }; desktop.ShutdownMode = ShutdownMode.OnMainWindowClose; - _ipcChannel.MessageReceived += repo => +#if !DISABLE_UPDATE_DETECTION + if (pref.ShouldCheck4UpdateOnStartup()) + Check4Update(); +#endif + } + + private void TryOpenRepository(string message) + { + if (string.IsNullOrWhiteSpace(message)) + return; + + string[] args = message.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); + ParsedArgs = ParseArgs(args, out string repo); + + if (!string.IsNullOrEmpty(repo) && Directory.Exists(repo)) { Dispatcher.UIThread.Invoke(() => { @@ -667,9 +710,44 @@ private string FixFontFamilyName(string input) } } - return trimmed.Count > 0 ? string.Join(',', trimmed) : string.Empty; + return string.Join(",", trimmed); + } + + public class LaunchArguments + { + public bool IgnoreWorkspace { get; set; } + public bool NoSaveWorkspace { get; set; } + public int? StartupViewIndex { get; set; } + } + + public static LaunchArguments ParseArgs(string[] args, out string repoPath) + { + repoPath = null; + var parsed = new LaunchArguments(); + for (int i = 0; i < args.Length; i++) + { + var arg = args[i].Trim(); + if (arg.Equals("--ignore-workspace", StringComparison.OrdinalIgnoreCase)) + parsed.IgnoreWorkspace = true; + else if (arg.Equals("--no-save-workspace", StringComparison.OrdinalIgnoreCase)) + parsed.NoSaveWorkspace = true; + else if (arg.Equals("--commit", StringComparison.OrdinalIgnoreCase)) + parsed.StartupViewIndex = 1; + else if (arg.Equals("--history", StringComparison.OrdinalIgnoreCase)) + parsed.StartupViewIndex = 0; + else if (arg.Equals("--stashes", StringComparison.OrdinalIgnoreCase)) + parsed.StartupViewIndex = 2; + else if (i == 0 && !arg.StartsWith("--")) + repoPath = arg; + } + return parsed; } + public static LaunchArguments ParsedArgs { get; set; } = new LaunchArguments(); + + [GeneratedRegex(@"^[a-z]+\s+([a-fA-F0-9]{4,40})(\s+.*)?$")] + private static partial Regex REG_REBASE_TODO(); + private Models.IpcChannel _ipcChannel = null; private ViewModels.Launcher _launcher = null; private ResourceDictionary _activeLocale = null; diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 4287cb9bd..c85276256 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -57,18 +57,21 @@ public Launcher(string startupRepo) ActiveWorkspace = pref.GetActiveWorkspace(); var repos = ActiveWorkspace.Repositories.ToArray(); - foreach (var repo in repos) + if (!App.ParsedArgs.IgnoreWorkspace) { - var node = pref.FindNode(repo) ?? - new RepositoryNode - { - Id = repo, - Name = Path.GetFileName(repo), - Bookmark = 0, - IsRepository = true, - }; + foreach (var repo in repos) + { + var node = pref.FindNode(repo) ?? + new RepositoryNode + { + Id = repo, + Name = Path.GetFileName(repo), + Bookmark = 0, + IsRepository = true, + }; - OpenRepositoryInTab(node, null); + OpenRepositoryInTab(node, null); + } } _ignoreIndexChange = false; diff --git a/src/ViewModels/Preferences.cs b/src/ViewModels/Preferences.cs index 04ffbeb9d..4849fb875 100644 --- a/src/ViewModels/Preferences.cs +++ b/src/ViewModels/Preferences.cs @@ -649,6 +649,9 @@ public void Save() if (_isLoading || _isReadonly) return; + if (App.ParsedArgs != null && App.ParsedArgs.NoSaveWorkspace) + return; + var file = Path.Combine(Native.OS.DataDir, "preference.json"); using var stream = File.Create(file); JsonSerializer.Serialize(stream, this, JsonCodeGen.Default.Preferences); diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 7f91241f5..13e82c3f7 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Text; @@ -465,7 +465,25 @@ public void Open() _stashesPage = new StashesPage(this); _searchCommitContext = new SearchCommitContext(this); - if (Preferences.Instance.ShowLocalChangesByDefault) + if (App.ParsedArgs != null && App.ParsedArgs.StartupViewIndex.HasValue) + { + switch (App.ParsedArgs.StartupViewIndex.Value) + { + case 1: + _selectedView = _workingCopy; + _selectedViewIndex = 1; + break; + case 2: + _selectedView = _stashesPage; + _selectedViewIndex = 2; + break; + default: + _selectedView = _histories; + _selectedViewIndex = 0; + break; + } + } + else if (Preferences.Instance.ShowLocalChangesByDefault) { _selectedView = _workingCopy; _selectedViewIndex = 1;