summary refs log tree commit diff
path: root/GitRepoViewer/Pages
diff options
context:
space:
mode:
Diffstat (limited to 'GitRepoViewer/Pages')
-rw-r--r--GitRepoViewer/Pages/Counter.razor19
-rw-r--r--GitRepoViewer/Pages/FetchData.razor60
-rw-r--r--GitRepoViewer/Pages/GitLog.razor121
-rw-r--r--GitRepoViewer/Pages/Index.razor9
-rw-r--r--GitRepoViewer/Pages/TestPage.razor225
5 files changed, 434 insertions, 0 deletions
diff --git a/GitRepoViewer/Pages/Counter.razor b/GitRepoViewer/Pages/Counter.razor
new file mode 100644
index 0000000..372905f
--- /dev/null
+++ b/GitRepoViewer/Pages/Counter.razor
@@ -0,0 +1,19 @@
+@page "/counter"
+
+<PageTitle>Counter</PageTitle>
+
+<h1>Counter</h1>
+
+<p role="status">Current count: @currentCount</p>
+
+<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
+
+@code {
+    private int currentCount = 0;
+
+    private void IncrementCount()
+    {
+        currentCount++;
+    }
+
+}
\ No newline at end of file
diff --git a/GitRepoViewer/Pages/FetchData.razor b/GitRepoViewer/Pages/FetchData.razor
new file mode 100644
index 0000000..d39268f
--- /dev/null
+++ b/GitRepoViewer/Pages/FetchData.razor
@@ -0,0 +1,60 @@
+@page "/fetchdata"
+@inject HttpClient Http
+
+<PageTitle>Weather forecast</PageTitle>
+
+<h1>Weather forecast</h1>
+
+<p>This component demonstrates fetching data from the server.</p>
+
+@if (forecasts == null)
+{
+    <p>
+        <em>Loading...</em>
+    </p>
+}
+else
+{
+    <table class="table">
+        <thead>
+        <tr>
+            <th>Date</th>
+            <th>Temp. (C)</th>
+            <th>Temp. (F)</th>
+            <th>Summary</th>
+        </tr>
+        </thead>
+        <tbody>
+        @foreach (var forecast in forecasts)
+        {
+            <tr>
+                <td>@forecast.Date.ToShortDateString()</td>
+                <td>@forecast.TemperatureC</td>
+                <td>@forecast.TemperatureF</td>
+                <td>@forecast.Summary</td>
+            </tr>
+        }
+        </tbody>
+    </table>
+}
+
+@code {
+    private WeatherForecast[]? forecasts;
+
+    protected override async Task OnInitializedAsync()
+    {
+        forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json");
+    }
+
+    public class WeatherForecast
+    {
+        public DateOnly Date { get; set; }
+
+        public int TemperatureC { get; set; }
+
+        public string? Summary { get; set; }
+
+        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+    }
+
+}
\ No newline at end of file
diff --git a/GitRepoViewer/Pages/GitLog.razor b/GitRepoViewer/Pages/GitLog.razor
new file mode 100644
index 0000000..e518bb6
--- /dev/null
+++ b/GitRepoViewer/Pages/GitLog.razor
@@ -0,0 +1,121 @@
+@page "/GitLog"
+@using System.Web
+@using LibGit
+@using LibGit.Extensions
+<h3>GitLog</h3>
+<p>Repo: @Repo</p>
+
+@if (heads.Count > 0)
+{
+    <p>
+        Revision:
+        <details>
+            <summary>@Rev</summary>
+        </details>
+    </p>
+}
+
+@if (commits != null)
+{
+    <table class="table">
+        <thead>
+        <tr>
+            <th>Heads</th>
+            <th>Commit</th>
+            <th>Author</th>
+            <th>Message</th>
+        </tr>
+        </thead>
+        <tbody>
+            @foreach (var commit in commits)
+            {
+                <tr>
+                    <td>
+                        @foreach (var _ref in heads.Where(x=>x.CommitId == commit.CommitId))
+                        {
+                            <p>@_ref.Name</p>
+                        }
+                    </td>
+                    <td>@commit.CommitId[..7]</td>
+                    <td>@commit.AuthorName</td>
+                    <td>@commit.Message</td>
+                </tr>
+            }
+        </tbody>
+    </table>
+}
+
+@code {
+
+    string? Repo { get; set; }
+    string? Rev { get; set; }
+    
+    List<CommitObject> commits = new();
+    List<GitRef> heads = new();
+
+    protected override async Task OnInitializedAsync()
+    {
+        var query = new Uri(NavigationManager.Uri).Query;
+        var queryDictionary = HttpUtility.ParseQueryString(query);
+        if((Repo = queryDictionary["repo"]) == null)
+        {
+            return;
+        }
+        
+        var repo = new GitRepo(new WebRepoSource(queryDictionary["repo"])
+        {
+            SessionStorage = sessionStorage
+        });
+        
+        if((Rev = queryDictionary["rev"]) == null)
+        {
+            Rev = "HEAD";
+        }
+
+        var ss = new SemaphoreSlim(2,2);
+        
+        var _heads = repo.GetRefs().GetAsyncEnumerator();
+        while (await _heads.MoveNextAsync())
+        {
+            heads.Add(_heads.Current);
+            var isCached = await ((WebRepoSource)repo.RepoSource).HasObjectCached(_heads.Current.CommitId);
+            Console.WriteLine(_heads.Current.Name+ " - cache miss: " + !isCached);
+            if (!isCached)
+            {
+
+                var _c = _heads.Current.CommitId;
+#pragma warning disable CS4014
+                Task.Run(async () =>
+#pragma warning restore CS4014
+                {
+                    await ss.WaitAsync();
+                    Console.WriteLine("hi from task");
+                    var a = new GitRepo(new WebRepoSource(queryDictionary["repo"])
+                    {
+                        SessionStorage = sessionStorage
+                    }).GetCommits(_c).GetAsyncEnumerator();
+                    while (
+                        await a.MoveNextAsync() 
+                        && !await ((WebRepoSource)repo.RepoSource)
+                            .HasObjectCached(a.Current.CommitId)
+                    ) Console.WriteLine($"Prefetched commit {a.Current.CommitId} with {a.Current.ParentIds.Count()} parents");
+                    Console.WriteLine($"Reached already-cached log: {a.Current.CommitId}");
+                    ss.Release();
+                });
+            }
+        }
+        
+
+        var log = repo.GetCommits(heads.First(x=>x.Name == Rev).CommitId).GetAsyncEnumerator();
+        while (await log.MoveNextAsync())
+        {
+            commits.Add(log.Current);
+            if (commits.Count % 50 == 0)
+            {
+                StateHasChanged();
+                await Task.Delay(1);
+            }
+        }
+        
+    }
+}
\ No newline at end of file
diff --git a/GitRepoViewer/Pages/Index.razor b/GitRepoViewer/Pages/Index.razor
new file mode 100644
index 0000000..66ce12c
--- /dev/null
+++ b/GitRepoViewer/Pages/Index.razor
@@ -0,0 +1,9 @@
+@page "/"
+
+<PageTitle>Index</PageTitle>
+
+<h1>Hello, world!</h1>
+
+Welcome to your new app.
+
+<SurveyPrompt Title="How is Blazor working for you?"/>
\ No newline at end of file
diff --git a/GitRepoViewer/Pages/TestPage.razor b/GitRepoViewer/Pages/TestPage.razor
new file mode 100644
index 0000000..2d29609
--- /dev/null
+++ b/GitRepoViewer/Pages/TestPage.razor
@@ -0,0 +1,225 @@
+@page "/TestPage"
+@using System.Collections.Concurrent
+@using Blazored.SessionStorage
+@using LibGit
+@using LibGit.Extensions
+
+<h3>TestPage</h3>
+
+<p>
+    Repo URL:
+    <InputText @bind-Value="RepoUrl"></InputText>
+</p>
+
+
+@if (!IsValidRepo)
+{
+    <p>Invalid Repo</p>
+    <p>This can happen if the repo isn't reachable, doesn't support dumb-http transport or only provides packs.</p>
+    <p>In the latter case, it might be worth running this script in that directory on the server, if you have permission to:</p>
+    <pre>mv objects/pack/ objects/pack-tmp; for pack in objects/pack-tmp/*.pack; do cat $pack | git unpack-objects; done; mv objects/pack-tmp/ objects/pack</pre>
+}
+else
+{
+    <p>
+
+        @code {
+
+            Dictionary<string, string> knownRefPrefixes = new Dictionary<string, string>()
+            {
+                { "refs/heads/", "Head" },
+                { "refs/pull/", "Pull" },
+                { "refs/tags/", "Tag" },
+                { "refs/remotes/", "Remote" },
+                { "refs/notes/", "Note" },
+                { "refs/stash", "Stash" },
+                { "refs/replace/", "Replace" },
+                { "refs/wip/", "WIP" },
+                { "refs/keep-around/", "Keep Around" },
+                { "refs/merges/", "Merge" },
+            };
+
+        }
+
+
+        @foreach (var (prefix, friendlyName) in knownRefPrefixes.Where(x => Refs.Any(y => y.Key.StartsWith(x.Key))))
+        {
+            <span>@friendlyName:</span>
+            <select @bind="CurrentRef">
+                @foreach (var refName in Refs.Where(x => x.Key.StartsWith(prefix)).Select(x => x.Key.Replace(prefix, "")).OrderBy(x => x))
+                {
+                    <option value="@(prefix + refName)">@refName</option>
+                }
+            </select>
+        }
+
+
+        @* Other: *@
+        @* <select @bind="CurrentRef"> *@
+        @* @foreach (var refName in Refs.Where(x => x.Key.StartsWith("refs/pull")).Select(x => x.Key.Replace("refs/pull/", "")).OrderBy(x => x)) *@
+        @* { *@
+        @* <option value="refs/pull/@refName">@refName</option> *@
+        @* } *@
+        @* </select> *@
+    </p>
+
+    <p>@_commits.Count commits</p>
+
+    <table>
+        <thead>--files--</thead>
+        <tbody>
+        <tr>
+    
+        </tr>
+        </tbody>
+    </table>
+    <table>
+        @foreach (var commit in _commits.Values.OrderByDescending(x => x.CommitDate))
+        {
+            <tr>
+                @* <td>@commit.Length</td> *@
+                <td style="width: 50%;">@commit.Message</td>
+                <td style="width: 25%;">@commit.CommitterName</td>
+                <td style="width: 25%;">@commit.CommitDate</td>
+            </tr>
+        }
+    </table>
+
+    @if (data != null)
+    {
+        <pre style="max-width: 100%; white-space: pre-wrap;">
+            @if (data is string)
+            {
+                @data
+            }
+            else
+            {
+                @ObjectExtensions.ToJson(data, unsafeContent: true)
+            }
+        </pre>
+    }
+}
+
+@code {
+
+    GitRepo repo { get; set; }
+    readonly ConcurrentDictionary<string, CommitObject> _commits = new();
+    bool IsValidRepo { get; set; } = true;
+    Dictionary<string, string> Refs = new();
+
+    string CurrentRef
+    {
+        get => _currentRef;
+        set
+        {
+            _currentRef = value;
+            _commits.Clear();
+            RefChanged();
+        }
+    }
+
+    string RepoUrl
+    {
+        get => _repoUrl;
+        set
+        {
+            _repoUrl = value;
+            if (!value.StartsWith("http"))
+            {
+                _repoUrl = NavigationManager.BaseUri + value;
+            }
+            _commits.Clear();
+            Refs.Clear();
+            RepoChanged();
+        }
+    }
+
+    dynamic data { get; set; }
+
+    protected override async Task OnInitializedAsync()
+    {
+        RepoUrl = "fosscord-server.git";
+    }
+
+    protected async Task RepoChanged()
+    {
+        Console.WriteLine("Repo changed!");
+        repo = new GitRepo(new WebRepoSource(RepoUrl));
+        ((WebRepoSource)repo.RepoSource).SessionStorage = sessionStorage;
+        var client = new HttpClient();
+        var response = await client.GetAsync(RepoUrl + "/info/refs");
+        if (!response.IsSuccessStatusCode)
+        {
+            IsValidRepo = false;
+            StateHasChanged();
+            return;
+        }
+        IsValidRepo = true;
+        var content = await response.Content.ReadAsStringAsync();
+        data = content;
+        StateHasChanged();
+        var lines = content.Split("\n").ToList();
+        var delay = Math.Max(lines.Count / 100, 50);
+        var index = 0;
+
+        while (lines.Count > 0)
+        {
+            var line = lines[0];
+            lines.Remove(line);
+            if (line == "")
+            {
+                break;
+            }
+            var parts = line.Split("\t");
+            Refs.Add(parts[1], parts[0]);
+            data = new
+            {
+                index,
+                delay,
+                untilNext = delay - index % delay,
+                line,
+                lines,
+                refs = Refs
+            };
+            if (++index % delay == 0)
+            {
+                StateHasChanged();
+                await Task.Delay(1);
+            }
+        }
+        response = await client.GetAsync(RepoUrl + "/HEAD");
+        content = await response.Content.ReadAsStringAsync();
+        if (content.StartsWith("ref: "))
+            CurrentRef = content.Substring(5).Trim();
+        StateHasChanged();
+    }
+
+    protected async Task RefChanged(string refName = null)
+    {
+        string currentRef;
+        data = currentRef = Refs[CurrentRef];
+        Console.WriteLine($"Ref changed: {currentRef}");
+        StateHasChanged();
+    //await LoadObject(currentRef);
+        await LoadGitLogSince(currentRef);
+    }
+
+    protected async Task LoadGitLogSince(string refName)
+    {
+        _commits.Clear();
+        var commit = await repo.GetCommit(refName);
+        _commits.TryAdd(commit.CommitId, commit);
+        while (commit.ParentIds.Count > 0)
+        {
+            Console.WriteLine($"{commit.CommitId[..7]} | {commit.AuthorName.PadRight(16)} | {commit.Message.PadRight(32)[..32]} | {commit.TreeId}");
+    // var tree = await commit.GetTreeAsync();
+    // await PrintTreeRecursive(tree);
+
+            commit = await repo.GetCommit(commit.ParentIds.First());
+            await Task.Delay(1);
+        }
+    }
+
+    private string _repoUrl = "http://localhost:5194/fosscord-server.git";
+    private string _currentRef;
+}
\ No newline at end of file