diff --git a/src/App.axaml.cs b/src/App.axaml.cs index 23fc0dcde..8b691dcb1 100644 --- a/src/App.axaml.cs +++ b/src/App.axaml.cs @@ -269,7 +269,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 @@ -457,8 +486,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(); @@ -484,7 +513,21 @@ private void TryLaunchAsNormal(IClassicDesktopStyleApplicationLifetime desktop) _ipcChannel = null; }; - _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(() => { @@ -564,6 +607,82 @@ private void ShowSelfUpdateResult(object data) } #endregion + private string FixFontFamilyName(string input) + { + if (string.IsNullOrEmpty(input)) + return string.Empty; + + var parts = input.Split(','); + var trimmed = new List(); + + foreach (var part in parts) + { + var t = part.Trim(); + if (string.IsNullOrEmpty(t)) + continue; + + var sb = new StringBuilder(); + var prevChar = '\0'; + + foreach (var c in t) + { + if (c == ' ' && prevChar == ' ') + continue; + sb.Append(c); + prevChar = c; + } + + var name = sb.ToString(); + try + { + var fontFamily = FontFamily.Parse(name); + if (fontFamily.FamilyTypefaces.Count > 0) + trimmed.Add(name); + } + catch + { + // Ignore exceptions. + } + } + + 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 5beb3f136..82dfb7af8 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 36c9864e8..c44ab4bec 100644 --- a/src/ViewModels/Preferences.cs +++ b/src/ViewModels/Preferences.cs @@ -652,10 +652,12 @@ public void Save() if (_isLoading || _isReadonly) return; + if (App.ParsedArgs != null && App.ParsedArgs.NoSaveWorkspace) + return; + var tmpfile = Path.Combine(Native.OS.DataDir, "preference_tmp.json"); var content = JsonSerializer.Serialize(this, JsonCodeGen.Default.Preferences); File.WriteAllText(tmpfile, content); - var finalFile = Path.Combine(Native.OS.DataDir, "preference.json"); File.Move(tmpfile, finalFile, true); } diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index e9c573bf7..9388fd024 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; @@ -479,7 +479,31 @@ public void Open() _workingCopy = new WorkingCopy(this) { CommitMessage = _uiStates.LastCommitMessage }; _stashesPage = new StashesPage(this); _searchCommitContext = new SearchCommitContext(this); - _selectedViewIndex = Preferences.Instance.ShowLocalChangesByDefault ? 1 : 0; + + 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 + { + _selectedViewIndex = Preferences.Instance.ShowLocalChangesByDefault ? 1 : 0; + _selectedView = (_selectedViewIndex == 1) ? _workingCopy : _histories; + } + _lastFetchTime = DateTime.Now; _autoFetchTimer = new Timer(AutoFetchByTimer, null, 5000, 5000); RefreshAll();