1 module caLib_util.tempdir;
2 
3 import std.file : tempDir, mkdirRecurse, rmdirRecurse, exists, dirEntries, SpanMode, FileException;
4 import std.random : uniform;
5 import std.conv : to;
6 import std.path : buildNormalizedPath;
7 import std.exception : enforce;
8 
9 
10 private immutable string tempDirsRoot;
11 
12 shared static this()
13 {
14 	if(tempDir() == ".")
15 		// if tempdir() returns "." it means that a temporary files root
16 		// could not be found. If this happens, we make on on our own
17 		tempDirsRoot = makeTempDirsRoot();
18 	else
19 		tempDirsRoot = tempDir();
20 
21 	// If there is any temporary files this program left behind before
22 	// (this could happen if the program crashed). Remove them
23 	removeTempFiles();
24 }
25 
26 shared static ~this()
27 {
28 	// Remove all the temporary files we created before exiting the program
29 	removeTempFiles();
30 }
31 
32 
33 
34 /**
35 * Creates and return a path to a private, temporary directory
36 *
37 * This function can be used when data needs to be writen to and
38 * manipulated on the disk without worring about it being overwritten by other
39 * programs or the user. This directory will be destroyed when the program
40 * exits.
41 *
42 * Returns:
43 *     A path to a newly created temporary directory
44 */
45 string makePrivateTempDir() { return makePrivateTempDir(0); }
46 
47 private string makePrivateTempDir(int n)
48 {
49 	// we will only try to make a temporary directory 1000 times
50 	enforce(n < 1000,
51 		"Could not create a temporary directory");
52 
53 	// path to the new temporary directory
54 	string dir = buildNormalizedPath(tempDirsRoot, "caLib3_",
55 		to!string(uniform(1000, 9999)));
56 
57 	// if there already exists a directory in ths location
58 	//redo the entire proccess
59 	if(exists(dir))
60 		return makePrivateTempDir(n+1);
61 
62 	// otherwise, make the directory and return the path to it
63 	mkdirRecurse(dir);
64 	return dir;
65 }
66 
67 
68 
69 private void removeTempFiles()
70 {
71 	// if the temporary root directory is gone (it really shoulden't but its
72 	// not our responibility), all the temporary files created by uss are gone.
73 	// Just return
74 	if(!exists(tempDirsRoot))
75 		return;
76 	
77 	// list all the directories in the temporary files root
78 	auto dirs = dirEntries(tempDirsRoot, SpanMode.shallow);
79 	
80 	// iterate over the entries
81 	foreach(dirPath ; dirs)
82 	{
83 		string dirName = dirPath[tempDirsRoot.length .. dirPath.length];
84 
85 		// if there is a entry starting with "caLib3_" ->
86 		// It was created by us -> remove the direcory
87 		if(dirName.length >= 7 && dirName[0 .. 7] == "caLib3_")
88 			rmdirRecurse(dirPath);
89 	}
90 }
91 
92 
93 
94 private string makeTempDirsRoot()
95 {
96 	assert(0, "Can't create temporary file:" ~
97 		"This os has no location for temporary files");
98 }