1 /**
2 Copyright: Copyright (c) 2015-2016 Andrey Penechko.
3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 Authors: Andrey Penechko.
5 */
6 module packager;
7 
8 import std.file;
9 import std.string;
10 import std.digest.crc;
11 import std.stdio;
12 import std.zip;
13 import std.path;
14 import std.process;
15 import std.datetime;
16 
17 enum ROOT_PATH = "../..";
18 
19 void main(string[] args)
20 {
21 	string semver = "0.6.1";
22 
23 	StopWatch sw;
24 	sw.start();
25 	completeBuild(Arch.x32, semver);
26 	completeBuild(Arch.x64, semver);
27 	sw.stop();
28 	writefln("Finished in %.1fs", sw.peek().to!("seconds", real));
29 }
30 
31 void completeBuild(Arch arch, string semver)
32 {
33 	string dub_arch = arch == Arch.x32 ? "x86" : "x86_64";
34 	string launcher_arch = arch == Arch.x32 ? "32" : "64";
35 	string dubCom(Arch arch) {
36 		return format(`dub run --root="tools/launcher" -q --build=release --arch=%s --nodeps -- --release=%s`,
37 				dub_arch, launcher_arch);
38 	}
39 
40 	string com = dubCom(arch);
41 	writefln("Executing '%s'", com); stdout.flush();
42 	auto dub = executeShell(com, null, Config.none, size_t.max, ROOT_PATH);
43 	if (dub.status != 0)
44 		writeln("Failed to run launcher");
45 	else dub.output.write;
46 	writefln("Packing %sbit", launcher_arch); stdout.flush();
47 	pack(semver, arch, Platform.windows);
48 }
49 
50 struct ReleasePackage
51 {
52 	string semver;
53 	Arch arch;
54 	Platform platform;
55 	ZipArchive zip;
56 	string fileRoot;
57 	string archRoot;
58 }
59 
60 void pack(string semver, Arch arch, Platform pl)
61 {
62 	ReleasePackage pack = ReleasePackage(
63 		semver,
64 		arch,
65 		pl,
66 		new ZipArchive,
67 		ROOT_PATH);
68 	string archName = archName(&pack, "voxelman");
69 	pack.archRoot = archName;
70 
71 	makePackage(&pack);
72 	writePackage(&pack, buildNormalizedPath(ROOT_PATH, archName) ~ ".zip");
73 }
74 
75 //enum allowedExt = ["exe", "d", "txt", "dll"];
76 //enum dirs = ["builds/default", "config", "lib", "pluginpacks", "plugins", "source"];
77 enum Arch { x64, x32 }
78 enum Platform { windows, linux, macos }
79 string[Platform] platformToString;
80 string[Arch] archToString;
81 static this()
82 {
83 	platformToString = [Platform.windows : "win", Platform.linux : "linux", Platform.macos : "mac"];
84 	archToString = [Arch.x64 : "64", Arch.x32 : "32"];
85 }
86 
87 void makePackage(ReleasePackage* pack)
88 {
89 	pack.addFiles("builds/default", "*.exe");
90 	pack.addFiles("config", "*.sdl");
91 	pack.addFiles("lib/"~archToString[pack.arch], "*.dll");
92 	pack.addFile("README.md");
93 	pack.addFile("CHANGELOG.md");
94 	pack.addFile("LICENSE.md");
95 	pack.addFile("pluginpacks/default.txt");
96 	pack.addFile("launcher.exe");
97 }
98 
99 void writePackage(ReleasePackage* pack, string path)
100 {
101 	std.file.write(path, pack.zip.build());
102 }
103 
104 string archName(R)(ReleasePackage* pack, R baseName)
105 {
106 	string arch = archToString[pack.arch];
107 	string platform = platformToString[pack.platform];
108 	return format("%s-v%s-%s%s", baseName, pack.semver, platform, arch);
109 }
110 
111 alias normPath = buildNormalizedPath;
112 alias absPath = absolutePath;
113 void addFiles(ReleasePackage* pack, string path, string pattern)
114 {
115 	import std.file : dirEntries, SpanMode;
116 
117 	string absRoot = pack.fileRoot.absPath.normPath;
118 	foreach (entry; dirEntries(buildPath(pack.fileRoot, path), pattern, SpanMode.depth))
119 	if (entry.isFile) {
120 		string absPath = entry.name.absPath.normPath;
121 		addFile(pack, absPath, relativePath(absPath, absRoot));
122 	}
123 }
124 
125 void addFile(ReleasePackage* pack, string arch_name)
126 {
127 	addFile(pack.zip, buildPath(pack.fileRoot, arch_name).absPath.normPath, buildPath(pack.archRoot, arch_name));
128 }
129 
130 void addFile(ReleasePackage* pack, string fs_name, string arch_name)
131 {
132 	addFile(pack.zip, fs_name.absPath.normPath, buildPath(pack.archRoot, arch_name));
133 }
134 
135 void addFile(ZipArchive arch, string fs_name, string arch_name)
136 {
137 	string norm = arch_name.normPath;
138 	writefln("Add %s as %s", fs_name, norm);
139 	void[] data = std.file.read(fs_name);
140 	ArchiveMember am = new ArchiveMember();
141 	am.name = norm;
142 	am.compressionMethod = CompressionMethod.deflate;
143 	am.expandedData(cast(ubyte[])data);
144 	arch.addMember(am);
145 }