diff options
Diffstat (limited to 'GitRepoViewer/WebRepoSource.cs')
-rw-r--r-- | GitRepoViewer/WebRepoSource.cs | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/GitRepoViewer/WebRepoSource.cs b/GitRepoViewer/WebRepoSource.cs new file mode 100644 index 0000000..d0770ec --- /dev/null +++ b/GitRepoViewer/WebRepoSource.cs @@ -0,0 +1,70 @@ +using Blazored.SessionStorage; +using LibGit.Extensions; +using LibGit.Interfaces; +using Microsoft.AspNetCore.Components.WebAssembly.Http; + + +namespace GitRepoViewer; + +public class WebRepoSource : IRepoSource +{ + private const bool _debug = false; + public WebRepoSource(string basePath) + { + BasePath = basePath; + } + + + public string BasePath { get; set; } + public ISessionStorageService? SessionStorage { private get; set; } + + public async Task<Stream> GetFileStream(string path) + { + if(_debug)Console.WriteLine("Fetching file: " + Path.Join(BasePath, path)); + + var _path = Path.Join(BasePath, path); + + if (SessionStorage != null && await SessionStorage.ContainKeyAsync(_path)) + { + //Console.WriteLine("Found file in session storage: " + _path); + return new MemoryStream((await SessionStorage.GetItemAsync<IEnumerable<byte>>(_path)).ToArray()); + } + + var request = new HttpRequestMessage(HttpMethod.Get, _path); + + // request.SetBrowserRequestMode(BrowserRequestMode.NoCors); + + var client = new HttpClient(); + + var response = await client.SendAsync(request); + + if(!response.IsSuccessStatusCode) throw new Exception("Failed to fetch file: " + _path); + if(SessionStorage != null && response.Content.Headers.ContentLength.HasValue && response.Content.Headers.ContentLength.Value < 1_000_000 && !noCachePathPrefixes.Any(prefix => path.StartsWith(prefix))) + { + Console.WriteLine($"Liberally caching file: {_path} ({response.Content.Headers.ContentLength.Value} bytes)"); + var stream = await response.Content.ReadAsStreamAsync(); + await SessionStorage.SetItemAsync(_path, stream.Peek(response.Content.Headers.ContentLength.Value)); + return stream; + } + if(!noCachePathPrefixes.Any(prefix => path.StartsWith(prefix))) + Console.WriteLine($"Not caching file: {_path} ({response.Content.Headers.ContentLength.Value} bytes): blacklisted prefix"); + return await response.Content.ReadAsStreamAsync(); + } + + public Task<Stream> GetObjectStreamById(string objectId) + { + Console.WriteLine("Fetching object: " + objectId + " from " + BasePath + "objects/" + objectId[..2] + "/" + objectId[2..] + ""); + return GetFileStream(Path.Join("objects", objectId[..2], objectId[2..])); + } + + public async Task<bool> HasObjectCached(string objectId) + { + + var _path = Path.Join(BasePath, "objects/", objectId[..2], "/", objectId[2..]); + + return SessionStorage != null && await SessionStorage.ContainKeyAsync(_path); + } + + + private static readonly string[] noCachePathPrefixes = { "HEAD", "info", "refs" }; +} \ No newline at end of file |