-
Notifications
You must be signed in to change notification settings - Fork 0
/
db-repository.adb
117 lines (104 loc) · 3.45 KB
/
db-repository.adb
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
with Ada.Text_IO;
with Ada.Directories;
use Ada.Directories;
with Bupstash_Types;
with Crypto.Decryption;
with Tree.Restorer;
with Tree.HTree_LL;
package body DB.Repository is
function Init(Key_File: in String; Repo_Directory: in String)
return Repository is
Num_Items: Integer := 0;
procedure Inc_Num_Items(Ent: in Directory_Entry_Type) is
pragma Unreferenced(Ent);
begin
Num_Items := Num_Items + 1;
end Inc_Num_Items;
Subdir: constant String := Compose(Repo_Directory, "items");
Flt: constant Filter_Type := (Ordinary_File => True,
others => False);
-- TODO z not so nice that we have to duplicate this just to
-- satisfy the limited type requirements...
KTMP: constant DB.Key.Key := DB.Key.Init(Key_File);
ST: Search_Type;
function Init_Next_Entry return DB.Item.Item is
DE: Directory_Entry_Type;
begin
if not More_Entries(ST) then
raise Constraint_Error with
"File(s) vanished while scanning.";
end if;
Get_Next_Entry(ST, DE);
return DB.Item.Init(KTMP, Full_Name(DE));
end Init_Next_Entry;
begin
Ada.Directories.Search(Subdir, "", Flt, Inc_Num_Items'Access);
Start_Search(ST, Subdir, "", Flt);
return RV: constant Repository := (N => Num_Items,
M => Repo_Directory'Length,
Root => Repo_Directory,
Key => DB.Key.Init(Key_File),
It => (others => Init_Next_Entry)) do
End_Search(ST);
end return;
end Init;
procedure Print_Info(Repo: in Repository) is
begin
Ada.Text_IO.Put_Line("repository: " & Repo.Root);
Repo.Key.Print;
Ada.Text_IO.Put_Line("items:");
for I of Repo.It loop
I.Print;
end loop;
end Print_Info;
procedure Restore(Repo: in Repository; Item_ID: in String) is
Item_XID: constant Bupstash_Types.XID :=
Bupstash_Types.From_Hex(Item_ID);
Data_Directory: constant String := Compose(Repo.Root, "data");
procedure Restore_With_Index(I: in DB.Item.Item) is
IT: Tree.HTree_LL.Tree_Reader :=
I.Init_HTree_Reader_For_Index_Tree;
DT: Tree.HTree_LL.Tree_Reader :=
I.Init_HTree_Reader_For_Data_Tree;
Index_DCTX: Crypto.Decryption.Decryption_Context :=
Crypto.Decryption.New_Decryption_Context(
Repo.Key.Get_Idx_SK, Repo.Key.Get_Idx_PSK);
Index_HK: constant Bupstash_Types.Hash_Key :=
I.Derive_Index_Hash_Key(Repo.Key);
Data_DCTX: Crypto.Decryption.Decryption_Context :=
Crypto.Decryption.New_Decryption_Context(
Repo.Key.Get_Data_SK, Repo.Key.Get_Data_PSK);
Data_HK: constant Bupstash_Types.Hash_Key :=
I.Derive_Data_Hash_Key(Repo.Key);
begin
Tree.Restorer.Restore_With_Index(IT, DT,
Index_DCTX, Index_HK, Data_DCTX, Data_HK,
Data_Directory);
end Restore_With_Index;
procedure Restore_Without_Index(I: in DB.Item.Item) is
DT: Tree.HTree_LL.Tree_Reader :=
I.Init_HTree_Reader_For_Data_Tree;
Data_DCTX: Crypto.Decryption.Decryption_Context :=
Crypto.Decryption.New_Decryption_Context(
Repo.Key.Get_Data_SK, Repo.Key.Get_Data_PSK);
Data_HK: constant Bupstash_Types.Hash_Key :=
I.Derive_Data_Hash_Key(Repo.Key);
begin
Tree.Restorer.Restore_Without_Index(DT, Data_DCTX,
Data_HK, Data_Directory);
end Restore_Without_Index;
begin
for I of Repo.It loop
if I.Has_XID(Item_XID) then
if I.Has_Index_Tree then
Restore_With_Index(I);
else
Restore_Without_Index(I);
end if;
return;
end if;
end loop;
raise Constraint_Error with "No item with ID <" &
Bupstash_Types.To_Hex(Item_XID) & "> found.";
end Restore;
end DB.Repository;