diff options
author | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
---|---|---|
committer | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
commit | 679147eead574d186ebf3069647b4c23e8ccace6 (patch) | |
tree | fc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /ninja/src/clean.cc | |
download | qtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz |
Initial import.
Diffstat (limited to 'ninja/src/clean.cc')
-rw-r--r-- | ninja/src/clean.cc | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/ninja/src/clean.cc b/ninja/src/clean.cc new file mode 100644 index 00000000000..5d1974e1582 --- /dev/null +++ b/ninja/src/clean.cc @@ -0,0 +1,259 @@ +// Copyright 2011 Google Inc. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "clean.h" + +#include <assert.h> +#include <stdio.h> + +#include "disk_interface.h" +#include "graph.h" +#include "state.h" +#include "util.h" + +Cleaner::Cleaner(State* state, const BuildConfig& config) + : state_(state), + config_(config), + removed_(), + cleaned_(), + cleaned_files_count_(0), + disk_interface_(new RealDiskInterface), + status_(0) { +} + +Cleaner::Cleaner(State* state, + const BuildConfig& config, + DiskInterface* disk_interface) + : state_(state), + config_(config), + removed_(), + cleaned_(), + cleaned_files_count_(0), + disk_interface_(disk_interface), + status_(0) { +} + +int Cleaner::RemoveFile(const string& path) { + return disk_interface_->RemoveFile(path); +} + +bool Cleaner::FileExists(const string& path) { + return disk_interface_->Stat(path) > 0; +} + +void Cleaner::Report(const string& path) { + ++cleaned_files_count_; + if (IsVerbose()) + printf("Remove %s\n", path.c_str()); +} + +void Cleaner::Remove(const string& path) { + if (!IsAlreadyRemoved(path)) { + removed_.insert(path); + if (config_.dry_run) { + if (FileExists(path)) + Report(path); + } else { + int ret = RemoveFile(path); + if (ret == 0) + Report(path); + else if (ret == -1) + status_ = 1; + } + } +} + +bool Cleaner::IsAlreadyRemoved(const string& path) { + set<string>::iterator i = removed_.find(path); + return (i != removed_.end()); +} + +void Cleaner::RemoveEdgeFiles(Edge* edge) { + string depfile = edge->GetBinding("depfile"); + if (!depfile.empty()) + Remove(depfile); + + string rspfile = edge->GetBinding("rspfile"); + if (!rspfile.empty()) + Remove(rspfile); +} + +void Cleaner::PrintHeader() { + if (config_.verbosity == BuildConfig::QUIET) + return; + printf("Cleaning..."); + if (IsVerbose()) + printf("\n"); + else + printf(" "); +} + +void Cleaner::PrintFooter() { + if (config_.verbosity == BuildConfig::QUIET) + return; + printf("%d files.\n", cleaned_files_count_); +} + +int Cleaner::CleanAll(bool generator) { + Reset(); + PrintHeader(); + for (vector<Edge*>::iterator e = state_->edges_.begin(); + e != state_->edges_.end(); ++e) { + // Do not try to remove phony targets + if ((*e)->is_phony()) + continue; + // Do not remove generator's files unless generator specified. + if (!generator && (*e)->GetBindingBool("generator")) + continue; + for (vector<Node*>::iterator out_node = (*e)->outputs_.begin(); + out_node != (*e)->outputs_.end(); ++out_node) { + Remove((*out_node)->path()); + } + + RemoveEdgeFiles(*e); + } + PrintFooter(); + return status_; +} + +void Cleaner::DoCleanTarget(Node* target) { + if (Edge* e = target->in_edge()) { + // Do not try to remove phony targets + if (!e->is_phony()) { + Remove(target->path()); + RemoveEdgeFiles(e); + } + for (vector<Node*>::iterator n = e->inputs_.begin(); n != e->inputs_.end(); + ++n) { + Node* next = *n; + // call DoCleanTarget recursively if this node has not been visited + if (cleaned_.count(next) == 0) { + DoCleanTarget(next); + } + } + } + + // mark this target to be cleaned already + cleaned_.insert(target); +} + +int Cleaner::CleanTarget(Node* target) { + assert(target); + + Reset(); + PrintHeader(); + DoCleanTarget(target); + PrintFooter(); + return status_; +} + +int Cleaner::CleanTarget(const char* target) { + assert(target); + + Reset(); + Node* node = state_->LookupNode(target); + if (node) { + CleanTarget(node); + } else { + Error("unknown target '%s'", target); + status_ = 1; + } + return status_; +} + +int Cleaner::CleanTargets(int target_count, char* targets[]) { + Reset(); + PrintHeader(); + for (int i = 0; i < target_count; ++i) { + const char* target_name = targets[i]; + Node* target = state_->LookupNode(target_name); + if (target) { + if (IsVerbose()) + printf("Target %s\n", target_name); + DoCleanTarget(target); + } else { + Error("unknown target '%s'", target_name); + status_ = 1; + } + } + PrintFooter(); + return status_; +} + +void Cleaner::DoCleanRule(const Rule* rule) { + assert(rule); + + for (vector<Edge*>::iterator e = state_->edges_.begin(); + e != state_->edges_.end(); ++e) { + if ((*e)->rule().name() == rule->name()) { + for (vector<Node*>::iterator out_node = (*e)->outputs_.begin(); + out_node != (*e)->outputs_.end(); ++out_node) { + Remove((*out_node)->path()); + RemoveEdgeFiles(*e); + } + } + } +} + +int Cleaner::CleanRule(const Rule* rule) { + assert(rule); + + Reset(); + PrintHeader(); + DoCleanRule(rule); + PrintFooter(); + return status_; +} + +int Cleaner::CleanRule(const char* rule) { + assert(rule); + + Reset(); + const Rule* r = state_->LookupRule(rule); + if (r) { + CleanRule(r); + } else { + Error("unknown rule '%s'", rule); + status_ = 1; + } + return status_; +} + +int Cleaner::CleanRules(int rule_count, char* rules[]) { + assert(rules); + + Reset(); + PrintHeader(); + for (int i = 0; i < rule_count; ++i) { + const char* rule_name = rules[i]; + const Rule* rule = state_->LookupRule(rule_name); + if (rule) { + if (IsVerbose()) + printf("Rule %s\n", rule_name); + DoCleanRule(rule); + } else { + Error("unknown rule '%s'", rule_name); + status_ = 1; + } + } + PrintFooter(); + return status_; +} + +void Cleaner::Reset() { + status_ = 0; + cleaned_files_count_ = 0; + removed_.clear(); + cleaned_.clear(); +} |