<commit_before>var async = require("async");
var fs = require("fs");
var mkdirp = require("mkdirp");
var path = require("path");
var solc = require("solc");
var path = require("path");
var Exec = require("./exec");
var Pudding = require("ether-pudding");
var PuddingGenerator = require("ether-pudding/generator");
var ConfigurationError = require("./errors/configurationerror");
var CompileError = require("./errors/compileerror");
var DeployError = require("./errors/deployerror");
var graphlib = require("graphlib");
var Graph = require("graphlib").Graph;
var isAcyclic = require("graphlib/lib/alg").isAcyclic;
var postOrder = require("graphlib/lib/alg").postorder;

var Contracts = {
  account: null,

  get_account: function(config, callback) {
    var self = this;

    if (config.app.resolved.rpc.from != null) {
      this.account = config.app.resolved.rpc.from;
    }

    if (this.account != null) {
      return callback(null, this.account);
    }

    config.web3.eth.getAccounts(function(err, result) {
      if (err != null) return callback(err);

      self.account = result[0];
      callback(null, self.account);
    });
  },

  update_sources(config, callback) {
    var contract_names = Object.keys(config.contracts.classes);
    async.each(contract_names, function(name, done) {
      var contract = config.contracts.classes[name];
      fs.readFile(contract.file, {encoding: "utf8"}, function(err, body) {
        if (err) return done(err);

        contract.body = body;
        done();
      });
    }, callback);
  },

  compile_necessary(config, callback) {
    var self = this;
    this.update_sources(config, function() {
      var contract_names = Object.keys(config.contracts.classes);

      var sources = {};
      var updated = {};
      var included = {};

      for (var i = 0; i < contract_names.length; i++) {
        var name = contract_names[i];
        var contract = config.contracts.classes[name];

        if (contract.source_modified_time > contract.compiled_time || config.argv.compileAll === true) {
          updated[name] = true;
        }
      }

      if (Object.keys(updated).length == 0 && config.argv.quietDeploy == null) {
        console.log("No contracts updated; skipping compilation.");
        return callback();
      }

      var dependsGraph = self.build_compile_dependency_graph(config, callback);

      if (dependsGraph == null) {
        return;
      }

      function is_updated(contract_name) {
        return updated[contract_name] === true;
      }

      function include_source_for(contract_name) {
        var contract = config.contracts.classes[contract_name];
        var source_path = path.relative(config.contracts.directory, contract.source);

        if (sources[source_path] != null) {
          return;
        }

        var full_path = path.resolve(config.working_dir, contract.source)
        sources[source_path] = fs.readFileSync(full_path, {encoding: "utf8"});

        // For graph traversing
        included[contract_name] = true;
      }

      function walk_down(contract_name) {
        if (included[contract_name] === true) {
          return;
        }

        include_source_for(contract_name);

        var dependencies = dependsGraph.successors(contract_name);

        // console.log("At: " + contract_name);
        // console.log("   Dependencies: ", dependencies);

        if (dependencies.length > 0) {
          dependencies.forEach(walk_down);
        }
      }

      function walk_from(contract_name) {
        // if (included[contract_name] === true) {
        //   return;
        // }

        var ancestors = dependsGraph.predecessors(contract_name);
        var dependencies = dependsGraph.successors(contract_name);

        // console.log("At: " + contract_name);
        // console.log("   Ancestors: ", ancestors);
        // console.log("   Dependencies: ", dependencies);

        include_source_for(contract_name);

        if (ancestors.length > 0) {
          ancestors.forEach(walk_from);
        }

        if (dependencies.length > 0) {
          dependencies.forEach(walk_down);
        }
      }

      Object.keys(updated).forEach(walk_from);

      Object.keys(sources).sort().forEach(function(file_path) {
        if (config.argv.quietDeploy == null) {
          console.log("Compiling " + file_path + "...");
        }
      });

      var result = solc.compile({sources: sources}, 1);
      var errors = result.errors || [];
      var warnings = result.errors || [];

      if (!config.argv.strict) {
        errors = errors.filter(function(error) {
          return error.indexOf("Warning:") < 0;
        });
        warnings = warnings.filter(function(error) {
          return error.indexOf("Warning:") >= 0;
        });

        if (config.argv.quietDeploy == null) {
          warnings.forEach(function(warning) {
            console.log(warning);
          });
        }
      }

      if (errors.length > 0) {
        return callback(new CompileError(result.errors.join()));
      }

      // Examine the sources, and ensure the contract we expected was defined
      var filenames = Object.keys(sources);
      for (var i = 0; i < filenames.length; i++) {
        var filename = filenames[i];
        var expected_contract = path.basename(filename, ".sol");

        if (result.contracts[expected_contract] == null) {
          return callback(new CompileError("Could not find expected contract or library in '" + filename + "': contract or library '" + expected_contract + "' not found."));
        }
      }

      for (var i = 0; i < contract_names.length; i++) {
        var name = contract_names[i];
        var contract = config.contracts.classes[name];
        var compiled_contract = result.contracts[name];

        // If we didn't compile this contract this run, continue.
        if (compiled_contract == null) {
          continue;
        }

        contract.binary = compiled_contract.bytecode;
        contract.unlinked_binary = compiled_contract.bytecode;
        contract.abi = JSON.parse(compiled_contract.interface);
      }

      callback();
    });
  },

  compile(config, callback) {
    var self = this;
    async.series([
      function(c) {
        self.compile_necessary(config, c);
      },
      function(c) {
        self.write_contracts(config, "contracts", c);
      }
    ], callback);
  },

  createContractAndWait(config, contract_name) {
    var self = this;

    var tx = {
      from: this.account,
      gas: config.app.resolved.rpc.gas || config.app.resolved.rpc.gasLimit,
      gasPrice: config.app.resolved.rpc.gasPrice, // 100 Shannon
      data: config.contracts.classes[contract_name].binary
    };

    return new Promise(function(accept, reject) {
      config.web3.eth.sendTransaction(tx, function(err, hash) {
        if (err != null) {
          return reject(err);
        }

        var interval = setInterval(function() {
          config.web3.eth.getTransactionReceipt(hash, function(err, receipt) {
            if (err != null) {
              clearInterval(interval);

              return reject(err);
            }
            if (receipt != null) {
              if (config.argv.quietDeploy == null) {
                console.log("Deployed: " + contract_name + " to address: " + receipt.contractAddress);
              }

              accept({
                name: contract_name,
                address: receipt.contractAddress
              });
              clearInterval(interval);
            }
          });
        }, 500);
      })
    });
  },

  build_compile_dependency_graph(config, errorCallback) {
    if (config.argv.quietDeploy == null) {
      console.log("Checking sources...");
    }
    // Iterate through all the contracts looking for libraries and building a dependency graph
    var dependsGraph = new Graph();
    var contract_names = Object.keys(config.contracts.classes);
    for (var i = 0; i < contract_names.length; i++) {
      var name = contract_names[i]
      var contract = config.contracts.classes[name];

      if (contract == null) {
        errorCallback(new CompileError("Could not find contract '" + name + "' for compiling. Check truffle.json."));
        return null;
      }

      // Add the contract to the depend graph
      dependsGraph.setNode(name);

      // Find import statements and resolve those import paths, adding them to the graph.
      contract.body.split(/;|\n/).filter(function(line) {
        return line.indexOf("import") >= 0;
      }).forEach(function(line) {
        var regex = /import.*("|')([^"']+)("|')*/g;
        var match = regex.exec(line);

        if (match == null) return;

        var file = match[2];
        var dependency_name = path.basename(file, ".sol");

        if (!dependsGraph.hasEdge(name, dependency_name)) {
          dependsGraph.setEdge(name, dependency_name);
        }
      });
    }
    // Check for cycles in the graph, the dependency graph needs to be a tree otherwise there's an error
    if (!isAcyclic(dependsGraph))
    {
      console.log("ERROR: Cycles in dependency graph");
      dependsGraph.edges().forEach(function(o){
        console.log(o.v+" -- depends on --> "+o.w);
      });
      errorCallback(new CompileError("Found cyclic dependencies. Adjust your import statements to remove cycles."));
      return null;
    }
    return dependsGraph;
  },

  build_deploy_dependency_graph(config, errorCallback) {
    if (config.argv.quietDeploy == null) {
      console.log("Collecting dependencies...");
    }
    // Iterate through all the contracts looking for libraries and building a dependency graph
    var dependsGraph = new Graph();
    for (var i = 0; i < config.app.resolved.deploy.length; i++) {
      var key = config.app.resolved.deploy[i];
      var contract_class = config.contracts.classes[key];

      if (contract_class == null) {
        errorCallback(new DeployError("Could not find contract '" + key + "' for linking. Check truffle.json."));
        return null;
      }

      if (contract_class.binary == null){
        errorCallback(new DeployError("Could not find compiled binary for contract '" + key + "'. Check truffle.json."));
        return null;
      }
      // Add the contract to the depend graph
      dependsGraph.setNode(key);

      // Find references to any librarys
      // Library references are embedded in the bytecode of contracts with the format
      //  "__Lib___________________________________" , where "Lib" is your library name and the whole
      //  string is 40 characters long. This is the placeholder for the Lib's address.

      var regex = /__([^_]*)_*/g;
      var matches;
      while ( (matches = regex.exec(contract_class.unlinked_binary)) !== null ) {
        var lib = matches[1];
        if (!dependsGraph.hasEdge(key,lib)) {
          dependsGraph.setEdge(key, lib);
        }
      }
    }
    // Check for cycles in the graph, the dependency graph needs to be a tree otherwise there's an error
    if (!isAcyclic(dependsGraph))
    {
      console.log("ERROR: Cycles in dependency graph");
      dependsGraph.edges().forEach(function(o){
        console.log(o.v+" -- depends on --> "+o.w);
      });
      errorCallback(new DeployError("Error  linker found cyclic dependencies. Adjust your import statements to remove cycles."));
      return null;
    }
    return dependsGraph;
  },

  link_dependencies(config, contract_name) {
    var self = this;
    return function(dependency_addresses) {
      var contract = config.contracts.classes[contract_name];

      //All of the library dependencies to this contract have been deployed
      //Inject the address of each lib into this contract and then deploy it.
      dependency_addresses.forEach(function(lib) {
        if (config.argv.quietDeploy == null) {
          console.log("Linking Library: " + lib.name + " to contract: " + contract_name + " at address: " + lib.address);
        }

        var bin_address = lib.address.replace("0x", "");
        var re = new RegExp("__" + lib.name + "_*", "g");
        contract.binary = contract.unlinked_binary.replace(re, bin_address);
      });

      return self.createContractAndWait(config, contract_name);
    }
  },

  deploy(config, compile, done_deploying) {
    var self = this;

    if (typeof compile == "function") {
      done_deploying = compile;
      compile = true;
    }

    if (compile == null) {
      compile == true;
    }

    async.series([
      function(c) {
        self.get_account(config, c);
      },
      function(c) {
        if (compile == true) {
          self.compile_necessary(config, c);
        } else {
          c();
        }
      },
      function(c) {
        Pudding.setWeb3(config.web3);
        var dependsGraph = self.build_deploy_dependency_graph(config, c);

        if( dependsGraph == null) {
          return;
        }

        var dependsOrdering = postOrder(dependsGraph, dependsGraph.nodes());
        var deploy_promise = null;
        var contract_name; // This is in global scope so that it can be used in the .catch below

        // Iterate over the dependency grpah in post order, deploy libraries first so we can
        // capture their addresses and use them to deploy the contracts that depend on them
        for(var i = 0; i < dependsOrdering.length; i++) {
          contract_name = dependsOrdering[i];
          var contract_class = config.contracts.classes[contract_name];

          if (contract_class == null) {
            c(new DeployError("Could not find contract '" + key + "' for deployment. Check truffle.json."));
            return;
          }

          var dependencies = dependsGraph.successors(contract_name);

          // When we encounter a Library that is not dependant on other libraries, we can just
          // deploy it as normal
          if (dependencies.length == 0) {
            deploy_promise = self.createContractAndWait(config, contract_name);

            // Store the promise in the graph so we can fetch it later
            dependsGraph.setNode(contract_name, deploy_promise);
          }
          // Contracts that have dependencies need to wait until those dependencies have been deployed
          // so we can inject the address into their byte code
          else
          {
            // Collect all the promises for the libraries this contract depends on into a list
            // NOTE: since this loop is traversing in post-order, we can be assured that this list
            // will contain ALL of the dependencies of this contract
            var depends_promises = dependencies.map(dependsGraph.node, dependsGraph);

            // Wait for all the dependencies to be committed and then do the linking step
            deploy_promise = Promise.all(depends_promises).then(
              self.link_dependencies(config, contract_name)
            );

            // It's possible that this contract is a dependency of some other contract so we store
            // it in the graph just in case
            dependsGraph.setNode(contract_name,deploy_promise);
          }
        }
        ///Now wait for all of the outstanding deployments to complete
        Promise.all(dependsGraph.nodes().map(dependsGraph.node, dependsGraph))
        .then(function(deployed_contracts) {
          deployed_contracts.forEach(function(a) {
            config.contracts.classes[a.name].address = a.address;
          });
          c();
        }).catch(function(err) {
          c(new DeployError(err.message, contract_name));
        });
      },
      function(c) {
        self.write_contracts(config, "built contract files", c);
      },
      function(c) {
        self.after_deploy(config, c);
      }
    ], function(err) {
      if (err != null) {
        done_deploying(err);
        return;
      } else {
        done_deploying();
      }
    });
  },

  after_deploy(config, done) {
    async.eachSeries(config.app.resolved.after_deploy, function(file, iterator_callback) {
      if (config.argv.quietDeploy == null) {
        console.log("Running post deploy script " + file + "...");
      }
      Exec.file(config, file, iterator_callback);
    }, done);
  },

  write_contracts(config, description, callback) {
    var destination = config.contracts.build_directory;

    description = description || "contracts";

    mkdirp(destination, function(err, result) {
      if (err != null) {
        callback(err);
        return;
      }

      var display_directory = "." + path.sep + path.relative(config.working_dir, destination); // path.join("./", destination.replace(config.working_dir, ""));
      if (config.argv.quietDeploy == null) {
        console.log("Writing " + description + " to " + display_directory);
      }

      PuddingGenerator.save(config.contracts.classes, destination, {removeExisting: true});

      callback();
    });
  }
}

module.exports = Contracts;
<commit_msg>Fix issue in error handling.<commit_after>var async = require("async");
var fs = require("fs");
var mkdirp = require("mkdirp");
var path = require("path");
var solc = require("solc");
var path = require("path");
var Exec = require("./exec");
var Pudding = require("ether-pudding");
var PuddingGenerator = require("ether-pudding/generator");
var ConfigurationError = require("./errors/configurationerror");
var CompileError = require("./errors/compileerror");
var DeployError = require("./errors/deployerror");
var graphlib = require("graphlib");
var Graph = require("graphlib").Graph;
var isAcyclic = require("graphlib/lib/alg").isAcyclic;
var postOrder = require("graphlib/lib/alg").postorder;

var Contracts = {
  account: null,

  get_account: function(config, callback) {
    var self = this;

    if (config.app.resolved.rpc.from != null) {
      this.account = config.app.resolved.rpc.from;
    }

    if (this.account != null) {
      return callback(null, this.account);
    }

    config.web3.eth.getAccounts(function(err, result) {
      if (err != null) return callback(err);

      self.account = result[0];
      callback(null, self.account);
    });
  },

  update_sources(config, callback) {
    var contract_names = Object.keys(config.contracts.classes);
    async.each(contract_names, function(name, done) {
      var contract = config.contracts.classes[name];
      fs.readFile(contract.file, {encoding: "utf8"}, function(err, body) {
        if (err) return done(err);

        contract.body = body;
        done();
      });
    }, callback);
  },

  compile_necessary(config, callback) {
    var self = this;
    this.update_sources(config, function() {
      var contract_names = Object.keys(config.contracts.classes);

      var sources = {};
      var updated = {};
      var included = {};

      for (var i = 0; i < contract_names.length; i++) {
        var name = contract_names[i];
        var contract = config.contracts.classes[name];

        if (contract.source_modified_time > contract.compiled_time || config.argv.compileAll === true) {
          updated[name] = true;
        }
      }

      if (Object.keys(updated).length == 0 && config.argv.quietDeploy == null) {
        console.log("No contracts updated; skipping compilation.");
        return callback();
      }

      var dependsGraph = self.build_compile_dependency_graph(config, callback);

      if (dependsGraph == null) {
        return;
      }

      function is_updated(contract_name) {
        return updated[contract_name] === true;
      }

      function include_source_for(contract_name) {
        var contract = config.contracts.classes[contract_name];
        var source_path = path.relative(config.contracts.directory, contract.source);

        if (sources[source_path] != null) {
          return;
        }

        var full_path = path.resolve(config.working_dir, contract.source)
        sources[source_path] = fs.readFileSync(full_path, {encoding: "utf8"});

        // For graph traversing
        included[contract_name] = true;
      }

      function walk_down(contract_name) {
        if (included[contract_name] === true) {
          return;
        }

        include_source_for(contract_name);

        var dependencies = dependsGraph.successors(contract_name);

        // console.log("At: " + contract_name);
        // console.log("   Dependencies: ", dependencies);

        if (dependencies.length > 0) {
          dependencies.forEach(walk_down);
        }
      }

      function walk_from(contract_name) {
        // if (included[contract_name] === true) {
        //   return;
        // }

        var ancestors = dependsGraph.predecessors(contract_name);
        var dependencies = dependsGraph.successors(contract_name);

        // console.log("At: " + contract_name);
        // console.log("   Ancestors: ", ancestors);
        // console.log("   Dependencies: ", dependencies);

        include_source_for(contract_name);

        if (ancestors.length > 0) {
          ancestors.forEach(walk_from);
        }

        if (dependencies.length > 0) {
          dependencies.forEach(walk_down);
        }
      }

      Object.keys(updated).forEach(walk_from);

      Object.keys(sources).sort().forEach(function(file_path) {
        if (config.argv.quietDeploy == null) {
          console.log("Compiling " + file_path + "...");
        }
      });

      var result = solc.compile({sources: sources}, 1);
      var errors = result.errors || [];
      var warnings = result.errors || [];

      if (!config.argv.strict) {
        errors = errors.filter(function(error) {
          return error.indexOf("Warning:") < 0;
        });
        warnings = warnings.filter(function(error) {
          return error.indexOf("Warning:") >= 0;
        });

        if (config.argv.quietDeploy == null) {
          warnings.forEach(function(warning) {
            console.log(warning);
          });
        }
      }

      if (errors.length > 0) {
        return callback(new CompileError(result.errors.join()));
      }

      // Examine the sources, and ensure the contract we expected was defined
      var filenames = Object.keys(sources);
      for (var i = 0; i < filenames.length; i++) {
        var filename = filenames[i];
        var expected_contract = path.basename(filename, ".sol");

        if (result.contracts[expected_contract] == null) {
          return callback(new CompileError("Could not find expected contract or library in '" + filename + "': contract or library '" + expected_contract + "' not found."));
        }
      }

      for (var i = 0; i < contract_names.length; i++) {
        var name = contract_names[i];
        var contract = config.contracts.classes[name];
        var compiled_contract = result.contracts[name];

        // If we didn't compile this contract this run, continue.
        if (compiled_contract == null) {
          continue;
        }

        contract.binary = compiled_contract.bytecode;
        contract.unlinked_binary = compiled_contract.bytecode;
        contract.abi = JSON.parse(compiled_contract.interface);
      }

      callback();
    });
  },

  compile(config, callback) {
    var self = this;
    async.series([
      function(c) {
        self.compile_necessary(config, c);
      },
      function(c) {
        self.write_contracts(config, "contracts", c);
      }
    ], callback);
  },

  createContractAndWait(config, contract_name) {
    var self = this;

    var tx = {
      from: this.account,
      gas: config.app.resolved.rpc.gas || config.app.resolved.rpc.gasLimit,
      gasPrice: config.app.resolved.rpc.gasPrice, // 100 Shannon
      data: config.contracts.classes[contract_name].binary
    };

    return new Promise(function(accept, reject) {
      config.web3.eth.sendTransaction(tx, function(err, hash) {
        if (err != null) {
          return reject(err);
        }

        var interval = setInterval(function() {
          config.web3.eth.getTransactionReceipt(hash, function(err, receipt) {
            if (err != null) {
              clearInterval(interval);

              return reject(err);
            }
            if (receipt != null) {
              if (config.argv.quietDeploy == null) {
                console.log("Deployed: " + contract_name + " to address: " + receipt.contractAddress);
              }

              accept({
                name: contract_name,
                address: receipt.contractAddress
              });
              clearInterval(interval);
            }
          });
        }, 500);
      })
    });
  },

  build_compile_dependency_graph(config, errorCallback) {
    if (config.argv.quietDeploy == null) {
      console.log("Checking sources...");
    }
    // Iterate through all the contracts looking for libraries and building a dependency graph
    var dependsGraph = new Graph();
    var contract_names = Object.keys(config.contracts.classes);
    for (var i = 0; i < contract_names.length; i++) {
      var name = contract_names[i]
      var contract = config.contracts.classes[name];

      if (contract == null) {
        errorCallback(new CompileError("Could not find contract '" + name + "' for compiling. Check truffle.json."));
        return null;
      }

      // Add the contract to the depend graph
      dependsGraph.setNode(name);

      // Find import statements and resolve those import paths, adding them to the graph.
      contract.body.split(/;|\n/).filter(function(line) {
        return line.indexOf("import") >= 0;
      }).forEach(function(line) {
        var regex = /import.*("|')([^"']+)("|')*/g;
        var match = regex.exec(line);

        if (match == null) return;

        var file = match[2];
        var dependency_name = path.basename(file, ".sol");

        if (!dependsGraph.hasEdge(name, dependency_name)) {
          dependsGraph.setEdge(name, dependency_name);
        }
      });
    }
    // Check for cycles in the graph, the dependency graph needs to be a tree otherwise there's an error
    if (!isAcyclic(dependsGraph))
    {
      console.log("ERROR: Cycles in dependency graph");
      dependsGraph.edges().forEach(function(o){
        console.log(o.v+" -- depends on --> "+o.w);
      });
      errorCallback(new CompileError("Found cyclic dependencies. Adjust your import statements to remove cycles."));
      return null;
    }
    return dependsGraph;
  },

  build_deploy_dependency_graph(config, errorCallback) {
    if (config.argv.quietDeploy == null) {
      console.log("Collecting dependencies...");
    }
    // Iterate through all the contracts looking for libraries and building a dependency graph
    var dependsGraph = new Graph();
    for (var i = 0; i < config.app.resolved.deploy.length; i++) {
      var key = config.app.resolved.deploy[i];
      var contract_class = config.contracts.classes[key];

      if (contract_class == null) {
        errorCallback(new DeployError("Could not find contract '" + key + "' for linking. Check truffle.json."));
        return null;
      }

      if (contract_class.binary == null){
        errorCallback(new DeployError("Could not find compiled binary for contract '" + key + "'. Check truffle.json."));
        return null;
      }
      // Add the contract to the depend graph
      dependsGraph.setNode(key);

      // Find references to any librarys
      // Library references are embedded in the bytecode of contracts with the format
      //  "__Lib___________________________________" , where "Lib" is your library name and the whole
      //  string is 40 characters long. This is the placeholder for the Lib's address.

      var regex = /__([^_]*)_*/g;
      var matches;
      while ( (matches = regex.exec(contract_class.unlinked_binary)) !== null ) {
        var lib = matches[1];
        if (!dependsGraph.hasEdge(key,lib)) {
          dependsGraph.setEdge(key, lib);
        }
      }
    }
    // Check for cycles in the graph, the dependency graph needs to be a tree otherwise there's an error
    if (!isAcyclic(dependsGraph))
    {
      console.log("ERROR: Cycles in dependency graph");
      dependsGraph.edges().forEach(function(o){
        console.log(o.v+" -- depends on --> "+o.w);
      });
      errorCallback(new DeployError("Error  linker found cyclic dependencies. Adjust your import statements to remove cycles."));
      return null;
    }
    return dependsGraph;
  },

  link_dependencies(config, contract_name) {
    var self = this;
    return function(dependency_addresses) {
      var contract = config.contracts.classes[contract_name];

      //All of the library dependencies to this contract have been deployed
      //Inject the address of each lib into this contract and then deploy it.
      dependency_addresses.forEach(function(lib) {
        if (config.argv.quietDeploy == null) {
          console.log("Linking Library: " + lib.name + " to contract: " + contract_name + " at address: " + lib.address);
        }

        var bin_address = lib.address.replace("0x", "");
        var re = new RegExp("__" + lib.name + "_*", "g");
        contract.binary = contract.unlinked_binary.replace(re, bin_address);
      });

      return self.createContractAndWait(config, contract_name);
    }
  },

  deploy(config, compile, done_deploying) {
    var self = this;

    if (typeof compile == "function") {
      done_deploying = compile;
      compile = true;
    }

    if (compile == null) {
      compile == true;
    }

    async.series([
      function(c) {
        self.get_account(config, c);
      },
      function(c) {
        if (compile == true) {
          self.compile_necessary(config, c);
        } else {
          c();
        }
      },
      function(c) {
        Pudding.setWeb3(config.web3);
        var dependsGraph = self.build_deploy_dependency_graph(config, c);

        if( dependsGraph == null) {
          return;
        }

        var dependsOrdering = postOrder(dependsGraph, dependsGraph.nodes());
        var deploy_promise = null;
        var contract_name; // This is in global scope so that it can be used in the .catch below

        // Iterate over the dependency grpah in post order, deploy libraries first so we can
        // capture their addresses and use them to deploy the contracts that depend on them
        for(var i = 0; i < dependsOrdering.length; i++) {
          contract_name = dependsOrdering[i];
          var contract_class = config.contracts.classes[contract_name];

          if (contract_class == null) {
            c(new DeployError("Could not find contract '" + contract_name + "' for deployment. Check truffle.json."));
            return;
          }

          var dependencies = dependsGraph.successors(contract_name);

          // When we encounter a Library that is not dependant on other libraries, we can just
          // deploy it as normal
          if (dependencies.length == 0) {
            deploy_promise = self.createContractAndWait(config, contract_name);

            // Store the promise in the graph so we can fetch it later
            dependsGraph.setNode(contract_name, deploy_promise);
          }
          // Contracts that have dependencies need to wait until those dependencies have been deployed
          // so we can inject the address into their byte code
          else
          {
            // Collect all the promises for the libraries this contract depends on into a list
            // NOTE: since this loop is traversing in post-order, we can be assured that this list
            // will contain ALL of the dependencies of this contract
            var depends_promises = dependencies.map(dependsGraph.node, dependsGraph);

            // Wait for all the dependencies to be committed and then do the linking step
            deploy_promise = Promise.all(depends_promises).then(
              self.link_dependencies(config, contract_name)
            );

            // It's possible that this contract is a dependency of some other contract so we store
            // it in the graph just in case
            dependsGraph.setNode(contract_name,deploy_promise);
          }
        }
        ///Now wait for all of the outstanding deployments to complete
        Promise.all(dependsGraph.nodes().map(dependsGraph.node, dependsGraph))
        .then(function(deployed_contracts) {
          deployed_contracts.forEach(function(a) {
            config.contracts.classes[a.name].address = a.address;
          });
          c();
        }).catch(function(err) {
          c(new DeployError(err.message, contract_name));
        });
      },
      function(c) {
        self.write_contracts(config, "built contract files", c);
      },
      function(c) {
        self.after_deploy(config, c);
      }
    ], function(err) {
      if (err != null) {
        done_deploying(err);
        return;
      } else {
        done_deploying();
      }
    });
  },

  after_deploy(config, done) {
    async.eachSeries(config.app.resolved.after_deploy, function(file, iterator_callback) {
      if (config.argv.quietDeploy == null) {
        console.log("Running post deploy script " + file + "...");
      }
      Exec.file(config, file, iterator_callback);
    }, done);
  },

  write_contracts(config, description, callback) {
    var destination = config.contracts.build_directory;

    description = description || "contracts";

    mkdirp(destination, function(err, result) {
      if (err != null) {
        callback(err);
        return;
      }

      var display_directory = "." + path.sep + path.relative(config.working_dir, destination); // path.join("./", destination.replace(config.working_dir, ""));
      if (config.argv.quietDeploy == null) {
        console.log("Writing " + description + " to " + display_directory);
      }

      PuddingGenerator.save(config.contracts.classes, destination, {removeExisting: true});

      callback();
    });
  }
}

module.exports = Contracts;
<|endoftext|>


<commit_before>import React from 'react';
import NavigationBar from '../NavigationBar/NavigationBar.js';
import SuccessButton from '../SuccessButton/SuccessButton.js';
import FindYourPath from '../FindYourPath/FindYourPath'

const App = () => (

    <NavigationBar />

    {/*<UniversityDropdown />*/}
    <FindYourPath />

);

export default App;
<commit_msg>Remove SuccessButton import<commit_after>import React from 'react';
import NavigationBar from '../NavigationBar/NavigationBar.js';
import FindYourPath from '../FindYourPath/FindYourPath'

const App = () => (

    <NavigationBar />

    {/*<UniversityDropdown />*/}
    <FindYourPath />

);

export default App;
<|endoftext|>


<commit_before>const path = require("path");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const webpack = require("webpack");
const pkg = require("./package.json");
const rootDir = path.join(__dirname, "../..");
const outputDir = path.join(__dirname, "build");

module.exports = {
  entry: {
    cli: path.join(
      __dirname,
      "../..",
      "node_modules",
      "@truffle/core",
      "cli.js"
    ),
    chain: path.join(
      __dirname,
      "../..",
      "node_modules",
      "@truffle/environment",
      "chain.js"
    ),
    analytics: path.join(
      __dirname,
      "../..",
      "node_modules",
      "@truffle/core",
      "lib",
      "services",
      "analytics",
      "main.js"
    ),
    library: path.join(
      __dirname,
      "../..",
      "node_modules",
      "@truffle/core",
      "index.js"
    )
  },
  target: "node",
  node: {
    // For this option, see here: https://github.com/webpack/webpack/issues/1599
    __dirname: false,
    __filename: false
  },
  context: rootDir,
  output: {
    path: outputDir,
    filename: "[name].bundled.js",
    library: "",
    libraryTarget: "commonjs"
  },
  devtool: "source-map",
  module: {
    rules: [
      {
        test: /\.js$/,
        include: [
          path.resolve(__dirname, "../core"),
          path.resolve(__dirname, "../environment")
        ],
        use: "shebang-loader"
      }
    ]
  },
  externals: [
    // If you look at webpack's docs, `externals` doesn't need to be a function.
    // But I never got it to work otherwise, so this is a function because "it works".
    function(context, request, callback) {
      // truffle-config uses the original-require module.
      // Here, we leave it as an external, and use the original-require
      // module that's a dependency of Truffle instead.
      if (/^original-require$/.test(request)) {
        return callback(null, "commonjs original-require");
      }

      // Mocha doesn't seem to bundle well either. This is a stop-gap until
      // I can look into it further.
      if (/^mocha$/.test(request)) {
        return callback(null, "commonjs mocha");
      }

      callback();
    }
  ],
  plugins: [
    new webpack.DefinePlugin({
      BUNDLE_VERSION: JSON.stringify(pkg.version),
      BUNDLE_CHAIN_FILENAME: JSON.stringify("chain.bundled.js"),
      BUNDLE_ANALYTICS_FILENAME: JSON.stringify("analytics.bundled.js"),
      BUNDLE_LIBRARY_FILENAME: JSON.stringify("library.bundled.js")
    }),

    // Put the shebang back on.
    new webpack.BannerPlugin({ banner: "#!/usr/bin/env node\n", raw: true }),

    // `truffle test`
    new CopyWebpackPlugin([
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "Assert.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertAddress.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertAddressArray.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertAddressPayableArray.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertBalance.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertBool.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertBytes32.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertBytes32Array.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertGeneral.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertInt.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertIntArray.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertString.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertUint.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertUintArray.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "NewSafeSend.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "OldSafeSend.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "templates/"
        ),
        to: "templates",
        flatten: true
      }
    ]),

    new CleanWebpackPlugin(["build"]),

    // Make web3 1.0 packable
    new webpack.IgnorePlugin(/^electron$/)
  ],
  resolve: {
    alias: {
      "ws": path.join(__dirname, "./nil.js"),
      "bn.js": path.join(
        __dirname,
        "../..",
        "node_modules",
        "bn.js",
        "lib",
        "bn.js"
      ),
      "original-fs": path.join(__dirname, "./nil.js"),
      "scrypt": "js-scrypt"
    }
  },
  stats: {
    warnings: false
  }
};
<commit_msg>add comment to explain shebang-loader usage (truffle/cli.webpack.config)<commit_after>const path = require("path");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const webpack = require("webpack");
const pkg = require("./package.json");
const rootDir = path.join(__dirname, "../..");
const outputDir = path.join(__dirname, "build");

module.exports = {
  entry: {
    cli: path.join(
      __dirname,
      "../..",
      "node_modules",
      "@truffle/core",
      "cli.js"
    ),
    chain: path.join(
      __dirname,
      "../..",
      "node_modules",
      "@truffle/environment",
      "chain.js"
    ),
    analytics: path.join(
      __dirname,
      "../..",
      "node_modules",
      "@truffle/core",
      "lib",
      "services",
      "analytics",
      "main.js"
    ),
    library: path.join(
      __dirname,
      "../..",
      "node_modules",
      "@truffle/core",
      "index.js"
    )
  },
  target: "node",
  node: {
    // For this option, see here: https://github.com/webpack/webpack/issues/1599
    __dirname: false,
    __filename: false
  },
  context: rootDir,
  output: {
    path: outputDir,
    filename: "[name].bundled.js",
    library: "",
    libraryTarget: "commonjs"
  },
  devtool: "source-map",
  module: {
    rules: [
      // ignores "#!/bin..." lines inside files
      {
        test: /\.js$/,
        include: [
          path.resolve(__dirname, "../core"),
          path.resolve(__dirname, "../environment")
        ],
        use: "shebang-loader"
      }
    ]
  },
  externals: [
    // If you look at webpack's docs, `externals` doesn't need to be a function.
    // But I never got it to work otherwise, so this is a function because "it works".
    function(context, request, callback) {
      // truffle-config uses the original-require module.
      // Here, we leave it as an external, and use the original-require
      // module that's a dependency of Truffle instead.
      if (/^original-require$/.test(request)) {
        return callback(null, "commonjs original-require");
      }

      // Mocha doesn't seem to bundle well either. This is a stop-gap until
      // I can look into it further.
      if (/^mocha$/.test(request)) {
        return callback(null, "commonjs mocha");
      }

      callback();
    }
  ],
  plugins: [
    new webpack.DefinePlugin({
      BUNDLE_VERSION: JSON.stringify(pkg.version),
      BUNDLE_CHAIN_FILENAME: JSON.stringify("chain.bundled.js"),
      BUNDLE_ANALYTICS_FILENAME: JSON.stringify("analytics.bundled.js"),
      BUNDLE_LIBRARY_FILENAME: JSON.stringify("library.bundled.js")
    }),

    // Put the shebang back on.
    new webpack.BannerPlugin({ banner: "#!/usr/bin/env node\n", raw: true }),

    // `truffle test`
    new CopyWebpackPlugin([
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "Assert.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertAddress.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertAddressArray.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertAddressPayableArray.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertBalance.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertBool.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertBytes32.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertBytes32Array.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertGeneral.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertInt.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertIntArray.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertString.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertUint.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "AssertUintArray.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "NewSafeSend.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "testing",
          "OldSafeSend.sol"
        )
      },
      {
        from: path.join(
          __dirname,
          "../..",
          "node_modules",
          "@truffle/core",
          "lib",
          "templates/"
        ),
        to: "templates",
        flatten: true
      }
    ]),

    new CleanWebpackPlugin(["build"]),

    // Make web3 1.0 packable
    new webpack.IgnorePlugin(/^electron$/)
  ],
  resolve: {
    alias: {
      "ws": path.join(__dirname, "./nil.js"),
      "bn.js": path.join(
        __dirname,
        "../..",
        "node_modules",
        "bn.js",
        "lib",
        "bn.js"
      ),
      "original-fs": path.join(__dirname, "./nil.js"),
      "scrypt": "js-scrypt"
    }
  },
  stats: {
    warnings: false
  }
};
<|endoftext|>


<commit_before>/**
 *
 *  Web Starter Kit
 *  Copyright 2014 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
 *
 */

'use strict';

// Include Gulp & Tools We'll Use
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var del = require('del');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
var pagespeed = require('psi');
var reload = browserSync.reload;
var exec = require('child_process').exec;

var AUTOPREFIXER_BROWSERS = [
  '> 5%',
  'last 2 versions',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

// Lint JavaScript
gulp.task('jshint', function () {
  return gulp.src('app/scripts/**/*.js')
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

// Optimize Images
gulp.task('images', function () {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));
});

// Copy all files (not dirs) at the root level (app)
gulp.task('copy', function () {
  return gulp.src([
    'app/*',
    '!app/_includes/*'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'))
    .pipe($.size({title: 'copy'}));
});

// Copy "fonts" folder
gulp.task('fonts', function () {
  return gulp.src(['app/fonts/**'])
    .pipe(gulp.dest('dist/fonts'))
    .pipe($.size({title: 'fonts'}));
});

// Copy "_layouts" folder
gulp.task('layouts', function () {
  return gulp.src(['app/_layouts/*'])
    .pipe(gulp.dest('dist/_layouts'))
    .pipe($.size({title: 'layouts'}));
});

// Copy "about" folder
gulp.task('about', function () {
  return gulp.src(['app/about/*'])
    .pipe(gulp.dest('dist/about'))
    .pipe($.size({title: 'about'}));
});

// Copy "blog" folder
gulp.task('blog', function () {
  return gulp.src(['app/blog/*'])
    .pipe(gulp.dest('dist/blog'))
    .pipe($.size({title: 'blog'}));
});

// Compile and Automatically Prefix Stylesheets
gulp.task('styles', function () {
  // For best performance, don't add Sass partials to `gulp.src`
  return gulp.src([
    'app/styles/*.scss',
    'app/styles/**/*.css',
    'app/styles/components/components.scss'
  ])
    .pipe($.sourcemaps.init())
    .pipe($.changed('styles', {extension: '.scss'}))
    .pipe($.sass({
      precision: 10,
      onError: console.error.bind(console, 'Sass error:')
    }))
    .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('.tmp/styles'))
    // Concatenate And Minify Styles
    .pipe($.if('*.css', $.csso()))
    .pipe(gulp.dest('dist/styles'))
    .pipe($.size({title: 'styles'}));
});

// Scan Your HTML For Assets & Optimize Them
gulp.task('html', function () {
  var assets = $.useref.assets({searchPath: '{.tmp,app}'});

  return gulp.src('app/_includes/*.html')
    .pipe(assets)
    // Concatenate And Minify JavaScript
    .pipe($.if('*.js', $.uglify({preserveComments: 'some'})))
    // Remove Any Unused CSS
    // Note: If not using the Style Guide, you can delete it from
    // the next line to only include styles your project uses.
    // .pipe($.if('*.css', $.uncss({
    //   html: [
    //     'app/index.html'
    //     // 'app/styleguide.html'
    //   ],
    //   // CSS Selectors for UnCSS to ignore
    //   // ignore: [
    //   //   /.side-nav.open/,
    //   //   /.header-bar.open/
    //   // ]
    // })))
    // Concatenate And Minify Styles
    // In case you are still using useref build blocks
    .pipe($.if('*.css', $.csso()))
    .pipe(assets.restore())
    .pipe($.useref())
    // Update Production Style Guide Paths
    .pipe($.replace('components/components.css', 'components/main.min.css'))
    // Minify Any HTML
    // .pipe($.if('*.html', $.minifyHtml()))
    // Output Files
    .pipe($.if('*.html', gulp.dest('dist/_includes'), gulp.dest('dist')))
    .pipe($.size({title: 'html'}));
});

// Static assets revisioning: unicorn.css → unicorn-098f6bcd.css
gulp.task('rev', function () {
  return gulp.src(['dist/styles/*.css', 'dist/scripts/*.js'], {base: 'dist'})
    .pipe(gulp.dest('dist'))
    .pipe($.rev())
    .pipe(gulp.dest('dist'))
    .pipe($.rev.manifest('dist/rev-manifest.json', {base: 'dist'}))
    .pipe(gulp.dest('dist'));
});

// Rewrite occurences of filenames which have been renamed by 'rev' task
gulp.task('rev-replace', function () {
  var manifest = gulp.src('dist/rev-manifest.json');
  return gulp.src('dist/_includes/*.html')
    .pipe($.revReplace({manifest: manifest}))
    .pipe(gulp.dest('dist/_includes'));
});

// Clean Output Directory
gulp.task('clean', del.bind(null, ['.tmp', 'dist/*', '!dist/.git', '!dist/_posts', '!dist/_drafts', '!dist/.gitignore']));

// Build Jekyll site (development)
gulp.task('jekyll', function (cb) {
  exec('jekyll build --drafts --source app --destination dist/_site', function (error, stdout, stderr) {
    if (error !== null) {
      console.log('stdout: ' + stdout);
      console.log('stderr: ' + stderr);
      throw error;
    }
    cb();
  });
});

// Build Jekyll site (assets compressed)
gulp.task('jekyll:dist', function (cb) {
  exec('jekyll build --drafts --source dist --destination dist/_site', function (error, stdout, stderr) {
    if (error !== null) {
      console.log('stdout: ' + stdout);
      console.log('stderr: ' + stderr);
      throw error;
    }
    cb();
  });
});

// Serve the Jekyll site and watch files for changes & reload
gulp.task('serve', ['styles', 'jekyll'], function () {
  browserSync({
    notify: false,
    // Run as an https by uncommenting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    // https: true,
    server: ['.tmp', 'dist/_site']
  });

  gulp.watch(['app/*.{yml,xml}'], ['jekyll', reload]);
  gulp.watch(['app/**/*.{html,md}'], ['jekyll', reload]);
  gulp.watch(['app/styles/**/*.{scss,css}'], ['styles', 'jekyll', reload]);
  gulp.watch(['app/scripts/**/*.js'], ['jshint', 'jekyll', reload]);
  gulp.watch(['app/images/**/*'], ['jekyll', reload]);
});

// Serve the Jekyll site from the dist build
gulp.task('serve:dist', function () {
  runSequence('default', 'jekyll:dist', function () {
    browserSync({
      notify: false,
      // Run as an https by uncommenting 'https: true'
      // Note: this uses an unsigned certificate which on first access
      //       will present a certificate warning in the browser.
      // https: true,
      server: 'dist/_site'
    });
  });
});

// Build site ready to be pushed to GitHub (assets compressed)
gulp.task('default', ['clean'], function (cb) {
  runSequence('styles',
              [ 'jshint',
                'html',
                'images',
                'fonts',
                'layouts',
                'about',
                'blog',
                'copy'
              ],
              'rev',
              'rev-replace',
              cb);
});

// Run PageSpeed Insights
// Update `url` below to the public URL for your site
gulp.task('pagespeed', pagespeed.bind(null, {
  // By default, we use the PageSpeed Insights
  // free (no API key) tier. You can use a Google
  // Developer API key if you have one. See
  // http://goo.gl/RkN0vE for info key: 'YOUR_API_KEY'
  url: 'https://www.sergiorus.com',
  strategy: 'mobile'
}));

// Load custom tasks from the `tasks` directory
try { require('require-dir')('tasks'); } catch (err) {}
<commit_msg>Ignore 'images' folder in 'clean' task<commit_after>/**
 *
 *  Web Starter Kit
 *  Copyright 2014 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
 *
 */

'use strict';

// Include Gulp & Tools We'll Use
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var del = require('del');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
var pagespeed = require('psi');
var reload = browserSync.reload;
var exec = require('child_process').exec;

var AUTOPREFIXER_BROWSERS = [
  '> 5%',
  'last 2 versions',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

// Lint JavaScript
gulp.task('jshint', function () {
  return gulp.src('app/scripts/**/*.js')
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

// Optimize Images
gulp.task('images', function () {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));
});

// Copy all files (not dirs) at the root level (app)
gulp.task('copy', function () {
  return gulp.src([
    'app/*',
    '!app/_includes/*'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'))
    .pipe($.size({title: 'copy'}));
});

// Copy "fonts" folder
gulp.task('fonts', function () {
  return gulp.src(['app/fonts/**'])
    .pipe(gulp.dest('dist/fonts'))
    .pipe($.size({title: 'fonts'}));
});

// Copy "_layouts" folder
gulp.task('layouts', function () {
  return gulp.src(['app/_layouts/*'])
    .pipe(gulp.dest('dist/_layouts'))
    .pipe($.size({title: 'layouts'}));
});

// Copy "about" folder
gulp.task('about', function () {
  return gulp.src(['app/about/*'])
    .pipe(gulp.dest('dist/about'))
    .pipe($.size({title: 'about'}));
});

// Copy "blog" folder
gulp.task('blog', function () {
  return gulp.src(['app/blog/*'])
    .pipe(gulp.dest('dist/blog'))
    .pipe($.size({title: 'blog'}));
});

// Compile and Automatically Prefix Stylesheets
gulp.task('styles', function () {
  // For best performance, don't add Sass partials to `gulp.src`
  return gulp.src([
    'app/styles/*.scss',
    'app/styles/**/*.css',
    'app/styles/components/components.scss'
  ])
    .pipe($.sourcemaps.init())
    .pipe($.changed('styles', {extension: '.scss'}))
    .pipe($.sass({
      precision: 10,
      onError: console.error.bind(console, 'Sass error:')
    }))
    .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('.tmp/styles'))
    // Concatenate And Minify Styles
    .pipe($.if('*.css', $.csso()))
    .pipe(gulp.dest('dist/styles'))
    .pipe($.size({title: 'styles'}));
});

// Scan Your HTML For Assets & Optimize Them
gulp.task('html', function () {
  var assets = $.useref.assets({searchPath: '{.tmp,app}'});

  return gulp.src('app/_includes/*.html')
    .pipe(assets)
    // Concatenate And Minify JavaScript
    .pipe($.if('*.js', $.uglify({preserveComments: 'some'})))
    // Remove Any Unused CSS
    // Note: If not using the Style Guide, you can delete it from
    // the next line to only include styles your project uses.
    // .pipe($.if('*.css', $.uncss({
    //   html: [
    //     'app/index.html'
    //     // 'app/styleguide.html'
    //   ],
    //   // CSS Selectors for UnCSS to ignore
    //   // ignore: [
    //   //   /.side-nav.open/,
    //   //   /.header-bar.open/
    //   // ]
    // })))
    // Concatenate And Minify Styles
    // In case you are still using useref build blocks
    .pipe($.if('*.css', $.csso()))
    .pipe(assets.restore())
    .pipe($.useref())
    // Update Production Style Guide Paths
    .pipe($.replace('components/components.css', 'components/main.min.css'))
    // Minify Any HTML
    // .pipe($.if('*.html', $.minifyHtml()))
    // Output Files
    .pipe($.if('*.html', gulp.dest('dist/_includes'), gulp.dest('dist')))
    .pipe($.size({title: 'html'}));
});

// Static assets revisioning: unicorn.css → unicorn-098f6bcd.css
gulp.task('rev', function () {
  return gulp.src(['dist/styles/*.css', 'dist/scripts/*.js'], {base: 'dist'})
    .pipe(gulp.dest('dist'))
    .pipe($.rev())
    .pipe(gulp.dest('dist'))
    .pipe($.rev.manifest('dist/rev-manifest.json', {base: 'dist'}))
    .pipe(gulp.dest('dist'));
});

// Rewrite occurences of filenames which have been renamed by 'rev' task
gulp.task('rev-replace', function () {
  var manifest = gulp.src('dist/rev-manifest.json');
  return gulp.src('dist/_includes/*.html')
    .pipe($.revReplace({manifest: manifest}))
    .pipe(gulp.dest('dist/_includes'));
});

// Clean Output Directory
gulp.task('clean', del.bind(null, ['.tmp', 'dist/*', '!dist/.git', '!dist/.gitignore', '!dist/_drafts', '!dist/_posts', '!dist/images']));

// Build Jekyll site (development)
gulp.task('jekyll', function (cb) {
  exec('jekyll build --drafts --source app --destination dist/_site', function (error, stdout, stderr) {
    if (error !== null) {
      console.log('stdout: ' + stdout);
      console.log('stderr: ' + stderr);
      throw error;
    }
    cb();
  });
});

// Build Jekyll site (assets compressed)
gulp.task('jekyll:dist', function (cb) {
  exec('jekyll build --drafts --source dist --destination dist/_site', function (error, stdout, stderr) {
    if (error !== null) {
      console.log('stdout: ' + stdout);
      console.log('stderr: ' + stderr);
      throw error;
    }
    cb();
  });
});

// Serve the Jekyll site and watch files for changes & reload
gulp.task('serve', ['styles', 'jekyll'], function () {
  browserSync({
    notify: false,
    // Run as an https by uncommenting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    // https: true,
    server: ['.tmp', 'dist/_site']
  });

  gulp.watch(['app/*.{yml,xml}'], ['jekyll', reload]);
  gulp.watch(['app/**/*.{html,md}'], ['jekyll', reload]);
  gulp.watch(['app/styles/**/*.{scss,css}'], ['styles', 'jekyll', reload]);
  gulp.watch(['app/scripts/**/*.js'], ['jshint', 'jekyll', reload]);
  gulp.watch(['app/images/**/*'], ['jekyll', reload]);
});

// Serve the Jekyll site from the dist build
gulp.task('serve:dist', function () {
  runSequence('default', 'jekyll:dist', function () {
    browserSync({
      notify: false,
      // Run as an https by uncommenting 'https: true'
      // Note: this uses an unsigned certificate which on first access
      //       will present a certificate warning in the browser.
      // https: true,
      server: 'dist/_site'
    });
  });
});

// Build site ready to be pushed to GitHub (assets compressed)
gulp.task('default', ['clean'], function (cb) {
  runSequence('styles',
              [ 'jshint',
                'html',
                'images',
                'fonts',
                'layouts',
                'about',
                'blog',
                'copy'
              ],
              'rev',
              'rev-replace',
              cb);
});

// Run PageSpeed Insights
// Update `url` below to the public URL for your site
gulp.task('pagespeed', pagespeed.bind(null, {
  // By default, we use the PageSpeed Insights
  // free (no API key) tier. You can use a Google
  // Developer API key if you have one. See
  // http://goo.gl/RkN0vE for info key: 'YOUR_API_KEY'
  url: 'https://www.sergiorus.com',
  strategy: 'mobile'
}));

// Load custom tasks from the `tasks` directory
try { require('require-dir')('tasks'); } catch (err) {}
<|endoftext|>


<commit_before>var test = require('tape');
var path = require('path');
var along = require('@turf/along');
var load = require('load-json-file');
var lineSliceAlong = require('.');

var line1 = load.sync(path.join(__dirname, 'test', 'fixtures', 'line1.geojson'));
var route1 = load.sync(path.join(__dirname, 'test', 'fixtures', 'route1.geojson'));
var route2 = load.sync(path.join(__dirname, 'test', 'fixtures', 'route2.geojson'));

test('turf-line-slice -- line1', function (t) {
    var start = 500;
    var stop = 750;
    var units = 'miles';

    var start_point = along(line1, start, units);
    var end_point = along(line1, stop, units);
    var sliced = lineSliceAlong(line1, start, stop, units);
    t.equal(sliced.type, 'Feature');
    t.equal(sliced.geometry.type, 'LineString');
    t.deepEqual(sliced.geometry.coordinates[0], start_point.geometry.coordinates);
    t.deepEqual(sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1], end_point.geometry.coordinates);
    t.end();
});

test('turf-line-slice -- line1 overshoot', function (t) {
		var start = 500;
		var stop = 1500;
	  var units = 'miles';

		var start_point = along(line1, start, units);
		var end_point = along(line1, stop, units);
		var sliced = lineSliceAlong(line1, start, stop, units);
		t.equal(sliced.type, 'Feature');
		t.equal(sliced.geometry.type, 'LineString');
		t.deepEqual(sliced.geometry.coordinates[0], start_point.geometry.coordinates);
		t.deepEqual(sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1], end_point.geometry.coordinates);
		t.end();
});

test('turf-line-slice-along -- route1', function (t) {
    var start = 500;
    var stop = 750;
    var units = 'miles';

    var start_point = along(route1, start, units);
    var end_point = along(route1, stop, units);
    var sliced = lineSliceAlong(route1, start, stop, units);
    t.equal(sliced.type, 'Feature');
    t.equal(sliced.geometry.type, 'LineString');
    t.deepEqual(sliced.geometry.coordinates[0], start_point.geometry.coordinates);
    t.deepEqual(sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1], end_point.geometry.coordinates);
    t.end();
});

test('turf-line-slice-along -- route2', function (t) {
    var start = 25;
    var stop = 50;
    var units = 'miles';

    var start_point = along(route2, start, units);
    var end_point = along(route2, stop, units);
    var sliced = lineSliceAlong(route2, start, stop, units);
    t.equal(sliced.type, 'Feature');
    t.equal(sliced.geometry.type, 'LineString');
    t.deepEqual(sliced.geometry.coordinates[0], start_point.geometry.coordinates);
    t.deepEqual(sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1], end_point.geometry.coordinates);
    t.end();
});
<commit_msg>Convert tabs to spaces<commit_after>var test = require('tape');
var path = require('path');
var along = require('@turf/along');
var load = require('load-json-file');
var lineSliceAlong = require('.');

var line1 = load.sync(path.join(__dirname, 'test', 'fixtures', 'line1.geojson'));
var route1 = load.sync(path.join(__dirname, 'test', 'fixtures', 'route1.geojson'));
var route2 = load.sync(path.join(__dirname, 'test', 'fixtures', 'route2.geojson'));

test('turf-line-slice -- line1', function (t) {
    var start = 500;
    var stop = 750;
    var units = 'miles';

    var start_point = along(line1, start, units);
    var end_point = along(line1, stop, units);
    var sliced = lineSliceAlong(line1, start, stop, units);
    t.equal(sliced.type, 'Feature');
    t.equal(sliced.geometry.type, 'LineString');
    t.deepEqual(sliced.geometry.coordinates[0], start_point.geometry.coordinates);
    t.deepEqual(sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1], end_point.geometry.coordinates);
    t.end();
});

test('turf-line-slice -- line1 overshoot', function (t) {
    var start = 500;
    var stop = 1500;
    var units = 'miles';

    var start_point = along(line1, start, units);
    var end_point = along(line1, stop, units);
    var sliced = lineSliceAlong(line1, start, stop, units);
    t.equal(sliced.type, 'Feature');
    t.equal(sliced.geometry.type, 'LineString');
    t.deepEqual(sliced.geometry.coordinates[0], start_point.geometry.coordinates);
    t.deepEqual(sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1], end_point.geometry.coordinates);
    t.end();
});

test('turf-line-slice-along -- route1', function (t) {
    var start = 500;
    var stop = 750;
    var units = 'miles';

    var start_point = along(route1, start, units);
    var end_point = along(route1, stop, units);
    var sliced = lineSliceAlong(route1, start, stop, units);
    t.equal(sliced.type, 'Feature');
    t.equal(sliced.geometry.type, 'LineString');
    t.deepEqual(sliced.geometry.coordinates[0], start_point.geometry.coordinates);
    t.deepEqual(sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1], end_point.geometry.coordinates);
    t.end();
});

test('turf-line-slice-along -- route2', function (t) {
    var start = 25;
    var stop = 50;
    var units = 'miles';

    var start_point = along(route2, start, units);
    var end_point = along(route2, stop, units);
    var sliced = lineSliceAlong(route2, start, stop, units);
    t.equal(sliced.type, 'Feature');
    t.equal(sliced.geometry.type, 'LineString');
    t.deepEqual(sliced.geometry.coordinates[0], start_point.geometry.coordinates);
    t.deepEqual(sliced.geometry.coordinates[sliced.geometry.coordinates.length - 1], end_point.geometry.coordinates);
    t.end();
});
<|endoftext|>


<commit_before>/**
 * @file levelHandler
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license GPL-3.0
 */

const levelUpMessages = xrequire('./assets/levelUpMessages.json');

/**
 * Handles user's experience points and levels
 * @param {Message} message Discord.js message object
 * @returns {void}
 */
module.exports = async message => {
  try {
    /**
     * Using <Model>.findOrCreate() won't require the use of
     * <ModelInstance>.save() but <Model>.findOrBuild() is used instead because
     * <Model>.findOrCreate() creates a race condition where a matching row is
     * created by another connection after the `find` but before the `insert`
     * call. However, it is not always possible to handle this case in SQLite,
     * specifically if one transaction inserts and another tries to select
     * before the first one has committed. TimeoutError is thrown instead.
     */
    let [ guildMemberModel, initialized ] = await message.client.database.models.guildMember.findOrBuild({
      where: {
        userID: message.author.id,
        guildID: message.guild.id
      },
      defaults: {
        experiencePoints: 0
      }
    });
    if (initialized) {
      await guildMemberModel.save();
    }

    let guildModel = await message.client.database.models.guild.findOne({
      attributes: [ 'levelUpMessages', 'levelUps' ],
      where: {
        guildID: message.guild.id
      },
      include: [
        {
          model: message.client.database.models.textChannel,
          attributes: [ 'channelID', 'ignoreXP' ]
        },
        {
          model: message.client.database.models.role,
          attributes: [ 'roleID', 'level', 'ignoreXP' ]
        }
      ]
    });

    let experienceIgnoredChannels = guildModel.textChannels.length && guildModel.textChannels.filter(model => model.dataValues.ignoreXP).map(model => model.dataValues.channelID);
    let isIgnoredChannel = experienceIgnoredChannels && experienceIgnoredChannels.includes(message.channel.id);

    if (isIgnoredChannel) return;

    let experienceIgnoredRoles = guildModel.roles.length && guildModel.roles.filter(model => model.dataValues.ignoreXP).map(model => model.dataValues.roleID);
    let hasIgnoredRole = experienceIgnoredRoles && message.member.roles.some(role => experienceIgnoredRoles.includes(role.id));

    if (hasIgnoredRole) return;

    guildMemberModel.dataValues.experiencePoints = parseInt(guildMemberModel.dataValues.experiencePoints);
    guildMemberModel.dataValues.level = parseInt(guildMemberModel.dataValues.level);
    guildMemberModel.dataValues.bastionCurrencies = parseInt(guildMemberModel.dataValues.bastionCurrencies);

    let currentLevel = Math.floor(0.15 * Math.sqrt(parseInt(guildMemberModel.dataValues.experiencePoints) + 1));

    // Level Up
    if (guildModel.dataValues.levelUps) {
      if (currentLevel > guildMemberModel.dataValues.level) {
        await message.client.database.models.guildMember.update({
          bastionCurrencies: guildMemberModel.dataValues.bastionCurrencies + currentLevel * 5,
          experiencePoints: guildMemberModel.dataValues.experiencePoints + 1,
          level: currentLevel
        },
        {
          where: {
            userID: message.author.id,
            guildID: message.guild.id
          },
          fields: [ 'bastionCurrencies', 'experiencePoints', 'level' ]
        });

        if (guildModel.dataValues.levelUpMessages) {
          let levelUpMessage = levelUpMessages[Math.floor(Math.random() * levelUpMessages.length)];

          message.channel.send({
            embed: {
              color: message.client.colors.BLUE,
              title: 'LEVELED UP!',
              description: levelUpMessage,
              thumbnail: {
                url: `https://dummyimage.com/250/40C4FB/&text=${currentLevel}`
              },
              fields: [
                {
                  name: `${message.author.tag} leveled up to Level ${currentLevel}`,
                  value: '\u200B'
                }
              ]
            }
          }).then(msg => {
            msg.delete(90000).catch(() => {});
          }).catch(e => {
            message.client.log.error(e);
          });
        }
      }
      else {
        await message.client.database.models.guildMember.update({
          experiencePoints: guildMemberModel.dataValues.experiencePoints + 1
        },
        {
          where: {
            userID: message.author.id,
            guildID: message.guild.id
          },
          fields: [ 'experiencePoints' ]
        });
      }
    }

    // Level up roles
    let levelUpRoles = guildModel.roles.filter(role => role.dataValues.level).map(role => role.dataValues);

    let levelUpRoleIDs = {};
    for (let role of levelUpRoles) {
      if (!levelUpRoleIDs.hasOwnProperty(role.level)) {
        levelUpRoleIDs[role.level] = [];
      }

      levelUpRoleIDs[role.level].push(role.roleID);
    }

    let level = `${currentLevel}`;
    if (levelUpRoleIDs.hasOwnProperty(level)) {
      await message.member.addRoles(levelUpRoleIDs[level], 'Level Up').catch(() => {});
    }
  }
  catch (e) {
    message.client.log.error(e);
  }
};
<commit_msg>handlers: implement exclusive roles in levelUpRoles<commit_after>/**
 * @file levelHandler
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license GPL-3.0
 */

const levelUpMessages = xrequire('./assets/levelUpMessages.json');

/**
 * Handles user's experience points and levels
 * @param {Message} message Discord.js message object
 * @returns {void}
 */
module.exports = async message => {
  try {
    /**
     * Using <Model>.findOrCreate() won't require the use of
     * <ModelInstance>.save() but <Model>.findOrBuild() is used instead because
     * <Model>.findOrCreate() creates a race condition where a matching row is
     * created by another connection after the `find` but before the `insert`
     * call. However, it is not always possible to handle this case in SQLite,
     * specifically if one transaction inserts and another tries to select
     * before the first one has committed. TimeoutError is thrown instead.
     */
    let [ guildMemberModel, initialized ] = await message.client.database.models.guildMember.findOrBuild({
      where: {
        userID: message.author.id,
        guildID: message.guild.id
      },
      defaults: {
        experiencePoints: 0
      }
    });
    if (initialized) {
      await guildMemberModel.save();
    }

    let guildModel = await message.client.database.models.guild.findOne({
      attributes: [ 'levelUpMessages', 'levelUps' ],
      where: {
        guildID: message.guild.id
      },
      include: [
        {
          model: message.client.database.models.textChannel,
          attributes: [ 'channelID', 'ignoreXP' ]
        },
        {
          model: message.client.database.models.role,
          attributes: [ 'roleID', 'level', 'exclusive', 'ignoreXP' ]
        }
      ]
    });

    let experienceIgnoredChannels = guildModel.textChannels.length && guildModel.textChannels.filter(model => model.dataValues.ignoreXP).map(model => model.dataValues.channelID);
    let isIgnoredChannel = experienceIgnoredChannels && experienceIgnoredChannels.includes(message.channel.id);

    if (isIgnoredChannel) return;

    let experienceIgnoredRoles = guildModel.roles.length && guildModel.roles.filter(model => model.dataValues.ignoreXP).map(model => model.dataValues.roleID);
    let hasIgnoredRole = experienceIgnoredRoles && message.member.roles.some(role => experienceIgnoredRoles.includes(role.id));

    if (hasIgnoredRole) return;

    guildMemberModel.dataValues.experiencePoints = parseInt(guildMemberModel.dataValues.experiencePoints);
    guildMemberModel.dataValues.level = parseInt(guildMemberModel.dataValues.level);
    guildMemberModel.dataValues.bastionCurrencies = parseInt(guildMemberModel.dataValues.bastionCurrencies);

    let currentLevel = Math.floor(0.15 * Math.sqrt(parseInt(guildMemberModel.dataValues.experiencePoints) + 1));

    // Level Up
    if (guildModel.dataValues.levelUps) {
      if (currentLevel > guildMemberModel.dataValues.level) {
        await message.client.database.models.guildMember.update({
          bastionCurrencies: guildMemberModel.dataValues.bastionCurrencies + currentLevel * 5,
          experiencePoints: guildMemberModel.dataValues.experiencePoints + 1,
          level: currentLevel
        },
        {
          where: {
            userID: message.author.id,
            guildID: message.guild.id
          },
          fields: [ 'bastionCurrencies', 'experiencePoints', 'level' ]
        });

        if (guildModel.dataValues.levelUpMessages) {
          let levelUpMessage = levelUpMessages[Math.floor(Math.random() * levelUpMessages.length)];

          message.channel.send({
            embed: {
              color: message.client.colors.BLUE,
              title: 'LEVELED UP!',
              description: levelUpMessage,
              thumbnail: {
                url: `https://dummyimage.com/250/40C4FB/&text=${currentLevel}`
              },
              fields: [
                {
                  name: `${message.author.tag} leveled up to Level ${currentLevel}`,
                  value: '\u200B'
                }
              ]
            }
          }).then(msg => {
            msg.delete(90000).catch(() => {});
          }).catch(e => {
            message.client.log.error(e);
          });
        }
      }
      else {
        await message.client.database.models.guildMember.update({
          experiencePoints: guildMemberModel.dataValues.experiencePoints + 1
        },
        {
          where: {
            userID: message.author.id,
            guildID: message.guild.id
          },
          fields: [ 'experiencePoints' ]
        });
      }
    }

    // Level up roles
    let levelUpRoles = guildModel.roles.filter(role => role.dataValues.level).map(role => role.dataValues);

    let levelUpRoleIDs = {};
    let exclusiveLevels = [];
    for (let role of levelUpRoles) {
      if (!levelUpRoleIDs.hasOwnProperty(role.level)) {
        levelUpRoleIDs[role.level] = [];
      }

      levelUpRoleIDs[role.level].push(role.roleID);

      if (role.exclusive) {
        if (!exclusiveLevels.includes(role.level)) {
          exclusiveLevels.push(role.level);
        }
      }
    }

    let level = `${currentLevel}`;
    if (levelUpRoleIDs.hasOwnProperty(level)) {
      if (exclusiveLevels.includes(level)) {
        let allLevelUpRoles = Object.values(levelUpRoleIDs).flatten().filter(role => !levelUpRoleIDs[level].includes(role));
        await message.member.removeRoles(allLevelUpRoles, 'Level Up').catch(() => {});
      }

      // HACK: When adding roles instantly after removing then just above this,
      // a race condition occurs which adds the old roles back to the member as
      // the cache hasn't been updated with the remove roles yet.
      // Therefore, I'm using a timeout to wait for a while before adding new
      // roles to prevent the race condition.
      // This hack should be removed when it's fixed in a stable version of
      // discord.js.
      setTimeout(async () => {
        await message.member.addRoles(levelUpRoleIDs[level], 'Level Up').catch(() => {});
      }, 500);
    }
  }
  catch (e) {
    message.client.log.error(e);
  }
};
<|endoftext|>


<commit_before>import Parameters from './Parameters';
import UniqueList from './util/UniqueList';
import {array, error, id, isArray} from 'vega-util';

var OP_ID = 0;
var PULSE = 'pulse';
var NO_PARAMS = new Parameters();

// Boolean Flags
var SKIP     = 1,
    MODIFIED = 2;

/**
 * An Operator is a processing node in a dataflow graph.
 * Each operator stores a value and an optional value update function.
 * Operators can accept a hash of named parameters. Parameter values can
 * either be direct (JavaScript literals, arrays, objects) or indirect
 * (other operators whose values will be pulled dynamically). Operators
 * included as parameters will have this operator added as a dependency.
 * @constructor
 * @param {*} [init] - The initial value for this operator.
 * @param {function(object, Pulse)} [update] - An update function. Upon
 *   evaluation of this operator, the update function will be invoked and the
 *   return value will be used as the new value of this operator.
 * @param {object} [params] - The parameters for this operator.
 * @param {boolean} [react=true] - Flag indicating if this operator should
 *   listen for changes to upstream operators included as parameters.
 * @see parameters
 */
export default function Operator(init, update, params, react) {
  this.id = ++OP_ID;
  this.value = init;
  this.stamp = -1;
  this.rank = -1;
  this.qrank = -1;
  this.flags = 0;

  if (update) {
    this._update = update;
  }
  if (params) this.parameters(params, react);
}

var prototype = Operator.prototype;

/**
 * Returns a list of target operators dependent on this operator.
 * If this list does not exist, it is created and then returned.
 * @return {UniqueList}
 */
prototype.targets = function() {
  return this._targets || (this._targets = UniqueList(id));
};

/**
 * Sets the value of this operator.
 * @param {*} value - the value to set.
 * @return {Number} Returns 1 if the operator value has changed
 *   according to strict equality, returns 0 otherwise.
 */
prototype.set = function(value) {
  if (this.value !== value) {
    this.value = value;
    return 1;
  } else {
    return 0;
  }
};

function flag(bit) {
  return function(state) {
    var f = this.flags;
    if (arguments.length === 0) return !!(f & bit);
    this.flags = state ? (f | bit) : (f & ~bit);
    return this;
  };
}

/**
 * Indicates that operator evaluation should be skipped on the next pulse.
 * This operator will still propagate incoming pulses, but its update function
 * will not be invoked. The skip flag is reset after every pulse, so calling
 * this method will affect processing of the next pulse only.
 */
prototype.skip = flag(SKIP);

/**
 * Indicates that this operator's value has been modified on its most recent
 * pulse. Normally modification is checked via strict equality; however, in
 * some cases it is more efficient to update the internal state of an object.
 * In those cases, the modified flag can be used to trigger propagation. Once
 * set, the modification flag persists across pulses until unset. The flag can
 * be used with the last timestamp to test if a modification is recent.
 */
prototype.modified = flag(MODIFIED);

/**
 * Sets the parameters for this operator. The parameter values are analyzed for
 * operator instances. If found, this operator will be added as a dependency
 * of the parameterizing operator. Operator values are dynamically marshalled
 * from each operator parameter prior to evaluation. If a parameter value is
 * an array, the array will also be searched for Operator instances. However,
 * the search does not recurse into sub-arrays or object properties.
 * @param {object} params - A hash of operator parameters.
 * @param {boolean} [react=true] - A flag indicating if this operator should
 *   automatically update (react) when parameter values change. In other words,
 *   this flag determines if the operator registers itself as a listener on
 *   any upstream operators included in the parameters.
 * @return {Operator[]} - An array of upstream dependencies.
 */
prototype.parameters = function(params, react) {
  react = react !== false;
  var self = this,
      argval = (self._argval = self._argval || new Parameters()),
      argops = (self._argops = self._argops || []),
      deps = [],
      name, value, n, i;

  function add(name, index, value) {
    if (value instanceof Operator) {
      if (value !== self) {
        if (react) value.targets().add(self);
        deps.push(value);
      }
      argops.push({op:value, name:name, index:index});
    } else {
      argval.set(name, index, value);
    }
  }

  for (name in params) {
    value = params[name];

    if (name === PULSE) {
      array(value).forEach(function(op) {
        if (!(op instanceof Operator)) {
          error('Pulse parameters must be operator instances.');
        } else if (op !== self) {
          op.targets().add(self);
          deps.push(op);
        }
      });
      self.source = value;
    } else if (isArray(value)) {
      argval.set(name, -1, Array(n = value.length));
      for (i=0; i<n; ++i) add(name, i, value[i]);
    } else {
      add(name, -1, value);
    }
  }

  this.marshall().clear(); // initialize values
  return deps;
};

/**
 * Internal method for marshalling parameter values.
 * Visits each operator dependency to pull the latest value.
 * @return {Parameters} A Parameters object to pass to the update function.
 */
prototype.marshall = function(stamp) {
  var argval = this._argval || NO_PARAMS,
      argops = this._argops, item, i, n, op, mod;

  if (argops && (n = argops.length)) {
    for (i=0; i<n; ++i) {
      item = argops[i];
      op = item.op;
      mod = op.modified() && op.stamp === stamp;
      argval.set(item.name, item.index, op.value, mod);
    }
  }
  return argval;
};

/**
 * Delegate method to perform operator processing.
 * Subclasses can override this method to perform custom processing.
 * By default, it marshalls parameters and calls the update function
 * if that function is defined. If the update function does not
 * change the operator value then StopPropagation is returned.
 * If no update function is defined, this method does nothing.
 * @param {Pulse} pulse - the current dataflow pulse.
 * @return The output pulse or StopPropagation. A falsy return value
 *   (including undefined) will let the input pulse pass through.
 */
prototype.evaluate = function(pulse) {
  if (this._update) {
    var params = this.marshall(pulse.stamp),
        v = this._update(params, pulse);

    params.clear();
    if (v !== this.value) {
      this.value = v;
    } else if (!this.modified()) {
      return pulse.StopPropagation;
    }
  }
};

/**
 * Run this operator for the current pulse. If this operator has already
 * been run at (or after) the pulse timestamp, returns StopPropagation.
 * Internally, this method calls {@link evaluate} to perform processing.
 * If {@link evaluate} returns a falsy value, the input pulse is returned.
 * This method should NOT be overridden, instead overrride {@link evaluate}.
 * @param {Pulse} pulse - the current dataflow pulse.
 * @return the output pulse for this operator (or StopPropagation)
 */
prototype.run = function(pulse) {
  if (pulse.stamp <= this.stamp) return pulse.StopPropagation;
  var rv;
  if (this.skip()) {
    this.skip(false);
    rv = 0;
  } else {
    rv = this.evaluate(pulse);
  }
  this.stamp = pulse.stamp;
  return (this.pulse = rv || pulse);
};
<commit_msg>Add operator initonly parameterization.<commit_after>import Parameters from './Parameters';
import UniqueList from './util/UniqueList';
import {array, error, id, isArray} from 'vega-util';

var OP_ID = 0;
var PULSE = 'pulse';
var NO_PARAMS = new Parameters();

// Boolean Flags
var SKIP     = 1,
    MODIFIED = 2;

/**
 * An Operator is a processing node in a dataflow graph.
 * Each operator stores a value and an optional value update function.
 * Operators can accept a hash of named parameters. Parameter values can
 * either be direct (JavaScript literals, arrays, objects) or indirect
 * (other operators whose values will be pulled dynamically). Operators
 * included as parameters will have this operator added as a dependency.
 * @constructor
 * @param {*} [init] - The initial value for this operator.
 * @param {function(object, Pulse)} [update] - An update function. Upon
 *   evaluation of this operator, the update function will be invoked and the
 *   return value will be used as the new value of this operator.
 * @param {object} [params] - The parameters for this operator.
 * @param {boolean} [react=true] - Flag indicating if this operator should
 *   listen for changes to upstream operators included as parameters.
 * @see parameters
 */
export default function Operator(init, update, params, react) {
  this.id = ++OP_ID;
  this.value = init;
  this.stamp = -1;
  this.rank = -1;
  this.qrank = -1;
  this.flags = 0;

  if (update) {
    this._update = update;
  }
  if (params) this.parameters(params, react);
}

var prototype = Operator.prototype;

/**
 * Returns a list of target operators dependent on this operator.
 * If this list does not exist, it is created and then returned.
 * @return {UniqueList}
 */
prototype.targets = function() {
  return this._targets || (this._targets = UniqueList(id));
};

/**
 * Sets the value of this operator.
 * @param {*} value - the value to set.
 * @return {Number} Returns 1 if the operator value has changed
 *   according to strict equality, returns 0 otherwise.
 */
prototype.set = function(value) {
  if (this.value !== value) {
    this.value = value;
    return 1;
  } else {
    return 0;
  }
};

function flag(bit) {
  return function(state) {
    var f = this.flags;
    if (arguments.length === 0) return !!(f & bit);
    this.flags = state ? (f | bit) : (f & ~bit);
    return this;
  };
}

/**
 * Indicates that operator evaluation should be skipped on the next pulse.
 * This operator will still propagate incoming pulses, but its update function
 * will not be invoked. The skip flag is reset after every pulse, so calling
 * this method will affect processing of the next pulse only.
 */
prototype.skip = flag(SKIP);

/**
 * Indicates that this operator's value has been modified on its most recent
 * pulse. Normally modification is checked via strict equality; however, in
 * some cases it is more efficient to update the internal state of an object.
 * In those cases, the modified flag can be used to trigger propagation. Once
 * set, the modification flag persists across pulses until unset. The flag can
 * be used with the last timestamp to test if a modification is recent.
 */
prototype.modified = flag(MODIFIED);

/**
 * Sets the parameters for this operator. The parameter values are analyzed for
 * operator instances. If found, this operator will be added as a dependency
 * of the parameterizing operator. Operator values are dynamically marshalled
 * from each operator parameter prior to evaluation. If a parameter value is
 * an array, the array will also be searched for Operator instances. However,
 * the search does not recurse into sub-arrays or object properties.
 * @param {object} params - A hash of operator parameters.
 * @param {boolean} [react=true] - A flag indicating if this operator should
 *   automatically update (react) when parameter values change. In other words,
 *   this flag determines if the operator registers itself as a listener on
 *   any upstream operators included in the parameters.
 * @param {boolean} [initonly=false] - A flag indicating if this operator
 *   should calculate an update only upon its initiatal evaluation, then
 *   deregister dependencies and suppress all future update invocations.
 * @return {Operator[]} - An array of upstream dependencies.
 */
prototype.parameters = function(params, react, initonly) {
  react = react !== false;
  var self = this,
      argval = (self._argval = self._argval || new Parameters()),
      argops = (self._argops = self._argops || []),
      deps = [],
      name, value, n, i;

  function add(name, index, value) {
    if (value instanceof Operator) {
      if (value !== self) {
        if (react) value.targets().add(self);
        deps.push(value);
      }
      argops.push({op:value, name:name, index:index});
    } else {
      argval.set(name, index, value);
    }
  }

  for (name in params) {
    value = params[name];

    if (name === PULSE) {
      array(value).forEach(function(op) {
        if (!(op instanceof Operator)) {
          error('Pulse parameters must be operator instances.');
        } else if (op !== self) {
          op.targets().add(self);
          deps.push(op);
        }
      });
      self.source = value;
    } else if (isArray(value)) {
      argval.set(name, -1, Array(n = value.length));
      for (i=0; i<n; ++i) add(name, i, value[i]);
    } else {
      add(name, -1, value);
    }
  }

  this.marshall().clear(); // initialize values
  if (initonly) argops.initonly = true;

  return deps;
};

/**
 * Internal method for marshalling parameter values.
 * Visits each operator dependency to pull the latest value.
 * @return {Parameters} A Parameters object to pass to the update function.
 */
prototype.marshall = function(stamp) {
  var argval = this._argval || NO_PARAMS,
      argops = this._argops, item, i, n, op, mod;

  if (argops) {
    for (i=0, n=argops.length; i<n; ++i) {
      item = argops[i];
      op = item.op;
      mod = op.modified() && op.stamp === stamp;
      argval.set(item.name, item.index, op.value, mod);
    }

    if (argops.initonly) {
      for (i=0; i<n; ++i) {
        item = argops[i];
        item.op.targets().remove(this);
      }
      this._argops = null;
      this._update = null;
    }
  }
  return argval;
};

/**
 * Delegate method to perform operator processing.
 * Subclasses can override this method to perform custom processing.
 * By default, it marshalls parameters and calls the update function
 * if that function is defined. If the update function does not
 * change the operator value then StopPropagation is returned.
 * If no update function is defined, this method does nothing.
 * @param {Pulse} pulse - the current dataflow pulse.
 * @return The output pulse or StopPropagation. A falsy return value
 *   (including undefined) will let the input pulse pass through.
 */
prototype.evaluate = function(pulse) {
  var update = this._update;
  if (update) {
    var params = this.marshall(pulse.stamp),
        v = update.call(this, params, pulse);

    params.clear();
    if (v !== this.value) {
      this.value = v;
    } else if (!this.modified()) {
      return pulse.StopPropagation;
    }
  }
};

/**
 * Run this operator for the current pulse. If this operator has already
 * been run at (or after) the pulse timestamp, returns StopPropagation.
 * Internally, this method calls {@link evaluate} to perform processing.
 * If {@link evaluate} returns a falsy value, the input pulse is returned.
 * This method should NOT be overridden, instead overrride {@link evaluate}.
 * @param {Pulse} pulse - the current dataflow pulse.
 * @return the output pulse for this operator (or StopPropagation)
 */
prototype.run = function(pulse) {
  if (pulse.stamp <= this.stamp) return pulse.StopPropagation;
  var rv;
  if (this.skip()) {
    this.skip(false);
    rv = 0;
  } else {
    rv = this.evaluate(pulse);
  }
  this.stamp = pulse.stamp;
  return (this.pulse = rv || pulse);
};
<|endoftext|>