summary refs log tree commit diff
path: root/GitRepoViewer/WebRepoSource.cs
diff options
context:
space:
mode:
Diffstat (limited to 'GitRepoViewer/WebRepoSource.cs')
-rw-r--r--GitRepoViewer/WebRepoSource.cs70
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