<commit_before>angular.module('chasselberg.slider', [])
    .directive('slider', SliderDirective);

function SliderDirective() {
    var directive = {
        restrict: 'EA',
        scope: {
            model: '=',
            min: '@',
            max: '@',
            step: '@'
        },
        link: linkFunction,
        template: '
' +
            '
' +
            '' +
            '' +
            '
' +
            '
'
    };
    return directive;

    function linkFunction($scope, $element, attributes) {
        var $slider = angular.element($element[0].querySelector('.ch-slider'));
        var $bar = angular.element($element[0].querySelector('.ch-slider-bar'));
        var $handle = angular.element($element[0].querySelector('.ch-slider-handle'));
        var $fill = angular.element($element[0].querySelector('.ch-slider-fill'));

        init();

        function init() {
            $scope.min = ($scope.min === undefined) ? 0 : parseFloat($scope.min);
            $scope.max = ($scope.max === undefined) ? 100 : parseFloat($scope.max);
            $scope.step = ($scope.step === undefined) ? 1 : parseFloat($scope.step);
            $scope.model = ($scope.model === undefined) ? ($scope.max - $scope.min) / 2 : parseFloat($scope.model);

            setupEvents();
            setupKeyboardEvents();
            setupWatches();

        }

        function setupEvents() {
            setupDragEvents();
            setupTouchEvents();
        }

        function setupDragEvents() {
            var isActive = false;
            $handle.on('touchstart', function(event) {
                if($scope.disabled !== true) {
                    isActive = true;
                    angular.element(window).on('touchmove', touchMove);
                    angular.element(window).on('touchend', touchEnd);
                }
            });

            $bar.on('touchstart', function(event) {
                if($scope.disabled !== true) {
                    isActive = true;
                    angular.element(window).on('touchmove', touchMove);
                    angular.element(window).on('touchend', touchEnd);
                    calcPosition(event);
                }
            });

            function touchMove(event) {
                if (isActive) {
                    event.preventDefault();
                    calcPosition(event);
                }
            }

            function touchEnd(event) {
                if (isActive) {
                    isActive = false;
                    angular.element(window).off('touchmove', touchMove);
                    angular.element(window).off('touchend', touchEnd);
                }
            }
        }

        function setupTouchEvents() {
            var isActive = false;
            $handle.on('mousedown', function(event) {
                if($scope.disabled !== true) {
                    isActive = true;
                    angular.element(window).on('mousemove', dragMove);
                    angular.element(window).on('mouseup', dragEnd);
                }
            });

            $bar.on('mousedown', function(event) {
                if($scope.disabled !== true) {
                    isActive = true;
                    angular.element(window).on('mousemove', dragMove);
                    angular.element(window).on('mouseup', dragEnd);
                    calcPosition(event);
                }
            });

            function dragMove(event) {
                if (isActive) {
                    event.preventDefault();
                    calcPosition(event);
                }
            }

            function dragEnd(event) {
                if (isActive) {
                    isActive = false;
                    angular.element(window).off('mousemove', dragMove);
                    angular.element(window).off('mouseup', dragEnd);
                }
            }
        }

        function setupKeyboardEvents() {

            $slider.on('keydown', handleKeys);

            var Keys = {
                UP: 38,
                DOWN: 40,
                LEFT: 37,
                RIGHT: 39,
                PAGEUP: 33,
                PAGEDOWN: 34,
                HOME: 36,
                END: 35
            };

            function handleKeys(event) {
                switch (event.keyCode) {
                    case Keys.UP:
                    case Keys.RIGHT:
                        setValue($scope.model + $scope.step, true, true);
                        break;
                    case Keys.DOWN:
                    case Keys.LEFT:
                        setValue($scope.model - $scope.step, true, true);
                        break;
                    case Keys.PAGEUP:
                    setValue($scope.model + ($scope.step * 10), true, true);
                    break;
                    case Keys.PAGEDOWN:
                    setValue($scope.model - ($scope.step * 10), true, true);
                    break;
                    case Keys.HOME:
                        setValue($scope.min, true, true);
                        break;
                    case Keys.END:
                        setValue($scope.max, true, true);
                        break;
                }
            }
        }

        function setupWatches() {
            $scope.$watch(function() {
                return $scope.model;
            }, function(value) {
                value = (value === undefined || value === '' || isNaN(value)) ? 0 : parseFloat(value);
                setValue(value, false);
            });

            attributes.$observe('min', function(value) {
                $scope.min = (value === undefined || value === '' || isNaN(value)) ? 0 : parseFloat(value);
                update();
            });
            attributes.$observe('max', function(value) {
                $scope.max = (value === undefined || value === '' || isNaN(value)) ? 100 : parseFloat(value);
                update();
            });
            attributes.$observe('step', function(value) {
                $scope.step = (value === undefined || value === '' || isNaN(value)) ? 1 : parseFloat(value);
                update();
            });
            $scope.$watch(function() { return $element.attr('disabled'); }, function(value) {
                $scope.disabled = (value === undefined) ? false : true;
            });

            function update() {
                setValue($scope.model);
            }
        }

        function calcPosition(event) {
            var pageX;
            // Touch events seem to behave differently across devices. This is mostly untested though
            if (event.type === 'touchstart' || event.type === 'touchmove') {
                var touch = event.changedTouches[0] || event.originalEvent.touches[0] || event.originalEvent.changedTouches[0];
                pageX = touch.pageX;
            } else {
                pageX = event.pageX;
            }
            var halfOfHandle = $handle[0].getBoundingClientRect().width / 2,
                barWidth = $bar[0].getBoundingClientRect().width,
                barOffset = (($bar[0].getBoundingClientRect().left + document.body.scrollLeft) - pageX),
                handlePosition = Math.abs(barOffset),
                value;

            if (barOffset > 0) {
                handlePosition = $scope.min;
                value = handlePosition;
            } else {
                var offsetPercentage = percent(handlePosition, barWidth);
                value = (($scope.max - $scope.min) * offsetPercentage) + parseFloat($scope.min);
            }
            setValue(value, true, true);

        }

        function setValue(value, normalize, forceDigest) {

            value = parseFloat(value);

            normalize = (normalize === undefined) ? true : normalize;
            forceDigest = (forceDigest === undefined) ? false : forceDigest;

            if (normalize) {
                value = roundToInterval(value, $scope.step);
            }

            if (value < $scope.min) {
                value = $scope.min;
            } else if (value > $scope.max) {
                value = $scope.max;
            }

            var halfOfHandle = $handle[0].getBoundingClientRect().width / 2,
                percentage = percent(value - $scope.min, $scope.max - $scope.min) * 100;

            if (percentage < 0) {
                percentage = 0;
            } else if (percentage > 100) {
                percentage = 100;
            }

            $handle.css('left', 'calc(' + percentage + '% - ' + halfOfHandle + 'px)');
            $fill.css('width', 'calc(' + percentage + '% - ' + halfOfHandle + 'px)');
            if (normalize) {
                $scope.model = value;
                if (forceDigest) {
                    $scope.$apply();
                }
            }
        }

        function percent(frac, num) {
            return (frac / num);
        }

        function roundToInterval(number, interval) {
            return Math.round(number / interval) * interval;
        }
    }

}
<commit_msg>Removed unused variable<commit_after>angular.module('chasselberg.slider', [])
    .directive('slider', SliderDirective);

function SliderDirective() {
    var directive = {
        restrict: 'EA',
        scope: {
            model: '=',
            min: '@',
            max: '@',
            step: '@'
        },
        link: linkFunction,
        template: '
' +
            '
' +
            '' +
            '' +
            '
' +
            '
'
    };
    return directive;

    function linkFunction($scope, $element, attributes) {
        var $slider = angular.element($element[0].querySelector('.ch-slider'));
        var $bar = angular.element($element[0].querySelector('.ch-slider-bar'));
        var $handle = angular.element($element[0].querySelector('.ch-slider-handle'));
        var $fill = angular.element($element[0].querySelector('.ch-slider-fill'));

        init();

        function init() {
            $scope.min = ($scope.min === undefined) ? 0 : parseFloat($scope.min);
            $scope.max = ($scope.max === undefined) ? 100 : parseFloat($scope.max);
            $scope.step = ($scope.step === undefined) ? 1 : parseFloat($scope.step);
            $scope.model = ($scope.model === undefined) ? ($scope.max - $scope.min) / 2 : parseFloat($scope.model);

            setupEvents();
            setupKeyboardEvents();
            setupWatches();

        }

        function setupEvents() {
            setupDragEvents();
            setupTouchEvents();
        }

        function setupDragEvents() {
            var isActive = false;
            $handle.on('touchstart', function(event) {
                if($scope.disabled !== true) {
                    isActive = true;
                    angular.element(window).on('touchmove', touchMove);
                    angular.element(window).on('touchend', touchEnd);
                }
            });

            $bar.on('touchstart', function(event) {
                if($scope.disabled !== true) {
                    isActive = true;
                    angular.element(window).on('touchmove', touchMove);
                    angular.element(window).on('touchend', touchEnd);
                    calcPosition(event);
                }
            });

            function touchMove(event) {
                if (isActive) {
                    event.preventDefault();
                    calcPosition(event);
                }
            }

            function touchEnd(event) {
                if (isActive) {
                    isActive = false;
                    angular.element(window).off('touchmove', touchMove);
                    angular.element(window).off('touchend', touchEnd);
                }
            }
        }

        function setupTouchEvents() {
            var isActive = false;
            $handle.on('mousedown', function(event) {
                if($scope.disabled !== true) {
                    isActive = true;
                    angular.element(window).on('mousemove', dragMove);
                    angular.element(window).on('mouseup', dragEnd);
                }
            });

            $bar.on('mousedown', function(event) {
                if($scope.disabled !== true) {
                    isActive = true;
                    angular.element(window).on('mousemove', dragMove);
                    angular.element(window).on('mouseup', dragEnd);
                    calcPosition(event);
                }
            });

            function dragMove(event) {
                if (isActive) {
                    event.preventDefault();
                    calcPosition(event);
                }
            }

            function dragEnd(event) {
                if (isActive) {
                    isActive = false;
                    angular.element(window).off('mousemove', dragMove);
                    angular.element(window).off('mouseup', dragEnd);
                }
            }
        }

        function setupKeyboardEvents() {

            $slider.on('keydown', handleKeys);

            var Keys = {
                UP: 38,
                DOWN: 40,
                LEFT: 37,
                RIGHT: 39,
                PAGEUP: 33,
                PAGEDOWN: 34,
                HOME: 36,
                END: 35
            };

            function handleKeys(event) {
                switch (event.keyCode) {
                    case Keys.UP:
                    case Keys.RIGHT:
                        setValue($scope.model + $scope.step, true, true);
                        break;
                    case Keys.DOWN:
                    case Keys.LEFT:
                        setValue($scope.model - $scope.step, true, true);
                        break;
                    case Keys.PAGEUP:
                    setValue($scope.model + ($scope.step * 10), true, true);
                    break;
                    case Keys.PAGEDOWN:
                    setValue($scope.model - ($scope.step * 10), true, true);
                    break;
                    case Keys.HOME:
                        setValue($scope.min, true, true);
                        break;
                    case Keys.END:
                        setValue($scope.max, true, true);
                        break;
                }
            }
        }

        function setupWatches() {
            $scope.$watch(function() {
                return $scope.model;
            }, function(value) {
                value = (value === undefined || value === '' || isNaN(value)) ? 0 : parseFloat(value);
                setValue(value, false);
            });

            attributes.$observe('min', function(value) {
                $scope.min = (value === undefined || value === '' || isNaN(value)) ? 0 : parseFloat(value);
                update();
            });
            attributes.$observe('max', function(value) {
                $scope.max = (value === undefined || value === '' || isNaN(value)) ? 100 : parseFloat(value);
                update();
            });
            attributes.$observe('step', function(value) {
                $scope.step = (value === undefined || value === '' || isNaN(value)) ? 1 : parseFloat(value);
                update();
            });
            $scope.$watch(function() { return $element.attr('disabled'); }, function(value) {
                $scope.disabled = (value === undefined) ? false : true;
            });

            function update() {
                setValue($scope.model);
            }
        }

        function calcPosition(event) {
            var pageX;
            // Touch events seem to behave differently across devices. This is mostly untested though
            if (event.type === 'touchstart' || event.type === 'touchmove') {
                var touch = event.changedTouches[0] || event.originalEvent.touches[0] || event.originalEvent.changedTouches[0];
                pageX = touch.pageX;
            } else {
                pageX = event.pageX;
            }
            var barWidth = $bar[0].getBoundingClientRect().width,
                barOffset = (($bar[0].getBoundingClientRect().left + document.body.scrollLeft) - pageX),
                handlePosition = Math.abs(barOffset),
                value;

            if (barOffset > 0) {
                handlePosition = $scope.min;
                value = handlePosition;
            } else {
                var offsetPercentage = percent(handlePosition, barWidth);
                value = (($scope.max - $scope.min) * offsetPercentage) + parseFloat($scope.min);
            }
            setValue(value, true, true);

        }

        function setValue(value, normalize, forceDigest) {

            value = parseFloat(value);

            normalize = (normalize === undefined) ? true : normalize;
            forceDigest = (forceDigest === undefined) ? false : forceDigest;

            if (normalize) {
                value = roundToInterval(value, $scope.step);
            }

            if (value < $scope.min) {
                value = $scope.min;
            } else if (value > $scope.max) {
                value = $scope.max;
            }

            var halfOfHandle = $handle[0].getBoundingClientRect().width / 2,
                percentage = percent(value - $scope.min, $scope.max - $scope.min) * 100;

            if (percentage < 0) {
                percentage = 0;
            } else if (percentage > 100) {
                percentage = 100;
            }

            $handle.css('left', 'calc(' + percentage + '% - ' + halfOfHandle + 'px)');
            $fill.css('width', 'calc(' + percentage + '% - ' + halfOfHandle + 'px)');
            if (normalize) {
                $scope.model = value;
                if (forceDigest) {
                    $scope.$apply();
                }
            }
        }

        function percent(frac, num) {
            return (frac / num);
        }

        function roundToInterval(number, interval) {
            return Math.round(number / interval) * interval;
        }
    }

}
<|endoftext|>


<commit_before>'use strict';
const request  = require('request');
const crypto   = require('crypto');
const debug    = require('debug')('gc:load-balancer');
const bluebird = require('bluebird')
const Tools    = require('./lib/tools.js');

/**
 * Load balancer
 * @constructor
 */
const LoadBalancer = function(opts) {
  this._rri = 0;
  this.processing_tasks = {};
};

/**
 * Method to find suitable peer
 * for now it only checks if peer is SYNCHRONIZED + TASKS have been started
 * @param req {object} Express req object
 */
LoadBalancer.prototype.findSuitablePeer = function(req) {
  let promise = (retry) => {
    if(retry++ > 100) {
      return reject(new Error('To many retries on route request while searching for a suitable peer')) ;
    }

    let peer_list = req.net_manager.getPeerList();
    let target = peer_list[this._rri++ % peer_list.length];

    //@todo take monitoring data into account
    if (target.identity.synchronized == false) {
      return bluebird.delay(100).then(() => promise(retry));
    }

    return Promise.resolve(target)
  }

  return promise(0)
};

/**
 * Main function to route a one-to-one action
 * exposed on api.js as:
 * http://127.0.0.1:10000/tasks/lb_trigger_single
 *
 * @param req.body.task_id = task id (script.handler)
 * @param req.body.data    = data to be passed to the task
 * @param req.body.opts    = extra options like 'timeout'
 */
LoadBalancer.prototype.route = function(req, res, next) {
  let task_id   = req.body.task_id;
  let task_data = req.body.data;
  let task_opts = req.body.opts || {};
  let uuid      = crypto.randomBytes(32).toString('hex');

  // Avoid integer overflow
  if (Number.isSafeInteger(this._rri) === false) {
    this._rri = 0;
  }

  this.findSuitablePeer(req)
    .then((peer) => {

      if (req.task_manager.taskExists(task_id) == false) {
        return res.send({err : Tools.safeClone(new Error('Task file ' + task_id.split('.')[0] + ' does not exists'))});
      }

    // @todo: do stats on task processing (invokation, errors...)
    this.processing_tasks[uuid] = {
      started_at : new Date(),
      peer_info  : peer.identity,
      task_id    : task_id
    };

    if (peer.local) {
      /**
       * send task action to local node
       */
      debug('Routing task %s to localhost', task_id);
      return req.task_manager.triggerTask({
        task_id  : task_id,
        task_data: task_data,
        task_opts: task_opts
      })
      .then((data) => {
        delete this.processing_tasks[uuid];
        data.server = req.net_manager.getLocalIdentity();
        res.send(data);
      })
      .catch((err) => {
        delete this.processing_tasks[uuid];
        res.send({err: err});
      });
    }

    debug('Routing task %s to %s:%s',
          task_id,
          peer.identity.public_ip,
          peer.identity.api_port);

    peer.send('trigger', {
      task_id : task_id,
      data    : task_data,
      opts    : task_opts
    }, function(err, data) {
      delete this.processing_tasks[uuid];
      if (err) {
        if (!data) data = {};
        data.err = err;
      }

      if (typeof(data) == 'string') {
        try {
          data = JSON.parse(data);
        } catch(e) {
        }
        data.server = peer.identity;
      }
      else if (typeof(data) == 'object')
        data.server = peer.identity;

      res.send(data);
    });
  });
};

LoadBalancer.prototype.broadcast = function(req, res, next) {
  //@todo http multistream
};

module.exports = LoadBalancer;
<commit_msg>gc: promise.reject<commit_after>'use strict';
const request  = require('request');
const crypto   = require('crypto');
const debug    = require('debug')('gc:load-balancer');
const bluebird = require('bluebird')
const Tools    = require('./lib/tools.js');

/**
 * Load balancer
 * @constructor
 */
const LoadBalancer = function(opts) {
  this._rri = 0;
  this.processing_tasks = {};
};

/**
 * Method to find suitable peer
 * for now it only checks if peer is SYNCHRONIZED + TASKS have been started
 * @param req {object} Express req object
 */
LoadBalancer.prototype.findSuitablePeer = function(req) {
  let promise = (retry) => {
    if(retry++ > 100) {
      return Promise.reject(new Error('To many retries on route request while searching for a suitable peer')) ;
    }

    let peer_list = req.net_manager.getPeerList();
    let target = peer_list[this._rri++ % peer_list.length];

    //@todo take monitoring data into account
    if (target.identity.synchronized == false) {
      return bluebird.delay(100).then(() => promise(retry));
    }

    return Promise.resolve(target)
  }

  return promise(0)
};

/**
 * Main function to route a one-to-one action
 * exposed on api.js as:
 * http://127.0.0.1:10000/tasks/lb_trigger_single
 *
 * @param req.body.task_id = task id (script.handler)
 * @param req.body.data    = data to be passed to the task
 * @param req.body.opts    = extra options like 'timeout'
 */
LoadBalancer.prototype.route = function(req, res, next) {
  let task_id   = req.body.task_id;
  let task_data = req.body.data;
  let task_opts = req.body.opts || {};
  let uuid      = crypto.randomBytes(32).toString('hex');

  // Avoid integer overflow
  if (Number.isSafeInteger(this._rri) === false) {
    this._rri = 0;
  }

  this.findSuitablePeer(req)
    .then((peer) => {

      if (req.task_manager.taskExists(task_id) == false) {
        return res.send({err : Tools.safeClone(new Error('Task file ' + task_id.split('.')[0] + ' does not exists'))});
      }

    // @todo: do stats on task processing (invokation, errors...)
    this.processing_tasks[uuid] = {
      started_at : new Date(),
      peer_info  : peer.identity,
      task_id    : task_id
    };

    if (peer.local) {
      /**
       * send task action to local node
       */
      debug('Routing task %s to localhost', task_id);
      return req.task_manager.triggerTask({
        task_id  : task_id,
        task_data: task_data,
        task_opts: task_opts
      })
      .then((data) => {
        delete this.processing_tasks[uuid];
        data.server = req.net_manager.getLocalIdentity();
        res.send(data);
      })
      .catch((err) => {
        delete this.processing_tasks[uuid];
        res.send({err: err});
      });
    }

    debug('Routing task %s to %s:%s',
          task_id,
          peer.identity.public_ip,
          peer.identity.api_port);

    peer.send('trigger', {
      task_id : task_id,
      data    : task_data,
      opts    : task_opts
    }, function(err, data) {
      delete this.processing_tasks[uuid];
      if (err) {
        if (!data) data = {};
        data.err = err;
      }

      if (typeof(data) == 'string') {
        try {
          data = JSON.parse(data);
        } catch(e) {
        }
        data.server = peer.identity;
      }
      else if (typeof(data) == 'object')
        data.server = peer.identity;

      res.send(data);
    });
  });
};

LoadBalancer.prototype.broadcast = function(req, res, next) {
  //@todo http multistream
};

module.exports = LoadBalancer;
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var ejs = require('ejs');
var logger = require('log-hanging-fruit').defaultLogger;
var settingsUtil = require('./settings');
var dbSetup = require('./models/dbSetup');
var app = express();

app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));

app.set('view engine', 'ejs');

app.use(express.bodyParser());
app.use(express.methodOverride());

app.use(express.cookieParser('drink more coffee'));
app.use(express.session({cookie: { httpOnly: false }}));

// static must appear before app.router!
var viewsPath = path.join(__dirname, 'public');
if(process.env.NODE_ENV == 'production') {
  var oneDay = 86400000;
  app.use(express.static(viewsPath, {maxAge: oneDay}));
}
else {
  app.use(express.static(viewsPath));
}

app.use(express.logger('dev'));
app.use(app.router);

// Global error handler
app.use( function(err, req, res, next) {
  logger.error("Global error handler. Error: " + err);
  res.status(500);
  if(req.xhr) {
    res.send({error: err + ""});
  }
  else {
    res.render('index', {error: err});
  }
});

app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));

// Helper function to set cache expire values in response object
// http://stackoverflow.com/a/16750445/446681
app.set('setCache', function(res, minutes) {

  var seconds = minutes * 60;
  var ms = seconds * 1000;

  if (!res.getHeader('Cache-Control') || !res.getHeader('Expires')) {
    res.setHeader("Cache-Control", "public, max-age=" + seconds);
    res.setHeader("Expires", new Date(Date.now() + ms).toUTCString());
  }

});

var devSettings = function() {

  var file = __dirname + "/settings.dev.json";
  logger.info('Loading settings from ' + file);

  var settings = settingsUtil.loadSync(file);
  dbSetup.init(settings.dbUrl);
  app.set("config", settings);

};
app.configure('development', devSettings);

var prodSettings = function() {

  var file = __dirname + "/settings.prod.json";
  logger.info('Loading settings from ' + file);

  var settings = settingsUtil.loadSync(file);
  if(process.env.DB_URL) {
    settings.dbUrl = process.env.DB_URL;
    dbSetup.init(settings.dbUrl);
  }
  else {
    logger.error("This is not good. No DB_URL environment variable was found.");
  }
  app.set("config", settings);

};
app.configure('production', prodSettings);

exports.app = app;
<commit_msg>Replace double quotes with single quotes<commit_after>var express = require('express');
var path = require('path');
var ejs = require('ejs');
var logger = require('log-hanging-fruit').defaultLogger;
var settingsUtil = require('./settings');
var dbSetup = require('./models/dbSetup');
var app = express();

app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));

app.set('view engine', 'ejs');

app.use(express.bodyParser());
app.use(express.methodOverride());

app.use(express.cookieParser('drink more coffee'));
app.use(express.session({cookie: { httpOnly: false }}));

// static must appear before app.router!
var viewsPath = path.join(__dirname, 'public');
if(process.env.NODE_ENV == 'production') {
  var oneDay = 86400000;
  app.use(express.static(viewsPath, {maxAge: oneDay}));
}
else {
  app.use(express.static(viewsPath));
}

app.use(express.logger('dev'));
app.use(app.router);

// Global error handler
app.use( function(err, req, res, next) {
  logger.error('Global error handler. Error: ' + err);
  res.status(500);
  if(req.xhr) {
    res.send({error: err + ''});
  }
  else {
    res.render('index', {error: err});
  }
});

app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));

// Helper function to set cache expire values in response object
// http://stackoverflow.com/a/16750445/446681
app.set('setCache', function(res, minutes) {

  var seconds = minutes * 60;
  var ms = seconds * 1000;

  if (!res.getHeader('Cache-Control') || !res.getHeader('Expires')) {
    res.setHeader('Cache-Control', 'public, max-age=' + seconds);
    res.setHeader('Expires', new Date(Date.now() + ms).toUTCString());
  }

});

var devSettings = function() {

  var file = __dirname + '/settings.dev.json';
  logger.info('Loading settings from ' + file);

  var settings = settingsUtil.loadSync(file);
  dbSetup.init(settings.dbUrl);
  app.set('config', settings);

};
app.configure('development', devSettings);

var prodSettings = function() {

  var file = __dirname + '/settings.prod.json';
  logger.info('Loading settings from ' + file);

  var settings = settingsUtil.loadSync(file);
  if(process.env.DB_URL) {
    settings.dbUrl = process.env.DB_URL;
    dbSetup.init(settings.dbUrl);
  }
  else {
    logger.error('This is not good. No DB_URL environment variable was found.');
  }
  app.set('config', settings);

};
app.configure('production', prodSettings);

exports.app = app;
<|endoftext|>


<commit_before>/*jshint node:true */
/*
 * grunt-component
 * https://github.com/anthonyshort/grunt-component-build
 *
 * Copyright (c) 2012 Anthony Short
 * Licensed under the MIT license.
 */

'use strict';

var Builder = require('component-builder');
var fs = require('fs');
var path = require('path');
var template = fs.readFileSync(__dirname + '/../lib/require.tmpl').toString();

module.exports = function(grunt) {

  // Please see the grunt documentation for more information regarding task and
  // helper creation: https://github.com/cowboy/grunt/blob/master/docs/toc.md

  // ==========================================================================
  // TASKS
  // ==========================================================================

  grunt.registerMultiTask('component_build', 'component-build for grunt.', function() {
    var self = this;
    var opts = this.data;
    var name = opts.name || this.target;
    var dir = path.resolve(opts.base || '');
    var output = path.resolve(this.data.output);
    var done = this.async();

    // The component builder
    var builder = new Builder(dir);

    // Where to output the final file
    builder.copyAssetsTo(output);

    // Prefix urls
    if (opts.prefix) {
      builder.prefixUrls(opts.prefix);
    }

    // Development mode
    if (opts.dev) {
      builder.development();
    }

    if (opts.sourceUrls === true) {
      builder.addSourceURLs();
    }

    // Ignore component parts
    if (opts.ignore) {
      Object.keys(opts.ignore).forEach(function(n) {
        var type = opts.ignore[n];
        builder.ignore(n, type);
      });
    }

    // By default Builder takes the paths of the dependencies
    // from the current directory (here the Gruntfile path).
    // So in case the dependencies are not stored in the /components
    // but in the baseOption/components, we have to add it to the lookup.
    builder.addLookup(path.join(dir, 'components'));

    // The component config
    var config = require(path.join(dir, 'component.json'));

    if (config.paths) {
      config.paths = config.paths.map(function(p) {
        return path.resolve(dir, p);
      });

      builder.addLookup(config.paths);
    }

    // Set the config on the builder. We've modified
    // the original config from the file and this will
    // override settings during the build
    builder.config = config;

    if (opts.plugins) {
      opts.plugins.forEach(function(name) {
        var plugin = require('../plugins/' + name);
        builder.use(plugin);
      });
    }

    // Configure hook
    if (opts.configure) {
      opts.configure.call(this, builder);
    }

    var start = new Date();

    // Build the component
    builder.build(function(err, obj) {
      if (err) {
        grunt.log.error(err.message);
        grunt.fatal(err.message);
      }

      opts.verbose && grunt.log.writeln( 'duration: ' + ( new Date - start ) + 'ms' );

      // Write CSS file
      if (opts.styles !== false) {
        var cssFile = path.join(output, name + '.css');
        grunt.file.write(cssFile, obj.css.trim());

        opts.verbose && grunt.log.writeln( 'write: ' + path.join(self.data.output, name + '.css') + ' (' + ( obj.css.trim().length / 1024 | 0 ) + 'kb)' );
      }

      // Write JS file
      if (opts.scripts !== false) {
        var jsFile = path.join(output, name + '.js');
        var size = 0;
        if (opts.standalone) {
          // Defines the name of the global variable (window[opts.name]).
          // By default we use the name defined in the component.json,
          // else we use the `standalone` option defined in the Gruntfile.
          obj.name = (typeof opts.standalone === 'string') ? opts.standalone : config.name;
          obj.config = config;

          var string = grunt.template.process(template, { data: obj });
          grunt.file.write(jsFile, string);
          size = string.length;
        } else {
          grunt.file.write(jsFile, obj.require + obj.js);
          size = obj.require.length + obj.js.length;
        }

        opts.verbose && grunt.log.writeln( 'write: ' + path.join(self.data.output, name + '.js') + ' (' + ( size / 1024 | 0 ) + 'kb)' );

      }

      done();
    });
  });
};
<commit_msg>Refactor<commit_after>/*jshint node:true */
/*
 * grunt-component
 * https://github.com/anthonyshort/grunt-component-build
 *
 * Copyright (c) 2012 Anthony Short
 * Licensed under the MIT license.
 */

'use strict';

var Builder = require('component-builder');
var fs = require('fs');
var path = require('path');
var template = fs.readFileSync(__dirname + '/../lib/require.tmpl').toString();

module.exports = function(grunt) {

  // Please see the grunt documentation for more information regarding task and
  // helper creation: https://github.com/cowboy/grunt/blob/master/docs/toc.md

  // ==========================================================================
  // TASKS
  // ==========================================================================

  grunt.registerMultiTask('component_build', 'component-build for grunt.', function() {
    var self = this;
    var opts = this.data;
    var name = opts.name || this.target;
    var verbose = opts.verbose;
    var dir = path.resolve(opts.base || '');
    var output = path.resolve(this.data.output);
    var done = this.async();

    var verboseLog = function(str) {
      if (verbose) {
        grunt.log.writeln(str);
      }
    };

    // The component builder
    var builder = new Builder(dir);

    // Where to output the final file
    builder.copyAssetsTo(output);

    // Prefix urls
    if (opts.prefix) {
      builder.prefixUrls(opts.prefix);
    }

    // Development mode
    if (opts.dev) {
      builder.development();
    }

    if (opts.sourceUrls === true) {
      builder.addSourceURLs();
    }

    // Ignore component parts
    if (opts.ignore) {
      Object.keys(opts.ignore).forEach(function(n) {
        var type = opts.ignore[n];
        builder.ignore(n, type);
      });
    }

    // By default Builder takes the paths of the dependencies
    // from the current directory (here the Gruntfile path).
    // So in case the dependencies are not stored in the /components
    // but in the baseOption/components, we have to add it to the lookup.
    builder.addLookup(path.join(dir, 'components'));

    // The component config
    var config = require(path.join(dir, 'component.json'));

    if (config.paths) {
      config.paths = config.paths.map(function(p) {
        return path.resolve(dir, p);
      });

      builder.addLookup(config.paths);
    }

    // Set the config on the builder. We've modified
    // the original config from the file and this will
    // override settings during the build
    builder.config = config;

    if (opts.plugins) {
      opts.plugins.forEach(function(name) {
        var plugin = require('../plugins/' + name);
        builder.use(plugin);
      });
    }

    // Configure hook
    if (opts.configure) {
      opts.configure.call(this, builder);
    }

    var start = new Date();

    // Build the component
    builder.build(function(err, obj) {
      if (err) {
        grunt.log.error(err.message);
        grunt.fatal(err.message);
      }

      verboseLog('duration: ' + (new Date() - start) + 'ms');

      // Write CSS file
      if (opts.styles !== false) {
        var cssFile = path.join(output, name + '.css');
        grunt.file.write(cssFile, obj.css.trim());

        verboseLog('write: ' + path.join(self.data.output, name + '.css') + ' (' + (obj.css.trim().length / 1024 | 0) + 'kb)');
      }

      // Write JS file
      if (opts.scripts !== false) {
        var jsFile = path.join(output, name + '.js');
        var size = 0;
        if (opts.standalone) {
          // Defines the name of the global variable (window[opts.name]).
          // By default we use the name defined in the component.json,
          // else we use the `standalone` option defined in the Gruntfile.
          obj.name = (typeof opts.standalone === 'string') ? opts.standalone : config.name;
          obj.config = config;

          var string = grunt.template.process(template, { data: obj });
          grunt.file.write(jsFile, string);
          size = string.length;
        } else {
          grunt.file.write(jsFile, obj.require + obj.js);
          size = obj.require.length + obj.js.length;
        }

        verboseLog( 'write: ' + path.join(self.data.output, name + '.js') + ' (' + ( size / 1024 | 0 ) + 'kb)' );
      }

      done();
    });
  });
};
<|endoftext|>


<commit_before>/*
 * RailsAdmin remote form @VERSION
 *
 * License
 *
 * http://www.railsadmin.org
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 *   jquery.ui.dialog.js
 */
(function($) {
  $.widget("ra.remoteForm", {
    dialog: null,
    options: {
      dialogClass: "",
      width: 720
    },

    _create: function() {
      var widget = this;
      $(widget.element).bind("click", function(e){
        e.preventDefault();
        var dialog = widget._getDialog();
        $.ajax({
          url: $(this).attr("href"),
          beforeSend: function(xhr) {
            xhr.setRequestHeader("Accept", "text/javascript");
          },
          success: function(data, status, xhr) {
            dialog.html(data);
            widget._bindFormEvents();
          },
          error: function(xhr, status, error) {
            dialog.html(xhr.responseText);
          }
        });
      });
    },

    _bindFormEvents: function() {
      var dialog = this._getDialog(),
          form = dialog.find("form"),
          widget = this,
          saveButtonText = dialog.find("input[name=_save]").val(),
          cancelButtonText = dialog.find("input[name=_continue]").val();

      dialog.dialog("option", "title", $(".ui-widget-header", dialog).remove().text());

      form.attr("data-remote", true);
      dialog.find(".submit").remove();
      dialog.find(".ra-block-content").removeClass("ra-block-content");

      var buttons = {};

      buttons[saveButtonText] = function() {
				// We need to manually update CKeditor mapped textarea before ajax submit
				if(typeof CKEDITOR != 'undefined') {
					for ( instance in CKEDITOR.instances )
        		CKEDITOR.instances[instance].updateElement();
				}
        dialog.find("form").submit();
      };

      buttons[cancelButtonText] = function() {
        dialog.dialog("close");
      };

      dialog.dialog("option", "buttons", buttons);

      form.bind("ajax:success", function(e, data, status, xhr) {
				var json = $.parseJSON(data);
       	var select = widget.element.siblings('select');
				var input = widget.element.siblings('.ra-filtering-select-input');

				if(input.length > 0) {
 					input[0].value = json.label;
 				}

 				if(select.length > 0) {
 					select.html('<option value="' + json.id + '">' + json.label + '</option>' );
 					select[0].value = json.id;
 				}
				dialog.dialog("close");
      });

      form.bind("ajax:error", function(e, xhr, status, error) {
        dialog.html(xhr.responseText);
        widget._bindFormEvents();
      });
    },

    _getDialog: function() {
      if (!this.dialog) {
        var widget = this;
        this.dialog = $('

').dialog({
          autoShow: false,
          close: function(e, ui) {
            $(this).dialog("destroy");
            $(this).remove();
            widget.dialog = null;
          },
          modal: true,
          width: this.options.width
        });
      }
      return this.dialog;
    }
  });
})(jQuery);<commit_msg>Submit inputs are now button elements<commit_after>/*
 * RailsAdmin remote form @VERSION
 *
 * License
 *
 * http://www.railsadmin.org
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 *   jquery.ui.dialog.js
 */
(function($) {
  $.widget("ra.remoteForm", {
    dialog: null,
    options: {
      dialogClass: "",
      width: 720
    },

    _create: function() {
      var widget = this;
      $(widget.element).bind("click", function(e){
        e.preventDefault();
        var dialog = widget._getDialog();
        $.ajax({
          url: $(this).attr("href"),
          beforeSend: function(xhr) {
            xhr.setRequestHeader("Accept", "text/javascript");
          },
          success: function(data, status, xhr) {
            dialog.html(data);
            widget._bindFormEvents();
          },
          error: function(xhr, status, error) {
            dialog.html(xhr.responseText);
          }
        });
      });
    },

    _bindFormEvents: function() {
      var dialog = this._getDialog(),
          form = dialog.find("form"),
          widget = this,
          saveButtonText = dialog.find(":submit[name=_save]").text(),
          cancelButtonText = dialog.find(":submit[name=_continue]").text();

      dialog.dialog("option", "title", $(".ui-widget-header", dialog).remove().text());

      form.attr("data-remote", true);
      dialog.find(":submit").remove();
      dialog.find(".ra-block-content").removeClass("ra-block-content");

      var buttons = {};

      buttons[saveButtonText] = function() {
				// We need to manually update CKeditor mapped textarea before ajax submit
				if(typeof CKEDITOR != 'undefined') {
					for ( instance in CKEDITOR.instances )
        		CKEDITOR.instances[instance].updateElement();
				}
        dialog.find("form").submit();
      };

      buttons[cancelButtonText] = function() {
        dialog.dialog("close");
      };

      dialog.dialog("option", "buttons", buttons);

      form.bind("ajax:success", function(e, data, status, xhr) {
				var json = $.parseJSON(data);
       	var select = widget.element.siblings('select');
				var input = widget.element.siblings('.ra-filtering-select-input');

				if(input.length > 0) {
 					input[0].value = json.label;
 				}

 				if(select.length > 0) {
 					select.html('<option value="' + json.id + '">' + json.label + '</option>' );
 					select[0].value = json.id;
 				}
				dialog.dialog("close");
      });

      form.bind("ajax:error", function(e, xhr, status, error) {
        dialog.html(xhr.responseText);
        widget._bindFormEvents();
      });
    },

    _getDialog: function() {
      if (!this.dialog) {
        var widget = this;
        this.dialog = $('

').dialog({
          autoShow: false,
          close: function(e, ui) {
            $(this).dialog("destroy");
            $(this).remove();
            widget.dialog = null;
          },
          modal: true,
          width: this.options.width
        });
      }
      return this.dialog;
    }
  });
})(jQuery);<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var i<commit_msg>Fixed a typo<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var in<|endoftext|>


<commit_before>import Class from '../core/Class';
import BasicLoader from './BasicLoader';
import {
    getExtension
} from '../utils/util';

/**
 * @class
 */
const Loader = Class.create(/** @lends Loader.prototype */{
    /**
     * @default true
     * @type {boolean}
     */
    isLoader: true,
    /**
     * @default Loader
     * @type {string}
     */
    className: 'Loader',
    maxConnections: 2,
    Statics: {
        _loaderClassMap: {},
        _loaders: {},
        /**
         * 给Loader类添加扩展Loader
         * @memberOf Loader
         * @static
         * @param {string} ext 资源扩展，如gltf, png 等
         * @param {any} LoaderClass 用于加载的类，需要继承BasicLoader
         */
        addLoader(ext, LoaderClass) {
            Loader._loaderClassMap[ext] = LoaderClass;
        },
        getLoader(ext) {
            if (!Loader._loaders[ext]) {
                const LoaderClass = Loader._loaderClassMap[ext] ? Loader._loaderClassMap[ext] : BasicLoader;
                Loader._loaders[ext] = new LoaderClass();
            }
            return Loader._loaders[ext];
        }
    },
    /**
     * url 预处理函数
     * @type {Function}
     */
    preHandlerUrl: null,
    /**
     * load
     * @param  {Object|Array} data
     * @return {Promise<any>}
     */
    load(data) {
        if (data instanceof Array) {
            return Promise.all(data.map(d => this.load(d)));
        }
        const type = data.type || getExtension(data.src);
        const loader = Loader.getLoader(type);
        let loadData = data;
        if (this.preHandlerUrl) {
            loadData = Object.assign({}, data);
            loadData.src = this.preHandlerUrl(data.src);
        }
        return loader.load(loadData);
    }
});

export default Loader;
<commit_msg>docs: update Loader jsdoc comments<commit_after>import Class from '../core/Class';
import BasicLoader from './BasicLoader';
import {
    getExtension
} from '../utils/util';

/**
 * @class
 */
const Loader = Class.create(/** @lends Loader.prototype */{
    /**
     * @default true
     * @type {boolean}
     */
    isLoader: true,
    /**
     * @default Loader
     * @type {string}
     */
    className: 'Loader',
    maxConnections: 2,
    Statics: {
        _loaderClassMap: {},
        _loaders: {},
        /**
         * 给Loader类添加扩展Loader
         * @memberOf Loader
         * @static
         * @param {string} ext 资源扩展，如gltf, png 等
         * @param {any} LoaderClass 用于加载的类，需要继承BasicLoader
         */
        addLoader(ext, LoaderClass) {
            Loader._loaderClassMap[ext] = LoaderClass;
        },
        /**
         * 获取对应类型的 loader
         * @memberOf Loader
         * @static
         * @param  {string} ext
         * @return {any} loader
         */
        getLoader(ext) {
            if (!Loader._loaders[ext]) {
                const LoaderClass = Loader._loaderClassMap[ext] ? Loader._loaderClassMap[ext] : BasicLoader;
                Loader._loaders[ext] = new LoaderClass();
            }
            return Loader._loaders[ext];
        }
    },
    /**
     * url 预处理函数
     * @type {Function}
     */
    preHandlerUrl: null,
    /**
     * load
     * @param  {Object|Array} data
     * @return {Promise<any>}
     */
    load(data) {
        if (data instanceof Array) {
            return Promise.all(data.map(d => this.load(d)));
        }
        const type = data.type || getExtension(data.src);
        const loader = Loader.getLoader(type);
        let loadData = data;
        if (this.preHandlerUrl) {
            loadData = Object.assign({}, data);
            loadData.src = this.preHandlerUrl(data.src);
        }
        return loader.load(loadData);
    }
});

export default Loader;
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "dialog.error", "ui", "settings", "tabManager", "save",
        "menus", "preferences.keybindings", "preferences.general",
        "preferences.project", "c9", "commands", "watcher", "fs",
        "tree.favorites"
    ];
    main.provides = ["configure"];
    return main;

    function main(options, imports, register) {
        var Plugin = imports.Plugin;
        var settings = imports.settings;
        var commands = imports.commands;
        var save = imports.save;
        var menus = imports.menus;
        var watcher = imports.watcher;
        var tabManager = imports.tabManager;
        var ui = imports.ui;
        var c9 = imports.c9;
        var fs = imports.fs;
        var kbprefs = imports["preferences.keybindings"];
        var genprefs = imports["preferences.general"];
        var prjprefs = imports["preferences.project"];
        var showError = imports["dialog.error"].show;
        var favs = imports["tree.favorites"];

        var join = require("path").join;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        // var emit = plugin.getEmitter();

        var cssSession = new Plugin("Ajax.org", main.consumes);
        var services;

        var pathFromFavorite = options.pathFromFavorite;

        var loaded = false;
        function load() {
            if (loaded) return false;
            loaded = true;

            // Init Script
            var script = settings.get("user/config/init.js");
            if (script) {
                c9.once("ready", function(){
                    try { eval(script); }
                    catch (e){
                        setTimeout(function(){
                            showError("Error Executing init.js: ", e.message);
                        }, 500);
                    }
                });
            }

            // Init CSS
            var css = settings.get("user/config/styles.css");
            if (css)
                ui.insertCss(css, false, cssSession);

            commands.addCommand({
                name: "restartc9",
                group: "General",
                bindKey: { mac: "Command-R", win: "Ctrl-R" },
                exec: function(){
                    location.reload();
                }
            }, plugin);

            menus.addItemByPath("Cloud9/~", new ui.divider(), 350, plugin);
            menus.addItemByPath("Cloud9/Open Your Project Settings", new ui.item({
                onclick: editProjectSettings
            }), 400, plugin);
            menus.addItemByPath("Cloud9/Open Your User Settings", new ui.item({
                onclick: editUserSettings
            }), 400, plugin);
            menus.addItemByPath("Cloud9/Open Your Keymap", new ui.item({
                onclick: function(){
                    kbprefs.editUserKeys();
                }
            }), 600, plugin);
            menus.addItemByPath("Cloud9/Open Your Init Script", new ui.item({
                onclick: editInitJs
            }), 700, plugin);
            menus.addItemByPath("Cloud9/Open Your Stylesheet", new ui.item({
                onclick: editStylesCss
            }), 800, plugin);

            menus.addItemByPath("Cloud9/Restart Cloud9", new apf.item({
                command: "restartc9"
            }), 2000080, plugin);

            genprefs.on("edit", function(){
                editUserSettings();
            });
            prjprefs.on("edit", function(){
                editProjectSettings();
            });

            save.on("beforeSave", function(e) {
                if (!e.document.meta.config) return;

                var path = e.document.meta.config;

                // Doing save as, it is now a normal document
                if (e.path != path) {
                    delete e.document.meta.config;
                    delete e.document.meta.nofs;
                    return;
                }

                if (path == "~/.c9/init.js") {
                    settings.setJson("user/config/init.js", e.document.value);
                    showError("Please reload for these changes to take effect.");
                }
                else if (path == "~/.c9/styles.css") {
                    var css = e.document.value;
                    settings.setJson("user/config/styles.css", css);

                    cssSession.cleanUp();
                    ui.insertCss(css, false, cssSession);
                }
                else if (path == settings.paths.project) {
                    try { var project = JSON.parse(e.document.value); }
                    catch (e) {
                        showError("Syntax Error in Project Settings: " + e.message);
                        return false;
                    }

                    // @todo doesn't update UI
                    // settings.model.project = project;
                    settings.read({ project: project });
                    settings.save(true);
                }
                else if (path == settings.paths.user) {
                    try { var user = JSON.parse(e.document.value); }
                    catch (e) {
                        showError("Syntax Error in User Settings: " + e.message);
                        return false;
                    }

                    // @todo doesn't update UI
                    // settings.model.user = user;
                    settings.read({ user: user });
                    settings.save(true);
                }

                delete e.document.meta.newfile;
                e.document.undoManager.bookmark();

                return false;
            }, plugin);

            // Load initial project settings from disk and match against latest from database
            var initWatcher, projectPath;
            settings.on("read", function(){
                if (initWatcher) return;
                initWatcher = true;

                // Keep project file consistent with changes on disk
                watcher.on("change", function(e){
                    if (e.path == projectPath)
                        fs.readFile(e.path, readHandler);
                });
                watcher.on("delete", function(e){
                    if (e.path == projectPath)
                        watcher.watch(projectPath);
                });
                watcher.on("failed", function(e){
                    if (e.path == projectPath) {
                        setTimeout(function(){
                            watcher.watch(projectPath); // Retries once after 1s
                        });
                    }
                });

                function readHandler(err, data){
                    if (err) return;

                    settings.paths.project = projectPath;

                    try { var json = JSON.parse(data); }
                    catch(e) { return; }

                    settings.update("project", json);
                }

                // At startup read the project settings from disk
                if (pathFromFavorite) {
                    var originalPath = settings.paths.project;

                    function updateFavPath(){
                        var mainPath = favs.getFavoritePaths()[0];
                        if (mainPath)
                            mainPath = join(mainPath, ".c9/project.settings");
                        else
                            mainPath = originalPath;

                        // Unwatch old project path
                        if (projectPath)
                            watcher.unwatch(projectPath);

                        // Set new project path
                        projectPath = mainPath;

                        // Watch project path
                        watcher.watch(projectPath);

                        // Read from disk
                        fs.readFile(mainPath, readHandler);
                    }

                    favs.on("favoriteAdd", updateFavPath);
                    favs.on("favoriteRemove", updateFavPath);
                    favs.on("favoriteReorder", updateFavPath);

                    updateFavPath();
                }
                else {
                    projectPath = settings.paths.project;

                    // Watch project path
                    watcher.watch(projectPath);

                    // Read from disk
                    fs.readFile(projectPath, readHandler);
                }
            });
        }

        /***** Methods *****/

        function openTab(path, value, syntax, defaultValue) {
            tabManager.open({
                path: path,
                value: value || defaultValue,
                active: true,
                editorType: "ace",
                document: {
                    ace: { customSyntax: syntax },
                    meta: { config: path, newfile: !value.length, nofs: true }
                }
            }, function(err, tab) {

            });
        }

        function editInitJs(){
            var script = settings.get("user/config/init.js") || "";
            openTab("~/.c9/init.js", script, "javascript",
                "// You can access plugins via the 'services' global variable\n/*global services*/\n");
        }

        function editStylesCss(){
            var css = settings.get("user/config/styles.css") || "";
            openTab("~/.c9/styles.css", css, "css");
        }

        function editProjectSettings(){
            var value = JSON.stringify(settings.model.project, 0, "    ")
                .replace(/"true"/g, "true")
                .replace(/"false"/g, "false");
            openTab(settings.paths.project, value, "javascript");
        }
        function editUserSettings(){
            var value = JSON.stringify(settings.model.user, 0, "    ")
                .replace(/"true"/g, "true")
                .replace(/"false"/g, "false");
            openTab(settings.paths.user, value, "javascript");
        }

        /***** Lifecycle *****/

        plugin.on("load", function() {
            load();
        });
        plugin.on("enable", function() {

        });
        plugin.on("disable", function() {

        });
        plugin.on("unload", function() {
            loaded = false;
        });

        /***** Register and define API *****/

        /**
         *
         **/
        plugin.freezePublicAPI({
            get services(){ return services; },
            set services(value){ services = value; },

            /**
             *
             */
            editInitJs: editInitJs,

            /**
             *
             */
            editStylesCss: editStylesCss,

            /**
             *
             */
            editProjectSettings: editProjectSettings,

            /**
             *
             */
            editUserSettings: editUserSettings
        });

        register(null, {
            configure: plugin
        });
    }
});<commit_msg>Revert "Merge pull request +4132 from c9/fix/desktop"<commit_after>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "dialog.error", "ui", "settings", "tabManager", "save",
        "menus", "preferences.keybindings", "preferences.general",
        "preferences.project", "c9", "commands", "watcher", "fs"
    ];
    main.provides = ["configure"];
    return main;

    function main(options, imports, register) {
        var Plugin = imports.Plugin;
        var settings = imports.settings;
        var commands = imports.commands;
        var save = imports.save;
        var menus = imports.menus;
        var watcher = imports.watcher;
        var tabManager = imports.tabManager;
        var ui = imports.ui;
        var c9 = imports.c9;
        var fs = imports.fs;
        var kbprefs = imports["preferences.keybindings"];
        var genprefs = imports["preferences.general"];
        var prjprefs = imports["preferences.project"];
        var showError = imports["dialog.error"].show;

        var join = require("path").join;

        /***** Initialization *****/

        var plugin = new Plugin("Ajax.org", main.consumes);
        // var emit = plugin.getEmitter();

        var cssSession = new Plugin("Ajax.org", main.consumes);
        var services;

        var loaded = false;
        function load() {
            if (loaded) return false;
            loaded = true;

            // Init Script
            var script = settings.get("user/config/init.js");
            if (script) {
                c9.once("ready", function(){
                    try { eval(script); }
                    catch (e){
                        setTimeout(function(){
                            showError("Error Executing init.js: ", e.message);
                        }, 500);
                    }
                });
            }

            // Init CSS
            var css = settings.get("user/config/styles.css");
            if (css)
                ui.insertCss(css, false, cssSession);

            commands.addCommand({
                name: "restartc9",
                group: "General",
                bindKey: { mac: "Command-R", win: "Ctrl-R" },
                exec: function(){
                    location.reload();
                }
            }, plugin);

            menus.addItemByPath("Cloud9/~", new ui.divider(), 350, plugin);
            menus.addItemByPath("Cloud9/Open Your Project Settings", new ui.item({
                onclick: editProjectSettings
            }), 400, plugin);
            menus.addItemByPath("Cloud9/Open Your User Settings", new ui.item({
                onclick: editUserSettings
            }), 400, plugin);
            menus.addItemByPath("Cloud9/Open Your Keymap", new ui.item({
                onclick: function(){
                    kbprefs.editUserKeys();
                }
            }), 600, plugin);
            menus.addItemByPath("Cloud9/Open Your Init Script", new ui.item({
                onclick: editInitJs
            }), 700, plugin);
            menus.addItemByPath("Cloud9/Open Your Stylesheet", new ui.item({
                onclick: editStylesCss
            }), 800, plugin);

            menus.addItemByPath("Cloud9/Restart Cloud9", new apf.item({
                command: "restartc9"
            }), 2000080, plugin);

            genprefs.on("edit", function(){
                editUserSettings();
            })
            prjprefs.on("edit", function(){
                editProjectSettings();
            })

            save.on("beforeSave", function(e) {
                if (!e.document.meta.config) return;

                var path = e.document.meta.config;

                // Doing save as, it is now a normal document
                if (e.path != path) {
                    delete e.document.meta.config;
                    delete e.document.meta.nofs;
                    return;
                }

                if (path == "~/.c9/init.js") {
                    settings.setJson("user/config/init.js", e.document.value);
                    showError("Please reload for these changes to take effect.");
                }
                else if (path == "~/.c9/styles.css") {
                    var css = e.document.value;
                    settings.setJson("user/config/styles.css", css);

                    cssSession.cleanUp();
                    ui.insertCss(css, false, cssSession);
                }
                else if (path == settings.paths.project) {
                    try { var project = JSON.parse(e.document.value); }
                    catch (e) {
                        showError("Syntax Error in Project Settings: " + e.message);
                        return false;
                    }

                    // @todo doesn't update UI
                    // settings.model.project = project;
                    settings.read({ project: project });
                    settings.save(true);
                }
                else if (path == settings.paths.user) {
                    try { var user = JSON.parse(e.document.value); }
                    catch (e) {
                        showError("Syntax Error in User Settings: " + e.message);
                        return false;
                    }

                    // @todo doesn't update UI
                    // settings.model.user = user;
                    settings.read({ user: user });
                    settings.save(true);
                }

                delete e.document.meta.newfile;
                e.document.undoManager.bookmark();

                return false;
            }, plugin);

            // Load initial project settings from disk and match against latest from database
            var initWatcher;
            settings.on("read", function(){
                if (initWatcher) return;
                initWatcher = true;

                // Keep project file consistent with changes on disk
                watcher.watch(settings.paths.project);
                watcher.on("change", function(e){
                    if (e.path == settings.paths.project)
                        fs.readFile(e.path, readHandler);
                });
                watcher.on("delete", function(e){
                    if (e.path == settings.paths.project)
                        watcher.watch(settings.paths.project);
                });
                watcher.on("failed", function(e){
                    if (e.path == settings.paths.project) {
                        setTimeout(function(){
                            watcher.watch(settings.paths.project); // Retries once after 1s
                        });
                    }
                });

                function readHandler(err, data){
                    if (err) return;

                    try { var json = JSON.parse(data); }
                    catch(e) { return; }

                    // Do nothing if they are the same
                    if (JSON.stringify(settings.model.project) == JSON.stringify(json))
                        return;

                    // Compare key/values (assume source has same keys as target)
                    (function recur(source, target, base){
                        for (var prop in source) {
                            if (prop == "json()") {
                                settings.setJson(base, source[prop]);
                            }
                            else if (typeof source[prop] == "object") {
                                if (!target[prop]) target[prop] = {};
                                recur(source[prop], target[prop], join(base, prop));
                            }
                            else if (source[prop] != target[prop]) {
                                settings.set(join(base, prop), source[prop]);
                            }
                        }
                    })(json, settings.model.project, "project");
                }

                // At startup read the project settings from disk
                fs.readFile(settings.paths.project, readHandler);
            });
        }

        /***** Methods *****/

        function openTab(path, value, syntax, defaultValue) {
            tabManager.open({
                path: path,
                value: value || defaultValue,
                active: true,
                editorType: "ace",
                document: {
                    ace: { customSyntax: syntax },
                    meta: { config: path, newfile: !value.length, nofs: true }
                }
            }, function(err, tab) {

            });
        }

        function editInitJs(){
            var script = settings.get("user/config/init.js") || "";
            openTab("~/.c9/init.js", script, "javascript",
                "// You can access plugins via the 'services' global variable\n/*global services*/\n");
        }

        function editStylesCss(){
            var css = settings.get("user/config/styles.css") || "";
            openTab("~/.c9/styles.css", css, "css");
        }

        function editProjectSettings(){
            var value = JSON.stringify(settings.model.project, 0, "    ")
                .replace(/"true"/g, "true")
                .replace(/"false"/g, "false");
            openTab(settings.paths.project, value, "javascript");
        }
        function editUserSettings(){
            var value = JSON.stringify(settings.model.user, 0, "    ")
                .replace(/"true"/g, "true")
                .replace(/"false"/g, "false");
            openTab(settings.paths.user, value, "javascript");
        }

        /***** Lifecycle *****/

        plugin.on("load", function() {
            load();
        });
        plugin.on("enable", function() {

        });
        plugin.on("disable", function() {

        });
        plugin.on("unload", function() {
            loaded = false;
        });

        /***** Register and define API *****/

        /**
         *
         **/
        plugin.freezePublicAPI({
            get services(){ return services; },
            set services(value){ services = value; },

            /**
             *
             */
            editInitJs: editInitJs,

            /**
             *
             */
            editStylesCss: editStylesCss,

            /**
             *
             */
            editProjectSettings: editProjectSettings,

            /**
             *
             */
            editUserSettings: editUserSettings
        });

        register(null, {
            configure: plugin
        });
    }
});<|endoftext|>


<commit_before>/*
 * grunt-patch-wordpress
 * https://github.com/aaronjorbin/grunt-patch-wordpress
 * Based on https://gist.github.com/markjaquith/4219135
 *
 *
 * Copyright (c) 2013 Aaron Jorbin
 * Licensed under the MIT license.
 */

var request = require( 'request' ),
	exec =  require( 'child_process' ).exec,
	spawn = require( 'child_process' ).spawn,
	inquirer = require( 'inquirer' ),
	url = require( 'url' ),
	fs = require( 'fs' ),
	_ = require( 'underscore' ),
	trac = require( '../lib/trac.js' ),
	patch = require( '../lib/patch.js' ),
	regex = require( '../lib/regex.js' ),
	xmlrpc = require( 'xmlrpc' ),
	mapOldToNewFilePath = require( '../lib/map_old_to_new_file_path.js' );

_.str = _.str = require( 'underscore.string' );
_.mixin( _.str.exports() );

module.exports = function( grunt ) {
	var tempFile = 'wppatch.diff',
		defaults = {
			tracUrl: 'core.trac.wordpress.org'
		};

	function isSvn() {
		return fs.existsSync( '.svn' );
	}

	function workingDir() {
		return process.cwd();
	}

	function applyPatch( patchUrl, done, options ) {
		grunt.verbose.write( patchUrl );
		parsedUrl = url.parse( patchUrl );

		// What to do when either our patch is ready
		grunt.event.once( 'fileReady', function( level, moveToSrc ) {
			var patchOptions = {},
				patchArgs = [],
				patchProcess;

			// Set patch process to use the existing I/O streams, which will output
			// the command's results and allow for user input on patch error
			patchOptions.stdio = 'inherit';

			// Decide if we need to be in src
			if ( moveToSrc ) {
				patchOptions.cwd =  workingDir() + '/src';
				tempFile = workingDir() + '/' + tempFile;
			}

			// Set the patch command's arguments
			patchArgs.push( '-p' + level );
			patchArgs.push( '--input=' + tempFile );

			grunt.log.debug( 'patch options: ' + JSON.stringify( patchOptions ) );
			grunt.log.debug( 'patch arguments: ' + JSON.stringify( patchArgs ) );
			grunt.log.debug( 'patch tempFile: ' + JSON.stringify( tempFile ) );

			// Maps old file paths in patches to new file paths.
			if ( options.file_mappings ) {
				mapOldToNewFilePath( tempFile, options.file_mappings );
			}

			patchProcess = spawn( 'patch', patchArgs, patchOptions );

			patchProcess.on( 'exit', function( code, signal ) {
				if ( signal ) {
					grunt.log.debug( 'error signal: ' + signal );
				}

				// if debug is enabled, don't delete the file
				if ( grunt.option( 'debug' ) ) {
					grunt.log.debug( 'File Saved' );
				} else {
					grunt.file.delete( tempFile );
				}

				done( code );
			});
		});

		// or we know we have failed
		grunt.event.once( 'fileFail', function( msg ) {
			if ( 'string' === typeof msg ) {
				grunt.log.errorlns( msg );
			}

			done( false );
		});

		// if patchUrl is a github url
		if ( 'github.com' === parsedUrl.hostname ) {

			grunt.log.debug( 'github url detected: ' + patchUrl );
			if ( '.diff' !== patchUrl.slice( -5 ) &&  '.patch' !== patchUrl.slice( -6 ) ) {
				patchUrl += '.diff';
			}
			getPatch( patchUrl, options );

		// if patchUrl is a full url and is a raw-attachement, just apply it
		} else if ( parsedUrl.hostname === options.tracUrl && parsedUrl.pathname.match( /raw-attachment/ ) ) {
			getPatch( patchUrl, options );

		// if patchUrl is full url and is an attachment, convert it to a raw attachment
		} else if ( parsedUrl.hostname === options.tracUrl && parsedUrl.pathname.match( /attachment/ ) && parsedUrl.pathname.match( /(patch|diff)/ ) ) {
			getPatch( trac.convert_to_raw ( parsedUrl, options ) );

		// if patchUrl is just a ticket number, get a list of patches on that ticket and allow user to choose one
		} else if (  parsedUrl.hostname === options.tracUrl && parsedUrl.pathname.match( /ticket/ ) ) {
			getPatchFromTicket( patchUrl, options );

		// if we just enter a number, assume it is a ticket number
		} else if ( null === parsedUrl.hostname && ! parsedUrl.pathname.match( /\./ ) ) {
			getPatchFromTicketNumber( patchUrl, options );

		// if patchUrl is a local file, just use that
		} else if ( null === parsedUrl.hostname ) {
			getLocalPatch( patchUrl, options );

		// We've failed in our mission
		} else {
			grunt.event.emit( 'fileFile', 'All matching failed.  Please enter a ticket url, ticket number, patch url' );
		}
	}

	function getPatchFromTicketNumber( patchUrl, options  ) {
		grunt.log.debug( 'getPatchFromTicketNumber: ' + patchUrl );
		getPatchFromTicket( 'https://' + options.tracUrl + '/attachment/ticket/' + patchUrl + '/', options  );
	}

	function getPatchFromTicket( patchUrl, options ) {
		var matches,
			longMatches,
			matchUrl,
			possiblePatches;

		grunt.log.debug( 'getPatchFromTicket: ' + patchUrl );
		request( patchUrl, function( error, response, body ) {
			if ( ! error && 200 == response.statusCode ) {
				matches = regex.patchAttachments( body );
				grunt.log.debug( 'matches: ' + JSON.stringify( matches ) );

				if ( null == matches ) {
					grunt.event.emit( 'fileFail', patchUrl + '\ncontains no attachments' );
				} else if ( 1 === matches.length ) {
					matchUrl = options.tracUrl + regex.urlsFromAttachmentList(   matches[0])[1];
					getPatch( trac.convert_to_raw ( url.parse( 'https://' + matchUrl  ) ), options  );
				} else {
					longMatches = regex.longMatches( body );
					possiblePatches = regex.possiblePatches( longMatches );

					grunt.log.debug( 'possiblePatches: ' + JSON.stringify( possiblePatches ) );
					grunt.log.debug( 'longMatches: ' + JSON.stringify( longMatches ) );
					inquirer.prompt([
						{	type: 'list',
							name: 'patch_name',
							message: 'Please select a patch to apply',
							choices: possiblePatches,

							// preselect the most recent patch
							default: possiblePatches.length - 1
						}
					]).then(  answers => {
						grunt.log.debug( 'answers:' + JSON.stringify( answers ) );
						matchUrl = options.tracUrl +
						regex.urlsFromAttachmentList( matches[ _.indexOf( possiblePatches, answers.patch_name ) ])[1];
						getPatch( trac.convert_to_raw ( url.parse( 'https://' + matchUrl  ) ), options  );

					});
				}
			} else {

				// something went wrong
				grunt.event.emit( 'fileFail', 'getPatchFromTicket fail \n status: ' + response.statusCode );
			}
		});

		grunt.event.emit( 'fileFile', 'method not available yet' );
	}

	function getLocalPatch( patchUrl ) {
		var body = grunt.file.read( patchUrl ),
			level = patch.isAb( body ) ? 1 : 0,
			moveToSrc = patch.moveToSrc( body );

		grunt.file.copy( patchUrl, tempFile );
		grunt.event.emit( 'fileReady', level, moveToSrc );
	}

	function getPatch( patchUrl ) {
		grunt.log.debug( 'getting patch: ' + patchUrl );
		request( patchUrl, function( error, response, body ) {
			if ( ! error && 200 == response.statusCode ) {
				const level = patch.isAb( body ) ? 1 : 0;
				const moveToSrc = patch.moveToSrc( body );

				grunt.file.write( tempFile, body );
				grunt.event.emit( 'fileReady', level, moveToSrc );
			} else {

				// something went wrong
				grunt.event.emit( 'fileFail', 'getPatch_fail \n status: ' + response.statusCode );
			}
		});
	}

	function fileFail( done, msg ) {
		grunt.log.errorlns( 'Nothing to patch.' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( 'To use this command, please:' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '1) have a diff or patch in your WordPress Directory' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '2) enter a ticket number, e.g. grunt patch:15705' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '3) enter a ticket url, e.g. grunt patch:https://core.trac.wordpress.org/ticket/15705' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '4) enter a patch url, e.g. grunt patch:https://core.trac.wordpress.org/attachment/ticket/11817/13711.diff' );
		grunt.log.errorlns( '' );

		if ( 'string' === typeof( msg ) ) {
			grunt.verbose.errorlns( 'msg: ' + msg );
		}

		done( false );
	}

	function localFile( error, result, code, done, options ) {
		if ( ! error ) {
			files = _.filter( result.split( '\n' ), function( file ) {
				return ( _.str.include( file, 'patch' ) || _.str.include( file, 'diff' ) );
			});
			grunt.log.debug( 'files: ' + JSON.stringify( files ) );

			if ( 0 === files.length ) {
				fileFail( done );
			} else if ( 1 === files.length ) {
				applyPatch( regex.localFileClean( files[0]), done, options );
			} else {
				inquirer.prompt([
					{	type: 'list',
						name: 'file',
						message: 'Please select a file to apply',
						choices: files
					}
				]).then( answers => {
					var file = regex.localFileClean( answers.file );
					applyPatch( file, done, options );
				});
			}
		} else {
			fileFail( done, 'local file fail' );
		}
	}

	grunt.registerTask( 'patch_wordpress', 'Patch your develop-wordpress directory like a boss', function( ticket, afterProtocal ) {
		var done = this.async();
		var options = this.options( defaults );

		// since URLs contain a : which is the seperator for grunt, we
		// need to reassemble the url.
		if ( 'undefined' !== typeof afterProtocal ) {
			ticket = ticket + ':' + afterProtocal;
		}

		grunt.log.debug( 'ticket: ' + ticket );
		grunt.log.debug( 'options: ' + JSON.stringify( options ) );

		if ( 'undefined' === typeof ticket ) {

			// look for diffs and patches in the root of the checkout and
			// prompt using inquirer to pick one

			const fileFinderCommand = isSvn() ? 'svn status ' : 'git ls-files --other --exclude-standard';

			exec( fileFinderCommand, function( error, result, code ) {
				localFile( error, result, code, done, options );
			});
		} else {
			applyPatch( ticket, done, options );

		}

	});

	grunt.registerTask( 'upload_patch', 'Upload the current diff of your develop-wordpress directory to Trac', function( ticketNumber ) {
		var done = this.async();
		var options = this.options( defaults );

		grunt.log.debug( 'ticketNumber: ' + ticketNumber );
		grunt.log.debug( 'options: ' + JSON.stringify( options ) );

		ticketNumber = parseInt( ticketNumber, 10 );
		if ( 'number' != typeof ticketNumber ) {
			grunt.fail.warn( 'A ticket number is required to upload a patch.' );
		}

		const uploadPatchWithCredentials = function( username, password ) {
			var diffCommand = isSvn() ? 'svn diff --diff-cmd diff' : 'git diff';

			exec( diffCommand, function( error, result, code ) {
				var client = xmlrpc.createSecureClient({
					hostname: options.tracUrl,
					port: 443,
					path: '/login/xmlrpc',
					basic_auth: { // eslint-disable-line camelcase
						user: username,
						pass: password
					}
				});
				client.methodCall(
					'ticket.putAttachment',
					[
						ticketNumber,
						ticketNumber + '.diff',
						'', // description. empty for now.
						new Buffer( new Buffer( result ).toString( 'base64' ), 'base64' ),
						false // never overwrite the old file
					], function( err, value ) {
						if ( null === err ) {
							grunt.log.writeln( 'Uploaded patch.' );
							done();
						} else {
							grunt.fail.warn( 'Something went wrong when attempting to upload the patch. Please confirm your credentials and the ticket number. ' + err );
						}
					}
				);
			});
		};
		inquirer.prompt(
			[
				{ type: 'input', name: 'username', message: 'Enter your WordPress.org username' },
				{ type: 'password', name: 'password', message: 'Enter your WordPress.org password' }
			]).then(  answers => {
			uploadPatchWithCredentials( answers.username, answers.password );
		}
		);
	});

};
<commit_msg>fix mis-renamed trac.convert_to_raw<commit_after>/*
 * grunt-patch-wordpress
 * https://github.com/aaronjorbin/grunt-patch-wordpress
 * Based on https://gist.github.com/markjaquith/4219135
 *
 *
 * Copyright (c) 2013 Aaron Jorbin
 * Licensed under the MIT license.
 */

var request = require( 'request' ),
	exec =  require( 'child_process' ).exec,
	spawn = require( 'child_process' ).spawn,
	inquirer = require( 'inquirer' ),
	url = require( 'url' ),
	fs = require( 'fs' ),
	_ = require( 'underscore' ),
	trac = require( '../lib/trac.js' ),
	patch = require( '../lib/patch.js' ),
	regex = require( '../lib/regex.js' ),
	xmlrpc = require( 'xmlrpc' ),
	mapOldToNewFilePath = require( '../lib/map_old_to_new_file_path.js' );

_.str = _.str = require( 'underscore.string' );
_.mixin( _.str.exports() );

module.exports = function( grunt ) {
	var tempFile = 'wppatch.diff',
		defaults = {
			tracUrl: 'core.trac.wordpress.org'
		};

	function isSvn() {
		return fs.existsSync( '.svn' );
	}

	function workingDir() {
		return process.cwd();
	}

	function applyPatch( patchUrl, done, options ) {
		grunt.verbose.write( patchUrl );
		parsedUrl = url.parse( patchUrl );

		// What to do when either our patch is ready
		grunt.event.once( 'fileReady', function( level, moveToSrc ) {
			var patchOptions = {},
				patchArgs = [],
				patchProcess;

			// Set patch process to use the existing I/O streams, which will output
			// the command's results and allow for user input on patch error
			patchOptions.stdio = 'inherit';

			// Decide if we need to be in src
			if ( moveToSrc ) {
				patchOptions.cwd =  workingDir() + '/src';
				tempFile = workingDir() + '/' + tempFile;
			}

			// Set the patch command's arguments
			patchArgs.push( '-p' + level );
			patchArgs.push( '--input=' + tempFile );

			grunt.log.debug( 'patch options: ' + JSON.stringify( patchOptions ) );
			grunt.log.debug( 'patch arguments: ' + JSON.stringify( patchArgs ) );
			grunt.log.debug( 'patch tempFile: ' + JSON.stringify( tempFile ) );

			// Maps old file paths in patches to new file paths.
			if ( options.file_mappings ) {
				mapOldToNewFilePath( tempFile, options.file_mappings );
			}

			patchProcess = spawn( 'patch', patchArgs, patchOptions );

			patchProcess.on( 'exit', function( code, signal ) {
				if ( signal ) {
					grunt.log.debug( 'error signal: ' + signal );
				}

				// if debug is enabled, don't delete the file
				if ( grunt.option( 'debug' ) ) {
					grunt.log.debug( 'File Saved' );
				} else {
					grunt.file.delete( tempFile );
				}

				done( code );
			});
		});

		// or we know we have failed
		grunt.event.once( 'fileFail', function( msg ) {
			if ( 'string' === typeof msg ) {
				grunt.log.errorlns( msg );
			}

			done( false );
		});

		// if patchUrl is a github url
		if ( 'github.com' === parsedUrl.hostname ) {

			grunt.log.debug( 'github url detected: ' + patchUrl );
			if ( '.diff' !== patchUrl.slice( -5 ) &&  '.patch' !== patchUrl.slice( -6 ) ) {
				patchUrl += '.diff';
			}
			getPatch( patchUrl, options );

		// if patchUrl is a full url and is a raw-attachement, just apply it
		} else if ( parsedUrl.hostname === options.tracUrl && parsedUrl.pathname.match( /raw-attachment/ ) ) {
			getPatch( patchUrl, options );

		// if patchUrl is full url and is an attachment, convert it to a raw attachment
		} else if ( parsedUrl.hostname === options.tracUrl && parsedUrl.pathname.match( /attachment/ ) && parsedUrl.pathname.match( /(patch|diff)/ ) ) {
			getPatch( trac.convertToRaw ( parsedUrl, options ) );

		// if patchUrl is just a ticket number, get a list of patches on that ticket and allow user to choose one
		} else if (  parsedUrl.hostname === options.tracUrl && parsedUrl.pathname.match( /ticket/ ) ) {
			getPatchFromTicket( patchUrl, options );

		// if we just enter a number, assume it is a ticket number
		} else if ( null === parsedUrl.hostname && ! parsedUrl.pathname.match( /\./ ) ) {
			getPatchFromTicketNumber( patchUrl, options );

		// if patchUrl is a local file, just use that
		} else if ( null === parsedUrl.hostname ) {
			getLocalPatch( patchUrl, options );

		// We've failed in our mission
		} else {
			grunt.event.emit( 'fileFile', 'All matching failed.  Please enter a ticket url, ticket number, patch url' );
		}
	}

	function getPatchFromTicketNumber( patchUrl, options  ) {
		grunt.log.debug( 'getPatchFromTicketNumber: ' + patchUrl );
		getPatchFromTicket( 'https://' + options.tracUrl + '/attachment/ticket/' + patchUrl + '/', options  );
	}

	function getPatchFromTicket( patchUrl, options ) {
		var matches,
			longMatches,
			matchUrl,
			possiblePatches;

		grunt.log.debug( 'getPatchFromTicket: ' + patchUrl );
		request( patchUrl, function( error, response, body ) {
			if ( ! error && 200 == response.statusCode ) {
				matches = regex.patchAttachments( body );
				grunt.log.debug( 'matches: ' + JSON.stringify( matches ) );

				if ( null == matches ) {
					grunt.event.emit( 'fileFail', patchUrl + '\ncontains no attachments' );
				} else if ( 1 === matches.length ) {
					matchUrl = options.tracUrl + regex.urlsFromAttachmentList(   matches[0])[1];
					getPatch( trac.convertToRaw ( url.parse( 'https://' + matchUrl  ) ), options  );
				} else {
					longMatches = regex.longMatches( body );
					possiblePatches = regex.possiblePatches( longMatches );

					grunt.log.debug( 'possiblePatches: ' + JSON.stringify( possiblePatches ) );
					grunt.log.debug( 'longMatches: ' + JSON.stringify( longMatches ) );
					inquirer.prompt([
						{	type: 'list',
							name: 'patch_name',
							message: 'Please select a patch to apply',
							choices: possiblePatches,

							// preselect the most recent patch
							default: possiblePatches.length - 1
						}
					]).then(  answers => {
						grunt.log.debug( 'answers:' + JSON.stringify( answers ) );
						matchUrl = options.tracUrl +
						regex.urlsFromAttachmentList( matches[ _.indexOf( possiblePatches, answers.patch_name ) ])[1];
						getPatch( trac.convertToRaw ( url.parse( 'https://' + matchUrl  ) ), options  );

					});
				}
			} else {

				// something went wrong
				grunt.event.emit( 'fileFail', 'getPatchFromTicket fail \n status: ' + response.statusCode );
			}
		});

		grunt.event.emit( 'fileFile', 'method not available yet' );
	}

	function getLocalPatch( patchUrl ) {
		var body = grunt.file.read( patchUrl ),
			level = patch.isAb( body ) ? 1 : 0,
			moveToSrc = patch.moveToSrc( body );

		grunt.file.copy( patchUrl, tempFile );
		grunt.event.emit( 'fileReady', level, moveToSrc );
	}

	function getPatch( patchUrl ) {
		grunt.log.debug( 'getting patch: ' + patchUrl );
		request( patchUrl, function( error, response, body ) {
			if ( ! error && 200 == response.statusCode ) {
				const level = patch.isAb( body ) ? 1 : 0;
				const moveToSrc = patch.moveToSrc( body );

				grunt.file.write( tempFile, body );
				grunt.event.emit( 'fileReady', level, moveToSrc );
			} else {

				// something went wrong
				grunt.event.emit( 'fileFail', 'getPatch_fail \n status: ' + response.statusCode );
			}
		});
	}

	function fileFail( done, msg ) {
		grunt.log.errorlns( 'Nothing to patch.' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( 'To use this command, please:' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '1) have a diff or patch in your WordPress Directory' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '2) enter a ticket number, e.g. grunt patch:15705' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '3) enter a ticket url, e.g. grunt patch:https://core.trac.wordpress.org/ticket/15705' );
		grunt.log.errorlns( '' );
		grunt.log.errorlns( '4) enter a patch url, e.g. grunt patch:https://core.trac.wordpress.org/attachment/ticket/11817/13711.diff' );
		grunt.log.errorlns( '' );

		if ( 'string' === typeof( msg ) ) {
			grunt.verbose.errorlns( 'msg: ' + msg );
		}

		done( false );
	}

	function localFile( error, result, code, done, options ) {
		if ( ! error ) {
			files = _.filter( result.split( '\n' ), function( file ) {
				return ( _.str.include( file, 'patch' ) || _.str.include( file, 'diff' ) );
			});
			grunt.log.debug( 'files: ' + JSON.stringify( files ) );

			if ( 0 === files.length ) {
				fileFail( done );
			} else if ( 1 === files.length ) {
				applyPatch( regex.localFileClean( files[0]), done, options );
			} else {
				inquirer.prompt([
					{	type: 'list',
						name: 'file',
						message: 'Please select a file to apply',
						choices: files
					}
				]).then( answers => {
					var file = regex.localFileClean( answers.file );
					applyPatch( file, done, options );
				});
			}
		} else {
			fileFail( done, 'local file fail' );
		}
	}

	grunt.registerTask( 'patch_wordpress', 'Patch your develop-wordpress directory like a boss', function( ticket, afterProtocal ) {
		var done = this.async();
		var options = this.options( defaults );

		// since URLs contain a : which is the seperator for grunt, we
		// need to reassemble the url.
		if ( 'undefined' !== typeof afterProtocal ) {
			ticket = ticket + ':' + afterProtocal;
		}

		grunt.log.debug( 'ticket: ' + ticket );
		grunt.log.debug( 'options: ' + JSON.stringify( options ) );

		if ( 'undefined' === typeof ticket ) {

			// look for diffs and patches in the root of the checkout and
			// prompt using inquirer to pick one

			const fileFinderCommand = isSvn() ? 'svn status ' : 'git ls-files --other --exclude-standard';

			exec( fileFinderCommand, function( error, result, code ) {
				localFile( error, result, code, done, options );
			});
		} else {
			applyPatch( ticket, done, options );

		}

	});

	grunt.registerTask( 'upload_patch', 'Upload the current diff of your develop-wordpress directory to Trac', function( ticketNumber ) {
		var done = this.async();
		var options = this.options( defaults );

		grunt.log.debug( 'ticketNumber: ' + ticketNumber );
		grunt.log.debug( 'options: ' + JSON.stringify( options ) );

		ticketNumber = parseInt( ticketNumber, 10 );
		if ( 'number' != typeof ticketNumber ) {
			grunt.fail.warn( 'A ticket number is required to upload a patch.' );
		}

		const uploadPatchWithCredentials = function( username, password ) {
			var diffCommand = isSvn() ? 'svn diff --diff-cmd diff' : 'git diff';

			exec( diffCommand, function( error, result, code ) {
				var client = xmlrpc.createSecureClient({
					hostname: options.tracUrl,
					port: 443,
					path: '/login/xmlrpc',
					basic_auth: { // eslint-disable-line camelcase
						user: username,
						pass: password
					}
				});
				client.methodCall(
					'ticket.putAttachment',
					[
						ticketNumber,
						ticketNumber + '.diff',
						'', // description. empty for now.
						new Buffer( new Buffer( result ).toString( 'base64' ), 'base64' ),
						false // never overwrite the old file
					], function( err, value ) {
						if ( null === err ) {
							grunt.log.writeln( 'Uploaded patch.' );
							done();
						} else {
							grunt.fail.warn( 'Something went wrong when attempting to upload the patch. Please confirm your credentials and the ticket number. ' + err );
						}
					}
				);
			});
		};
		inquirer.prompt(
			[
				{ type: 'input', name: 'username', message: 'Enter your WordPress.org username' },
				{ type: 'password', name: 'password', message: 'Enter your WordPress.org password' }
			]).then(  answers => {
			uploadPatchWithCredentials( answers.username, answers.password );
		}
		);
	});

};
<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "F<commit_msg>Someone poisoned the waterhole!<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fi<|endoftext|>


<commit_before>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue<commit_msg>Work in Progress<commit_after>var fs = require('fs');
var child_process = require('child_process')
var max_sleep = 300
//Added a comment that achieves no real goal.

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue <|endoftext|>