-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathRepo.cs
More file actions
134 lines (115 loc) · 4.92 KB
/
Repo.cs
File metadata and controls
134 lines (115 loc) · 4.92 KB
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace thcrap_cs_lib
{
public class RepoPatch
{
public Repo Repo { get; set; }
public string Id { get; set; }
public string Title { get; set; }
// Initialized when calling AddToStack
public string Archive { get; set; }
public RepoPatch(Repo repo, ThcrapDll.repo_patch_t patch)
{
this.Repo = repo;
this.Id = ThcrapHelper.PtrToStringUTF8(patch.patch_id);
this.Title = ThcrapHelper.PtrToStringUTF8(patch.title);
}
private RepoPatch FindDependency(List<Repo> repoList, ThcrapDll.patch_desc_t dep)
{
string repo_id = ThcrapHelper.PtrToStringUTF8(dep.repo_id);
string patch_id = ThcrapHelper.PtrToStringUTF8(dep.patch_id);
// If we know the repo name, use it
if (repo_id != null)
return repoList.Find((Repo it) => it.Id == repo_id)?.Patches.Find((RepoPatch it) => it.Id == patch_id);
// Try in the current repo
RepoPatch patch = this.Repo.Patches.Find((RepoPatch it) => it.Id == patch_id);
if (patch != null)
return patch;
// Fall back to looking in every repo
foreach (var repo in repoList)
{
patch = repo.Patches.Find((RepoPatch it) => it.Id == patch_id);
if (patch != null)
return patch;
}
// Didn't find anything
return null;
}
private void LoadDependencies(List<Repo> repoList, HashSet<RepoPatch> knownPatches, IntPtr dependenciesPtr)
{
if (dependenciesPtr == IntPtr.Zero)
return;
var deps = ThcrapHelper.ParseNullTerminatedStructArray<ThcrapDll.patch_desc_t>(dependenciesPtr, 4);
foreach (var dep in deps)
{
RepoPatch patch = FindDependency(repoList, dep);
if (patch != null)
patch.AddToStack(repoList, knownPatches);
}
}
public void AddToStack(List<Repo> repoList, HashSet<RepoPatch> knownPatches)
{
if (knownPatches.Contains(this))
return;
knownPatches.Add(this);
ThcrapDll.patch_desc_t patch_desc;
patch_desc.repo_id = ThcrapHelper.StringUTF8ToPtr(this.Repo.Id);
patch_desc.patch_id = ThcrapHelper.StringUTF8ToPtr(this.Id);
IntPtr patch_desc_ptr = ThcrapHelper.AllocStructure(patch_desc);
ThcrapDll.patch_t patch_info = ThcrapDll.patch_bootstrap_wrapper(patch_desc_ptr, this.Repo.repo_ptr);
this.Archive = ThcrapHelper.PtrToStringUTF8(patch_info.archive);
ThcrapDll.patch_t patch_full = ThcrapDll.patch_init(this.Archive, IntPtr.Zero, 0);
this.LoadDependencies(repoList, knownPatches, patch_full.dependencies);
IntPtr patch_full_ptr = ThcrapHelper.AllocStructure(patch_full);
ThcrapDll.stack_add_patch(patch_full_ptr);
Marshal.FreeHGlobal(patch_desc.patch_id);
Marshal.FreeHGlobal(patch_desc.repo_id);
ThcrapHelper.FreeStructure<ThcrapDll.patch_desc_t>(patch_desc_ptr);
ThcrapHelper.FreeStructure<ThcrapDll.patch_t>(patch_full_ptr);
}
}
public class Repo
{
public IntPtr repo_ptr;
public string Id { get; set; }
public string Title { get; set; }
public List<RepoPatch> Patches { get; set; }
public static List<Repo> Discovery(string start_url)
{
IntPtr repo_list = ThcrapDll.RepoDiscover_wrapper(start_url);
if (repo_list == IntPtr.Zero)
return new List<Repo>();
var out_list = new List<Repo>();
int current_repo = 0;
IntPtr repo_ptr = Marshal.ReadIntPtr(repo_list, current_repo * IntPtr.Size);
while (repo_ptr != IntPtr.Zero)
{
out_list.Add(new Repo(repo_ptr));
current_repo++;
repo_ptr = Marshal.ReadIntPtr(repo_list, current_repo * IntPtr.Size);
}
ThcrapDll.thcrap_free(repo_list);
return out_list;
}
private Repo(IntPtr repo_ptr)
{
ThcrapDll.repo_t repo = Marshal.PtrToStructure<ThcrapDll.repo_t>(repo_ptr);
Id = ThcrapHelper.PtrToStringUTF8(repo.id);
Title = ThcrapHelper.PtrToStringUTF8(repo.title);
this.repo_ptr = repo_ptr;
var patchesList = ThcrapHelper.ParseNullTerminatedStructArray<ThcrapDll.repo_patch_t>(repo.patches);
Patches = new List<RepoPatch>();
foreach (var it in patchesList)
Patches.Add(new RepoPatch(this, it));
}
~Repo()
{
ThcrapDll.RepoFree(repo_ptr);
}
}
}