Skip to content

Commit aa12ea5

Browse files
committed
enhance: try load lfs image from local cache first before loading it by git lfs smudge command
Signed-off-by: leo <[email protected]>
1 parent 7642651 commit aa12ea5

File tree

8 files changed

+82
-23
lines changed

8 files changed

+82
-23
lines changed

src/Commands/QueryGitCommonDir.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System.IO;
2+
using System.Threading.Tasks;
3+
4+
namespace SourceGit.Commands
5+
{
6+
public class QueryGitCommonDir : Command
7+
{
8+
public QueryGitCommonDir(string workDir)
9+
{
10+
WorkingDirectory = workDir;
11+
Args = "rev-parse --git-common-dir";
12+
RaiseError = false;
13+
}
14+
15+
public async Task<string> GetResultAsync()
16+
{
17+
var rs = await ReadToEndAsync().ConfigureAwait(false);
18+
if (!rs.IsSuccess || string.IsNullOrEmpty(rs.StdOut))
19+
return string.Empty;
20+
21+
var dir = rs.StdOut.Trim();
22+
if (Path.IsPathRooted(dir))
23+
return dir;
24+
return Path.GetFullPath(Path.Combine(WorkingDirectory, dir));
25+
}
26+
}
27+
}

src/Models/LFSObject.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Text.RegularExpressions;
1+
using System.IO;
2+
using System.Text.RegularExpressions;
23

34
namespace SourceGit.Models
45
{
@@ -10,6 +11,9 @@ public partial class LFSObject
1011
public string Oid { get; set; } = string.Empty;
1112
public long Size { get; set; } = 0;
1213

14+
public bool IsValid => !string.IsNullOrEmpty(Oid) && Size > 0;
15+
public string LocalFileInGitCommonDir => Path.Combine("lfs", "objects", Oid.Substring(0, 2), Oid.Substring(2, 2), Oid);
16+
1317
public static LFSObject Parse(string content)
1418
{
1519
var match = REG_FORMAT().Match(content);

src/ViewModels/CommitDetail.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ private async Task SetViewingBlobAsync(Models.Object file)
529529
{
530530
var imgDecoder = ImageSource.GetDecoder(file.Path);
531531
if (imgDecoder != Models.ImageDecoder.None)
532-
ViewRevisionFileContent = new RevisionLFSImage(_repo.FullPath, file.Path, lfs, imgDecoder);
532+
ViewRevisionFileContent = new RevisionLFSImage(_repo, file.Path, lfs, imgDecoder);
533533
else
534534
ViewRevisionFileContent = new Models.RevisionLFSObject() { Object = lfs };
535535
}

src/ViewModels/FileHistories.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ private async Task<object> GetRevisionFileContentAsync(Models.Object obj)
124124
var imgDecoder = ImageSource.GetDecoder(_file);
125125
if (imgDecoder != Models.ImageDecoder.None)
126126
{
127-
var combined = new RevisionLFSImage(_repo.FullPath, _file, lfs, imgDecoder);
127+
var combined = new RevisionLFSImage(_repo, _file, lfs, imgDecoder);
128128
return new FileHistoriesRevisionFile(_file, combined, true);
129129
}
130130

src/ViewModels/ImageSource.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Runtime.InteropServices;
55
using System.Threading.Tasks;
6+
67
using Avalonia;
78
using Avalonia.Media.Imaging;
89
using Avalonia.Platform;
@@ -49,10 +50,7 @@ public static async Task<ImageSource> FromRevisionAsync(string repo, string revi
4950

5051
public static async Task<ImageSource> FromLFSObjectAsync(string repo, Models.LFSObject lfs, Models.ImageDecoder decoder)
5152
{
52-
if (string.IsNullOrEmpty(lfs.Oid) || lfs.Size == 0)
53-
return new ImageSource(null, 0);
54-
55-
var stream = await Commands.QueryFileContent.FromLFSAsync(repo, lfs.Oid, lfs.Size).ConfigureAwait(false);
53+
await using var stream = await Commands.QueryFileContent.FromLFSAsync(repo, lfs.Oid, lfs.Size).ConfigureAwait(false);
5654
return await Task.Run(() => LoadFromStream(stream, decoder)).ConfigureAwait(false);
5755
}
5856

src/ViewModels/LFSImageDiff.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Threading.Tasks;
1+
using System.IO;
2+
using System.Threading.Tasks;
3+
24
using Avalonia.Threading;
35
using CommunityToolkit.Mvvm.ComponentModel;
46

@@ -23,8 +25,9 @@ public LFSImageDiff(string repo, Models.LFSDiff lfs, Models.ImageDecoder decoder
2325

2426
Task.Run(async () =>
2527
{
26-
var oldImage = await ImageSource.FromLFSObjectAsync(repo, lfs.Old, decoder).ConfigureAwait(false);
27-
var newImage = await ImageSource.FromLFSObjectAsync(repo, lfs.New, decoder).ConfigureAwait(false);
28+
var commonDir = await new Commands.QueryGitCommonDir(repo).GetResultAsync().ConfigureAwait(false);
29+
var oldImage = await LoadAsync(repo, commonDir, lfs.Old, decoder).ConfigureAwait(false);
30+
var newImage = await LoadAsync(repo, commonDir, lfs.New, decoder).ConfigureAwait(false);
2831

2932
var img = new Models.ImageDiff()
3033
{
@@ -38,6 +41,17 @@ public LFSImageDiff(string repo, Models.LFSDiff lfs, Models.ImageDecoder decoder
3841
});
3942
}
4043

44+
private async Task<ImageSource> LoadAsync(string repo, string commonDir, Models.LFSObject lfs, Models.ImageDecoder decoder)
45+
{
46+
if (!lfs.IsValid)
47+
return new ImageSource(null, 0);
48+
49+
var file = Path.Combine(commonDir, lfs.LocalFileInGitCommonDir);
50+
return File.Exists(file) ?
51+
await ImageSource.FromFileAsync(file, decoder).ConfigureAwait(false) :
52+
await ImageSource.FromLFSObjectAsync(repo, lfs, decoder).ConfigureAwait(false);
53+
}
54+
4155
private Models.ImageDiff _image;
4256
}
4357
}

src/ViewModels/Repository.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public string GitDir
3030
get;
3131
}
3232

33+
public string GitCommonDir
34+
{
35+
get;
36+
}
37+
3338
public Models.RepositorySettings Settings
3439
{
3540
get => _settings;
@@ -504,17 +509,17 @@ public Repository(bool isBare, string path, string gitDir)
504509
if (!Path.IsPathRooted(commonDir))
505510
commonDir = new DirectoryInfo(Path.Combine(GitDir, commonDir)).FullName;
506511

507-
_gitCommonDir = commonDir;
512+
GitCommonDir = commonDir;
508513
}
509514
else
510515
{
511-
_gitCommonDir = GitDir;
516+
GitCommonDir = GitDir;
512517
}
513518
}
514519

515520
public void Open()
516521
{
517-
var settingsFile = Path.Combine(_gitCommonDir, "sourcegit.settings");
522+
var settingsFile = Path.Combine(GitCommonDir, "sourcegit.settings");
518523
if (File.Exists(settingsFile))
519524
{
520525
try
@@ -534,7 +539,7 @@ public void Open()
534539

535540
try
536541
{
537-
_watcher = new Models.Watcher(this, FullPath, _gitCommonDir);
542+
_watcher = new Models.Watcher(this, FullPath, GitCommonDir);
538543
}
539544
catch (Exception ex)
540545
{
@@ -574,7 +579,7 @@ public void Close()
574579
if (!_isWorktree)
575580
{
576581
_settings.LastCommitMessage = _workingCopy.CommitMessage;
577-
using var stream = File.Create(Path.Combine(_gitCommonDir, "sourcegit.settings"));
582+
using var stream = File.Create(Path.Combine(GitCommonDir, "sourcegit.settings"));
578583
JsonSerializer.Serialize(stream, _settings, JsonCodeGen.Default.RepositorySettings);
579584
}
580585

@@ -2039,7 +2044,6 @@ private void FetchInBackground(object sender)
20392044
}
20402045

20412046
private readonly bool _isWorktree = false;
2042-
private readonly string _gitCommonDir = null;
20432047
private Models.RepositorySettings _settings = null;
20442048
private Models.FilterMode _historiesFilterMode = Models.FilterMode.None;
20452049
private bool _hasAllowedSignersFile = false;

src/ViewModels/RevisionLFSImage.cs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.Threading.Tasks;
1+
using System.IO;
2+
using System.Threading.Tasks;
3+
24
using Avalonia.Threading;
35
using CommunityToolkit.Mvvm.ComponentModel;
46

@@ -17,16 +19,26 @@ public Models.RevisionImageFile Image
1719
private set => SetProperty(ref _image, value);
1820
}
1921

20-
public RevisionLFSImage(string repo, string file, Models.LFSObject lfs, Models.ImageDecoder decoder)
22+
public RevisionLFSImage(Repository repo, string file, Models.LFSObject lfs, Models.ImageDecoder decoder)
2123
{
2224
LFS = new Models.RevisionLFSObject() { Object = lfs };
2325

24-
Task.Run(async () =>
26+
if (lfs.IsValid)
27+
{
28+
Task.Run(async () =>
29+
{
30+
var localFile = Path.Combine(repo.GitCommonDir, lfs.LocalFileInGitCommonDir);
31+
var source = File.Exists(localFile) ?
32+
await ImageSource.FromFileAsync(localFile, decoder) :
33+
await ImageSource.FromLFSObjectAsync(repo.FullPath, lfs, decoder);
34+
var img = new Models.RevisionImageFile(file, source.Bitmap, source.Size);
35+
Dispatcher.UIThread.Post(() => Image = img);
36+
});
37+
}
38+
else
2539
{
26-
var source = await ImageSource.FromLFSObjectAsync(repo, lfs, decoder).ConfigureAwait(false);
27-
var img = new Models.RevisionImageFile(file, source.Bitmap, source.Size);
28-
Dispatcher.UIThread.Invoke(() => Image = img);
29-
});
40+
_image = new Models.RevisionImageFile(file, null, 0);
41+
}
3042
}
3143

3244
private Models.RevisionImageFile _image = null;

0 commit comments

Comments
 (0)