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 +/