<commit_before>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You 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.
 */

var fs = require('fs');
var path = require('path');

var async = require('async');
var sprintf = require('sprintf').sprintf;

var hooks = require('deployment/hooks');
var deployTemplates = require('deployment/templates');
var deployServices = require('deployment/services');
var deployFiles = require('deployment/files');
var deployConstants = require('deployment/constants');

var serviceManagement = require('service_management');
var manifest = require('manifest');
var manifestConstants = require('manifest/constants');
var config = require('util/config');
var fsutil = require('util/fs');
var flowctrl = require('util/flow_control');
var misc = require('util/misc');

var Errorf = misc.Errorf;

function Instance(name) {
  this.name = name;
  this.root = path.join(config.get()['app_dir'], name);
  this._bundleName = null;
}

/**
 * Check if an instance exists
 *
 * @param {String} instanceName The name of the instance.
 * @param {Function} callback Callback which is called with a boolean 'exists'.
 */
Instance.prototype.exists = function(callback) {
  fs.stat(this.root, function(err, stats) {
    if (!err && stats.isDirectory()) {
      callback(true);
      return;
    }

    callback(false);
    return;
  });
};

/**
 * Get the name of the bundle used by an instance. This is probably the
 * nastiest part of this whole instance filesystem layout because it requires
 * reading a link. To keep things fast this gets cached on the Instance object.
 *
 * @param {Function} callback Callback which is called with (err, bundleName).
 */
Instance.prototype.getBundleName = function(callback) {
  var self = this;
  if (self._bundleName) {
    process.nextTick(function() {
      callback(null, self._bundleName);
    });
  }
  else {
    var bundleLinkPath = path.join(self.root, 'bundle');
    fs.readlink(bundleLinkPath, function(err, target) {
      if (!err) {
        self._bundleName = path.basename(target);
      }
      callback(err, self._bundleName);
      return;
    });
  }
};

/**
 * Get the version pointed to by the 'current' link.
 *
 * @param {Function} callback Callback which is called with (err, version).
 */
Instance.prototype.getBundleVersion = function(callback) {
  var self = this;
  var currentLinkPath = path.join(self.root, 'current');
  fs.readlink(currentLinkPath, function(err, target) {
    if (err) {
      callback(err);
      return;
    }
    else {
      callback(null, target.split('@', 2)[1]);
      return;
    }
  });
};

/**
 * Get the path at which a version of this instance would reside. This does
 * not guarantee that this version exists, merely returns the hypothetical
 * path at which it would reside.
 *
 * @param {String} version    The version to get the path to.
 * @param {Function} callback A callback that takes (err, versionPath).
 */
Instance.prototype.getVersionPath = function(version, callback) {
  var self = this;
  self.getBundleName(function(err, bundleName) {
    var bundleNameFull = bundleName + '@' + version;
    var versionPath = path.join(self.root, 'versions', bundleNameFull);
    callback(err, versionPath);
    return;
  });
};

/**
 * Get the path at which the extracted bundle for the specified version would
 * reside. Again, this doesn't verify that the path actually exists.
 *
 * @param {String} version    The version to get the path to.
 * @param {Function} callback A callback that takes (err, bundleVersionPath).
 */
Instance.prototype.getBundleVersionPath = function(version, callback) {
  var self = this;
  self.getBundleName(function(err, bundleName) {
    var bundleNameFull = bundleName + '@' + version;
    var bundleVersionPath = path.join(config.get()['extracted_dir'], bundleName, bundleNameFull);
    callback(err, bundleVersionPath);
    return;
  });
};

/**
 * Remove all data related to an instance, including the instance, its data,
 * and any services. This performs very little validation (doesn't even check
 * that the instance exists first), it just starts deleting stuff.
 *
 * @param {Function} callback Callback which is called when the cleanup process has finished.
 */
Instance.prototype.destroy = function(callback) {
  var self = this;

  function getBundleVersion(callback) {
    self.getBundleVersion(callback);
  }

  function removeInstanceDirectory(bundleVersion, callback) {
    flowctrl.callIgnoringError(fsutil.rmtree, null, self.root, function(err) {
      callback(null, bundleVersion);
    });
  }<commit_msg>Add docstring and remove unused variable.<commit_after>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You 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.
 */

var fs = require('fs');
var path = require('path');

var async = require('async');
var sprintf = require('sprintf').sprintf;

var hooks = require('deployment/hooks');
var deployTemplates = require('deployment/templates');
var deployServices = require('deployment/services');
var deployFiles = require('deployment/files');
var deployConstants = require('deployment/constants');

var serviceManagement = require('service_management');
var manifest = require('manifest');
var manifestConstants = require('manifest/constants');
var config = require('util/config');
var fsutil = require('util/fs');
var flowctrl = require('util/flow_control');
var misc = require('util/misc');

var Errorf = misc.Errorf;

/**
 * Represents an instance.
 * @constructor
 *
 * @param {String} name Instance name.
 */
function Instance(name) {
  this.name = name;
  this.root = path.join(config.get()['app_dir'], name);
  this._bundleName = null;
}

/**
 * Check if an instance exists
 *
 * @param {String} instanceName The name of the instance.
 * @param {Function} callback Callback which is called with a boolean 'exists'.
 */
Instance.prototype.exists = function(callback) {
  fs.stat(this.root, function(err, stats) {
    if (!err && stats.isDirectory()) {
      callback(true);
      return;
    }

    callback(false);
    return;
  });
};

/**
 * Get the name of the bundle used by an instance. This is probably the
 * nastiest part of this whole instance filesystem layout because it requires
 * reading a link. To keep things fast this gets cached on the Instance object.
 *
 * @param {Function} callback Callback which is called with (err, bundleName).
 */
Instance.prototype.getBundleName = function(callback) {
  var self = this;
  if (self._bundleName) {
    process.nextTick(function() {
      callback(null, self._bundleName);
    });
  }
  else {
    var bundleLinkPath = path.join(self.root, 'bundle');
    fs.readlink(bundleLinkPath, function(err, target) {
      if (!err) {
        self._bundleName = path.basename(target);
      }
      callback(err, self._bundleName);
      return;
    });
  }
};

/**
 * Get the version pointed to by the 'current' link.
 *
 * @param {Function} callback Callback which is called with (err, version).
 */
Instance.prototype.getBundleVersion = function(callback) {
  var self = this;
  var currentLinkPath = path.join(self.root, 'current');
  fs.readlink(currentLinkPath, function(err, target) {
    if (err) {
      callback(err);
      return;
    }
    else {
      callback(null, target.split('@', 2)[1]);
      return;
    }
  });
};

/**
 * Get the path at which a version of this instance would reside. This does
 * not guarantee that this version exists, merely returns the hypothetical
 * path at which it would reside.
 *
 * @param {String} version    The version to get the path to.
 * @param {Function} callback A callback that takes (err, versionPath).
 */
Instance.prototype.getVersionPath = function(version, callback) {
  var self = this;
  self.getBundleName(function(err, bundleName) {
    var bundleNameFull = bundleName + '@' + version;
    var versionPath = path.join(self.root, 'versions', bundleNameFull);
    callback(err, versionPath);
    return;
  });
};

/**
 * Get the path at which the extracted bundle for the specified version would
 * reside. Again, this doesn't verify that the path actually exists.
 *
 * @param {String} version    The version to get the path to.
 * @param {Function} callback A callback that takes (err, bundleVersionPath).
 */
Instance.prototype.getBundleVersionPath = function(version, callback) {
  this.getBundleName(function(err, bundleName) {
    var bundleNameFull = bundleName + '@' + version;
    var bundleVersionPath = path.join(config.get()['extracted_dir'], bundleName, bundleNameFull);
    callback(err, bundleVersionPath);
    return;
  });
};

/**
 * Remove all data related to an instance, including the instance, its data,
 * and any services. This performs very little validation (doesn't even check
 * that the instance exists first), it just starts deleting stuff.
 *
 * @param {Function} callback Callback which is called when the cleanup process has finished.
 */
Instance.prototype.destroy = function(callback) {
  var self = this;

  function getBundleVersion(callback) {
    self.getBundleVersion(callback);
  }

  function removeInstanceDirectory(bundleVersion, callback) {
    flowctrl.callIgnoringError(fsutil.rmtree, null, self.root, function(err) {
      callback(null, bundleVersion);
    });
  }
{'fraction_non_alphanumeric': 0.11387163561076605, 'fraction_numerical': 0.001129305477131564, 'mean_word_length': 3.9543123543123544, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2331944', 'n_tokens_mistral': 2926, 'n_tokens_neox': 2895, 'n_words': 1039}