42 extern char* mkdtemp(
char* name_template);
52 char* mkdtemp(
char* name_template) {
53 int err = _mktemp_s(name_template, strlen(name_template) + 1);
59 err = _mkdir(name_template);
69 string GetSystemTempDir() {
72 if (!GetTempPath(
sizeof(buf), buf))
76 const char* tempdir = getenv(
"TMPDIR");
92 " command = cat $in > $out\n");
96 EXPECT_FALSE(strpbrk(path.c_str(),
"/\\"));
97 return state_.GetNode(path, 0);
104 EXPECT_TRUE(parser.
ParseTest(input, &err));
114 for (vector<Edge*>::const_iterator e = state.
edges_.begin();
115 e != state.
edges_.end(); ++e) {
117 EXPECT_FALSE((*e)->outputs_.empty());
119 for (vector<Node*>::const_iterator in_node = (*e)->inputs_.begin();
120 in_node != (*e)->inputs_.end(); ++in_node) {
121 const vector<Edge*>& out_edges = (*in_node)->out_edges();
122 EXPECT_NE(find(out_edges.begin(), out_edges.end(), *e),
126 for (vector<Node*>::const_iterator out_node = (*e)->outputs_.begin();
127 out_node != (*e)->outputs_.end(); ++out_node) {
128 EXPECT_EQ((*out_node)->in_edge(), *e);
133 set<const Edge*> node_edge_set;
134 for (State::Paths::const_iterator p = state.
paths_.begin();
135 p != state.
paths_.end(); ++p) {
136 const Node* n = p->second;
138 node_edge_set.insert(n->
in_edge());
141 set<const Edge*> edge_set(state.
edges_.begin(), state.
edges_.end());
142 EXPECT_EQ(node_edge_set, edge_set);
146 const string& contents) {
147 files_[path].mtime = now_;
148 files_[path].contents = contents;
149 files_created_.insert(path);
153 FileMap::const_iterator i = files_.find(path);
154 if (i != files_.end()) {
155 *err = i->second.stat_error;
156 return i->second.mtime;
163 Create(path, contents);
168 directories_made_.push_back(path);
175 files_read_.push_back(path);
176 FileMap::iterator i = files_.find(path);
177 if (i != files_.end()) {
178 *contents = i->second.contents;
181 *err = strerror(ENOENT);
186 if (find(directories_made_.begin(), directories_made_.end(), path)
187 != directories_made_.end())
189 FileMap::iterator i = files_.find(path);
190 if (i != files_.end()) {
192 files_removed_.insert(path);
201 start_dir_ = GetSystemTempDir();
202 if (start_dir_.empty())
203 Fatal(
"couldn't get system temp dir");
204 if (chdir(start_dir_.c_str()) < 0)
205 Fatal(
"chdir: %s", strerror(errno));
208 char name_template[1024];
209 strcpy(name_template, name.c_str());
210 strcat(name_template,
"-XXXXXX");
211 char* tempname = mkdtemp(name_template);
213 Fatal(
"mkdtemp: %s", strerror(errno));
214 temp_dir_name_ = tempname;
217 if (chdir(temp_dir_name_.c_str()) < 0)
218 Fatal(
"chdir: %s", strerror(errno));
222 if (temp_dir_name_.empty())
226 if (chdir(start_dir_.c_str()) < 0)
227 Fatal(
"chdir: %s", strerror(errno));
230 string command =
"rmdir /s /q " + temp_dir_name_;
232 string command =
"rm -rf " + temp_dir_name_;
234 if (system(command.c_str()) < 0)
235 Fatal(
"system: %s", strerror(errno));
237 temp_dir_name_.clear();
241 : path_(std::move(other.path_)), released_(other.released_) {
242 other.released_ =
true;
249 if (
this != &other) {
static uint64_t HashCommand(StringPiece command)
Status
Result of ReadFile.
bool ParseTest(const std::string &input, std::string *err)
Parse a text string of input. Used by tests.
Information about a node in the dependency graph: the file, whether it's dirty, mtime,...
const std::vector< Edge * > & out_edges() const
A class that records a file path and ensures that it is removed on destruction.
void Release()
Release the file, the destructor will not remove the file.
~ScopedFilePath()
Destructor destroys the file, unless Release() was called.
ScopedFilePath & operator=(ScopedFilePath &&) noexcept
It would be nice to use '= default' here instead but some old compilers such as GCC from Ubuntu 16....
ScopedFilePath(const std::string &path)
Constructor just records the file path.
void CreateAndEnter(const std::string &name)
Create a temporary directory and chdir into it.
void Cleanup()
Clean up the temporary directory.
void AddCatRule(State *state)
Add a "cat" rule to state.
StateTestWithBuiltinRules()
Node * GetNode(const std::string &path)
Short way to get a Node by its path from state_.
Global state (file status) for a single run.
std::vector< Edge * > edges_
All the edges of the graph.
bool WriteFile(const std::string &path, const std::string &contents, bool) override
Create a file, with the specified name and contents If crlf_on_windows is true, will be converted t...
bool MakeDir(const std::string &path) override
Create a directory, returning false on failure.
int RemoveFile(const std::string &path) override
Remove the file named path.
Status ReadFile(const std::string &path, std::string *contents, std::string *err) override
Read and store in given string.
TimeStamp Stat(const std::string &path, std::string *err) const override
stat() a file, returning the mtime, or 0 if missing and -1 on other errors.
void Create(const std::string &path, const std::string &contents)
"Create" a file with contents.
void AssertParse(State *state, const char *input, ManifestParserOptions opts)
void AssertHash(const char *expected, uint64_t actual)
void VerifyGraph(const State &state)
int platformAwareUnlink(const char *filename)
void Fatal(const char *msg,...)
Log a fatal message and exit.
unsigned long long uint64_t