diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index c997f8221..b89f0f3d1 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -1023,6 +1023,7 @@ Template: ${0}$ WORKSPACE: Configure Workspaces... + Fetch All Repositories WORKTREE BRANCH Copy Path diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index cf27832e7..cd82711e6 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -1027,6 +1027,7 @@ 模板:${0}$ 工作区: 配置工作区... + 拉取工作区所有仓库 本地工作树 連結分支 复制工作树路径 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index fcf0003dd..73a2ec861 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -1027,6 +1027,7 @@ 範本: ${0}$ 工作區: 設定工作區... + 提取工作區所有存放庫 本機工作區 分支 複製工作區路徑 diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 68e3db43d..cc1c37ad9 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.IO; using System.Text; +using System.Threading.Tasks; using Avalonia.Collections; using Avalonia.Threading; @@ -116,6 +118,26 @@ public void CloseAll() _ignoreIndexChange = false; } + public async Task FetchAllRepositoriesAsync() + { + // avoid collection was modified while enumerating. + var pages = new List(); + pages.AddRange(Pages); + + var count = 0; + foreach (var page in pages) + { + if (page.Data is Repository repo) + { + if (await repo.FetchAllRemotesAsync()) + count++; + } + } + + if (count > 0) + Models.Notification.Send(null, $"Fetched {count} repositories"); + } + public void SwitchWorkspace(Workspace to) { if (to == null || to.IsActive) diff --git a/src/ViewModels/Repository.cs b/src/ViewModels/Repository.cs index 8c08dbe7f..55abefd85 100644 --- a/src/ViewModels/Repository.cs +++ b/src/ViewModels/Repository.cs @@ -675,6 +675,40 @@ public async Task FetchAsync(bool autoStart) ShowPopup(new Fetch(this)); } + public async Task FetchAllRemotesAsync() + { + if (IsAutoFetching) + return false; + + CommandLog log = null; + + try + { + var lockFile = Path.Combine(GitDir, "index.lock"); + if (File.Exists(lockFile)) + return false; + + if (_remotes.Count == 0) + return false; + + IsAutoFetching = true; + log = CreateLog("Fetch"); + + foreach (var remote in _remotes) + await new Commands.Fetch(FullPath, remote.Name).Use(log).RunAsync(); + + _lastFetchTime = DateTime.Now; + } + catch + { + // Ignore all exceptions. + } + + IsAutoFetching = false; + log?.Complete(); + return true; + } + public async Task PullAsync(bool autoStart) { if (IsBare || !CanCreatePopup()) diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index 27b213c28..e67108ed1 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using Avalonia; using Avalonia.Controls; @@ -395,6 +396,19 @@ private void OnOpenWorkspaceMenu(object sender, RoutedEventArgs e) menu.Items.Add(new MenuItem() { Header = "-" }); + var hasRepos = launcher.Pages.Any(p => p.Data is ViewModels.Repository); + + var fetchAll = new MenuItem(); + fetchAll.Header = App.Text("Workspace.FetchAllRepositories"); + fetchAll.Icon = this.CreateMenuIcon("Icons.Fetch"); + fetchAll.IsEnabled = hasRepos; + fetchAll.Click += async (_, ev) => + { + await launcher.FetchAllRepositoriesAsync(); + ev.Handled = true; + }; + menu.Items.Add(fetchAll); + var configure = new MenuItem(); configure.Header = App.Text("Workspace.Configure"); configure.Click += async (_, ev) =>