<commit_before>'use strict';

var dot = require('dot');
dot.templateSettings.strip = false;

var Source = require('../node/nodes/source');

var debug = require('../util/debug')('database-service');

var QueryRunner = require('../postgresql/query-runner');
var QueryParser = require('../postgresql/query-parser');
var BatchClient = require('../postgresql/batch-client');

var QUERY_RUNNER_READONLY_OP = true;
var QUERY_RUNNER_WRITE_OP = !QUERY_RUNNER_READONLY_OP;

var createQueryTemplate = dot.template([
    'CREATE TABLE {{=it._targetTableName}} AS',
    '{{=it._query}}',
    'LIMIT 0'
].join('\n'));

function DatabaseService(dbParams, batchParams) {
    this.queryRunner = new QueryRunner(dbParams);
    this.queryParser = new QueryParser(this.queryRunner);
    this.batchClient = new BatchClient(batchParams.endpoint, batchParams.username, batchParams.apiKey);
}

module.exports = DatabaseService;

DatabaseService.prototype.run = function(query, callback) {
    this.queryRunner.run(query, QUERY_RUNNER_READONLY_OP, callback);
};

var affectedTableRegexCache = {
    bbox: /!bbox!/g,
    scaleDenominator: /!scale_denominator!/g,
    pixelWidth: /!pixel_width!/g,
    pixelHeight: /!pixel_height!/g
};

DatabaseService.prototype.getAffectedTables = function(sql, callback) {
    sql = sql
        .replace(affectedTableRegexCache.bbox, 'ST_MakeEnvelope(0,0,0,0)')
        .replace(affectedTableRegexCache.scaleDenominator, '0')
        .replace(affectedTableRegexCache.pixelWidth, '1')
        .replace(affectedTableRegexCache.pixelHeight, '1');
    sql = 'SELECT * FROM CDB_QueryTables_Updated_At($camshaft$' + sql + '$camshaft$)';
    this.queryRunner.run(sql, QUERY_RUNNER_READONLY_OP, function(err, resultSet) {
        if (err) {
            return callback(err);
        }
        var affectedTables = resultSet.rows.map(function(row) {
            // jshint camelcase:false
            return row.schema_name + '.' + row.table_name;
        });
        return callback(null, affectedTables);
    });
};

DatabaseService.prototype.createTable = function(targetTableName, query, callback) {
    var createQuery = createQueryTemplate({
        _targetTableName: targetTableName,
        _query: query
    });

    this.queryRunner.run(createQuery, QUERY_RUNNER_WRITE_OP, function(err, resultSet) {
        debug('TODO: register table');
        return callback(err, resultSet);
    });
};

DatabaseService.prototype.tableExists = function(targetTableName, callback) {
    var existsQuery = 'select * from ' + targetTableName + ' limit 0';
    this.queryRunner.run(existsQuery, QUERY_RUNNER_READONLY_OP, function(err, resultSet) {
        var tableExists = !err && resultSet;
        return callback(null, tableExists);
    });
};

DatabaseService.prototype.createTableIfNotExists = function(targetTableName, outputQuery, callback) {
    var self = this;
    this.tableExists(targetTableName, function(err, tableExists) {
        if (tableExists) {
            return callback(null, tableExists);
        }

        self.createTable(targetTableName, outputQuery, function(err) {
            if (err) {
                return callback(err, tableExists);
            }

            return callback(null, tableExists);
        });
    });
};

DatabaseService.prototype.getColumnNames = function(query, callback) {
    this.queryParser.getColumnNames(query, callback);
};

DatabaseService.prototype.enqueue = function(query, callback) {
    this.batchClient.enqueue(query, callback);
};

var registerNodeQueryTemplate = dot.template([
    'SELECT',
    '    \'{{=it._nodeId}}\',',
    '    $json_def${{=it._analysisDef}}$json_def$::json,',
    '    {{=it._inputNodes}}',
    'WHERE NOT EXISTS (SELECT * FROM cdb_analysis_catalog WHERE node_id = \'{{=it._nodeId}}\')'
].join('\n'));

var EMPTY_ARRAY_SQL = '\'{}\'';
function pgArray(input, cast) {
    if (input.length === 0) {
        return cast ? ('ARRAY[]::' + cast + '[]') : EMPTY_ARRAY_SQL;
    }
    return 'ARRAY[' + input.join(', ') + ']';
}

function pgQuoteCastMapper(cast) {
    return function(input) {
        return '\'' + input + '\'' + (cast ? ('::' + cast) : '');
    };
}

DatabaseService.prototype.registerNodesInCatalog = function(nodes, callback) {
    if (!Array.isArray(nodes) || nodes.length === 0) {
        return callback(null);
    }
    var nodesSql = [];
    nodes.forEach(function(node) {
        nodesSql.push(registerNodeQueryTemplate({
            _nodeId: node.id(),
            _inputNodes: pgArray(
                node.getInputNodes().map(function(node) { return node.id(); }).map(pgQuoteCastMapper()), 'char[40]'
            ),
            _analysisDef: JSON.stringify(node.toJSON())
        }));
    });
    var sql = 'INSERT INTO cdb_analysis_catalog' +
        '(node_id, analysis_def, input_nodes)\n' + nodesSql.join('\nUNION ALL\n');

    debug('Registering node with SQL: %s', sql);
    this.queryRunner.run(sql, QUERY_RUNNER_WRITE_OP, function(err, resultSet) {
        debug(err, resultSet);
        return callback(err);
    });
};

var trackNodeQueryTemplate = dot.template([
    'WITH RECURSIVE search_dag(node_id, input_nodes) AS (',
    '    SELECT node_id, input_nodes FROM cdb_analysis_catalog WHERE node_id = \'{{=it._nodeId}}\'',
    '    UNION',
    '    -- recursive search',
    '    SELECT c.node_id, c.input_nodes',
    '    FROM search_dag s, cdb_analysis_catalog c',
    '    WHERE c.node_id = ANY(s.input_nodes)',
    ')',
    'UPDATE cdb_analysis_catalog',
    'SET',
    '    used_at = NOW(),',
    '    hits = hits + 1,',
    '    last_used_from = \'{{=it._nodeId}}\'',
    'WHERE node_id IN (select node_id from search_dag)',
].join('\n'));

DatabaseService.prototype.trackNode = function(node, callback) {
    // we don't want to track source nodes as high level nodes
    if (node.type === Source.TYPE) {
        return callback(null);
    }
    var sql = trackNodeQueryTemplate({ _nodeId: node.id() });
    debug('Tracking analysis with SQL: %s', sql);
    this.queryRunner.run(sql, QUERY_RUNNER_WRITE_OP, function(err, resultSet) {
        debug(err, resultSet);
        return callback(err);
    });
};
<commit_msg>Remove unneeded comma<commit_after>'use strict';

var dot = require('dot');
dot.templateSettings.strip = false;

var Source = require('../node/nodes/source');

var debug = require('../util/debug')('database-service');

var QueryRunner = require('../postgresql/query-runner');
var QueryParser = require('../postgresql/query-parser');
var BatchClient = require('../postgresql/batch-client');

var QUERY_RUNNER_READONLY_OP = true;
var QUERY_RUNNER_WRITE_OP = !QUERY_RUNNER_READONLY_OP;

var createQueryTemplate = dot.template([
    'CREATE TABLE {{=it._targetTableName}} AS',
    '{{=it._query}}',
    'LIMIT 0'
].join('\n'));

function DatabaseService(dbParams, batchParams) {
    this.queryRunner = new QueryRunner(dbParams);
    this.queryParser = new QueryParser(this.queryRunner);
    this.batchClient = new BatchClient(batchParams.endpoint, batchParams.username, batchParams.apiKey);
}

module.exports = DatabaseService;

DatabaseService.prototype.run = function(query, callback) {
    this.queryRunner.run(query, QUERY_RUNNER_READONLY_OP, callback);
};

var affectedTableRegexCache = {
    bbox: /!bbox!/g,
    scaleDenominator: /!scale_denominator!/g,
    pixelWidth: /!pixel_width!/g,
    pixelHeight: /!pixel_height!/g
};

DatabaseService.prototype.getAffectedTables = function(sql, callback) {
    sql = sql
        .replace(affectedTableRegexCache.bbox, 'ST_MakeEnvelope(0,0,0,0)')
        .replace(affectedTableRegexCache.scaleDenominator, '0')
        .replace(affectedTableRegexCache.pixelWidth, '1')
        .replace(affectedTableRegexCache.pixelHeight, '1');
    sql = 'SELECT * FROM CDB_QueryTables_Updated_At($camshaft$' + sql + '$camshaft$)';
    this.queryRunner.run(sql, QUERY_RUNNER_READONLY_OP, function(err, resultSet) {
        if (err) {
            return callback(err);
        }
        var affectedTables = resultSet.rows.map(function(row) {
            // jshint camelcase:false
            return row.schema_name + '.' + row.table_name;
        });
        return callback(null, affectedTables);
    });
};

DatabaseService.prototype.createTable = function(targetTableName, query, callback) {
    var createQuery = createQueryTemplate({
        _targetTableName: targetTableName,
        _query: query
    });

    this.queryRunner.run(createQuery, QUERY_RUNNER_WRITE_OP, function(err, resultSet) {
        debug('TODO: register table');
        return callback(err, resultSet);
    });
};

DatabaseService.prototype.tableExists = function(targetTableName, callback) {
    var existsQuery = 'select * from ' + targetTableName + ' limit 0';
    this.queryRunner.run(existsQuery, QUERY_RUNNER_READONLY_OP, function(err, resultSet) {
        var tableExists = !err && resultSet;
        return callback(null, tableExists);
    });
};

DatabaseService.prototype.createTableIfNotExists = function(targetTableName, outputQuery, callback) {
    var self = this;
    this.tableExists(targetTableName, function(err, tableExists) {
        if (tableExists) {
            return callback(null, tableExists);
        }

        self.createTable(targetTableName, outputQuery, function(err) {
            if (err) {
                return callback(err, tableExists);
            }

            return callback(null, tableExists);
        });
    });
};

DatabaseService.prototype.getColumnNames = function(query, callback) {
    this.queryParser.getColumnNames(query, callback);
};

DatabaseService.prototype.enqueue = function(query, callback) {
    this.batchClient.enqueue(query, callback);
};

var registerNodeQueryTemplate = dot.template([
    'SELECT',
    '    \'{{=it._nodeId}}\',',
    '    $json_def${{=it._analysisDef}}$json_def$::json,',
    '    {{=it._inputNodes}}',
    'WHERE NOT EXISTS (SELECT * FROM cdb_analysis_catalog WHERE node_id = \'{{=it._nodeId}}\')'
].join('\n'));

var EMPTY_ARRAY_SQL = '\'{}\'';
function pgArray(input, cast) {
    if (input.length === 0) {
        return cast ? ('ARRAY[]::' + cast + '[]') : EMPTY_ARRAY_SQL;
    }
    return 'ARRAY[' + input.join(', ') + ']';
}

function pgQuoteCastMapper(cast) {
    return function(input) {
        return '\'' + input + '\'' + (cast ? ('::' + cast) : '');
    };
}

DatabaseService.prototype.registerNodesInCatalog = function(nodes, callback) {
    if (!Array.isArray(nodes) || nodes.length === 0) {
        return callback(null);
    }
    var nodesSql = [];
    nodes.forEach(function(node) {
        nodesSql.push(registerNodeQueryTemplate({
            _nodeId: node.id(),
            _inputNodes: pgArray(
                node.getInputNodes().map(function(node) { return node.id(); }).map(pgQuoteCastMapper()), 'char[40]'
            ),
            _analysisDef: JSON.stringify(node.toJSON())
        }));
    });
    var sql = 'INSERT INTO cdb_analysis_catalog' +
        '(node_id, analysis_def, input_nodes)\n' + nodesSql.join('\nUNION ALL\n');

    debug('Registering node with SQL: %s', sql);
    this.queryRunner.run(sql, QUERY_RUNNER_WRITE_OP, function(err, resultSet) {
        debug(err, resultSet);
        return callback(err);
    });
};

var trackNodeQueryTemplate = dot.template([
    'WITH RECURSIVE search_dag(node_id, input_nodes) AS (',
    '    SELECT node_id, input_nodes FROM cdb_analysis_catalog WHERE node_id = \'{{=it._nodeId}}\'',
    '    UNION',
    '    -- recursive search',
    '    SELECT c.node_id, c.input_nodes',
    '    FROM search_dag s, cdb_analysis_catalog c',
    '    WHERE c.node_id = ANY(s.input_nodes)',
    ')',
    'UPDATE cdb_analysis_catalog',
    'SET',
    '    used_at = NOW(),',
    '    hits = hits + 1,',
    '    last_used_from = \'{{=it._nodeId}}\'',
    'WHERE node_id IN (select node_id from search_dag)'
].join('\n'));

DatabaseService.prototype.trackNode = function(node, callback) {
    // we don't want to track source nodes as high level nodes
    if (node.type === Source.TYPE) {
        return callback(null);
    }
    var sql = trackNodeQueryTemplate({ _nodeId: node.id() });
    debug('Tracking analysis with SQL: %s', sql);
    this.queryRunner.run(sql, QUERY_RUNNER_WRITE_OP, function(err, resultSet) {
        debug(err, resultSet);
        return callback(err);
    });
};
<|endoftext|>


<commit_before>/**
 * @private
 * @class Session
 * @description Creates session
 * @requires crypto
 * @requires utilities
 * @requires resources
 */
'use strict';
const crypto = require('crypto');
const Utilities = require('../components/utilities');
const Resources = require('../components/resources');

class Session {

  /**
  * @private
  * @description Sets the class properties, validate signature,
  * and if it's not a super class - set resources as properties
  * @param {string} url1
  * @param {string} apiKey
  * @param {string} secret
  * @param {object} params
  * @param {boolean} isSuper
  * @throws {error} Invalid signature
  */
  constructor(url1, apiKey, secret, params, isSuper) {
    let expireTime;
    let timestamp;
    this.url = url1;
    this.apiKey = apiKey;
    this.secret = secret;
    this.params = params || {};
    if (this.params.signature) {
      timestamp = new Date(this.params.timestamp).getTime();
      expireTime = new Date().getTime() - 24 * 84600;
      if (!this.validateSignature(this.params) && expireTime > timestamp) {
        throw new Error('Invalid signature: Possible malicious login.');
      }
    }
    if (!isSuper) {
      this.getResources();
    }
  }

  /**
  * @private
  * @description Returns the protocol that will be used for this session
  * @returns {string} protocol
  */
  get protocol() {
    return 'https';
  }

  /**
  * @private
  * @description Creates permission url which will be used to obtain access
  * @returns {string} url
  */
  createPermissionUrl() {
    if (!Utilities.isEmptyString(this.url)
     && !Utilities.isEmptyString(this.apiKey)) {
      return 'http://' + this.url + '/admin/api/auth?api_key=' + this.apiKey;
    }
  }

  /**
  * @private
  * @description Generates the store url by contatinating the protocol,
  * the store name, and the admin ext.
  * @returns {string} protocol
  */
  site() {
    let site = this.protocol + '://' + this.apiKey + ':' + this.secret;
    return site + '@' + this.url + '/admin';
  }

  /**
  * @private
  * @description ?????
  * @returns {string} protocol
  */
  valid() {
    return !Utilities.isEmptyString(this.url);
  }

  /**
  * @private
  * @description Prepare the url for the store which will be used with
  * current session
  * @param {string} url
  * @returns {string} url
  */
  prepareUrl(url) {
    if (Utilities.isEmptyString(url)) {
      return '';
    }
    url.replace(/https?:\/\//, '');
    if (url.indexOf('.') === -1) {
      url += '.myshopify.com';
    }
    return url;
  }

  /**
  * @private
  * @description Check if the current signature is valid
  * @param {object} params
  * @returns {boolean}
  */
  validateSignature(params) {
    let generatedSignature;
    let k;
    let v;
    this.signature = params.signature;
    generatedSignature = this.secret;
    params = Utilities.sortObj(params);
    for (k in params) {
      v = params[k];
      if (k !== 'signature'
       && k !== 'action'
       && k !== 'controller'
       && !Utilities.isNumeric(k)
       && k) {
        generatedSignature += k + '=' + v;
      }
    }
    generatedSignature = crypto.createHash('md5')
    .update('' + generatedSignature).digest('hex');
    return generatedSignature === this.signature;
  }

  /**
  * @private
  * @description Sets all available resources as properties to this class
  */
  setResources() {
    let resources = Resources.getResources(this.site());
    Object.keys(resources).map(key => {
      this[key] = resources[key];
    });
  }

}

module.exports = Session;
<commit_msg>[fix] Add resources to the session instance<commit_after>/**
 * @private
 * @class Session
 * @description Creates session
 * @requires crypto
 * @requires utilities
 * @requires resources
 */
'use strict';
const crypto = require('crypto');
const Utilities = require('../components/utilities');
const Resources = require('../components/resources');

class Session {

  /**
  * @private
  * @description Sets the class properties, validate signature,
  * and if it's not a super class - set resources as properties
  * @param {string} url1
  * @param {string} apiKey
  * @param {string} secret
  * @param {object} params
  * @param {boolean} isSuper
  * @throws {error} Invalid signature
  */
  constructor(url1, apiKey, secret, params, isSuper) {
    let expireTime;
    let timestamp;
    this.url = url1;
    this.apiKey = apiKey;
    this.secret = secret;
    this.params = params || {};
    if (this.params.signature) {
      timestamp = new Date(this.params.timestamp).getTime();
      expireTime = new Date().getTime() - 24 * 84600;
      if (!this.validateSignature(this.params) && expireTime > timestamp) {
        throw new Error('Invalid signature: Possible malicious login.');
      }
    }
    if (!isSuper) {
      this.setResources();
    }
  }

  /**
  * @private
  * @description Returns the protocol that will be used for this session
  * @returns {string} protocol
  */
  get protocol() {
    return 'https';
  }

  /**
  * @private
  * @description Creates permission url which will be used to obtain access
  * @returns {string} url
  */
  createPermissionUrl() {
    if (!Utilities.isEmptyString(this.url)
     && !Utilities.isEmptyString(this.apiKey)) {
      return 'http://' + this.url + '/admin/api/auth?api_key=' + this.apiKey;
    }
  }

  /**
  * @private
  * @description Generates the store url by contatinating the protocol,
  * the store name, and the admin ext.
  * @returns {string} protocol
  */
  site() {
    let site = this.protocol + '://' + this.apiKey + ':' + this.secret;
    return site + '@' + this.url + '/admin';
  }

  /**
  * @private
  * @description ?????
  * @returns {string} protocol
  */
  valid() {
    return !Utilities.isEmptyString(this.url);
  }

  /**
  * @private
  * @description Prepare the url for the store which will be used with
  * current session
  * @param {string} url
  * @returns {string} url
  */
  prepareUrl(url) {
    if (Utilities.isEmptyString(url)) {
      return '';
    }
    url.replace(/https?:\/\//, '');
    if (url.indexOf('.') === -1) {
      url += '.myshopify.com';
    }
    return url;
  }

  /**
  * @private
  * @description Check if the current signature is valid
  * @param {object} params
  * @returns {boolean}
  */
  validateSignature(params) {
    let generatedSignature;
    let k;
    let v;
    this.signature = params.signature;
    generatedSignature = this.secret;
    params = Utilities.sortObj(params);
    for (k in params) {
      v = params[k];
      if (k !== 'signature'
       && k !== 'action'
       && k !== 'controller'
       && !Utilities.isNumeric(k)
       && k) {
        generatedSignature += k + '=' + v;
      }
    }
    generatedSignature = crypto.createHash('md5')
    .update('' + generatedSignature).digest('hex');
    return generatedSignature === this.signature;
  }

  /**
  * @private
  * @description Sets all available resources as properties to this class
  */
  setResources() {
    let resources = Resources.getResources(this.site());
    Object.keys(resources).map(key => {
      this[key] = resources[key];
    });
  }

}

module.exports = Session;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016, Two Sigma Open Source
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of slim nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * This module contains methods for committing.
 */

const assert = require("assert");
const co     = require("co");

const GitUtil       = require("./slmu_gitutil");
const SubmoduleUtil = require("./slmu_submoduleutil");

/**
 * Create a commit across modified repositories and the meta-repository with
 * the specified `message`, if provided, prompting the user if no message is
 * provided.  If the specified `all` is provided, automatically stage modified
 * files.
 *
 * @async
 * @param {Boolean} all
 * @param {String}  message
 */
exports.commit = co.wrap(function *(all, message) {
    // TODO: 1. Prompt with editor if no message.
    //       2. Consider adding an "amend" that does something smart, like
    //          amending only repos changed by last commit in meta-repository.

    assert.notEqual(null, message, "message prompting not implemented");

    const commitRepo = co.wrap(function *(repo, doAll) {
        const branch = yield repo.getCurrentBranch();
        if (null === branch) {
            return null;
        }
        var areStagedFiles = false;
        var indexUpdated = false;
        const index = yield repo.index();
        const statuses = yield repo.getStatusExt();

        // Loop through all the status entries on the repo.  If 'all' is
        // selected, stage unstaged files.  If differences on the index are
        // found, remember that the index has been updated so we'll know to do
        // a commit.

        statuses.forEach(status => {

            // If we're doing all files, stage unstaged (non-new) files.

            if (doAll && null !== status.indexToWorkdir() && !status.isNew()) {
                indexUpdated = true;
                areStagedFiles = true;
                index.addByPath(status.path());
            }
            else {
                // Note that files have been staged.
                areStagedFiles = areStagedFiles || (0 !== status.inIndex());
            }
        });
        if (indexUpdated) {
            index.write();
        }
        if (areStagedFiles) {
            const signature = repo.defaultSignature();
            return yield repo.createCommitOnHead([],
                                                 signature,
                                                 signature,
                                                 message);
        }
        return null;
    });
    const metaRepo = yield GitUtil.getCurrentRepo();
    const subRepos = yield SubmoduleUtil.getSubmoduleRepos(metaRepo);
    const committers = subRepos.map(sub => commitRepo(sub.repo, all));

    // Commit to sub-repos first; can't update the meta-repo until the
    // sub-repos are done.

    yield committers;

    // We always commit all for the metaRepo.

    const metaResult = yield commitRepo(metaRepo, true);

    // If we didn't generate a commit on the meta-repo that means we didn't
    // commit anything; we warn the user.

    if (null === metaResult) {
        console.warn("Nothing to commit.");
    }
});
<commit_msg>factored out function to commit a single repo<commit_after>/*
 * Copyright (c) 2016, Two Sigma Open Source
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of slim nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * This module contains methods for committing.
 */

const assert = require("assert");
const co     = require("co");

const GitUtil       = require("./slmu_gitutil");
const SubmoduleUtil = require("./slmu_submoduleutil");

/**
 * Commit changes in the specified `repo`.  If the specified `doAll` is true,
 * commit staged and unstaged files; otherwise, commit only staged files.  Use
 * the specified `message` as the commit message.  If there are no files to
 * commit, do nothing and return null; otherwise, return the created commit
 * object.
 *
 * @async
 * @param {NodeGit.Repository} repo
 * @param {Boolean}            doAll
 * @param {String}             message
 * @return {NodeGit.Commit|null}
 */
exports.commitRepo = co.wrap(function *(repo, doAll, message) {
    var areStagedFiles = false;
    var indexUpdated = false;
    const index = yield repo.index();
    const statuses = yield repo.getStatusExt();

    // Loop through all the status entries on the repo.  If 'all' is
    // selected, stage unstaged files.  If differences on the index are
    // found, remember that the index has been updated so we'll know to do
    // a commit.

    statuses.forEach(status => {

        // If we're doing all files, stage unstaged (non-new) files.

        if (doAll && null !== status.indexToWorkdir() && !status.isNew()) {
            indexUpdated = true;
            areStagedFiles = true;
            index.addByPath(status.path());
        }
        else {
            // Note that files have been staged.
            areStagedFiles = areStagedFiles || (0 !== status.inIndex());
        }
    });
    if (indexUpdated) {
        index.write();
    }
    if (areStagedFiles) {
        const signature = repo.defaultSignature();
        return yield repo.createCommitOnHead([],
                                             signature,
                                             signature,
                                             message);
    }
    return null;
});

/**
 * Create a commit across modified repositories and the meta-repository with
 * the specified `message`, if provided, prompting the user if no message is
 * provided.  If the specified `all` is provided, automatically stage modified
 * files.
 *
 * @async
 * @param {Boolean} all
 * @param {String}  message
 */
exports.commit = co.wrap(function *(all, message) {
    // TODO: 1. Prompt with editor if no message.
    //       2. Consider adding an "amend" that does something smart, like
    //          amending only repos changed by last commit in meta-repository.

    assert.notEqual(null, message, "message prompting not implemented");

    const metaRepo = yield GitUtil.getCurrentRepo();
    const subRepos = yield SubmoduleUtil.getSubmoduleRepos(metaRepo);
    const committers = subRepos.map(sub => {
        return exports.commitRepo(sub.repo, all, message);
    });

    // Commit to sub-repos first; can't update the meta-repo until the
    // sub-repos are done.

    yield committers;

    // We always commit all for the metaRepo.

    const metaResult = yield exports.commitRepo(metaRepo, true, message);

    // If we didn't generate a commit on the meta-repo that means we didn't
    // commit anything; we warn the user.

    if (null === metaResult) {
        console.warn("Nothing to commit.");
    }
});
<|endoftext|>


<commit_before>#!  /usr/bin/node

var rep = require("./representation.js");
var tools = require("./tools.js");
var error = require("./errors.js");
var operators = Object.keys(rep.OPInfo);

var matchop = tools.opMatch(operators);

function isDigit(a) {
  if (!a)
    return false;
  var code = a.charCodeAt();
  return (46 < code && code < 58 || code < 58 && code > 46);
}

function isWhitespace(a) {
  if (!a)
    return true;

  var code = a.charCodeAt();
  return (code === 9 || code === 32 || code === 10 || code === 13 || code === 11);
}

function isIdentifier(a) {
  var code = a.charCodeAt();
  return code !== 41 && code !== 40 && code && 125 && code && 123 && code !== 93 && code !== 91 && code !== 44;
}

function tokenizeNum(tokstream, charnum, linenum) {
  var number = [];
  var code = tokstream[0].charCodeAt();
  var isFloat = false;
  var n = 0;
  // + -
  // might want to remove this since it probably won't ever get run?
  if (code === 43 || code === 45) { // + or -
    number.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
  }
  else if (code === 46) { // .
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
    number.push('0');
    number.push('.');
    isFloat = true;
  }

  while (isDigit(tokstream[0]) && tokstream.length !== 0) {
    number.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    charnum++;
    n++;
  }
  if (tokstream[0] === '.' && isDigit(tokstream[1])) {
    number.push('.');
    number.push(tokstream[1]);
    tokstream = tokstream.substr(2);
    charnum++; charnum++;
    n++; n++;
    while (isDigit(tokstream[0]) && tokstream.length !== 0) {
      number.push(tokstream[0]);
      tokstream = tokstream.substr(1);
      n++;
      charnum++;
    }
    return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]];
  }
  if (!isFloat)
    return [n, ["integer", parseInt(number.join(''), 10), charnum, linenum]];
  else
    return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]];
}

/* Split up the tokenized identifier if an operator appears in it
 * prefer longer identifiers that start with the same character(s) as shorter ones
 * e.g. ++ over +
 * Everything after the operator goes back on to the token stream
 */

function tokenizeIdent(tokstream, charnum, linenum) {
  var identifier = [];
  var n = 0;
  while ((!isWhitespace(tokstream[0])) && isIdentifier(tokstream[0]) && !matchop(tokstream)) {
    identifier.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
  }
  identifier = identifier.join('');

  return [[n, ["identifier", identifier, charnum, linenum]]];
}

function tokenizeStr(tokstream, charnum, linenum) {
  var stringlit = [];
  var n = 1;
  tokstream = tokstream.substr(1);
  while (tokstream[0].charCodeAt() !== 34) {
    stringlit.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
    if (tokstream.length < 1) {
      throw error.JSyntaxError(linenum, charnum, "Error: missing quotation mark");
    }
  }
  n++;
  return [n, ["stringlit", stringlit.join(''), charnum, linenum]];

}

function tokenizeT(tokstream, charnum, linenum) {
  if (tokstream.length < 4)
    return false;
  var next4 = tokstream.substr(0,4);
  if (next4 === "then")
    return ["thenexp", "then"];
  else if (next4 === "true")
    return ["truelit", "true"];
  return false;
}

function peek(tokstream, toktype, word, charnum, linenum) {
  var n = word.length;
  if (tokstream.length < n)
    return false;
  var nextN = tokstream.substr(0, n);
  if (nextN == word) {
    return [toktype, word];
  }
  return false;
}

function tokenize(tokstream) {
  var tokens = [];
  var charnum = 1;
  var linenum = 1;

  while (tokstream) {
    switch (tokstream[0].charCodeAt()) {
      case 9: // '\t'
        charnum++;
        tokens.push(["whitespace", '\t', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 32: // ' '
        charnum++;
        tokens.push(["whitespace", ' ', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 10: // '\n'
        linenum++;
        charnum = 1;
        tokens.push(["whitespace", '\n', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 44: // ','
        charnum++;
        tokens.push(["comma", ",", charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 40: // '('
        charnum++;
        tokens.push(["left_paren", '(', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 41: // ')'
        charnum++;
        tokens.push(["right_paren", ')', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 123: // '{'
        charnum++;
        tokens.push(["left_brace", '{', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 125: // '}'
        charnum++;
        tokens.push(["right_brace", '}', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 91: // '['
        charnum++;
        tokens.push(["left_square", '[', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 93: // ']'
        charnum++;
        tokens.push(["right_square", ']', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 34: // '"'
        var result = tokenizeStr(tokstream, charnum, linenum);
        var str = result[1];
        var i = result[0];
        tokens.push(str);
        tokstream = tokstream.substr(i);
        break;

      case 45: // '-'
        var lambda = peek(tokstream, "arrow", "->");
        if (lambda) {
          tokens.push(lambda);
          tokstream = tokstream.substr(2);
          break;
        }
        else {
          tokens.push(["identifier", "-", charnum, linenum]);
          charnum++;
          tokstream = tokstream.substr(1);
          break;
        }

      case 46: // '.'
        if (isDigit(tokstream[1])) {
          var result = tokenizeNum(tokstream, charnum, linenum);
          var num = result[1];
          var i = result[0];
          if (num[1] !== NaN)
            tokens.push(num);
          tokstream = tokstream.substr(i);
          break;
        }
      case 116: // 't'
        var result = tokenizeT(tokstream);
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(4); // 4 = length of either token
          break;
        }

      case 105: // 'i'
        var ifexp = peek(tokstream, "ifexp", "if");
        if (ifexp) {
          tokens.push(ifexp);
          tokstream = tokstream.substr(2);
          break;
        }
        var inkeyword = peek(tokstream, "in", "in");
        if (inkeyword) {
          tokens.push(inkeyword);
          tokstream = tokstream.substr(2);
          break;
        }

      case 100: // 'd'
        var result = peek(tokstream, "def", "def");
        if (result) {
          tokens.push(["def", "def", charnum, linenum]);
          tokstream = tokstream.substr(3);
          break;
        }
      case 101: // e
        var result = peek(tokstream, "elsexp", "else");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(4);
          break;
        }
      case 102: // f
        var result = peek(tokstream, "falselit", "false");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(5);
          break;
        }
      case 108: // l
        var lambda = peek(tokstream, "lambda", "lambda");
        if (lambda) {
          tokens.push(lambda);
          tokstream = tokstream.substr(6);
          break;
        }
        var letexp = peek(tokstream, "let", "let");
        if (letexp) {
          tokens.push(letexp);
          tokstream = tokstream.substr(3);
          break;
        }

      default:
        if (isDigit(tokstream[0])) {
          var result = tokenizeNum(tokstream, charnum, linenum);
          var num = result[1];
          var i = result[0];
          if (num[1] !== NaN)
            tokens.push(num);
          tokstream = tokstream.substr(i);
          break;
        }
        var op = matchop(tokstream);
        if (op) {
          var l = op.length;
          charnum = charnum + l;
          tokstream = tokstream.substr(l);
          tokens.push(["identifier", op, charnum, linenum]);
        }
        else {
          var result = tokenizeIdent(tokstream, charnum, linenum);
          result.map(function(x) {
            charnum++;
            tokens.push(x[1]);
            tokstream = tokstream.substr(x[0]);
          });
        }
    }
  }
  return tokens;
}

function tokenizeFull(input) {
  try {
    return tokenize(input).reverse().filter(function(x) {
      return x[0] !== "whitespace";
    });
  } catch (e) {
    console.log(e.stxerror());
    process.exit(1);
  }
}

module.exports = {tokenize : tokenizeFull};
<commit_msg>preliminary support for user-defined operators<commit_after>#!  /usr/bin/node

var rep = require("./representation.js");
var tools = require("./tools.js");
var error = require("./errors.js");
var operators = Object.keys(rep.OPInfo);

var matchop = tools.opMatch(operators);

function isDigit(a) {
  if (!a)
    return false;
  var code = a.charCodeAt();
  return (46 < code && code < 58 || code < 58 && code > 46);
}

function isWhitespace(a) {
  if (!a)
    return true;

  var code = a.charCodeAt();
  return (code === 9 || code === 32 || code === 10 || code === 13 || code === 11);
}

function isIdentifier(a) {
  var code = a.charCodeAt();
  return code !== 41 && code !== 40 && code && 125 && code && 123 && code !== 93 && code !== 91 && code !== 44;
}

function tokenizeNum(tokstream, charnum, linenum) {
  var number = [];
  var code = tokstream[0].charCodeAt();
  var isFloat = false;
  var n = 0;
  // + -
  // might want to remove this since it probably won't ever get run?
  if (code === 43 || code === 45) { // + or -
    number.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
  }
  else if (code === 46) { // .
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
    number.push('0');
    number.push('.');
    isFloat = true;
  }

  while (isDigit(tokstream[0]) && tokstream.length !== 0) {
    number.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    charnum++;
    n++;
  }
  if (tokstream[0] === '.' && isDigit(tokstream[1])) {
    number.push('.');
    number.push(tokstream[1]);
    tokstream = tokstream.substr(2);
    charnum++; charnum++;
    n++; n++;
    while (isDigit(tokstream[0]) && tokstream.length !== 0) {
      number.push(tokstream[0]);
      tokstream = tokstream.substr(1);
      n++;
      charnum++;
    }
    return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]];
  }
  if (!isFloat)
    return [n, ["integer", parseInt(number.join(''), 10), charnum, linenum]];
  else
    return [n, ["float", parseFloat(number.join(''), 10), charnum, linenum]];
}

/* Split up the tokenized identifier if an operator appears in it
 * prefer longer identifiers that start with the same character(s) as shorter ones
 * e.g. ++ over +
 * Everything after the operator goes back on to the token stream
 */

function tokenizeIdent(tokstream, charnum, linenum) {
  var identifier = [];
  var n = 0;
  while ((!isWhitespace(tokstream[0])) && isIdentifier(tokstream[0]) && !matchop(tokstream)) {
    identifier.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
  }
  identifier = identifier.join('');

  return [[n, ["identifier", identifier, charnum, linenum]]];
}

function tokenizeStr(tokstream, charnum, linenum) {
  var stringlit = [];
  var n = 1;
  tokstream = tokstream.substr(1);
  while (tokstream[0].charCodeAt() !== 34) {
    stringlit.push(tokstream[0]);
    tokstream = tokstream.substr(1);
    n++;
    charnum++;
    if (tokstream.length < 1) {
      throw error.JSyntaxError(linenum, charnum, "Error: missing quotation mark");
    }
  }
  n++;
  return [n, ["stringlit", stringlit.join(''), charnum, linenum]];

}

function tokenizeT(tokstream, charnum, linenum) {
  if (tokstream.length < 4)
    return false;
  var next4 = tokstream.substr(0,4);
  if (next4 === "then")
    return ["thenexp", "then"];
  else if (next4 === "true")
    return ["truelit", "true"];
  return false;
}

function peek(tokstream, toktype, word, charnum, linenum) {
  var n = word.length;
  if (tokstream.length < n)
    return false;
  var nextN = tokstream.substr(0, n);
  if (nextN == word) {
    return [toktype, word];
  }
  return false;
}

function tokenize(tokstream) {
  var tokens = [];
  var charnum = 1;
  var linenum = 1;

  while (tokstream) {
    switch (tokstream[0].charCodeAt()) {
      case 9: // '\t'
        charnum++;
        tokens.push(["whitespace", '\t', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 32: // ' '
        charnum++;
        tokens.push(["whitespace", ' ', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 10: // '\n'
        linenum++;
        charnum = 1;
        tokens.push(["whitespace", '\n', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 44: // ','
        charnum++;
        tokens.push(["comma", ",", charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 40: // '('
        charnum++;
        tokens.push(["left_paren", '(', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 41: // ')'
        charnum++;
        tokens.push(["right_paren", ')', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 123: // '{'
        charnum++;
        tokens.push(["left_brace", '{', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 125: // '}'
        charnum++;
        tokens.push(["right_brace", '}', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 91: // '['
        charnum++;
        tokens.push(["left_square", '[', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 93: // ']'
        charnum++;
        tokens.push(["right_square", ']', charnum, linenum]);
        tokstream = tokstream.substr(1);
        break;
      case 34: // '"'
        var result = tokenizeStr(tokstream, charnum, linenum);
        var str = result[1];
        var i = result[0];
        tokens.push(str);
        tokstream = tokstream.substr(i);
        break;

      case 45: // '-'
        var lambda = peek(tokstream, "arrow", "->");
        if (lambda) {
          tokens.push(lambda);
          tokstream = tokstream.substr(2);
          break;
        }
        else {
          tokens.push(["identifier", "-", charnum, linenum]);
          charnum++;
          tokstream = tokstream.substr(1);
          break;
        }

      case 46: // '.'
        if (isDigit(tokstream[1])) {
          var result = tokenizeNum(tokstream, charnum, linenum);
          var num = result[1];
          var i = result[0];
          if (num[1] !== NaN)
            tokens.push(num);
          tokstream = tokstream.substr(i);
          break;
        }
      case 116: // 't'
        var result = tokenizeT(tokstream);
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(4); // 4 = length of either token
          break;
        }

      case 105: // 'i'
        var ifexp = peek(tokstream, "ifexp", "if");
        if (ifexp) {
          tokens.push(ifexp);
          tokstream = tokstream.substr(2);
          break;
        }
        var inkeyword = peek(tokstream, "in", "in");
        if (inkeyword) {
          tokens.push(inkeyword);
          tokstream = tokstream.substr(2);
          break;
        }

      case 100: // 'd'
        var defop = peek(tokstream, "defop", "defop");
        if (defop) {
          tokens.push(["defop", "defop", charnum, linenum]);
          tokstream = tokstream.substr(5);
        }
        var def = peek(tokstream, "def", "def");
        if (def) {
          tokens.push(["def", "def", charnum, linenum]);
          tokstream = tokstream.substr(3);
          break;
        }
      case 101: // e
        var result = peek(tokstream, "elsexp", "else");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(4);
          break;
        }
      case 102: // f
        var result = peek(tokstream, "falselit", "false");
        if (result) {
          tokens.push(result);
          tokstream = tokstream.substr(5);
          break;
        }
      case 108: // l
        var lambda = peek(tokstream, "lambda", "lambda");
        if (lambda) {
          tokens.push(lambda);
          tokstream = tokstream.substr(6);
          break;
        }
        var letexp = peek(tokstream, "let", "let");
        if (letexp) {
          tokens.push(letexp);
          tokstream = tokstream.substr(3);
          break;
        }

      default:
        if (isDigit(tokstream[0])) {
          var result = tokenizeNum(tokstream, charnum, linenum);
          var num = result[1];
          var i = result[0];
          if (num[1] !== NaN)
            tokens.push(num);
          tokstream = tokstream.substr(i);
          break;
        }
        var op = matchop(tokstream);
        if (op) {
          var l = op.length;
          charnum = charnum + l;
          tokstream = tokstream.substr(l);
          tokens.push(["identifier", op, charnum, linenum]);
        }
        else {
          var result = tokenizeIdent(tokstream, charnum, linenum);
          result.map(function(x) {
            charnum++;
            tokens.push(x[1]);
            tokstream = tokstream.substr(x[0]);
          });
        }
    }
  }
  return tokens;
}

function tokenizeFull(input) {
  try {
    return tokenize(input).reverse().filter(function(x) {
      return x[0] !== "whitespace";
    });
  } catch (e) {
    console.log(e.stxerror());
    process.exit(1);
  }
}

module.exports = {tokenize : tokenizeFull};
<|endoftext|>


<commit_before>(function (w, $) {
	w.toolbelt = {};

	w.toolbelt.resizeFunctions = [];
	w.toolbelt.addEventOnWindowResize = function (f) {
		$(window).unbind('resize').bind('resize', w.toolbelt.runWindowResizeEvents);
		w.toolbelt.resizeFunctions.push(f);
		f();
	};
	w.toolbelt.runWindowResizeEvents = function () {
		for (var i = 0, l = w.toolbelt.resizeFunctions.length; i < l; i++) {
			w.toolbelt.resizeFunctions[i]();
		}
	};

	w.toolbelt.checkSWFObject = function (cb, preferredUrl) {
		if (typeof swfobject === 'undefined' || swfobject === null) {
			$.getScript(w.toolbelt.exists(preferredUrl) ? preferredUrl : window.location.protocol + '//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js', function () {
				if (!!cb) {
					cb();
				}
			});
		} else {
			if (!!cb) {
				cb();
			}
		}
	};

	w.toolbelt.exists = function(obj) {
		return typeof obj !== 'undefined' && !!obj;
	};

	w.toolbelt.reRender = function() {
		w.scrollTo(0, w.pageYOffset);
		$(w).trigger('scroll');
	};

	//I know people don't like this, but sometimes you need to know if it's iOS, IE or Android, sorry
	w.toolbelt.checkBrowser = function(browser) {
		return navigator.userAgent.toLowerCase().match(new RegExp(browser)) != null;
	};
	w.toolbelt.isMobile = function() {
		return w.toolbelt.checkBrowser('iphone|ipod|ipad|mobile|android');
	};
	w.toolbelt.isIOS = function() {
		return w.toolbelt.checkBrowser('iphone|ipod|ipad|mobile safari');
	};
	w.toolbelt.isIPad = function() {
		return w.toolbelt.checkBrowser('ipad');
	};
	w.toolbelt.isIPod = function() {
		return w.toolbelt.checkBrowser('ipod');
	};
	w.toolbelt.isIPhone = function() {
		return w.toolbelt.checkBrowser('iphone');
	};
	w.toolbelt.isAndroid = function() {
		return w.toolbelt.checkBrowser('android');
	};
	w.toolbelt.isWindowsPhone = function() {
		return w.toolbelt.checkBrowser('iemobile|Windows Phone');
	};

	w.toolbelt.isVisible = function(obj) {
		if (typeof obj === 'string') {
			obj = $(obj);
		}

		if (!obj.is(':visible')) {
			return false;
		} else if (obj.is(':hidden')) {
			return true;
		}

		var $window = $(w),
			docViewTop = $window.scrollTop(),
			docViewBottom = docViewTop + $window.height(),
			elemTop = obj.offset().top,
			elemBottom = elemTop + obj.height();

		return elemBottom >= docViewTop && elemTop <= docViewBottom;
	};

	var useSessionStorage = null,
		checkSessionStorage = function() {
			try {
				if (useSessionStorage === null) {
					useSessionStorage = w.toolbelt.exists(Storage) && w.toolbelt.exists(sessionStorage);
				}
			} catch(e) {
				useSessionStorage= false;
			}

			return useSessionStorage;
		},
		setSessionItem = function(key, obj) {
			if (checkSessionStorage()) {
				try {
					sessionStorage.setItem(key, JSON.stringify(obj));
				} catch (e) { }
			}
		},
		getSessionItem = function(key) {
			var val = null;
			if (checkSessionStorage()) {
				try {
					val = JSON.parse(sessionStorage.getItem(key));
				} catch (e) { }
			}
			return val;
		};

	w.toolbelt.cachedAjax = function(options) {
		var val = null;
		options = options || {};
		if (!w.toolbelt.exists(options.cache) || !options.cache) {
			val = getSessionItem(options.url);
			if (w.toolbelt.exists(options.expires) && options.expires > 0 && !!val && !!val.expiration
				&& val.expiration < new Date().getTime()) {

				val = null;
				//TODO: add cache removal
			}
		}

		if (val === null) {
			var success = function(val) {
				if (w.toolbelt.exists(options.expires) && options.expires > 0) {
					var now = new Date();
					val.expiration = now.setSeconds(now.getSeconds() + options.expires);
				}
				setSessionItem(options.url, val);
				options.success(val);
			};
			options.success = success;
			$.ajax(options);
		} else if (w.toolbelt.exists(options.success)) {
			options.success(val);
		}
	};
}(window, jQuery));<commit_msg>Add clearing of cache<commit_after>(function (w, $) {
	w.toolbelt = {};

	w.toolbelt.resizeFunctions = [];
	w.toolbelt.addEventOnWindowResize = function (f) {
		$(window).unbind('resize').bind('resize', w.toolbelt.runWindowResizeEvents);
		w.toolbelt.resizeFunctions.push(f);
		f();
	};
	w.toolbelt.runWindowResizeEvents = function () {
		for (var i = 0, l = w.toolbelt.resizeFunctions.length; i < l; i++) {
			w.toolbelt.resizeFunctions[i]();
		}
	};

	w.toolbelt.checkSWFObject = function (cb, preferredUrl) {
		if (typeof swfobject === 'undefined' || swfobject === null) {
			$.getScript(w.toolbelt.exists(preferredUrl) ? preferredUrl : window.location.protocol + '//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js', function () {
				if (!!cb) {
					cb();
				}
			});
		} else {
			if (!!cb) {
				cb();
			}
		}
	};

	w.toolbelt.exists = function(obj) {
		return typeof obj !== 'undefined' && !!obj;
	};

	w.toolbelt.reRender = function() {
		w.scrollTo(0, w.pageYOffset);
		$(w).trigger('scroll');
	};

	//I know people don't like this, but sometimes you need to know if it's iOS, IE or Android, sorry
	w.toolbelt.checkBrowser = function(browser) {
		return navigator.userAgent.toLowerCase().match(new RegExp(browser)) != null;
	};
	w.toolbelt.isMobile = function() {
		return w.toolbelt.checkBrowser('iphone|ipod|ipad|mobile|android');
	};
	w.toolbelt.isIOS = function() {
		return w.toolbelt.checkBrowser('iphone|ipod|ipad|mobile safari');
	};
	w.toolbelt.isIPad = function() {
		return w.toolbelt.checkBrowser('ipad');
	};
	w.toolbelt.isIPod = function() {
		return w.toolbelt.checkBrowser('ipod');
	};
	w.toolbelt.isIPhone = function() {
		return w.toolbelt.checkBrowser('iphone');
	};
	w.toolbelt.isAndroid = function() {
		return w.toolbelt.checkBrowser('android');
	};
	w.toolbelt.isWindowsPhone = function() {
		return w.toolbelt.checkBrowser('iemobile|Windows Phone');
	};

	w.toolbelt.isVisible = function(obj) {
		if (typeof obj === 'string') {
			obj = $(obj);
		}

		if (!obj.is(':visible')) {
			return false;
		} else if (obj.is(':hidden')) {
			return true;
		}

		var $window = $(w),
			docViewTop = $window.scrollTop(),
			docViewBottom = docViewTop + $window.height(),
			elemTop = obj.offset().top,
			elemBottom = elemTop + obj.height();

		return elemBottom >= docViewTop && elemTop <= docViewBottom;
	};

	var useSessionStorage = null,
		checkSessionStorage = function() {
			try {
				if (useSessionStorage === null) {
					useSessionStorage = w.toolbelt.exists(Storage) && w.toolbelt.exists(sessionStorage);
				}
			} catch(e) {
				useSessionStorage= false;
			}

			return useSessionStorage;
		},
		setSessionItem = function(key, obj) {
			if (checkSessionStorage()) {
				try {
					sessionStorage.setItem(key, JSON.stringify(obj));
				} catch (e) { }
			}
		},
		getSessionItem = function(key) {
			var val = null;
			if (checkSessionStorage()) {
				try {
					val = JSON.parse(sessionStorage.getItem(key));
				} catch (e) { }
			}
			return val;
		},
		removeSessionItem = function(key) {
			if (checkSessionStorage()) {
				try {
				sessionStorage.removeItem(key);
				} catch (e) { }
			}
		};

	w.toolbelt.cachedAjax = function(options) {
		var val = null;
		options = options || {};
		if (!w.toolbelt.exists(options.cache) || !options.cache) {
			val = getSessionItem(options.url);
			if (w.toolbelt.exists(options.expires) && options.expires > 0 && !!val && !!val.expiration
				&& val.expiration < new Date().getTime()) {

				val = null;
				removeSessionItem(options.url);
			}
		}

		if (val === null) {
			var success = function(val) {
				if (w.toolbelt.exists(options.expires) && options.expires > 0) {
					var now = new Date();
					val.expiration = now.setSeconds(now.getSeconds() + options.expires);
				}
				setSessionItem(options.url, val);
				options.success(val);
			};
			options.success = success;
			$.ajax(options);
		} else if (w.toolbelt.exists(options.success)) {
			options.success(val);
		}
	};
}(window, jQuery));<|endoftext|>


<commit_before>(function() {

    // Constants.
    var fontFamily = '"Helvetica Neue", "Arial", sans-serif';
    var highRed = 204, highGreen = 0, highBlue = 0;
    var mediumRed = 170, mediumGreen = 170, mediumBlue = 0;
    var lowRed = 0, lowGreen = 204, lowBlue = 0;

    // Throttles the excution of the given throttledFunction to run
    // at most every given interval.
    var throttle = function(interval, throttledFunction) {
        if (interval <= 0) {
            return throttledFunction;
        }

        var lastTrigger = 0;
        var timeout;
        var lastArguments;
        return function() {

            lastArguments = arguments;
            if (timeout) {
                return;
            }

            var context = this;
            var now = +new Date();
            var delay = interval - now + lastTrigger;

            if (delay <= 0) {
                lastTrigger = now;
                throttledFunction.apply(context, lastArguments);

            } else {
                timeout = setTimeout(function() {
                    lastTrigger = now;
                    timeout = null;
                    throttledFunction.apply(context, lastArguments);
                }, delay);
            }
        };
    };

    // Calculates the boundary that can contain all elements between
    // the given $start and $end.
    var calculateBoundary = function($start, $stop) {
        var minX, minY, maxX, maxY;

        $start.nextUntil($stop).each(function() {
            var $child = $(this);
            var childOffset = $child.offset();
            var childMinX = childOffset.left;
            var childMinY = childOffset.top;
            var childMaxX = childMinX + $child.outerWidth(true);
            var childMaxY = childMinY + $child.outerHeight(true);

            if (!minX || minX > childMinX) {
                minX = childMinX;
            }
            if (!minY || minY > childMinY) {
                minY = childMinY;
            }
            if (!maxX || maxX < childMaxX) {
                maxX = childMaxX;
            }
            if (!maxY || maxY < childMaxY) {
                maxY = childMaxY;
            }
        });

        return {
            'left': minX,
            'top': minY,
            'width': maxX - minX,
            'height': maxY - minY
        };
    };

    // Main entry point.
    var main = function($) {
        var $body = $('body');

        // Tooltip that shows profile information around the element
        // under the mouse.
        var $tooltip = $('
', {
            'css': {
                'background-color': 'rgba(0, 0, 0, 0.8)',
                '-moz-border-radius': '5px',
                '-webkit-border-radius': '5px',
                'border-radius': '5px',
                'color': 'white',
                'display': 'none',
                'font-family': fontFamily,
                'font-size': '12px',
                'max-width': '25%',
                'padding': '5px',
                'position': 'fixed',
                'top': '5px',
                'right': '5px',
                'z-index': 3000000
            }
        });
        $body.append($tooltip);

        // Create an IFRAME for the profile result so that it can
        // be shown with its own CSS.
        var $profile = $('');
        $profile.css({
            'border': 'none',
            'height': 1,
            'margin': 0,
            'padding': 0,
            'position': 'relative',
            'width': '100%',
            'z-index': 1000000
        });

        $profile.load(function() {
            var $profile = $(this);
            var $profileBody = $(this.contentDocument.body);

            $profileBody.html($('#_profile-result').remove().html());
            $profile.height($profileBody.height() + 30);
            var $events = $profileBody.find('#_profile-eventTimeline tbody tr');

            var lastHoverElement;
            $(window).mousemove(throttle(100, function(event) {

                var $container = $(this);
                var x = event.pageX - $container.scrollLeft();
                var y = event.pageY - $container.scrollTop();

                // Hovering over a different element?
                $('._profile-openEditor').hide();
                var hoverElement = document.elementFromPoint(x, y);
                $('._profile-openEditor').show();
                if (hoverElement === lastHoverElement) {
                    return;
                } else {
                    lastHoverElement = hoverElement;
                }

                var $hoverElement = $(hoverElement);
                var tooltipHtml = '';

                // Over a visual display of an event.
                if ($hoverElement.is('._profile-eventDisplay')) {
                    var index = parseInt($hoverElement.attr('data-index'));
                    var $event = $events.eq(index);
                    tooltipHtml += 'Event #' + index + '
';
                    tooltipHtml += 'Start: ' + $event.find('td:eq(1)').html() + '
';
                    tooltipHtml += 'Total: ' + $event.find('td:eq(2)').html() + '
';
                    tooltipHtml += 'Own: ' + $event.find('td:eq(3)').html() + '
';
                    tooltipHtml += 'Objects: ' + $event.find('td:eq(4)').html();

                // Try to find all JSPs that may be associated with
                // rendering the element under the mouse.
                } else {
                    $('._profile-openEditor').remove();

                    var $parent = $hoverElement;
                    var isFirst = true;
                    var padding = 0;
                    for (; $parent.length > 0; $parent = $parent.parent()) (function() {

                        var $start;
                        var $stop;
                        var jsp;
                        var $prev = $parent;
                        for (; $prev.length > 0; $prev = $prev.prev()) {

                            if ($prev.is('._profile-jspStart')) {
                                $start = $prev;
                                var prevJsp = $prev.attr('data-jsp');
                                if (prevJsp.indexOf('/_draft/') > -1) {
                                    continue;
                                }

                                var $next = $parent;
                                for (; $next.length > 0; $next = $next.next()) {
                                    if ($next.is('._profile-jspStop[data-jsp=' + prevJsp + ']')) {
                                        $stop = $next;
                                        jsp = prevJsp;
                                        tooltipHtml += (isFirst ? 'JSP: ' : '
Called from ') + jsp;
                                        isFirst = false;
                                        break;
                                    }
                                }
                                break;

                            } else if ($prev.is('._profile-jspStop')) {
                                break;
                            }
                        }

                        if (!jsp) {
                            return;
                        }

                        var boundary = calculateBoundary($start, $stop);
                        padding += 4;

                        $('body').append($('', {
                            'class': '_profile-openEditor',
                            'data-padding': padding,
                            'target': '_blank',
                            'href': '/_debug/code' +
                                    '?action=edit' +
                                    '&type=JSP' +
                                    '&servletPath=' + encodeURIComponent(jsp) +
                                    '&jspPreviewUrl=' + encodeURIComponent(location.href),
                            'css': {
                                'border': '1px solid rgba(204, 0, 0, 0.8)',
                                '-moz-border-radius': '4px',
                                '-webkit-border-radius': '4px',
                                'border-radius': '4px',
                                'display': 'block',
                                'height': boundary.height + (padding * 2),
                                'left': boundary.left - padding,
                                'position': 'absolute',
                                'top': boundary.top - padding,
                                'width': boundary.width + (padding * 2),
                                'z-index': 1000000 - padding
                            }
                        }));
                    })();
                }

                if (tooltipHtml) {
                    $tooltip.html(tooltipHtml);
                    $tooltip.fadeIn();
                } else {
                    $tooltip.fadeOut();
                }
            }));

            var maxOwn = 100;
            $events.each(function() {
                var own = parseFloat($(this).find('td:eq(3)').text());
                if (maxOwn < own) {
                    maxOwn = own;
                }
            });

            // Visual display of all events.
            $('._profile-eventStart').each(function() {
                var $eventStart = $(this);
                var index = parseInt($eventStart.attr('data-index'));
                var $event = $events.eq(index);
                var own = parseFloat($event.find('td:eq(3)').text());
                var ratio = own / maxOwn;
                var size = 40 + ratio * 160;

                if (own < 1) {
                    return;
                }

                // Find the closest parent that's visible so that
                // the display shows in the correct position.
                while ($eventStart.length > 0 && !$eventStart.is(':visible')) {
                    $eventStart = $eventStart.parent();
                }
                if ($eventStart.length < 1) {
                    return
                }

                var pointOffset = $eventStart.offset();
                var pointLeft = pointOffset.left;
                var pointTop = pointOffset.top;

                // Center it.
                pointLeft -= size / 2;
                pointTop -= size / 2;

                // Make sure it's not off-screen.
                if (pointLeft < 0) {
                    pointLeft = 0;
                }
                if (pointTop < 0) {
                    pointTop = 0;
                }

                // Color based on how long the event took.
                var red, green, blue, alpha = ratio * 0.2 + 0.2;
                if (ratio > 0.5) {
                    var r = (ratio - 0.5) * 2;
                    red = mediumRed + (highRed - mediumRed) * r;
                    green = mediumGreen + (highGreen - mediumGreen) * r;
                    blue = mediumBlue + (highBlue - mediumBlue) * r;

                } else {
                    var r = ratio * 2;
                    red = lowRed + (mediumRed - lowRed) * r;
                    green = lowGreen + (mediumGreen - lowGreen) * r;
                    blue = lowBlue + (mediumBlue - lowBlue) * r;
                }

                $body.append($('
', {
                    'class': '_profile-eventDisplay',
                    'data-index': index,
                    'text': Math.floor(own),
                    'css': {
                        'background-color': 'rgba(' + Math.floor(red) + ', ' + Math.floor(green) + ', ' + Math.floor(blue) + ', ' + alpha + ')',
                        '-moz-border-radius': size,
                        '-webkit-border-radius': size,
                        'border-radius': size,
                        'color': 'white',
                        'cursor': 'pointer',
                        'height': size,
                        'font-family': fontFamily,
                        'font-size': size * 0.4,
                        'left': pointLeft,
                        'line-height': size + 'px',
                        'position': 'absolute',
                        'text-align': 'center',
                        'text-shadow': 'rgba(0, 0, 0, 0.5) 0 0 ' + Math.floor(ratio * 4 + 3) + 'px',
                        'top': pointTop,
                        'width': size,
                        'z-index': Math.floor(2000000 + ratio * 1000)
                    },
                    'click': function() {
                        $tooltip.fadeOut();
                        $body.animate({ 'scrollTop': $profile.offset().top + $event.offset().top });
                        return false;
                    }
                }));
            });

            $profileBody.find('#_profile-overview :checkbox').live('change', function() {
                var $checkbox = $(this);
                var $events = $profileBody.find('#_profile-eventTimeline .' + $checkbox.val());

                if ($checkbox.is(':checked')) {
                    $events.show();
                } else {
                    $events.hide();
                }
            });

            $profileBody.on('click', '#_profile-eventTimeline .tree', function() {
                var $tree = $(this);
                var $tr = $tree.closest('tr');

                if ($tree.is('.icon-chevron-down')) {
                    $tree.removeClass('icon-chevron-down');
                    $tree.addClass('icon-chevron-right');
                    $tr.nextUntil('[data-depth=' + $tr.attr('data-depth') + ']').hide();

                } else {
                    $tree.removeClass('icon-chevron-right');
                    $tree.addClass('icon-chevron-down');
                    $tr.nextUntil('[data-depth=' + $tr.attr('data-depth') + ']').show();
                }
            });
        });

        $body.append($profile);
    };

    var jqScript = document.createElement('script');
    jqScript.src = '/_resource/jquery/jquery-1.7.1.min.js';
    jqScript.onload = function() { main(jQuery.noConflict(true)); };
    document.body.appendChild(jqScript);
})();
<commit_msg>Adds the ability to click on the whole row to toggle events in debug profile.<commit_after>(function() {

    // Constants.
    var fontFamily = '"Helvetica Neue", "Arial", sans-serif';
    var highRed = 204, highGreen = 0, highBlue = 0;
    var mediumRed = 170, mediumGreen = 170, mediumBlue = 0;
    var lowRed = 0, lowGreen = 204, lowBlue = 0;

    // Throttles the excution of the given throttledFunction to run
    // at most every given interval.
    var throttle = function(interval, throttledFunction) {
        if (interval <= 0) {
            return throttledFunction;
        }

        var lastTrigger = 0;
        var timeout;
        var lastArguments;
        return function() {

            lastArguments = arguments;
            if (timeout) {
                return;
            }

            var context = this;
            var now = +new Date();
            var delay = interval - now + lastTrigger;

            if (delay <= 0) {
                lastTrigger = now;
                throttledFunction.apply(context, lastArguments);

            } else {
                timeout = setTimeout(function() {
                    lastTrigger = now;
                    timeout = null;
                    throttledFunction.apply(context, lastArguments);
                }, delay);
            }
        };
    };

    // Calculates the boundary that can contain all elements between
    // the given $start and $end.
    var calculateBoundary = function($start, $stop) {
        var minX, minY, maxX, maxY;

        $start.nextUntil($stop).each(function() {
            var $child = $(this);
            var childOffset = $child.offset();
            var childMinX = childOffset.left;
            var childMinY = childOffset.top;
            var childMaxX = childMinX + $child.outerWidth(true);
            var childMaxY = childMinY + $child.outerHeight(true);

            if (!minX || minX > childMinX) {
                minX = childMinX;
            }
            if (!minY || minY > childMinY) {
                minY = childMinY;
            }
            if (!maxX || maxX < childMaxX) {
                maxX = childMaxX;
            }
            if (!maxY || maxY < childMaxY) {
                maxY = childMaxY;
            }
        });

        return {
            'left': minX,
            'top': minY,
            'width': maxX - minX,
            'height': maxY - minY
        };
    };

    // Main entry point.
    var main = function($) {
        var $body = $('body');

        // Tooltip that shows profile information around the element
        // under the mouse.
        var $tooltip = $('
', {
            'css': {
                'background-color': 'rgba(0, 0, 0, 0.8)',
                '-moz-border-radius': '5px',
                '-webkit-border-radius': '5px',
                'border-radius': '5px',
                'color': 'white',
                'display': 'none',
                'font-family': fontFamily,
                'font-size': '12px',
                'max-width': '25%',
                'padding': '5px',
                'position': 'fixed',
                'top': '5px',
                'right': '5px',
                'z-index': 3000000
            }
        });
        $body.append($tooltip);

        // Create an IFRAME for the profile result so that it can
        // be shown with its own CSS.
        var $profile = $('');
        $profile.css({
            'border': 'none',
            'height': 1,
            'margin': 0,
            'padding': 0,
            'position': 'relative',
            'width': '100%',
            'z-index': 1000000
        });

        $profile.load(function() {
            var $profile = $(this);
            var $profileBody = $(this.contentDocument.body);

            $profileBody.html($('#_profile-result').remove().html());
            $profile.height($profileBody.height() + 30);
            var $events = $profileBody.find('#_profile-eventTimeline tbody tr');

            var lastHoverElement;
            $(window).mousemove(throttle(100, function(event) {

                var $container = $(this);
                var x = event.pageX - $container.scrollLeft();
                var y = event.pageY - $container.scrollTop();

                // Hovering over a different element?
                $('._profile-openEditor').hide();
                var hoverElement = document.elementFromPoint(x, y);
                $('._profile-openEditor').show();
                if (hoverElement === lastHoverElement) {
                    return;
                } else {
                    lastHoverElement = hoverElement;
                }

                var $hoverElement = $(hoverElement);
                var tooltipHtml = '';

                // Over a visual display of an event.
                if ($hoverElement.is('._profile-eventDisplay')) {
                    var index = parseInt($hoverElement.attr('data-index'));
                    var $event = $events.eq(index);
                    tooltipHtml += 'Event #' + index + '
';
                    tooltipHtml += 'Start: ' + $event.find('td:eq(1)').html() + '
';
                    tooltipHtml += 'Total: ' + $event.find('td:eq(2)').html() + '
';
                    tooltipHtml += 'Own: ' + $event.find('td:eq(3)').html() + '
';
                    tooltipHtml += 'Objects: ' + $event.find('td:eq(4)').html();

                // Try to find all JSPs that may be associated with
                // rendering the element under the mouse.
                } else {
                    $('._profile-openEditor').remove();

                    var $parent = $hoverElement;
                    var isFirst = true;
                    var padding = 0;
                    for (; $parent.length > 0; $parent = $parent.parent()) (function() {

                        var $start;
                        var $stop;
                        var jsp;
                        var $prev = $parent;
                        for (; $prev.length > 0; $prev = $prev.prev()) {

                            if ($prev.is('._profile-jspStart')) {
                                $start = $prev;
                                var prevJsp = $prev.attr('data-jsp');
                                if (prevJsp.indexOf('/_draft/') > -1) {
                                    continue;
                                }

                                var $next = $parent;
                                for (; $next.length > 0; $next = $next.next()) {
                                    if ($next.is('._profile-jspStop[data-jsp=' + prevJsp + ']')) {
                                        $stop = $next;
                                        jsp = prevJsp;
                                        tooltipHtml += (isFirst ? 'JSP: ' : '
Called from ') + jsp;
                                        isFirst = false;
                                        break;
                                    }
                                }
                                break;

                            } else if ($prev.is('._profile-jspStop')) {
                                break;
                            }
                        }

                        if (!jsp) {
                            return;
                        }

                        var boundary = calculateBoundary($start, $stop);
                        padding += 4;

                        $('body').append($('', {
                            'class': '_profile-openEditor',
                            'data-padding': padding,
                            'target': '_blank',
                            'href': '/_debug/code' +
                                    '?action=edit' +
                                    '&type=JSP' +
                                    '&servletPath=' + encodeURIComponent(jsp) +
                                    '&jspPreviewUrl=' + encodeURIComponent(location.href),
                            'css': {
                                'border': '1px solid rgba(204, 0, 0, 0.8)',
                                '-moz-border-radius': '4px',
                                '-webkit-border-radius': '4px',
                                'border-radius': '4px',
                                'display': 'block',
                                'height': boundary.height + (padding * 2),
                                'left': boundary.left - padding,
                                'position': 'absolute',
                                'top': boundary.top - padding,
                                'width': boundary.width + (padding * 2),
                                'z-index': 1000000 - padding
                            }
                        }));
                    })();
                }

                if (tooltipHtml) {
                    $tooltip.html(tooltipHtml);
                    $tooltip.fadeIn();
                } else {
                    $tooltip.fadeOut();
                }
            }));

            var maxOwn = 100;
            $events.each(function() {
                var own = parseFloat($(this).find('td:eq(3)').text());
                if (maxOwn < own) {
                    maxOwn = own;
                }
            });

            // Visual display of all events.
            $('._profile-eventStart').each(function() {
                var $eventStart = $(this);
                var index = parseInt($eventStart.attr('data-index'));
                var $event = $events.eq(index);
                var own = parseFloat($event.find('td:eq(3)').text());
                var ratio = own / maxOwn;
                var size = 40 + ratio * 160;

                if (own < 1) {
                    return;
                }

                // Find the closest parent that's visible so that
                // the display shows in the correct position.
                while ($eventStart.length > 0 && !$eventStart.is(':visible')) {
                    $eventStart = $eventStart.parent();
                }
                if ($eventStart.length < 1) {
                    return
                }

                var pointOffset = $eventStart.offset();
                var pointLeft = pointOffset.left;
                var pointTop = pointOffset.top;

                // Center it.
                pointLeft -= size / 2;
                pointTop -= size / 2;

                // Make sure it's not off-screen.
                if (pointLeft < 0) {
                    pointLeft = 0;
                }
                if (pointTop < 0) {
                    pointTop = 0;
                }

                // Color based on how long the event took.
                var red, green, blue, alpha = ratio * 0.2 + 0.2;
                if (ratio > 0.5) {
                    var r = (ratio - 0.5) * 2;
                    red = mediumRed + (highRed - mediumRed) * r;
                    green = mediumGreen + (highGreen - mediumGreen) * r;
                    blue = mediumBlue + (highBlue - mediumBlue) * r;

                } else {
                    var r = ratio * 2;
                    red = lowRed + (mediumRed - lowRed) * r;
                    green = lowGreen + (mediumGreen - lowGreen) * r;
                    blue = lowBlue + (mediumBlue - lowBlue) * r;
                }

                $body.append($('
', {
                    'class': '_profile-eventDisplay',
                    'data-index': index,
                    'text': Math.floor(own),
                    'css': {
                        'background-color': 'rgba(' + Math.floor(red) + ', ' + Math.floor(green) + ', ' + Math.floor(blue) + ', ' + alpha + ')',
                        '-moz-border-radius': size,
                        '-webkit-border-radius': size,
                        'border-radius': size,
                        'color': 'white',
                        'cursor': 'pointer',
                        'height': size,
                        'font-family': fontFamily,
                        'font-size': size * 0.4,
                        'left': pointLeft,
                        'line-height': size + 'px',
                        'position': 'absolute',
                        'text-align': 'center',
                        'text-shadow': 'rgba(0, 0, 0, 0.5) 0 0 ' + Math.floor(ratio * 4 + 3) + 'px',
                        'top': pointTop,
                        'width': size,
                        'z-index': Math.floor(2000000 + ratio * 1000)
                    },
                    'click': function() {
                        $tooltip.fadeOut();
                        $body.animate({ 'scrollTop': $profile.offset().top + $event.offset().top });
                        return false;
                    }
                }));
            });

            $profileBody.on('click', '#_profile-overview tr', function() {
                var $checkbox = $(this).find(':checkbox');

                $checkbox.prop('checked', !$checkbox.prop('checked'));
                $checkbox.change();
                return false;
            });

            $profileBody.find('#_profile-overview :checkbox').live('change', function() {
                var $checkbox = $(this);
                var $events = $profileBody.find('#_profile-eventTimeline .' + $checkbox.val());

                if ($checkbox.is(':checked')) {
                    $events.show();
                } else {
                    $events.hide();
                }
            });

            $profileBody.on('click', '#_profile-eventTimeline .tree', function() {
                var $tree = $(this);
                var $tr = $tree.closest('tr');

                if ($tree.is('.icon-chevron-down')) {
                    $tree.removeClass('icon-chevron-down');
                    $tree.addClass('icon-chevron-right');
                    $tr.nextUntil('[data-depth=' + $tr.attr('data-depth') + ']').hide();

                } else {
                    $tree.removeClass('icon-chevron-right');
                    $tree.addClass('icon-chevron-down');
                    $tr.nextUntil('[data-depth=' + $tr.attr('data-depth') + ']').show();
                }
            });
        });

        $body.append($profile);
    };

    var jqScript = document.createElement('script');
    jqScript.src = '/_resource/jquery/jquery-1.7.1.min.js';
    jqScript.onload = function() { main(jQuery.noConflict(true)); };
    document.body.appendChild(jqScript);
})();
<|endoftext|>


<commit_before>(function($)
{
	var Relabel = Garnish.Base.extend({

	},
	{
		ASSET:          'asset',
		ASSET_SOURCE:   'assetSource',
		CATEGORY:       'category',
		CATEGORY_GROUP: 'categoryGroup',
		GLOBAL:         'global',
		GLOBAL_SET:     'globalSet',
		ENTRY:          'entry',
		ENTRY_TYPE:     'entryType',
		TAG:            'tag',
		TAG_GROUP:      'tagGroup',

		// This field will be populated in the RelabelPlugin.php file
		fields: {},

		getContext: function(element)
		{
			var $form = $(element);
			var $action = $form.find('input[name="action"]');
			var action = $action.val();

			if(action)
			{
				switch(action)
				{
					// TODO Element modal forms are tricky, need a way of detecting this for them
					case 'assetSources/saveSource': return this.ASSET_SOURCE;
					case 'categories/saveCategory': return this.CATEGORY;
					case 'categories/saveGroup':    return this.CATEGORY_GROUP;
					case 'globals/saveContent':     return this.GLOBAL;
					case 'globals/saveSet':         return this.GLOBAL_SET;
					case 'entries/saveEntry':       return this.ENTRY;
					case 'sections/saveEntryType':  return this.ENTRY_TYPE;
					case 'tags/saveTagGroup':       return this.TAG_GROUP;
				}
			}

			return false;
		},

		getContextId: function(element)
		{
			var $form = $(element);
			var type = this.getContext($form);
			var selector;

			// TODO Element modal forms are tricky for assets, categories and tags, need to find a way of detecting the field layout types
			var $namespace = $form.find('input[name="namespace"]');
			var namespace = $namespace.val();
			namespace = namespace ? namespace : '';

			switch(type)
			{
				case this.ASSET:    break;
				case this.CATEGORY: selector = 'input[name="groupId"]'; break;
				case this.GLOBAL:   selector = 'input[name="setId"]'; break;
				case this.ENTRY:    selector = 'input[name="entryTypeId"], #' + namespace + 'entryType'; break;
				case this.TAG:      break;
			}

			var $input = $form.find(selector);

			return $input.length ? ($input.val() | 0) : false;
		},

		getFieldInfo: function(id)
		{
			return this.fields[id];
		}
	});

	window.Relabel = Relabel;

})(jQuery);
<commit_msg>Added check for users<commit_after>(function($)
{
	var Relabel = Garnish.Base.extend({

	},
	{
		ASSET:          'asset',
		ASSET_SOURCE:   'assetSource',
		CATEGORY:       'category',
		CATEGORY_GROUP: 'categoryGroup',
		GLOBAL:         'global',
		GLOBAL_SET:     'globalSet',
		ENTRY:          'entry',
		ENTRY_TYPE:     'entryType',
		TAG:            'tag',
		TAG_GROUP:      'tagGroup',
		USER:           'user',
		USER_FIELDS:    'userFields',

		// This field will be populated in the RelabelPlugin.php file
		fields: {},

		getContext: function(element)
		{
			var $form = $(element);
			var $action = $form.find('input[name="action"]');
			var action = $action.val();

			if(action)
			{
				switch(action)
				{
					// TODO Element modal forms are tricky, need a way of detecting this for them
					case 'assetSources/saveSource': return this.ASSET_SOURCE;
					case 'categories/saveCategory': return this.CATEGORY;
					case 'categories/saveGroup':    return this.CATEGORY_GROUP;
					case 'globals/saveContent':     return this.GLOBAL;
					case 'globals/saveSet':         return this.GLOBAL_SET;
					case 'entries/saveEntry':       return this.ENTRY;
					case 'sections/saveEntryType':  return this.ENTRY_TYPE;
					case 'tags/saveTagGroup':       return this.TAG_GROUP;
					case 'users/users/saveUser':    return this.USER;
					case 'users/saveFieldLayout':   return this.USER_FIELDS;
				}
			}

			return false;
		},

		getContextId: function(element)
		{
			var $form = $(element);
			var type = this.getContext($form);
			var selector;

			// TODO Element modal forms are tricky for assets, categories and tags, need to find a way of detecting the field layout types
			var $namespace = $form.find('input[name="namespace"]');
			var namespace = $namespace.val();
			namespace = namespace ? namespace : '';

			switch(type)
			{
				case this.ASSET:    break;
				case this.CATEGORY: selector = 'input[name="groupId"]'; break;
				case this.GLOBAL:   selector = 'input[name="setId"]'; break;
				case this.ENTRY:    selector = 'input[name="entryTypeId"], #' + namespace + 'entryType'; break;
				case this.TAG:      break;
			}

			var $input = $form.find(selector);

			return $input.length ? ($input.val() | 0) : false;
		},

		getFieldInfo: function(id)
		{
			return this.fields[id];
		}
	});

	window.Relabel = Relabel;

})(jQuery);
<|endoftext|>


<commit_before>/**
 * 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.
 */

/*global describe, it, before */

'use strict';

var assert = require('assert');
var async = require('async');

var env = require('./env.js');
var gcloud = require('../lib');

var topicNames = ['topic1', 'topic2', 'topic3'];
var subscriptions = [
  {
    name: 'sub1',
    ackDeadlineSeconds: 30
  },
  {
    name: 'sub2',
    ackDeadlineSeconds: 60
  }
];

var conn = new gcloud.pubsub.Connection(env);

before(function(done) {
  // TODO: Handle pagination.
  var createFn = function(name, callback) {
    conn.createTopic(name, callback);
  };
  conn.listTopics(function(err, topics) {
    assert.ifError(err);
    var fns = topics.map(function(t) {
      return function(cb) {
        t.del(cb);
      };
    });
    async.parallel(fns, function(err) {
      assert.ifError(err);
      async.map(topicNames, createFn, done);
    });
  });
});

describe('Topic', function() {
  it('should be listed', function(done) {
    conn.listTopics(function(err, topics) {
      assert(topics.length, 3);
      done(err);
    });
  });

  it('should return a nextQuery if there are more results', function(done) {
    conn.listTopics({ maxResults: 2 }, function(err, topics, next) {
      assert(topics.length, 2);
      assert(next.maxResults, 2);
      assert(!!next.pageToken, true);
      done(err);
    });
  });

  it('should be created', function(done) {
    conn.createTopic('topic-new', done);
  });

  it('should be gettable', function(done) {
    conn.getTopic('topic1', done);
  });

  it('should publish a message', function(done) {
    conn.getTopic('topic1', function(err, topic) {
      topic.publish('message from me', done);
    });
  });

  it('should be deleted', function(done) {
    conn.getTopic('topic3', function(err, topic) {
      topic.del(done);
    });
  });
});

describe('Subscription', function() {
  before(function(done) {
    var createFn = function(item, callback) {
      conn.createSubscription({
        name: item.name,
        topic: 'topic1',
        ackDeadlineSeconds: item.ackDeadlineSeconds
      }, callback);
    };
    conn.listSubscriptions(function(err, subs) {
      assert.ifError(err);
      var fns = subs.map(function(sub) {
        return function(cb) {
          sub.del(cb);
        };
      });
      async.series(fns, function(err) {
        assert.ifError(err);
        async.map(subscriptions, createFn, done);
      });
    });
  });

  it('should be listed', function(done) {
    conn.listSubscriptions(function(err, subs) {
      assert.strictEqual(subs.length, 2);
      done(err);
    });
  });

  it('should be gettable', function(done) {
    conn.getSubscription('sub1', function(err, sub) {
      assert.ifError(err);
      assert.strictEqual(sub.name, '/subscriptions/' + env.projectId + '/sub1');
      done();
    });
  });

  it('should error while getting a non-existent subscription', function(done){
    conn.getSubscription('sub-nothing-is-here', function(err) {
      assert.strictEqual(err.code, 404);
      done();
    });
  });

  it('should be created', function(done) {
    conn.createSubscription({
      topic: 'topic1',
      name: 'new-sub'
    }, done);
  });

  it('should be able to pull and ack', function(done) {
    conn.getTopic('topic1', function(err, topic) {
      assert.ifError(err);
      topic.publish('hello', function(err) {
        assert.ifError(err);
      });
    });
    conn.getSubscription('sub1', function(err, sub) {
      assert.ifError(err);
      sub.on('message', function(msg) {
        sub.ack(msg.ackId, done);
      });
      sub.pull({}, done);
    });
  });
});
<commit_msg>Test case should be done when we acknowledge.<commit_after>/**
 * 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.
 */

/*global describe, it, before */

'use strict';

var assert = require('assert');
var async = require('async');

var env = require('./env.js');
var gcloud = require('../lib');

var topicNames = ['topic1', 'topic2', 'topic3'];
var subscriptions = [
  {
    name: 'sub1',
    ackDeadlineSeconds: 30
  },
  {
    name: 'sub2',
    ackDeadlineSeconds: 60
  }
];

var conn = new gcloud.pubsub.Connection(env);

before(function(done) {
  // TODO: Handle pagination.
  var createFn = function(name, callback) {
    conn.createTopic(name, callback);
  };
  conn.listTopics(function(err, topics) {
    assert.ifError(err);
    var fns = topics.map(function(t) {
      return function(cb) {
        t.del(cb);
      };
    });
    async.parallel(fns, function(err) {
      assert.ifError(err);
      async.map(topicNames, createFn, done);
    });
  });
});

describe('Topic', function() {
  it('should be listed', function(done) {
    conn.listTopics(function(err, topics) {
      assert(topics.length, 3);
      done(err);
    });
  });

  it('should return a nextQuery if there are more results', function(done) {
    conn.listTopics({ maxResults: 2 }, function(err, topics, next) {
      assert(topics.length, 2);
      assert(next.maxResults, 2);
      assert(!!next.pageToken, true);
      done(err);
    });
  });

  it('should be created', function(done) {
    conn.createTopic('topic-new', done);
  });

  it('should be gettable', function(done) {
    conn.getTopic('topic1', done);
  });

  it('should publish a message', function(done) {
    conn.getTopic('topic1', function(err, topic) {
      topic.publish('message from me', done);
    });
  });

  it('should be deleted', function(done) {
    conn.getTopic('topic3', function(err, topic) {
      topic.del(done);
    });
  });
});

describe('Subscription', function() {
  before(function(done) {
    var createFn = function(item, callback) {
      conn.createSubscription({
        name: item.name,
        topic: 'topic1',
        ackDeadlineSeconds: item.ackDeadlineSeconds
      }, callback);
    };
    conn.listSubscriptions(function(err, subs) {
      assert.ifError(err);
      var fns = subs.map(function(sub) {
        return function(cb) {
          sub.del(cb);
        };
      });
      async.series(fns, function(err) {
        assert.ifError(err);
        async.map(subscriptions, createFn, done);
      });
    });
  });

  it('should be listed', function(done) {
    conn.listSubscriptions(function(err, subs) {
      assert.strictEqual(subs.length, 2);
      done(err);
    });
  });

  it('should be gettable', function(done) {
    conn.getSubscription('sub1', function(err, sub) {
      assert.ifError(err);
      assert.strictEqual(sub.name, '/subscriptions/' + env.projectId + '/sub1');
      done();
    });
  });

  it('should error while getting a non-existent subscription', function(done){
    conn.getSubscription('sub-nothing-is-here', function(err) {
      assert.strictEqual(err.code, 404);
      done();
    });
  });

  it('should be created', function(done) {
    conn.createSubscription({
      topic: 'topic1',
      name: 'new-sub'
    }, done);
  });

  it('should be able to pull and ack', function(done) {
    conn.getTopic('topic1', function(err, topic) {
      assert.ifError(err);
      topic.publish('hello', function(err) {
        assert.ifError(err);
      });
    });
    conn.getSubscription('sub1', function(err, sub) {
      assert.ifError(err);
      sub.on('message', function(msg) {
        sub.ack(msg.ackId, done);
      });
      sub.pull({}, function() {});
    });
  });
});
<|endoftext|>