Skip to content

Commit 95163cc

Browse files
Fix: Moved Git operations to a different thread (#13608)
1 parent bd78721 commit 95163cc

18 files changed

+420
-189
lines changed

src/Files.App/App.xaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ await SafetyExtensions.IgnoreExceptions(async () =>
369369
},
370370
Logger);
371371

372+
// Dispose git operations' thread
373+
GitHelpers.TryDispose();
374+
372375
// Destroy cached properties windows
373376
FilePropertiesHelpers.DestroyCachedWindows();
374377
AppModel.IsMainWindowClosed = true;

src/Files.App/Data/Models/CurrentInstanceViewModel.cs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -165,27 +165,15 @@ public string? GitRepositoryPath
165165
set
166166
{
167167
if (SetProperty(ref gitRepositoryPath, value))
168-
{
169168
OnPropertyChanged(nameof(IsGitRepository));
170-
OnPropertyChanged(nameof(GitBranchName));
171-
}
172169
}
173170
}
174171

172+
private string gitBranchName = string.Empty;
175173
public string GitBranchName
176174
{
177-
get
178-
{
179-
if (IsGitRepository)
180-
return GitHelpers.GetRepositoryHeadName(gitRepositoryPath);
181-
182-
return string.Empty;
183-
}
184-
}
185-
186-
public void UpdateCurrentBranchName()
187-
{
188-
OnPropertyChanged(nameof(GitBranchName));
175+
get => gitBranchName;
176+
set => SetProperty(ref gitBranchName, value);
189177
}
190178
}
191179
}

src/Files.App/Data/Models/DirectoryPropertiesViewModel.cs

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public class DirectoryPropertiesViewModel : ObservableObject
1818

1919
private readonly ObservableCollection<string> _remoteBranches = new();
2020

21+
public bool IsBranchesFlyoutExpaned { get; set; } = false;
22+
2123
private string? _DirectoryItemCount;
2224
public string? DirectoryItemCount
2325
{
@@ -92,38 +94,46 @@ public DirectoryPropertiesViewModel()
9294
=> GitHelpers.CreateNewBranchAsync(_gitRepositoryPath!, _localBranches[ACTIVE_BRANCH_INDEX]));
9395
}
9496

95-
public void UpdateGitInfo(bool isGitRepository, string? repositoryPath, BranchItem[] branches)
97+
public void UpdateGitInfo(bool isGitRepository, string? repositoryPath, BranchItem? head)
9698
{
9799
GitBranchDisplayName = isGitRepository &&
98-
branches.Any() &&
99-
!(ContentPageContext.ShellPage!.InstanceViewModel.IsPageTypeSearchResults)
100-
? branches[ACTIVE_BRANCH_INDEX].Name
100+
head is not null &&
101+
!ContentPageContext.ShellPage!.InstanceViewModel.IsPageTypeSearchResults
102+
? head.Name
101103
: null;
102104

103105
_gitRepositoryPath = repositoryPath;
104-
ShowLocals = true;
106+
107+
// Change ShowLocals value only if branches flyout is closed
108+
if (!IsBranchesFlyoutExpaned)
109+
ShowLocals = true;
105110

106-
var behind = branches.Any() ? branches[0].BehindBy ?? 0 : 0;
107-
var ahead = branches.Any() ? branches[0].AheadBy ?? 0 : 0;
111+
var behind = head is not null ? head.BehindBy ?? 0 : 0;
112+
var ahead = head is not null ? head.AheadBy ?? 0 : 0;
108113

109114
ExtendedStatusInfo = string.Format("GitSyncStatusExtendedInfo".GetLocalizedResource(), ahead, behind);
110115
StatusInfo = $"{ahead} / {behind}";
116+
}
111117

112-
if (isGitRepository)
113-
{
114-
_localBranches.Clear();
115-
_remoteBranches.Clear();
118+
public async Task LoadBranches()
119+
{
120+
if (string.IsNullOrEmpty(_gitRepositoryPath))
121+
return;
116122

117-
foreach (var branch in branches)
118-
{
119-
if (branch.IsRemote)
120-
_remoteBranches.Add(branch.Name);
121-
else
122-
_localBranches.Add(branch.Name);
123-
}
123+
var branches = await GitHelpers.GetBranchesNames(_gitRepositoryPath);
124+
125+
_localBranches.Clear();
126+
_remoteBranches.Clear();
124127

125-
SelectedBranchIndex = ACTIVE_BRANCH_INDEX;
128+
foreach (var branch in branches)
129+
{
130+
if (branch.IsRemote)
131+
_remoteBranches.Add(branch.Name);
132+
else
133+
_localBranches.Add(branch.Name);
126134
}
135+
136+
SelectedBranchIndex = ShowLocals ? ACTIVE_BRANCH_INDEX : -1;
127137
}
128138
}
129139
}

src/Files.App/Data/Models/ItemViewModel.cs

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,13 @@ public GitProperties EnabledGitProperties
7777
{
7878
if (SetProperty(ref _EnabledGitProperties, value) && value is not GitProperties.None)
7979
{
80-
filesAndFolders.ToList().ForEach(async item => {
80+
filesAndFolders.ToList().ForEach(async item =>
81+
{
8182
if (item is GitItem gitItem &&
8283
(!gitItem.StatusPropertiesInitialized && value is GitProperties.All or GitProperties.Status
8384
|| !gitItem.CommitPropertiesInitialized && value is GitProperties.All or GitProperties.Commit))
8485
{
85-
try
86-
{
87-
await Task.Run(async () => await LoadGitPropertiesAsync(gitItem, loadPropsCTS));
88-
}
89-
catch (OperationCanceledException)
90-
{
91-
// Ignored
92-
}
86+
await LoadGitPropertiesAsync(gitItem);
9387
}
9488
});
9589
}
@@ -169,7 +163,7 @@ public async Task SetWorkingDirectoryAsync(string? value)
169163
}
170164

171165
GitDirectory = GitHelpers.GetGitRepositoryPath(WorkingDirectory, pathRoot);
172-
IsValidGitDirectory = !string.IsNullOrEmpty(GitHelpers.GetRepositoryHeadName(GitDirectory));
166+
IsValidGitDirectory = !string.IsNullOrEmpty((await GitHelpers.GetRepositoryHead(GitDirectory))?.Name);
173167

174168
OnPropertyChanged(nameof(WorkingDirectory));
175169
}
@@ -1229,9 +1223,6 @@ await SafetyExtensions.IgnoreExceptions(() =>
12291223
gp.InitializeExtendedGroupHeaderInfoAsync();
12301224
}));
12311225
}
1232-
1233-
if (EnabledGitProperties != GitProperties.None && item is GitItem gitItem)
1234-
await LoadGitPropertiesAsync(gitItem, cts);
12351226
}
12361227
}, cts.Token);
12371228
}
@@ -1245,57 +1236,70 @@ await SafetyExtensions.IgnoreExceptions(() =>
12451236
}
12461237
}
12471238

1248-
private async Task LoadGitPropertiesAsync(GitItem gitItem, CancellationTokenSource cts)
1239+
public async Task LoadGitPropertiesAsync(GitItem gitItem)
12491240
{
12501241
var getStatus = EnabledGitProperties is GitProperties.All or GitProperties.Status && !gitItem.StatusPropertiesInitialized;
12511242
var getCommit = EnabledGitProperties is GitProperties.All or GitProperties.Commit && !gitItem.CommitPropertiesInitialized;
1252-
1243+
12531244
if (!getStatus && !getCommit)
12541245
return;
12551246

1256-
if (GitHelpers.IsRepositoryEx(gitItem.ItemPath, out var repoPath) &&
1257-
!string.IsNullOrEmpty(repoPath))
1258-
{
1259-
cts.Token.ThrowIfCancellationRequested();
1260-
1261-
if (getStatus)
1262-
gitItem.StatusPropertiesInitialized = true;
1263-
1264-
if (getCommit)
1265-
gitItem.CommitPropertiesInitialized = true;
1247+
var cts = loadPropsCTS;
12661248

1267-
await SafetyExtensions.IgnoreExceptions(() =>
1249+
try
1250+
{
1251+
await Task.Run(async () =>
12681252
{
1269-
return dispatcherQueue.EnqueueOrInvokeAsync(() =>
1253+
1254+
if (GitHelpers.IsRepositoryEx(gitItem.ItemPath, out var repoPath) &&
1255+
!string.IsNullOrEmpty(repoPath))
12701256
{
1271-
var repo = new Repository(repoPath);
1272-
GitItemModel gitItemModel = GitHelpers.GetGitInformationForItem(repo, gitItem.ItemPath, getStatus, getCommit);
1257+
cts.Token.ThrowIfCancellationRequested();
12731258

12741259
if (getStatus)
1275-
{
1276-
gitItem.UnmergedGitStatusIcon = gitItemModel.Status switch
1277-
{
1278-
ChangeKind.Added => (Microsoft.UI.Xaml.Style)Microsoft.UI.Xaml.Application.Current.Resources["ColorIconGitAdded"],
1279-
ChangeKind.Deleted => (Microsoft.UI.Xaml.Style)Microsoft.UI.Xaml.Application.Current.Resources["ColorIconGitDeleted"],
1280-
ChangeKind.Modified => (Microsoft.UI.Xaml.Style)Microsoft.UI.Xaml.Application.Current.Resources["ColorIconGitModified"],
1281-
ChangeKind.Untracked => (Microsoft.UI.Xaml.Style)Microsoft.UI.Xaml.Application.Current.Resources["ColorIconGitUntracked"],
1282-
_ => null,
1283-
};
1284-
gitItem.UnmergedGitStatusName = gitItemModel.StatusHumanized;
1285-
}
1260+
gitItem.StatusPropertiesInitialized = true;
1261+
12861262
if (getCommit)
1263+
gitItem.CommitPropertiesInitialized = true;
1264+
1265+
await SafetyExtensions.IgnoreExceptions(() =>
12871266
{
1288-
gitItem.GitLastCommitDate = gitItemModel.LastCommit?.Author.When;
1289-
gitItem.GitLastCommitMessage = gitItemModel.LastCommit?.MessageShort;
1290-
gitItem.GitLastCommitAuthor = gitItemModel.LastCommit?.Author.Name;
1291-
gitItem.GitLastCommitSha = gitItemModel.LastCommit?.Sha.Substring(0, 7);
1292-
gitItem.GitLastCommitFullSha = gitItemModel.LastCommit?.Sha;
1293-
}
1267+
return dispatcherQueue.EnqueueOrInvokeAsync(() =>
1268+
{
1269+
var repo = new Repository(repoPath);
1270+
GitItemModel gitItemModel = GitHelpers.GetGitInformationForItem(repo, gitItem.ItemPath, getStatus, getCommit);
12941271

1295-
repo.Dispose();
1296-
},
1297-
Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
1298-
});
1272+
if (getStatus)
1273+
{
1274+
gitItem.UnmergedGitStatusIcon = gitItemModel.Status switch
1275+
{
1276+
ChangeKind.Added => (Microsoft.UI.Xaml.Style)Microsoft.UI.Xaml.Application.Current.Resources["ColorIconGitAdded"],
1277+
ChangeKind.Deleted => (Microsoft.UI.Xaml.Style)Microsoft.UI.Xaml.Application.Current.Resources["ColorIconGitDeleted"],
1278+
ChangeKind.Modified => (Microsoft.UI.Xaml.Style)Microsoft.UI.Xaml.Application.Current.Resources["ColorIconGitModified"],
1279+
ChangeKind.Untracked => (Microsoft.UI.Xaml.Style)Microsoft.UI.Xaml.Application.Current.Resources["ColorIconGitUntracked"],
1280+
_ => null,
1281+
};
1282+
gitItem.UnmergedGitStatusName = gitItemModel.StatusHumanized;
1283+
}
1284+
if (getCommit)
1285+
{
1286+
gitItem.GitLastCommitDate = gitItemModel.LastCommit?.Author.When;
1287+
gitItem.GitLastCommitMessage = gitItemModel.LastCommit?.MessageShort;
1288+
gitItem.GitLastCommitAuthor = gitItemModel.LastCommit?.Author.Name;
1289+
gitItem.GitLastCommitSha = gitItemModel.LastCommit?.Sha.Substring(0, 7);
1290+
gitItem.GitLastCommitFullSha = gitItemModel.LastCommit?.Sha;
1291+
}
1292+
1293+
repo.Dispose();
1294+
},
1295+
Microsoft.UI.Dispatching.DispatcherQueuePriority.Low);
1296+
});
1297+
}
1298+
}, cts.Token);
1299+
}
1300+
catch (OperationCanceledException)
1301+
{
1302+
// Ignored
12991303
}
13001304
}
13011305

@@ -1439,7 +1443,7 @@ private async Task RapidAddItemsToCollectionAsync(string? path, LibraryItem? lib
14391443
IsTypeCloudDrive = syncStatus != CloudDriveSyncStatus.NotSynced && syncStatus != CloudDriveSyncStatus.Unknown,
14401444
IsTypeGitRepository = IsValidGitDirectory
14411445
});
1442-
1446+
14431447
if (!HasNoWatcher)
14441448
WatchForDirectoryChanges(path, syncStatus);
14451449
if (IsValidGitDirectory)

src/Files.App/Services/Settings/FoldersSettingsService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ public bool ShowSizeColumn
197197

198198
public bool ShowGitStatusColumn
199199
{
200-
get => Get(true);
200+
get => Get(false);
201201
set => Set(value);
202202
}
203203

src/Files.App/UserControls/StatusBarControl.xaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,10 @@
296296
</Button.Content>
297297

298298
<Button.Flyout>
299-
<Flyout x:Name="BranchesFlyout" Opening="BranchesFlyout_Opening">
299+
<Flyout
300+
x:Name="BranchesFlyout"
301+
Closing="BranchesFlyout_Closing"
302+
Opening="BranchesFlyout_Opening">
300303
<Grid
301304
Width="300"
302305
Height="340"

src/Files.App/UserControls/StatusBarControl.xaml.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,18 +45,28 @@ public StatusBarControl()
4545
InitializeComponent();
4646
}
4747

48-
private void BranchesFlyout_Opening(object sender, object e)
48+
private async void BranchesFlyout_Opening(object _, object e)
4949
{
5050
if (DirectoryPropertiesViewModel is null)
5151
return;
5252

53+
DirectoryPropertiesViewModel.IsBranchesFlyoutExpaned = true;
5354
DirectoryPropertiesViewModel.ShowLocals = true;
55+
await DirectoryPropertiesViewModel.LoadBranches();
5456
DirectoryPropertiesViewModel.SelectedBranchIndex = DirectoryPropertiesViewModel.ACTIVE_BRANCH_INDEX;
5557
}
5658

5759
private void BranchesList_ItemClick(object sender, ItemClickEventArgs e)
5860
{
5961
BranchesFlyout.Hide();
6062
}
63+
64+
private void BranchesFlyout_Closing(object _, object e)
65+
{
66+
if (DirectoryPropertiesViewModel is null)
67+
return;
68+
69+
DirectoryPropertiesViewModel.IsBranchesFlyoutExpaned = false;
70+
}
6171
}
6272
}

0 commit comments

Comments
 (0)