summary refs log tree commit diff
path: root/GitRepoViewer/WebRepoSource.cs
blob: d0770ece3e447df22c948a91ae9397f451763fd1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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" };
}