|
Ninja
|
00001 // Copyright 2011 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #include "clean.h" 00016 00017 #include <assert.h> 00018 #include <errno.h> 00019 #include <stdio.h> 00020 #include <string.h> 00021 #include <sys/stat.h> 00022 00023 #include "disk_interface.h" 00024 #include "graph.h" 00025 #include "state.h" 00026 #include "util.h" 00027 00028 Cleaner::Cleaner(State* state, const BuildConfig& config) 00029 : state_(state), 00030 config_(config), 00031 removed_(), 00032 cleaned_files_count_(0), 00033 disk_interface_(new RealDiskInterface), 00034 status_(0) { 00035 } 00036 00037 Cleaner::Cleaner(State* state, 00038 const BuildConfig& config, 00039 DiskInterface* disk_interface) 00040 : state_(state), 00041 config_(config), 00042 removed_(), 00043 cleaned_files_count_(0), 00044 disk_interface_(disk_interface), 00045 status_(0) { 00046 } 00047 00048 int Cleaner::RemoveFile(const string& path) { 00049 return disk_interface_->RemoveFile(path); 00050 } 00051 00052 bool Cleaner::FileExists(const string& path) { 00053 return disk_interface_->Stat(path) > 0; 00054 } 00055 00056 void Cleaner::Report(const string& path) { 00057 ++cleaned_files_count_; 00058 if (IsVerbose()) 00059 printf("Remove %s\n", path.c_str()); 00060 } 00061 00062 void Cleaner::Remove(const string& path) { 00063 if (!IsAlreadyRemoved(path)) { 00064 removed_.insert(path); 00065 if (config_.dry_run) { 00066 if (FileExists(path)) 00067 Report(path); 00068 } else { 00069 int ret = RemoveFile(path); 00070 if (ret == 0) 00071 Report(path); 00072 else if (ret == -1) 00073 status_ = 1; 00074 } 00075 } 00076 } 00077 00078 bool Cleaner::IsAlreadyRemoved(const string& path) { 00079 set<string>::iterator i = removed_.find(path); 00080 return (i != removed_.end()); 00081 } 00082 00083 void Cleaner::PrintHeader() { 00084 if (config_.verbosity == BuildConfig::QUIET) 00085 return; 00086 printf("Cleaning..."); 00087 if (IsVerbose()) 00088 printf("\n"); 00089 else 00090 printf(" "); 00091 } 00092 00093 void Cleaner::PrintFooter() { 00094 if (config_.verbosity == BuildConfig::QUIET) 00095 return; 00096 printf("%d files.\n", cleaned_files_count_); 00097 } 00098 00099 int Cleaner::CleanAll(bool generator) { 00100 Reset(); 00101 PrintHeader(); 00102 for (vector<Edge*>::iterator e = state_->edges_.begin(); 00103 e != state_->edges_.end(); ++e) { 00104 // Do not try to remove phony targets 00105 if ((*e)->rule_ == &State::kPhonyRule) 00106 continue; 00107 // Do not remove generator's files unless generator specified. 00108 if (!generator && (*e)->rule_->generator_) 00109 continue; 00110 for (vector<Node*>::iterator out_node = (*e)->outputs_.begin(); 00111 out_node != (*e)->outputs_.end(); ++out_node) { 00112 Remove((*out_node)->file_->path_); 00113 } 00114 } 00115 PrintFooter(); 00116 return status_; 00117 } 00118 00119 void Cleaner::DoCleanTarget(Node* target) { 00120 if (target->in_edge_) { 00121 Remove(target->file_->path_); 00122 for (vector<Node*>::iterator n = target->in_edge_->inputs_.begin(); 00123 n != target->in_edge_->inputs_.end(); 00124 ++n) { 00125 DoCleanTarget(*n); 00126 } 00127 } 00128 } 00129 00130 int Cleaner::CleanTarget(Node* target) { 00131 assert(target); 00132 00133 Reset(); 00134 PrintHeader(); 00135 DoCleanTarget(target); 00136 PrintFooter(); 00137 return status_; 00138 } 00139 00140 int Cleaner::CleanTarget(const char* target) { 00141 assert(target); 00142 00143 Reset(); 00144 Node* node = state_->LookupNode(target); 00145 if (node) { 00146 CleanTarget(node); 00147 } else { 00148 Error("unknown target '%s'", target); 00149 status_ = 1; 00150 } 00151 return status_; 00152 } 00153 00154 int Cleaner::CleanTargets(int target_count, char* targets[]) { 00155 Reset(); 00156 PrintHeader(); 00157 for (int i = 0; i < target_count; ++i) { 00158 const char* target_name = targets[i]; 00159 Node* target = state_->LookupNode(target_name); 00160 if (target) { 00161 if (IsVerbose()) 00162 printf("Target %s\n", target_name); 00163 DoCleanTarget(target); 00164 } else { 00165 Error("unknown target '%s'", target_name); 00166 status_ = 1; 00167 } 00168 } 00169 PrintFooter(); 00170 return status_; 00171 } 00172 00173 void Cleaner::DoCleanRule(const Rule* rule) { 00174 assert(rule); 00175 00176 for (vector<Edge*>::iterator e = state_->edges_.begin(); 00177 e != state_->edges_.end(); 00178 ++e) 00179 if ((*e)->rule_->name_ == rule->name_) 00180 for (vector<Node*>::iterator out_node = (*e)->outputs_.begin(); 00181 out_node != (*e)->outputs_.end(); 00182 ++out_node) 00183 Remove((*out_node)->file_->path_); 00184 } 00185 00186 int Cleaner::CleanRule(const Rule* rule) { 00187 assert(rule); 00188 00189 Reset(); 00190 PrintHeader(); 00191 DoCleanRule(rule); 00192 PrintFooter(); 00193 return status_; 00194 } 00195 00196 int Cleaner::CleanRule(const char* rule) { 00197 assert(rule); 00198 00199 Reset(); 00200 const Rule* r = state_->LookupRule(rule); 00201 if (r) { 00202 CleanRule(r); 00203 } else { 00204 Error("unknown rule '%s'", rule); 00205 status_ = 1; 00206 } 00207 return status_; 00208 } 00209 00210 int Cleaner::CleanRules(int rule_count, char* rules[]) { 00211 assert(rules); 00212 00213 Reset(); 00214 PrintHeader(); 00215 for (int i = 0; i < rule_count; ++i) { 00216 const char* rule_name = rules[i]; 00217 const Rule* rule = state_->LookupRule(rule_name); 00218 if (rule) { 00219 if (IsVerbose()) 00220 printf("Rule %s\n", rule_name); 00221 DoCleanRule(rule); 00222 } else { 00223 Error("unknown rule '%s'", rule_name); 00224 status_ = 1; 00225 } 00226 } 00227 PrintFooter(); 00228 return status_; 00229 } 00230 00231 void Cleaner::Reset() { 00232 status_ = 0; 00233 cleaned_files_count_ = 0; 00234 removed_.clear(); 00235 }
1.7.5.1