// 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 "graph.h"

#include <deque>
#include <unordered_set>
#include <assert.h>
#include <stdio.h>

#include "build_log.h"
#include "debug_flags.h"
#include "depfile_parser.h"
#include "deps_log.h"
#include "disk_interface.h"
#include "metrics.h"
#include "parallel_map.h"
#include "state.h"
#include "util.h"

bool Node::PrecomputeStat(DiskInterface* disk_interface, std::string* err) {
  if (in_edge() != nullptr) {
    if (in_edge()->IsPhonyOutput()) {
      return true;
    }
    return (precomputed_mtime_ = disk_interface->LStat(globalPath().h.data(), nullptr, nullptr, err)) != -1;
  } else {
    return (precomputed_mtime_ = disk_interface->Stat(globalPath().h.data(), err)) != -1;
  }
}

bool Node::Stat(DiskInterface* disk_interface, string* err) {
  if (in_edge() != nullptr) {
    assert(!in_edge()->IsPhonyOutput());
    return (mtime_ = disk_interface->LStat(globalPath().h.data(), nullptr, nullptr, err)) != -1;
  } else {
    return (mtime_ = disk_interface->Stat(globalPath().h.data(), err)) != -1;
  }
}

void Node::UpdatePhonyMtime(TimeStamp mtime) {
  if (!exists()) {
    mtime_ = std::max(mtime_, mtime);
  }
}

bool Node::LStat(
  DiskInterface* disk_interface, bool* is_dir, bool* is_symlink, string* err) {
  assert(in_edge() != nullptr);
  assert(!in_edge()->IsPhonyOutput());
  return (mtime_ = disk_interface->LStat(globalPath().h.data(), is_dir, is_symlink, err)) != -1;
}

bool DependencyScan::RecomputeNodesDirty(const std::vector<Node*>& initial_nodes,
                                         std::vector<Node*>* validation_nodes,
                                         std::string* err) {
  METRIC_RECORD("dep scan");
  std::vector<Node*> all_nodes;
  std::vector<Edge*> all_edges;
  std::unique_ptr<ThreadPool> thread_pool = CreateThreadPool();

  {
    METRIC_RECORD("dep scan : collect nodes+edges");
    for (Node* node : initial_nodes)
      CollectPrecomputeLists(node, &all_nodes, &all_edges);
  }

  bool success = true;
  if (!PrecomputeNodesDirty(all_nodes, all_edges, thread_pool.get(), err))
    success = false;


  std::deque<Node*> nodes(initial_nodes.begin(), initial_nodes.end());

  if (success) {
    METRIC_RECORD("dep scan : main pass");
    std::vector<Node*> stack;
    std::vector<Node*> new_validation_nodes;
    while (!nodes.empty()) {
      Node* node = nodes.front();
      nodes.pop_front();

      stack.clear();
      new_validation_nodes.clear();
      if (!RecomputeNodeDirty(node, &stack, &new_validation_nodes, err)) {
        success = false;
        break;
      }
      nodes.insert(nodes.end(), new_validation_nodes.begin(),
                                new_validation_nodes.end());
      if (!new_validation_nodes.empty()) {
        assert(validation_nodes &&
               "validations require RecomputeDirty to be called with validation_nodes");
        validation_nodes->insert(validation_nodes->end(),
                                 new_validation_nodes.begin(),
                                 new_validation_nodes.end());
      }
    }
  }

  {
    // Ensure that the precomputed mtime information can't be used after this
    // dependency scan finishes.
    METRIC_RECORD("dep scan : clear pre-stat");
    ParallelMap(thread_pool.get(), all_nodes, [](Node* node) {
      node->ClearPrecomputedStat();
    });
  }

  return success;
}

void DependencyScan::CollectPrecomputeLists(Node* node,
                                            std::vector<Node*>* nodes,
                                            std::vector<Edge*>* edges) {
  if (node->precomputed_dirtiness())
    return;
  node->set_precomputed_dirtiness(true);
  nodes->push_back(node);

  Edge* edge = node->in_edge();
  if (edge && !edge->precomputed_dirtiness_) {
    edge->precomputed_dirtiness_ = true;
    edges->push_back(edge);

    for (Node* node : edge->inputs_) {
      // Duplicate the dirtiness check here to avoid an unnecessary function
      // call. (The precomputed_dirtiness() will be inlined, but the recursive
      // call can't be.)
      if (!node->precomputed_dirtiness())
        CollectPrecomputeLists(node, nodes, edges);
    }

    if (!edge->validations_.empty()) {
      for (Node* node : edge->validations_) {
        // Duplicate the dirtiness check here to avoid an unnecessary function
        // call. (The precomputed_dirtiness() will be inlined, but the recursive
        // call can't be.)
        if (!node->precomputed_dirtiness())
          CollectPrecomputeLists(node, nodes, edges);
      }
    }
  }

  // Collect dependencies from the deps log. This pass could also examine
  // depfiles, but it would be a more intrusive design change, because we don't
  // want to parse a depfile twice.
  if (DepsLog::Deps* deps = deps_log()->GetDeps(node)) {
    for (int i = 0; i < deps->node_count; ++i) {
      Node* node = deps->nodes[i];
      // Duplicate the dirtiness check here to avoid an unnecessary function
      // call.
      if (!node->precomputed_dirtiness()) {
        CollectPrecomputeLists(node, nodes, edges);
      }
    }
  }
}

bool DependencyScan::PrecomputeNodesDirty(const std::vector<Node*>& nodes,
                                          const std::vector<Edge*>& edges,
                                          ThreadPool* thread_pool,
                                          std::string* err) {
  // Optimize the "null build" case by calling Stat in parallel on every node in
  // the transitive closure.
  //
  // The Windows RealDiskInterface::Stat uses a directory-based cache that isn't
  // thread-safe. Various tests also uses a non-thread-safe Stat, so disable the
  // parallelized stat'ing for them as well.
  if (disk_interface_->IsStatThreadSafe() &&
      GetOptimalThreadPoolJobCount() > 1) {
    METRIC_RECORD("dep scan : pre-stat nodes");
    if (!PropagateError(err, ParallelMap(thread_pool, nodes,
        [this](Node* node) {
      // Each node is guaranteed to appear at most once in the collected list
      // of nodes, so it's safe to modify the nodes from worker threads.
      std::string err;
      node->PrecomputeStat(disk_interface_, &err);
      return err;
    }))) {
      return false;
    }
  }

  {
    METRIC_RECORD("dep scan : precompute edge info");
    if (!PropagateError(err, ParallelMap(thread_pool, edges, [](Edge* edge) {
      // As with the node list, each edge appears at most once in the
      // collected list, so it's safe to modify the edges from worker threads.
      std::string err;
      edge->PrecomputeDepScanInfo(&err);
      return err;
    }))) {
      return false;
    }
  }

  return true;
}

bool DependencyScan::RecomputeNodeDirty(Node* node, std::vector<Node*>* stack,
                                        std::vector<Node*>* validation_nodes,
                                        std::string* err) {
  Edge* edge = node->in_edge();
  if (!edge) {
    // If we already visited this leaf node then we are done.
    if (node->status_known())
      return true;
    // This node has no in-edge; it is dirty if it is missing.
    if (!node->StatIfNecessary(disk_interface_, err))
      return false;
    if (!node->exists())
      EXPLAIN("%s has no in-edge and is missing", node->globalPath().h.data());
    node->set_dirty(!node->exists());
    return true;
  }

  // If we already finished this edge then we are done.
  if (edge->mark_ == Edge::VisitDone)
    return true;

  // If we encountered this edge earlier in the call stack we have a cycle.
  if (!VerifyDAG(node, stack, err))
    return false;

  // Mark the edge temporarily while in the call stack.
  edge->mark_ = Edge::VisitInStack;
  stack->push_back(node);

  bool dirty = false;
  bool phony_output = edge->IsPhonyOutput();
  edge->outputs_ready_ = true;
  edge->deps_missing_ = false;

  if (phony_output) {
    EXPLAIN("edge with output %s is a phony output, so is always dirty",
            node->globalPath().h.data());
    dirty = true;

    if (edge->UsesDepsLog() || edge->UsesDepfile()) {
      *err = "phony output " + node->globalPath().h.str_view().AsString() +
             " has deps, which does not make sense.";
      return false;
    }
  } else {
    if (!edge->deps_loaded_) {
      // This is our first encounter with this edge.
      // If there is a pending dyndep file, visit it now:
      // * If the dyndep file is ready then load it now to get any
      //   additional inputs and outputs for this and other edges.
      //   Once the dyndep file is loaded it will no longer be pending
      //   if any other edges encounter it, but they will already have
      //   been updated.
      // * If the dyndep file is not ready then since is known to be an
      //   input to this edge, the edge will not be considered ready below.
      //   Later during the build the dyndep file will become ready and be
      //   loaded to update this edge before it can possibly be scheduled.
      if (edge->dyndep_ && edge->dyndep_->dyndep_pending()) {
        if (!RecomputeDirty(edge->dyndep_, stack, err))
          return false;

        if (!edge->dyndep_->in_edge() ||
            edge->dyndep_->in_edge()->outputs_ready()) {
          // The dyndep file is ready, so load it now.
          if (!LoadDyndeps(edge->dyndep_, err))
            return false;
        }
      }
    }

    // Load output mtimes so we can compare them to the most recent input below.
    for (vector<Node*>::iterator o = edge->outputs_.begin();
         o != edge->outputs_.end(); ++o) {
      if (!(*o)->StatIfNecessary(disk_interface_, err))
        return false;
    }

    if (!edge->deps_loaded_) {
      // This is our first encounter with this edge.  Load discovered deps.
      edge->deps_loaded_ = true;
      if (!dep_loader_.LoadDeps(edge, err)) {
        if (!err->empty())
          return false;
        // Failed to load dependency info: rebuild to regenerate it.
        // LoadDeps() did EXPLAIN() already, no need to do it here.
        dirty = edge->deps_missing_ = true;
      }
    }
  }

  // Store any validation nodes from the edge for adding to the initial
  // nodes.  Don't recurse into them, that would trigger the dependency
  // cycle detector if the validation node depends on this node.
  // RecomputeNodesDirty will add the validation nodes to the initial nodes
  // and recurse into them.
  validation_nodes->insert(validation_nodes->end(),
      edge->validations_.begin(), edge->validations_.end());

  // Visit all inputs; we're dirty if any of the inputs are dirty.
  Node* most_recent_input = NULL;
  for (vector<Node*>::iterator i = edge->inputs_.begin();
       i != edge->inputs_.end(); ++i) {
    // Visit this input.
    if (!RecomputeNodeDirty(*i, stack, validation_nodes, err))
      return false;

    // If an input is not ready, neither are our outputs.
    Edge* in_edge = (*i)->in_edge();
    if (in_edge != nullptr) {
      if (!in_edge->outputs_ready_)
        edge->outputs_ready_ = false;
    }

    if (!phony_output && !edge->is_order_only(i - edge->inputs_.begin())) {
      if (in_edge != nullptr && in_edge->IsPhonyOutput()) {
        *err = "real file '" + node->globalPath().h.str_view().AsString() +
               "' depends on phony output '" + (*i)->globalPath().h.str_view().AsString() + "'\n";
        return false;
      }

      // If a regular input is dirty (or missing), we're dirty.
      // Otherwise consider mtime.
      if ((*i)->dirty()) {
        EXPLAIN("%s is dirty", (*i)->globalPath().h.data());
        dirty = true;
      } else {
        if (!most_recent_input || (*i)->mtime() > most_recent_input->mtime()) {
          most_recent_input = *i;
        }
      }
    }
  }

  // We may also be dirty due to output state: missing outputs, out of
  // date outputs, etc.  Visit all outputs and determine whether they're dirty.
  if (!dirty)
    if (!RecomputeOutputsDirty(edge, most_recent_input, &dirty, err))
      return false;

  // Finally, visit each output and update their dirty state if necessary.
  for (vector<Node*>::iterator o = edge->outputs_.begin();
       o != edge->outputs_.end(); ++o) {
    if (dirty)
      (*o)->MarkDirty();
  }

  // If an edge is dirty, its outputs are normally not ready.  (It's
  // possible to be clean but still not be ready in the presence of
  // order-only inputs.)
  // But phony edges with no inputs have nothing to do, so are always
  // ready.
  if (dirty && !(edge->is_phony() && edge->inputs_.empty()))
    edge->outputs_ready_ = false;

  // Mark the edge as finished during this walk now that it will no longer
  // be in the call stack.
  edge->mark_ = Edge::VisitDone;
  assert(stack->back() == node);
  stack->pop_back();

  return true;
}

bool DependencyScan::VerifyDAG(Node* node, vector<Node*>* stack, string* err) {
  Edge* edge = node->in_edge();
  assert(edge != NULL);

  // If we have no temporary mark on the edge then we do not yet have a cycle.
  if (edge->mark_ != Edge::VisitInStack)
    return true;

  // We have this edge earlier in the call stack.  Find it.
  vector<Node*>::iterator start = stack->begin();
  while (start != stack->end() && (*start)->in_edge() != edge)
    ++start;
  assert(start != stack->end());

  // Make the cycle clear by reporting its start as the node at its end
  // instead of some other output of the starting edge.  For example,
  // running 'ninja b' on
  //   build a b: cat c
  //   build c: cat a
  // should report a -> c -> a instead of b -> c -> a.
  *start = node;

  // Construct the error message rejecting the cycle.
  *err = "dependency cycle: ";
  for (vector<Node*>::const_iterator i = start; i != stack->end(); ++i) {
    err->append((*i)->globalPath().h.data());
    err->append(" -> ");
  }
  err->append((*start)->globalPath().h.data());

  if ((start + 1) == stack->end() && edge->maybe_phonycycle_diagnostic()) {
    // The manifest parser would have filtered out the self-referencing
    // input if it were not configured to allow the error.
    err->append(" [-w phonycycle=err]");
  }

  return false;
}

bool DependencyScan::RecomputeOutputsDirty(Edge* edge, Node* most_recent_input,
                                           bool* outputs_dirty, string* err) {
  assert(!edge->IsPhonyOutput());

  uint64_t command_hash = edge->GetCommandHash();
  for (vector<Node*>::iterator o = edge->outputs_.begin();
       o != edge->outputs_.end(); ++o) {
    if (edge->is_phony()) {
      // Phony edges don't write any output.  Outputs are only dirty if
      // there are no inputs and we're missing the output.
      if (edge->inputs_.empty() && !(*o)->exists()) {
        // For phony targets defined in the ninja file, error when using dirty phony edges.
        // The phony edges automatically created from depfiles still need the old behavior.
        if (missing_phony_is_err_ && !edge->phony_from_depfile_) {
          *err = "output " + (*o)->globalPath().h.str_view().AsString() +
                " of phony edge doesn't exist. Missing 'phony_output = true'?";
          return false;
        } else {
          EXPLAIN("output %s of phony edge with no inputs doesn't exist",
                  (*o)->globalPath().h.data());
          *outputs_dirty = true;
          return true;
        }
      }

      // Update the mtime with the newest input. Dependents can thus call mtime()
      // on the fake node and get the latest mtime of the dependencies
      if (most_recent_input) {
        (*o)->UpdatePhonyMtime(most_recent_input->mtime());
      }
      continue;
    }
    if (RecomputeOutputDirty(edge, most_recent_input, command_hash, *o)) {
      *outputs_dirty = true;
      return true;
    }
  }
  return true;
}

bool DependencyScan::RecomputeOutputDirty(Edge* edge,
                                          Node* most_recent_input,
                                          uint64_t command_hash,
                                          Node* output) {
  assert(!edge->is_phony());

  BuildLog::LogEntry* entry = 0;

  // Dirty if we're missing the output.
  if (!output->exists()) {
    EXPLAIN("output %s doesn't exist", output->globalPath().h.data());
    return true;
  }

  // Dirty if the output is older than the input.
  if (most_recent_input && output->mtime() < most_recent_input->mtime()) {
    TimeStamp output_mtime = output->mtime();

    // If this is a restat rule, we may have cleaned the output with a restat
    // rule in a previous run and stored the most recent input mtime in the
    // build log.  Use that mtime instead, so that the file will only be
    // considered dirty if an input was modified since the previous run.
    bool used_restat = false;
    if (edge->IsRestat() && build_log() &&
        (entry = build_log()->LookupByOutput(output->globalPath()))) {
      output_mtime = entry->mtime;
      used_restat = true;
      output->set_restat_mtime(output_mtime);
    }

    if (output_mtime < most_recent_input->mtime()) {
      EXPLAIN("%soutput %s older than most recent input %s "
              "(%" PRId64 " vs %" PRId64 ")",
              used_restat ? "restat of " : "", output->globalPath().h.data(),
              most_recent_input->globalPath().h.data(),
              output_mtime, most_recent_input->mtime());
      return true;
    }
  }

  if (build_log()) {
    bool generator = edge->IsGenerator();
    if (entry || (entry = build_log()->LookupByOutput(output->globalPath()))) {
      if (!generator &&
          command_hash != entry->command_hash) {
        // May also be dirty due to the command changing since the last build.
        // But if this is a generator rule, the command changing does not make us
        // dirty.
        EXPLAIN("command line changed for %s", output->globalPath().h.data());
        return true;
      }
      if (most_recent_input && entry->mtime < most_recent_input->mtime()) {
        // May also be dirty due to the mtime in the log being older than the
        // mtime of the most recent input.  This can occur even when the mtime
        // on disk is newer if a previous run wrote to the output file but
        // exited with an error or was interrupted.
        EXPLAIN("recorded mtime of %s older than most recent input %s (%" PRId64 " vs %" PRId64 ")",
                output->globalPath().h.data(), most_recent_input->globalPath().h.data(),
                entry->mtime, most_recent_input->mtime());
        return true;
      }
    }
    if (!entry && !generator) {
      EXPLAIN("command line not found in log for %s", output->globalPath().h.data());
      return true;
    }
  }

  return false;
}

bool DependencyScan::LoadDyndeps(Node* node, string* err) const {
  return dyndep_loader_.LoadDyndeps(node, err);
}

bool DependencyScan::LoadDyndeps(Node* node, DyndepFile* ddf,
                                 string* err) const {
  return dyndep_loader_.LoadDyndeps(node, ddf, err);
}

bool Edge::AllInputsReady() const {
  for (vector<Node*>::const_iterator i = inputs_.begin();
       i != inputs_.end(); ++i) {
    if ((*i)->in_edge() && !(*i)->in_edge()->outputs_ready())
      return false;
  }
  return true;
}

static const HashedStrView kIn        { "in" };
static const HashedStrView kInNewline { "in_newline" };
static const HashedStrView kOut       { "out" };

bool EdgeEval::EvaluateVariable(std::string* out_append,
                                const HashedStrView& var,
                                Scope* target,
                                std::string* err) {
  if (var == kIn || var == kInNewline) {
    int explicit_deps_count = edge_->inputs_.size() - edge_->implicit_deps_ -
      edge_->order_only_deps_;
    AppendPathList(out_append,
                   edge_->inputs_.begin(),
                   edge_->inputs_.begin() + explicit_deps_count,
                   var == kIn ? ' ' : '\n', target);
    return true;
  } else if (var == kOut) {
    int explicit_outs_count = edge_->outputs_.size() - edge_->implicit_outs_;
    AppendPathList(out_append,
                   edge_->outputs_.begin(),
                   edge_->outputs_.begin() + explicit_outs_count,
                   ' ', target);
    return true;
  }

  if (edge_->EvaluateVariableSelfOnly(out_append, var))
    return true;

  // Search for a matching rule binding.
  if (const std::string* binding_pattern = edge_->rule().GetBinding(var)) {
    // Detect recursive rule variable usage.
    if (recursion_count_ == kEvalRecursionLimit) {
      std::string cycle = recursion_vars_[0].AsString();
      for (int i = 1; i < kEvalRecursionLimit; ++i) {
        cycle += " -> " + recursion_vars_[i].AsString();
        if (recursion_vars_[i] == recursion_vars_[0])
          break;
      }
      *err = "cycle in rule variables: " + cycle;
      return false;
    }
    recursion_vars_[recursion_count_++] = var.str_view();

    return EvaluateBindingOnRule(out_append, *binding_pattern, this, target, err);
  }

  // Fall back to the edge's enclosing scope.
  if (eval_phase_ == EdgeEval::kParseTime) {
    Scope::EvaluateVariableAtPos(out_append, var, edge_->pos_.scope_pos());
  } else {
    Scope::EvaluateVariable(out_append, var, edge_->pos_.scope());
  }
  return true;
}

void EdgeEval::AppendPathList(std::string* out_append,
                              std::vector<Node*>::iterator begin,
                              std::vector<Node*>::iterator end,
                              char sep, Scope* target) {
  for (auto it = begin; it != end; ++it) {
    if (it != begin)
      out_append->push_back(sep);

    string path = (*it)->PathDecanonicalized(target);
    if (escape_in_out_ == kShellEscape) {
#if _WIN32
      GetWin32EscapedString(path, out_append);
#else
      GetShellEscapedString(path, out_append);
#endif
    } else {
      out_append->append(path);
    }
  }
}

static const HashedStrView kCommand         { "command" };
static const HashedStrView kDepfile         { "depfile" };
static const HashedStrView kDyndep          { "dyndep" };
static const HashedStrView kRspfile         { "rspfile" };
static const HashedStrView kRspFileContent  { "rspfile_content" };

bool Edge::EvaluateCommand(std::string* out_append, bool incl_rsp_file,
                           std::string* err) {
  METRIC_RECORD("eval command");
  auto len_pre_chdir = out_append->size();
  if (!pos_.scope()->chdir().empty()) {
#ifdef _WIN32
    out_append->append(NINJA_WIN32_CD_DELIM);
    out_append->append(pos_.scope()->chdir());
    out_append->append(NINJA_WIN32_CD_DELIM);
#else
    out_append->append("cd \"");
    out_append->append(pos_.scope()->chdir());
    out_append->append("\" && ");
#endif
  }
  auto len_post_chdir = out_append->size();
  if (!EvaluateVariable(out_append, kCommand, pos_.scope(), err))
    return false;
  // out_append has the chdir in it, waiting, but the correct output
  // is the empty string if EvaluateVariable() produced the empty string.
  // In other words, clean up chdir if it's the only thing in out_append.
  if (!pos_.scope()->chdir().empty() && out_append->size() == len_post_chdir) {
    out_append->resize(len_pre_chdir);
  }

  if (incl_rsp_file) {
    std::string rspfile_content;
    if (!EvaluateVariable(&rspfile_content, kRspFileContent, pos_.scope(), err))
      return false;
    if (!rspfile_content.empty()) {
      out_append->append(";rspfile=");
      out_append->append(rspfile_content);
    }
  }
  return true;
}

void Edge::EvaluateCommand(EdgeCommand* out, bool incl_rsp_file) {
  std::string err;
  if (!EvaluateCommand(&out->command, incl_rsp_file, &err))
    Fatal("%s", err.c_str());
  out->use_console = use_console();
  out->env = cmdEnviron;
}

static const HashedStrView kRestat      { "restat" };
static const HashedStrView kGenerator   { "generator" };
static const HashedStrView kDeps        { "deps" };
static const HashedStrView kPhonyOutput  { "phony_output" };

bool Edge::PrecomputeDepScanInfo(std::string* err) {
  if (dep_scan_info_.valid)
    return true;

  // Precompute boolean flags.
  auto get_bool_var = [this, err](const HashedStrView& var,
                                  EdgeEval::EscapeKind escape, bool* out) {
    std::string value;
    if (!EvaluateVariable(&value, var, pos_.scope(), err, EdgeEval::kFinalScope, escape))
      return false;
    *out = !value.empty();
    return true;
  };
  if (!get_bool_var(kRestat,      EdgeEval::kShellEscape, &dep_scan_info_.restat))       return false;
  if (!get_bool_var(kGenerator,   EdgeEval::kShellEscape, &dep_scan_info_.generator))    return false;
  if (!get_bool_var(kDeps,        EdgeEval::kShellEscape, &dep_scan_info_.deps))         return false;
  if (!get_bool_var(kDepfile,     EdgeEval::kDoNotEscape, &dep_scan_info_.depfile))      return false;
  if (!get_bool_var(kPhonyOutput, EdgeEval::kShellEscape, &dep_scan_info_.phony_output)) return false;

  // Precompute the command hash.
  std::string command;
  if (!EvaluateCommand(&command, /*incl_rsp_file=*/true, err))
    return false;
  dep_scan_info_.command_hash = BuildLog::LogEntry::HashCommand(command);

  dep_scan_info_.valid = true;
  return true;
}

/// Returns dependency-scanning info or exits with a fatal error.
const Edge::DepScanInfo& Edge::ComputeDepScanInfo() {
  std::string err;
  if (!PrecomputeDepScanInfo(&err))
    Fatal("%s", err.c_str());
  return dep_scan_info_;
}

void Edge::SetRestat() {
  std::string err;
  if (!PrecomputeDepScanInfo(&err))
    Fatal("%s", err.c_str());
  dep_scan_info_.restat = true;
}

bool Edge::EvaluateVariable(std::string* out_append, const HashedStrView& key,
                            Scope* target, std::string* err,
                            EdgeEval::EvalPhase phase,
                            EdgeEval::EscapeKind escape) {
  EdgeEval eval(this, phase, escape);
  return eval.EvaluateVariable(out_append, key, target, err);
}

std::string Edge::GetBindingImpl(const HashedStrView& key,
                                 EdgeEval::EvalPhase phase,
                                 EdgeEval::EscapeKind escape) {
  std::string result;
  std::string err;
  if (!EvaluateVariable(&result, key, pos_.scope(), &err, phase, escape))
    Fatal("%s", err.c_str());
  return result;
}

std::string Edge::GetBinding(const HashedStrView& key) {
  return GetBindingImpl(key, EdgeEval::kFinalScope, EdgeEval::kShellEscape);
}

std::string Edge::GetUnescapedDepfile() {
  return GetBindingImpl(kDepfile, EdgeEval::kFinalScope, EdgeEval::kDoNotEscape);
}

std::string Edge::GetUnescapedDyndep() {
  return GetBindingImpl(kDyndep, EdgeEval::kFinalScope, EdgeEval::kDoNotEscape);
}

std::string Edge::GetUnescapedRspfile() {
  return GetBindingImpl(kRspfile, EdgeEval::kFinalScope, EdgeEval::kDoNotEscape);
}

void Edge::Dump(const char* prefix) const {
  printf("%s[ ", prefix);
  for (vector<Node*>::const_iterator i = inputs_.begin();
       i != inputs_.end() && *i != NULL; ++i) {
    printf("%s ", (*i)->path().c_str());
  }
  printf("--%s-> ", rule_->name().c_str());
  for (vector<Node*>::const_iterator i = outputs_.begin();
       i != outputs_.end() && *i != NULL; ++i) {
    printf("%s ", (*i)->path().c_str());
  }
  if (!validations_.empty()) {
    printf(" validations ");
    for (vector<Node*>::const_iterator i = validations_.begin();
         i != validations_.end() && *i != NULL; ++i) {
      printf("%s ", (*i)->path().c_str());
    }
  }
  if (pool_) {
    if (!pool_->name().empty()) {
      printf("(in pool '%s')", pool_->name().c_str());
    }
  } else {
    printf("(null pool?)");
  }
  printf("] 0x%p\n", this);
}

bool Edge::is_phony() const {
  return rule_ == &State::kPhonyRule;
}

bool Edge::use_console() const {
  return pool() == &State::kConsolePool;
}

bool Edge::maybe_phonycycle_diagnostic() const {
  // CMake 2.8.12.x and 3.0.x produced self-referencing phony rules
  // of the form "build a: phony ... a ...".   Restrict our
  // "phonycycle" diagnostic option to the form it used.
  return is_phony() && outputs_.size() == 1 && implicit_outs_ == 0 &&
      implicit_deps_ == 0 && order_only_deps_ == 0;
}

bool Edge::EvaluateVariableSelfOnly(std::string* out_append,
                                    const HashedStrView& var) const {
  // ninja allows declaring the same binding repeatedly on an edge. Use the
  // last matching binding.
  const auto it_end = unevaled_bindings_.rend();
  for (auto it = unevaled_bindings_.rbegin(); it != it_end; ++it) {
    if (var == it->first) {
      EvaluateBindingInScope(out_append, it->second, pos_.scope_pos());
      return true;
    }
  }
  return false;
}

// static
string Node::PathDecanonicalized(const string& path, uint64_t slash_bits) {
  string result = path;
#ifdef _WIN32
  uint64_t mask = 1;
  for (char* c = &result[0]; (c = strchr(c, '/')) != NULL;) {
    if (slash_bits & mask)
      *c = '\\';
    c++;
    mask <<= 1;
  }
#endif
  return result;
}

Node::~Node() {
  EdgeList* node = out_edges_.load();
  while (node != nullptr) {
    EdgeList* next = node->next;
    delete node;
    node = next;
  }
}

// Does the node have at least one out edge?
bool Node::has_out_edge() const {
  return out_edges_.load() != nullptr;
}

std::vector<Edge*> Node::GetOutEdges() const {
  // Include out-edges from the manifest.
  std::vector<Edge*> result;
  for (EdgeList* node = out_edges_.load(); node != nullptr; node = node->next) {
    result.push_back(node->edge);
  }
  std::sort(result.begin(), result.end(), EdgeCmp());

  // Add extra out-edges from depfiles and the deps log. Preserve the order
  // of these extra edges; don't sort them.
  std::copy(dep_scan_out_edges_.begin(), dep_scan_out_edges_.end(),
            std::back_inserter(result));

  return result;
}

std::vector<Edge*> Node::GetValidationOutEdges() const {
  std::vector<Edge*> result;
  for (EdgeList* node = validation_out_edges_.load(); node != nullptr; node = node->next) {
    result.push_back(node->edge);
  }
  std::sort(result.begin(), result.end(), EdgeCmp());

  return result;
}

std::vector<Edge*> Node::GetAllOutEdges() const {
  std::vector<Edge*> result = this->GetOutEdges();
  std::vector<Edge*> extra = this->GetValidationOutEdges();
  if (!extra.empty()) {
    result.insert(result.end(), extra.begin(), extra.end());
  }
  return result;
}

void Node::AddOutEdge(Edge* edge) {
  EdgeList* new_node = new EdgeList { edge };
  while (true) {
    EdgeList* cur_head = out_edges_.load();
    new_node->next = cur_head;
    if (out_edges_.compare_exchange_weak(cur_head, new_node))
      break;
  }
}

void Node::AddValidationOutEdge(Edge* edge) {
  EdgeList* new_node = new EdgeList { edge };
  while (true) {
    EdgeList* cur_head = validation_out_edges_.load();
    new_node->next = cur_head;
    if (validation_out_edges_.compare_exchange_weak(cur_head, new_node))
      break;
  }
}

void Node::Dump(const char* prefix) const {
  printf("%s <%s 0x%p> mtime: %" PRId64 "%s, (:%s), ",
         prefix, path().c_str(), this,
         mtime(), mtime() ? "" : " (:missing)",
         dirty() ? " dirty" : " clean");
  if (in_edge()) {
    in_edge()->Dump("in-edge: ");
  } else {
    printf("no in-edge\n");
  }
  printf(" out edges:\n");
  const std::vector<Edge*> out_edges = GetOutEdges();
  for (vector<Edge*>::const_iterator e = out_edges.begin();
       e != out_edges.end() && *e != NULL; ++e) {
    (*e)->Dump(" +- ");
  }
  const std::vector<Edge*> validation_out_edges = GetValidationOutEdges();
  if (!validation_out_edges.empty()) {
    printf(" validation out edges:\n");
    for (vector<Edge*>::const_iterator e = validation_out_edges.begin();
         e != validation_out_edges.end() && *e != NULL; ++e) {
      (*e)->Dump(" +- ");
    }
  }
}

GlobalPathStr Node::globalPath() {
  return scope_->GlobalPath(path_);
}

static void GetDependencyPathsDfs(Node* node, Node* out,
                                  DepPath& path_till_here,
                                  std::unordered_set<Node*>& dead_ends,
                                  std::vector<DepPath>& output) {
  if (node == out) {
    path_till_here.push_back(node);
    output.push_back(path_till_here);
    path_till_here.pop_back();
    return;
  }

  if (dead_ends.find(node) != dead_ends.end())
    return;
  const size_t result_count = output.size();

  path_till_here.push_back(node);
  node->set_dirty(true);
  for (Edge* edge : node->GetAllOutEdges()) {
    for (Node* next : edge->outputs_) {
      if (!next->dirty()) {
        GetDependencyPathsDfs(next, out, path_till_here, dead_ends, output);
      }
    }
  }
  node->set_dirty(false);
  path_till_here.pop_back();

  if (output.size() == result_count) {
    // There are no paths from `node` to `out`, so skip `node` for the rest of
    // the search.
    dead_ends.insert(node);
  }
}

std::vector<DepPath> GetDependencyPaths(Node* in, Node* out) {
  assert(in != nullptr && out != nullptr);
  std::unordered_set<Node*> dead_ends;
  std::vector<DepPath> result;
  DepPath path_till_here;
  GetDependencyPathsDfs(in, out, path_till_here, dead_ends, result);
  return result;
}

bool ImplicitDepLoader::LoadDeps(Edge* edge, string* err) {
  if (edge->UsesDepsLog())
    return LoadDepsFromLog(edge, err);

  if (edge->UsesDepfile()) {
    std::string depfile = edge->GetUnescapedDepfile();
    assert(!depfile.empty() &&
           "UsesDepfile was set, so the depfile should be non-empty");
    return LoadDepFile(edge, depfile, err);
  }

  // No deps to load.
  return true;
}

bool ImplicitDepLoader::LoadDepFile(Edge* edge, const string& path,
                                    string* err) {
  METRIC_RECORD("depfile load");
  // Read depfile content.  Treat a missing depfile as empty.
  string content;
  switch (disk_interface_->ReadFile(path, &content, err)) {
  case DiskInterface::Okay:
    break;
  case DiskInterface::NotFound:
    err->clear();
    break;
  case DiskInterface::OtherError:
    *err = "loading '" + path + "': " + *err;
    return false;
  }
  // On a missing depfile: return false and empty *err.
  if (content.empty()) {
    EXPLAIN("depfile '%s' is missing", path.c_str());
    return false;
  }

  DepfileParser depfile(depfile_parser_options_
                        ? *depfile_parser_options_
                        : DepfileParserOptions());
  string depfile_err;
  string depfile_warn;
  if (!depfile.Parse(&content, &depfile_warn, &depfile_err)) {
    *err = path + ": " + depfile_err;
    return false;
  }

  if (!depfile_warn.empty()) {
    Warning("%s: %s", path.c_str(), depfile_warn.c_str());
  }

  uint64_t unused;
  if (!CanonicalizePath(const_cast<char*>(depfile.out_.str_),
                        &depfile.out_.len_, &unused, err)) {
    *err = path + ": " + *err;
    return false;
  }

  // Check that this depfile matches the edge's output, if not return false to
  // mark the edge as dirty.
  Node* first_output = edge->outputs_[0];
  if (first_output->path() != depfile.out_) {
    EXPLAIN("expected depfile '%s' to mention '%s', got '%s'", path.c_str(),
            first_output->path().c_str(), depfile.out_.AsString().c_str());
    return false;
  }

  // Preallocate space in edge->inputs_ to be filled in below.
  vector<Node*>::iterator implicit_dep =
      PreallocateSpace(edge, depfile.ins_.size());

  // Add all its in-edges.
  for (vector<StringPiece>::iterator i = depfile.ins_.begin();
       i != depfile.ins_.end(); ++i, ++implicit_dep) {
    uint64_t slash_bits;
    if (!CanonicalizePath(const_cast<char*>(i->str_), &i->len_, &slash_bits,
                          err))
      return false;

    Node* node = state_->GetNode(edge->pos_.scope()->GlobalPath(*i),
                                 slash_bits);
    *implicit_dep = node;
    node->AddOutEdgeDepScan(edge);
    CreatePhonyInEdge(node);
  }

  return true;
}

bool ImplicitDepLoader::LoadDepsFromLog(Edge* edge, string* err) {
  // NOTE: deps are only supported for single-target edges.
  Node* output = edge->outputs_[0];
  DepsLog::Deps* deps = deps_log_->GetDeps(output);
  if (!deps) {
    EXPLAIN("deps for '%s' are missing", output->path().c_str());
    return false;
  }

  // Deps are invalid if the output is newer than the deps.
  if (output->mtime() > deps->mtime) {
    EXPLAIN("stored deps info out of date for '%s' (%" PRId64 " vs %" PRId64 ")",
            output->path().c_str(), deps->mtime, output->mtime());
    return false;
  }

  vector<Node*>::iterator implicit_dep =
      PreallocateSpace(edge, deps->node_count);
  for (int i = 0; i < deps->node_count; ++i, ++implicit_dep) {
    Node* node = deps->nodes[i];
    *implicit_dep = node;
    node->AddOutEdgeDepScan(edge);
    CreatePhonyInEdge(node);
  }
  return true;
}

vector<Node*>::iterator ImplicitDepLoader::PreallocateSpace(Edge* edge,
                                                            int count) {
  edge->inputs_.insert(edge->inputs_.end() - edge->order_only_deps_,
                       (size_t)count, 0);
  edge->implicit_deps_ += count;
  return edge->inputs_.end() - edge->order_only_deps_ - count;
}

void ImplicitDepLoader::CreatePhonyInEdge(Node* node) {
  if (node->in_edge())
    return;

  Edge* phony_edge = state_->AddEdge(&State::kPhonyRule);
  node->set_in_edge(phony_edge);
  phony_edge->outputs_.push_back(node);
  ++phony_edge->explicit_outs_;

  // RecomputeDirty might not be called for phony_edge if a previous call
  // to RecomputeDirty had caused the file to be stat'ed.  Because previous
  // invocations of RecomputeDirty would have seen this node without an
  // input edge (and therefore ready), we have to set outputs_ready_ to true
  // to avoid a potential stuck build.  If we do call RecomputeDirty for
  // this node, it will simply set outputs_ready_ to the correct value.
  phony_edge->outputs_ready_ = true;

  phony_edge->phony_from_depfile_ = true;
}
