1 // Copyright 2011 Google Inc. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
20 #include "disk_interface.h"
25 Cleaner::Cleaner(State* state, const BuildConfig& config)
30 cleaned_files_count_(0),
31 disk_interface_(new RealDiskInterface),
35 Cleaner::Cleaner(State* state,
36 const BuildConfig& config,
37 DiskInterface* disk_interface)
42 cleaned_files_count_(0),
43 disk_interface_(disk_interface),
47 int Cleaner::RemoveFile(const string& path) {
48 return disk_interface_->RemoveFile(path);
51 bool Cleaner::FileExists(const string& path) {
53 TimeStamp mtime = disk_interface_->Stat(path, &err);
55 Error("%s", err.c_str());
56 return mtime > 0; // Treat Stat() errors as "file does not exist".
59 void Cleaner::Report(const string& path) {
60 ++cleaned_files_count_;
62 printf("Remove %s\n", path.c_str());
65 void Cleaner::Remove(const string& path) {
66 if (!IsAlreadyRemoved(path)) {
67 removed_.insert(path);
68 if (config_.dry_run) {
72 int ret = RemoveFile(path);
81 bool Cleaner::IsAlreadyRemoved(const string& path) {
82 set<string>::iterator i = removed_.find(path);
83 return (i != removed_.end());
86 void Cleaner::RemoveEdgeFiles(Edge* edge) {
87 string depfile = edge->GetUnescapedDepfile();
91 string rspfile = edge->GetUnescapedRspfile();
96 void Cleaner::PrintHeader() {
97 if (config_.verbosity == BuildConfig::QUIET)
99 printf("Cleaning...");
106 void Cleaner::PrintFooter() {
107 if (config_.verbosity == BuildConfig::QUIET)
109 printf("%d files.\n", cleaned_files_count_);
112 int Cleaner::CleanAll(bool generator) {
115 for (vector<Edge*>::iterator e = state_->edges_.begin();
116 e != state_->edges_.end(); ++e) {
117 // Do not try to remove phony targets
118 if ((*e)->is_phony())
120 // Do not remove generator's files unless generator specified.
121 if (!generator && (*e)->GetBindingBool("generator"))
123 for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
124 out_node != (*e)->outputs_.end(); ++out_node) {
125 Remove((*out_node)->path());
134 void Cleaner::DoCleanTarget(Node* target) {
135 if (Edge* e = target->in_edge()) {
136 // Do not try to remove phony targets
137 if (!e->is_phony()) {
138 Remove(target->path());
141 for (vector<Node*>::iterator n = e->inputs_.begin(); n != e->inputs_.end();
144 // call DoCleanTarget recursively if this node has not been visited
145 if (cleaned_.count(next) == 0) {
151 // mark this target to be cleaned already
152 cleaned_.insert(target);
155 int Cleaner::CleanTarget(Node* target) {
160 DoCleanTarget(target);
165 int Cleaner::CleanTarget(const char* target) {
169 Node* node = state_->LookupNode(target);
173 Error("unknown target '%s'", target);
179 int Cleaner::CleanTargets(int target_count, char* targets[]) {
182 for (int i = 0; i < target_count; ++i) {
183 const char* target_name = targets[i];
184 Node* target = state_->LookupNode(target_name);
187 printf("Target %s\n", target_name);
188 DoCleanTarget(target);
190 Error("unknown target '%s'", target_name);
198 void Cleaner::DoCleanRule(const Rule* rule) {
201 for (vector<Edge*>::iterator e = state_->edges_.begin();
202 e != state_->edges_.end(); ++e) {
203 if ((*e)->rule().name() == rule->name()) {
204 for (vector<Node*>::iterator out_node = (*e)->outputs_.begin();
205 out_node != (*e)->outputs_.end(); ++out_node) {
206 Remove((*out_node)->path());
213 int Cleaner::CleanRule(const Rule* rule) {
223 int Cleaner::CleanRule(const char* rule) {
227 const Rule* r = state_->bindings_.LookupRule(rule);
231 Error("unknown rule '%s'", rule);
237 int Cleaner::CleanRules(int rule_count, char* rules[]) {
242 for (int i = 0; i < rule_count; ++i) {
243 const char* rule_name = rules[i];
244 const Rule* rule = state_->bindings_.LookupRule(rule_name);
247 printf("Rule %s\n", rule_name);
250 Error("unknown rule '%s'", rule_name);
258 void Cleaner::Reset() {
260 cleaned_files_count_ = 0;