1 
2 module zipfs;
3 
4 import std.zip;
5 import std.file;
6 import std.path;
7 import std.stdio;
8 import std.algorithm;
9 import std.range;
10 import std.datetime;
11 
12 import std.datetime;
13 //import unit_threaded;
14 import std.conv;
15 
16 string[] parentDirs(string pathname) {
17   return pathname.split("/")[0..$-1];
18 }
19 /+
20 unittest {
21   "abc/".parentDirs.shouldEqual(["abc"]);
22 }
23 +/
24 string file(string pathname) {
25   auto res = pathname.split("/")[$-1];
26   if (res == "") {
27     return null;
28   }
29   return res;
30 }
31 /+
32 unittest {
33   "abc/".file.shouldEqual(null);
34   "abc/def".file.shouldEqual("def");
35 }
36 +/
37 class ZipFile {
38   string name;
39   ArchiveMember member;
40   ZipFile[string] children;
41   size_t weight;
42   this(string name, ArchiveMember member) {
43     this(name);
44     this.member = member;
45   }
46   this(string name) {
47     this.name = name;
48   }
49   ZipFile[] childs() {
50     return children.byValue().array;
51   }
52   string getName() {
53     return name;
54   }
55   bool isDirectory() {
56     return member is null || member.fileAttributes.attrIsDir;
57   }
58   static ZipFile create(ZipArchive archive) {
59     ZipFile res = new ZipFile("ZipArchive");
60     foreach (member; archive.directory.byValue()) {
61       res.add(member);
62     }
63     res.calcSize();
64     return res;
65   }
66   private void calcSize() {
67     if (children !is null) {
68       foreach (child; childs) {
69         child.calcSize();
70       }
71       weight = childs.map!(v => v.weight).sum;
72     } else {
73       if (!member) {
74         weight = 0;
75       } else {
76         weight = member.expandedSize;
77       }
78     }
79   }
80   void add(ArchiveMember member) {
81     auto dirs = parentDirs(member.name);
82     auto h = this;
83     foreach (dir; dirs) {
84       if (!(dir in h.children)) {
85         h.children[dir] = new ZipFile(dir);
86       }
87       h = h.children[dir];
88     }
89     auto file = file(member.name);
90     if (file != null) {
91       h.children[file] = new ZipFile(file, member);
92     }
93   }
94   override string toString() {
95     return toString("");
96   }
97   string toString(string prefix) {
98     auto res = prefix ~ (member !is null ? member.name : name) ~ " (" ~ weight.to!string ~ ")\n";
99     foreach (child; childs) {
100       res ~= child.toString(prefix ~ "  ");
101     }
102     return res;
103   }
104 }
105 /+
106 unittest {
107   auto zip = new ZipArchive(read("test.zip"));
108   auto zf = ZipFile.create(zip);
109   writelnUt("1234");
110   writelnUt("\n" ~ zf.toString());
111   /*
112   writelnUt("Archive: test.zip");
113   writelnUt("%-10s  %-8s  Name", "Length", "CRC-32");
114   foreach (key, v; zip.directory) {
115     writelnUt(key);
116   }
117   zip.directory.length.shouldEqual(17);
118   auto r = zip.directory.byKey();
119   auto f1 = r.front; r.popFront;
120   f1.shouldEqual("source/zipped/package.d~");
121   zip.directory[f1].fileAttributes.attrIsDir.shouldEqual(false);
122   auto f2 = r.front;
123   f2.shouldEqual(".dub/");
124   zip.directory[f2].fileAttributes.attrIsDir.shouldEqual(true);
125   */
126 }
127 
128 +/