summaryrefslogtreecommitdiff
path: root/ninja/src/clean.cc
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
committerZeno Albisser <zeno.albisser@digia.com>2013-08-15 21:46:11 +0200
commit679147eead574d186ebf3069647b4c23e8ccace6 (patch)
treefc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /ninja/src/clean.cc
downloadqtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz
Initial import.
Diffstat (limited to 'ninja/src/clean.cc')
-rw-r--r--ninja/src/clean.cc259
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();
+}