-
-
Notifications
You must be signed in to change notification settings - Fork 113
/
Copy pathdirectory_path.cpp
134 lines (116 loc) · 3.37 KB
/
directory_path.cpp
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "stdafx.h"
#include "directory_path.h"
#include "file_path.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "dirent.h"
DirectoryPath::DirectoryPath(string p) : path(std::move(p)) {
}
FilePath DirectoryPath::file(const std::string& f) const {
return FilePath(*this, f);
}
DirectoryPath DirectoryPath::subdirectory(const std::string& s) const {
return DirectoryPath(path + "/" + s);
}
static bool isDirectory(const string& path) {
struct stat path_stat;
if (stat(path.c_str(), &path_stat))
return false;
else
return S_ISDIR(path_stat.st_mode);
}
bool DirectoryPath::exists() const {
return isDirectory(getPath());
}
void DirectoryPath::createIfDoesntExist() const {
if (!exists()) {
#ifndef WINDOWS
USER_CHECK(!mkdir(path.data(), 0750)) << "Unable to create directory \"" + path + "\": " + strerror(errno);
#else
USER_CHECK(!mkdir(path.data())) << "Unable to create directory \"" + path + "\": " + strerror(errno);
#endif
}
}
void DirectoryPath::removeRecursively() const {
if (exists()) {
for (auto file : getFiles())
remove(file.getPath());
for (auto subdir : getSubDirs())
subdirectory(subdir).removeRecursively();
rmdir(getPath());
}
}
static bool isRegularFile(const string& path) {
struct stat path_stat;
if (stat(path.c_str(), &path_stat))
return false;
else
return S_ISREG(path_stat.st_mode);
}
vector<FilePath> DirectoryPath::getFiles() const {
vector<FilePath> ret;
if (DIR* dir = opendir(path.data())) {
while (dirent* ent = readdir(dir))
if (isRegularFile(path + "/" + ent->d_name))
ret.push_back(FilePath(*this, ent->d_name));
closedir(dir);
}
return ret;
}
vector<string> DirectoryPath::getSubDirs() const {
vector<string> ret;
if (DIR* dir = opendir(path.data())) {
while (dirent* ent = readdir(dir))
if (isDirectory(path + "/" + ent->d_name) && strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
ret.push_back(ent->d_name);
closedir(dir);
}
return ret;
}
const char* DirectoryPath::getPath() const {
return path.data();
}
std::ostream& operator <<(std::ostream& d, const DirectoryPath& path) {
return d << path.getPath();
}
bool isAbsolutePath(const char* str) {
#ifdef WINDOWS
if ((str[0] >= 'a' && str[0] <= 'z') || (str[0] >= 'A' && str[0] <= 'Z'))
if (str[1] == ':' && (str[2] == '/' || str[2] == '\\'))
return true;
#else
if (str[0] == '/')
return true;
#endif
return false;
}
string getAbsolute(const char* path) {
if (isAbsolutePath(path))
return path;
// TODO: this is not exactly right if paths contain dots (../../)
return DirectoryPath::current().getPath() + string("/") + path;
}
DirectoryPath DirectoryPath::current() {
char buffer[2048];
char* name = getcwd(buffer, sizeof(buffer) - 1);
CHECK(name && "getcwd error");
return DirectoryPath(name);
}
optional<string> DirectoryPath::copyRecursively(DirectoryPath to) {
to.createIfDoesntExist();
for (auto file : getFiles())
file.copyTo(to.file(file.getFileName()));
for (auto dir : getSubDirs()) {
DirectoryPath subTo = to.subdirectory(dir);
DirectoryPath subFrom = subdirectory(dir);
subFrom.copyRecursively(subTo);
}
return none;
}
bool DirectoryPath::isAbsolute() const {
return isAbsolutePath(path.c_str());
}
DirectoryPath DirectoryPath::absolute() const {
return DirectoryPath(getAbsolute(path.data()));
}