diff --git a/AssetFile b/AssetFile
index 85294d28..9b7bd723 100644
--- a/AssetFile
+++ b/AssetFile
@@ -4,13 +4,15 @@ require 'rake-pipeline-web-filters'
require 'rake-pipeline/travis'
require 'compass'
+roots ||= [Pathname.new(File.expand_path('.'))]
+
Compass.configuration.images_path = 'assets/images'
Compass.configuration.add_import_path File.expand_path('../assets/stylesheets', __FILE__)
Travis::Version.update
output 'public/javascripts'
-input 'assets/javascripts' do
+input roots.map { |root| root.join('assets/javascripts').to_s } do
match 'app/templates/**/*.hbs' do
filter Travis::HandlebarsFilter
concat 'app/templates.js'
@@ -33,7 +35,7 @@ input 'assets/javascripts' do
match 'min/**/*.js' do
filter Travis::ProductionFilter
- uglify max_line_length: 50, squeeze: true
+ uglify max_line_length: 32 * 1024, squeeze: true
filter Travis::SafeConcatFilter do
'application.min.js'
end
@@ -45,7 +47,7 @@ input 'assets/javascripts' do
end
output 'public/stylesheets'
-input 'assets/stylesheets' do
+input roots.map { |root| root.join('assets/stylesheets').to_s } do
match '**/*.{scss,sass}' do
filter Rake::Pipeline::Web::Filters::SassFilter
concat [], 'application.css'
@@ -53,33 +55,15 @@ input 'assets/stylesheets' do
end
output 'public/images'
-input 'assets/images' do
+input roots.map { |root| root.join('assets/images').to_s } do
match '**/*' do
copy
end
end
output 'public'
-input 'assets/static' do
+input roots.map { |root| root.join('assets/public').to_s } do
match '**/*' do
copy
end
end
-
-# # DOH. how to simplify this.
-# input 'assets/javascripts/spec' do
-# match 'vendor/*.js' do
-# files = %w(
-# vendor/jasmine.js
-# vendor/jasmine-html.js
-# vendor/jasmine-runner.js
-# vendor/sinon.js
-# )
-# concat files, 'specs/vendor.js'
-# end
-#
-# match '**/*.coffee' do
-# coffee_script
-# concat 'specs/specs.js'
-# end
-# end
diff --git a/Gemfile.lock b/Gemfile.lock
index 6ffb0c32..5cef6770 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -42,7 +42,7 @@ GIT
GIT
remote: git://github.com/travis-ci/travis-api.git
- revision: f6957636fba447ed61565e16a466eed8325900a5
+ revision: c9c9dc61d8e2f24b331fd0e1b1549aff32178b29
specs:
travis-api (0.0.1)
backports (~> 2.5)
diff --git a/Guardfile b/Guardfile
index 76bbfc9c..7d9e087e 100644
--- a/Guardfile
+++ b/Guardfile
@@ -1,7 +1,7 @@
$: << 'lib'
guard 'assets' do
- watch(%r(^AssetFile))
+ watch(%r(^Assetfile))
watch(%r(^assets))
end
diff --git a/lib/rake-pipeline/travis/filters.rb b/lib/rake-pipeline/travis/filters.rb
index 12152197..f3abf3f5 100644
--- a/lib/rake-pipeline/travis/filters.rb
+++ b/lib/rake-pipeline/travis/filters.rb
@@ -1,18 +1,23 @@
require 'rake-pipeline'
require 'execjs'
require 'uglifier'
+require 'pathname'
module Travis
class HandlebarsFilter < Rake::Pipeline::Filter
class << self
def source
[
- File.read('lib/rake-pipeline/ember-headless.js'),
- File.read('assets/javascripts/vendor/handlebars.js'),
- File.read('assets/javascripts/vendor/ember.js')
+ File.read(root.join('lib/rake-pipeline/ember-headless.js')),
+ File.read(root.join('assets/javascripts/vendor/handlebars.js')),
+ File.read(root.join('assets/javascripts/vendor/ember.js'))
].join("\n")
end
+ def root
+ @root ||= Pathname.new(File.expand_path('../../../../', __FILE__))
+ end
+
def context
@@context ||= ExecJS.compile(source)
end
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index 87aa0e20..37e5b171 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -30146,4 +30146,4 @@ var _require=function(){function c(a,c){document.addEventListener?a.addEventList
++g&&setTimeout(c,0)})}}();
(function(){!window.WebSocket&&window.MozWebSocket&&(window.WebSocket=window.MozWebSocket);if(window.WebSocket)Pusher.Transport=window.WebSocket,Pusher.TransportType="native";var c=(document.location.protocol=="http:"?Pusher.cdn_http:Pusher.cdn_https)+Pusher.VERSION,a=[];window.JSON||a.push(c+"/json2"+Pusher.dependency_suffix+".js");if(!window.WebSocket)window.WEB_SOCKET_DISABLE_AUTO_INITIALIZATION=!0,a.push(c+"/flashfallback"+Pusher.dependency_suffix+".js");var b=function(){return window.WebSocket?function(){Pusher.ready()}:
function(){window.WebSocket?(Pusher.Transport=window.WebSocket,Pusher.TransportType="flash",window.WEB_SOCKET_SWF_LOCATION=c+"/WebSocketMain.swf",WebSocket.__addTask(function(){Pusher.ready()}),WebSocket.__initialize()):(Pusher.Transport=null,Pusher.TransportType="none",Pusher.ready())}}(),e=function(a){var b=function(){document.body?a():setTimeout(b,0)};b()},g=function(){e(b)};a.length>0?_require(a,g):g()})();
-minispade.register('app', "(function() {(function() {\nminispade.require('travis');\nminispade.require('auth');\nminispade.require('controllers');\nminispade.require('helpers');\nminispade.require('models');\nminispade.require('pusher');\nminispade.require('routes');\nminispade.require('slider');\nminispade.require('store');\nminispade.require('tailing');\nminispade.require('templates');\nminispade.require('views');\nminispade.require('config/locales');\nminispade.require('data/sponsors');\n\n Travis.reopen({\n App: Em.Application.extend({\n autoinit: false,\n currentUserBinding: 'auth.user',\n authStateBinding: 'auth.state',\n init: function() {\n this._super.apply(this, arguments);\n this.store = Travis.Store.create();\n this.store.loadMany(Travis.Sponsor, Travis.SPONSORS);\n this.set('auth', Travis.Auth.create({\n store: this.store,\n endpoint: Travis.config.api_endpoint\n }));\n this.slider = new Travis.Slider();\n this.pusher = new Travis.Pusher(Travis.config.pusher);\n return this.tailing = new Travis.Tailing();\n },\n signIn: function() {\n return this.get('auth').signIn();\n },\n signOut: function() {\n this.get('auth').signOut();\n return this.get('router').send('showAuthenticated');\n },\n receive: function() {\n return this.store.receive.apply(this.store, arguments);\n },\n toggleSidebar: function() {\n var element;\n $('body').toggleClass('maximized');\n element = $('');\n $('#top .profile').append(element);\n Em.run.later((function() {\n return element.remove();\n }), 10);\n element = $('');\n $('#repository').append(element);\n return Em.run.later((function() {\n return element.remove();\n }), 10);\n }\n })\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=app");minispade.register('auth', "(function() {(function() {\n\n this.Travis.Auth = Ember.Object.extend({\n iframe: $('').hide(),\n timeout: 5000,\n state: 'signed-out',\n receivingEnd: \"\" + location.protocol + \"//\" + location.host,\n init: function() {\n var _this = this;\n this.iframe.appendTo('body');\n window.addEventListener('message', function(e) {\n return _this.receiveMessage(e);\n });\n return this.loadUser();\n },\n accessToken: (function() {\n return sessionStorage.getItem('travis.token');\n }).property(),\n loadUser: function() {\n var user;\n if (user = typeof sessionStorage !== \"undefined\" && sessionStorage !== null ? sessionStorage.getItem('travis.user') : void 0) {\n return this.setData({\n user: JSON.parse(user)\n });\n } else if (typeof localStorage !== \"undefined\" && localStorage !== null ? localStorage.getItem('travis.auto_signin') : void 0) {\n return this.trySignIn();\n }\n },\n signIn: function() {\n this.set('state', 'signing-in');\n this.trySignIn();\n return Ember.run.later(this, this.checkSignIn.bind(this), this.timeout);\n },\n trySignIn: function() {\n return this.iframe.attr('src', \"\" + this.endpoint + \"/auth/post_message?origin=\" + this.receivingEnd);\n },\n checkSignIn: function() {\n if (this.get('state') === 'signing-in') {\n return this.forceSignIn();\n }\n },\n forceSignIn: function() {\n if (typeof localStorage !== \"undefined\" && localStorage !== null) {\n localStorage.setItem('travis.auto_signin', 'true');\n }\n return window.location = \"\" + this.endpoint + \"/auth/handshake?redirect_uri=\" + location;\n },\n signOut: function() {\n if (typeof localStorage !== \"undefined\" && localStorage !== null) {\n localStorage.clear();\n }\n if (typeof sessionStorage !== \"undefined\" && sessionStorage !== null) {\n sessionStorage.clear();\n }\n return this.setData();\n },\n setData: function(data) {\n var user;\n if (typeof data === 'string') {\n data = JSON.parse(data);\n }\n if (data != null ? data.token : void 0) {\n this.storeToken(data.token);\n }\n if (data != null ? data.user : void 0) {\n user = this.storeUser(data.user);\n }\n this.set('state', user ? 'signed-in' : 'signed-out');\n return this.set('user', user ? user : void 0);\n },\n storeToken: function(token) {\n if (typeof sessionStorage !== \"undefined\" && sessionStorage !== null) {\n sessionStorage.setItem('travis.token', token);\n }\n return this.notifyPropertyChange('accessToken');\n },\n storeUser: function(user) {\n if (typeof localStorage !== \"undefined\" && localStorage !== null) {\n localStorage.setItem('travis.auto_signin', 'true');\n }\n if (typeof sessionStorage !== \"undefined\" && sessionStorage !== null) {\n sessionStorage.setItem('travis.user', JSON.stringify(user));\n }\n this.store.load(Travis.User, user);\n return this.store.find(Travis.User, user.id);\n },\n receiveMessage: function(event) {\n if (event.origin === this.expectedOrigin()) {\n this.setData(event.data);\n return console.log(\"signed in as \" + event.data.user.login);\n } else {\n return console.log(\"unexpected message \" + event.origin + \": \" + event.data);\n }\n },\n expectedOrigin: function() {\n if (this.endpoint[0] === '/') {\n return this.receivingEnd;\n } else {\n return this.endpoint;\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=auth");minispade.register('controllers', "(function() {(function() {\nminispade.require('helpers');\nminispade.require('travis/ticker');\n\n Travis.reopen({\n Controller: Em.Controller.extend({\n connectOutlet: function() {\n var view, _connectedOutletViews;\n view = this._super.apply(this, arguments);\n if (view) {\n _connectedOutletViews = Travis.app.get('_connectedOutletViews');\n if (!_connectedOutletViews) {\n _connectedOutletViews = [];\n }\n _connectedOutletViews.pushObject(view);\n Travis.app.set('_connectedOutletViews', _connectedOutletViews);\n }\n return view;\n }\n }),\n TopController: Em.Controller.extend({\n userBinding: 'Travis.app.currentUser'\n }),\n ApplicationController: Em.Controller.extend(),\n MainController: Em.Controller.extend(),\n StatsLayoutController: Em.Controller.extend(),\n ProfileLayoutController: Em.Controller.extend()\n });\nminispade.require('controllers/accounts');\nminispade.require('controllers/builds');\nminispade.require('controllers/home');\nminispade.require('controllers/profile');\nminispade.require('controllers/repositories');\nminispade.require('controllers/repository');\nminispade.require('controllers/sidebar');\nminispade.require('controllers/stats');\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers");minispade.register('controllers/accounts', "(function() {(function() {\n\n Travis.AccountsController = Ember.ArrayController.extend({\n tab: 'accounts',\n init: function() {\n return this._super();\n },\n findByLogin: function(login) {\n return this.find(function(account) {\n return account.get('login') === 'login';\n });\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers/accounts");minispade.register('controllers/builds', "(function() {(function() {\n\n Travis.BuildsController = Em.ArrayController.extend({\n repositoryBinding: 'parent.repository',\n contentBinding: 'parent.builds'\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers/builds");minispade.register('controllers/home', "(function() {(function() {\n\n Travis.HomeController = Travis.Controller.extend();\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers/home");minispade.register('controllers/job', "(function() {(function() {\n\n\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers/job");minispade.register('controllers/profile', "(function() {(function() {\n\n Travis.ProfileController = Travis.Controller.extend({\n name: 'profile',\n userBinding: 'Travis.app.currentUser',\n accountsBinding: 'Travis.app.router.accountsController',\n account: (function() {\n var login;\n login = this.get('params.login') || Travis.app.get('currentUser.login');\n return this.get('accounts').filter(function(account) {\n if (account.get('login') === login) {\n return account;\n }\n })[0];\n }).property('accounts.length', 'params.login'),\n activate: function(action, params) {\n this.setParams(params || this.get('params'));\n return this[\"view\" + ($.camelize(action))]();\n },\n viewHooks: function() {\n this.connectTab('hooks');\n return this.set('hooks', Travis.Hook.find({\n owner_name: this.get('params.login') || Travis.app.get('currentUser.login')\n }));\n },\n viewUser: function() {\n return this.connectTab('user');\n },\n connectTab: function(tab) {\n var viewClass;\n viewClass = Travis[\"\" + ($.camelize(tab)) + \"View\"];\n this.set('tab', tab);\n return this.connectOutlet({\n outletName: 'pane',\n controller: this,\n viewClass: viewClass\n });\n },\n setParams: function(params) {\n var key, value, _results;\n this.set('params', {});\n _results = [];\n for (key in params) {\n value = params[key];\n _results.push(this.set(\"params.\" + key, params[key]));\n }\n return _results;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers/profile");minispade.register('controllers/repositories', "(function() {(function() {\n\n Travis.RepositoriesController = Ember.ArrayController.extend({\n defaultTab: 'recent',\n sortProperties: ['sortOrder'],\n init: function() {\n this.activate(this.defaultTab);\n return Ember.run.later(this.updateTimes.bind(this), Travis.INTERVALS.updateTimes);\n },\n updateTimes: function() {\n var content;\n if (content = this.get('content')) {\n content.forEach(function(r) {\n return r.updateTimes();\n });\n }\n return Ember.run.later(this.updateTimes.bind(this), Travis.INTERVALS.updateTimes);\n },\n activate: function(tab, params) {\n this.set('tab', tab);\n return this[\"view\" + ($.camelize(tab))](params);\n },\n viewRecent: function() {\n return this.set('content', Travis.Repository.find());\n },\n viewOwned: function() {\n return this.set('content', Travis.Repository.ownedBy(Travis.app.get('currentUser.login')));\n },\n viewSearch: function(params) {\n return this.set('content', Travis.Repository.search(params.search));\n },\n searchObserver: (function() {\n var search, tab;\n search = this.get('search');\n tab = search ? 'search' : 'recent';\n return this.activate(tab, {\n search: search\n });\n }).observes('search')\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers/repositories");minispade.register('controllers/repository', "(function() {(function() {\n\n Travis.RepositoryController = Travis.Controller.extend({\n bindings: [],\n init: function() {\n this._super.apply(this, arguments);\n return Ember.run.later(this.updateTimes.bind(this), Travis.INTERVALS.updateTimes);\n },\n updateTimes: function() {\n var build, builds;\n if (builds = this.get('builds')) {\n builds.forEach(function(b) {\n return b.updateTimes();\n });\n }\n if (build = this.get('build')) {\n build.updateTimes();\n build.get('jobs').forEach(function(j) {\n return j.updateTimes();\n });\n }\n return Ember.run.later(this.updateTimes.bind(this), Travis.INTERVALS.updateTimes);\n },\n activate: function(action) {\n this._unbind();\n return this[\"view\" + ($.camelize(action))]();\n },\n viewIndex: function() {\n this._bind('repository', 'controllers.repositoriesController.firstObject');\n this._bind('build', 'repository.lastBuild');\n return this.connectTab('current');\n },\n viewCurrent: function() {\n this.connectTab('current');\n return this._bind('build', 'repository.lastBuild');\n },\n viewBuilds: function() {\n this.connectTab('builds');\n return this._bind('builds', 'repository.builds');\n },\n viewPullRequests: function() {\n this.connectTab('pull_requests');\n return this._bind('builds', 'repository.pullRequests');\n },\n viewBranches: function() {\n this.connectTab('branches');\n return this._bind('builds', 'repository.branches');\n },\n viewBuild: function() {\n return this.connectTab('build');\n },\n viewJob: function() {\n this._bind('build', 'job.build');\n return this.connectTab('job');\n },\n repositoryObserver: (function() {\n var repository;\n repository = this.get('repository');\n if (repository) {\n return repository.select();\n }\n }).observes('repository.id'),\n connectTab: function(tab) {\n var name, viewClass;\n name = tab === 'current' ? 'build' : tab;\n viewClass = name === 'builds' || name === 'branches' || name === 'pull_requests' ? Travis.BuildsView : Travis[\"\" + ($.camelize(name)) + \"View\"];\n this.set('tab', tab);\n return this.connectOutlet({\n outletName: 'pane',\n controller: this,\n viewClass: viewClass\n });\n },\n _bind: function(to, from) {\n return this.bindings.push(Ember.oneWay(this, to, from));\n },\n _unbind: function() {\n var binding, _i, _len, _ref;\n _ref = this.bindings;\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n binding = _ref[_i];\n binding.disconnect(this);\n }\n return this.bindings.length = 0;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers/repository");minispade.register('controllers/sidebar', "(function() {(function() {\n\n Travis.reopen({\n SidebarController: Em.ArrayController.extend({\n init: function() {\n this.tickables = [];\n return Travis.Ticker.create({\n target: this,\n interval: Travis.INTERVALS.sponsors\n });\n },\n tick: function() {\n var tickable, _i, _len, _ref, _results;\n _ref = this.tickables;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n tickable = _ref[_i];\n _results.push(tickable.tick());\n }\n return _results;\n }\n }),\n QueuesController: Em.ArrayController.extend(),\n WorkersController: Em.ArrayController.extend({\n groups: (function() {\n var content, groups, host, worker, _i, _len, _ref;\n if (content = this.get('content')) {\n groups = {};\n _ref = content.toArray();\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n worker = _ref[_i];\n host = worker.get('host');\n if (!groups[host]) {\n groups[host] = Em.ArrayProxy.create({\n content: []\n });\n }\n groups[host].pushObject(worker);\n }\n return $.values(groups);\n }\n }).property('content.length')\n }),\n SponsorsController: Em.ArrayController.extend({\n page: 0,\n arrangedContent: (function() {\n return this.get('shuffled').slice(this.start(), this.end());\n }).property('shuffled.length', 'page'),\n shuffled: (function() {\n var content;\n if (content = this.get('content')) {\n return $.shuffle(content);\n } else {\n return [];\n }\n }).property('content.length'),\n tick: function() {\n return this.set('page', this.isLast() ? 0 : this.get('page') + 1);\n },\n pages: (function() {\n var length;\n length = this.get('content.length');\n if (length) {\n return parseInt(length / this.get('perPage') + 1);\n } else {\n return 1;\n }\n }).property('length'),\n isLast: function() {\n return this.get('page') === this.get('pages') - 1;\n },\n start: function() {\n return this.get('page') * this.get('perPage');\n },\n end: function() {\n return this.start() + this.get('perPage');\n }\n })\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers/sidebar");minispade.register('controllers/stats', "(function() {(function() {\n\n Travis.StatsController = Travis.Controller.extend({\n name: 'stats',\n init: function() {\n return this._super('top');\n },\n activate: function(action, params) {}\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=controllers/stats");minispade.register('helpers', "(function() {(function() {\nminispade.require('helpers/handlebars');\nminispade.require('helpers/helpers');\nminispade.require('helpers/urls');\n\n}).call(this);\n\n})();\n//@ sourceURL=helpers");minispade.register('helpers/handlebars', "(function() {(function() {\n var safe;\nminispade.require('ext/ember/bound_helper');\n\n safe = function(string) {\n return new Handlebars.SafeString(string);\n };\n\n Handlebars.registerHelper('tipsy', function(text, tip) {\n return safe('' + text + '');\n });\n\n Handlebars.registerHelper('t', function(key) {\n return safe(I18n.t(key));\n });\n\n Ember.registerBoundHelper('formatTime', function(value, options) {\n return safe(Travis.Helpers.timeAgoInWords(value) || '-');\n });\n\n Ember.registerBoundHelper('formatDuration', function(duration, options) {\n return safe(Travis.Helpers.timeInWords(duration));\n });\n\n Ember.registerBoundHelper('formatCommit', function(commit, options) {\n if (commit) {\n return safe(Travis.Helpers.formatCommit(commit.get('sha'), commit.get('branch')));\n }\n });\n\n Ember.registerBoundHelper('formatSha', function(sha, options) {\n return safe(Travis.Helpers.formatSha(sha));\n });\n\n Ember.registerBoundHelper('pathFrom', function(url, options) {\n return safe(Travis.Helpers.pathFrom(url));\n });\n\n Ember.registerBoundHelper('formatMessage', function(message, options) {\n return safe(Travis.Helpers.formatMessage(message, options));\n });\n\n Ember.registerBoundHelper('formatConfig', function(config, options) {\n return safe(Travis.Helpers.formatConfig(config));\n });\n\n Ember.registerBoundHelper('formatLog', function(log, options) {\n return Travis.Helpers.formatLog(log) || '';\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=helpers/handlebars");minispade.register('helpers/helpers', "(function() {(function() {\nminispade.require('travis/log');\nminispade.require('emoij');\n\n this.Travis.Helpers = {\n compact: function(object) {\n var key, result, value, _ref;\n result = {};\n _ref = object || {};\n for (key in _ref) {\n value = _ref[key];\n if (!$.isEmpty(value)) {\n result[key] = value;\n }\n }\n return result;\n },\n safe: function(string) {\n return new Handlebars.SafeString(string);\n },\n colorForResult: function(result) {\n if (result === 0) {\n return 'green';\n } else {\n if (result === 1) {\n return 'red';\n } else {\n return null;\n }\n }\n },\n formatCommit: function(sha, branch) {\n return Travis.Helpers.formatSha(sha) + (branch ? \" (\" + branch + \")\" : '');\n },\n formatSha: function(sha) {\n return (sha || '').substr(0, 7);\n },\n formatConfig: function(config) {\n var values;\n config = $.only(config, 'rvm', 'gemfile', 'env', 'otp_release', 'php', 'node_js', 'scala', 'jdk', 'python', 'perl');\n values = $.map(config, function(value, key) {\n value = (value && value.join ? value.join(', ') : value) || '';\n return '%@: %@'.fmt($.camelize(key), value);\n });\n if (values.length === 0) {\n return '-';\n } else {\n return values.join(', ');\n }\n },\n formatMessage: function(message, options) {\n message = message || '';\n if (options.short) {\n message = message.split(/\\n/)[0];\n }\n return this._emojize(this._escape(message)).replace(/\\n/g, '
');\n },\n formatLog: function(log) {\n return Travis.Log.filter(log);\n },\n pathFrom: function(url) {\n return (url || '').split('/').pop();\n },\n timeAgoInWords: function(date) {\n return $.timeago.distanceInWords(date);\n },\n durationFrom: function(started, finished) {\n started = started && this._toUtc(new Date(this._normalizeDateString(started)));\n finished = finished ? this._toUtc(new Date(this._normalizeDateString(finished))) : this._nowUtc();\n if (started && finished) {\n return Math.round((finished - started) / 1000);\n } else {\n return 0;\n }\n },\n timeInWords: function(duration) {\n var days, hours, minutes, result, seconds;\n days = Math.floor(duration / 86400);\n hours = Math.floor(duration % 86400 / 3600);\n minutes = Math.floor(duration % 3600 / 60);\n seconds = duration % 60;\n if (days > 0) {\n return 'more than 24 hrs';\n } else {\n result = [];\n if (hours === 1) {\n result.push(hours + ' hr');\n }\n if (hours > 1) {\n result.push(hours + ' hrs');\n }\n if (minutes > 0) {\n result.push(minutes + ' min');\n }\n if (seconds > 0) {\n result.push(seconds + ' sec');\n }\n if (result.length > 0) {\n return result.join(' ');\n } else {\n return '-';\n }\n }\n },\n _normalizeDateString: function(string) {\n if (window.JHW) {\n string = string.replace('T', ' ').replace(/-/g, '/');\n string = string.replace('Z', '').replace(/\\..*$/, '');\n }\n return string;\n },\n _nowUtc: function() {\n return this._toUtc(new Date());\n },\n _toUtc: function(date) {\n return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());\n },\n _emojize: function(text) {\n var emojis;\n emojis = text.match(/:\\S+?:/g);\n if (emojis !== null) {\n $.each(emojis.uniq(), function(ix, emoji) {\n var image, strippedEmoji;\n strippedEmoji = emoji.substring(1, emoji.length - 1);\n if (EmojiDictionary.indexOf(strippedEmoji) !== -1) {\n image = '';\n return text = text.replace(new RegExp(emoji, 'g'), image);\n }\n });\n }\n return text;\n },\n _escape: function(text) {\n return text.replace(/&/g, '&').replace(//g, '>');\n }\n };\n\n}).call(this);\n\n})();\n//@ sourceURL=helpers/helpers");minispade.register('helpers/urls', "(function() {(function() {\n\n this.Travis.Urls = {\n repository: function(slug) {\n return \"/\" + slug;\n },\n builds: function(slug) {\n return \"/\" + slug + \"/builds\";\n },\n pullRequests: function(slug) {\n return \"/\" + slug + \"/pull_requests\";\n },\n branches: function(slug) {\n return \"/\" + slug + \"/branches\";\n },\n build: function(slug, id) {\n return \"/\" + slug + \"/builds/\" + id;\n },\n job: function(slug, id) {\n return \"/\" + slug + \"/jobs/\" + id;\n },\n githubCommit: function(slug, sha) {\n return \"http://github.com/\" + slug + \"/commit/\" + sha;\n },\n githubRepository: function(slug) {\n return \"http://github.com/\" + slug;\n },\n githubWatchers: function(slug) {\n return \"http://github.com/\" + slug + \"/watchers\";\n },\n githubNetwork: function(slug) {\n return \"http://github.com/\" + slug + \"/network\";\n },\n githubAdmin: function(slug) {\n return \"http://github.com/\" + slug + \"/admin/hooks#travis_minibucket\";\n },\n statusImage: function(slug, branch) {\n return (\"https://secure.travis-ci.org/\" + slug + \".png\") + (branch ? \"?branch=\" + branch : '');\n },\n email: function(email) {\n return \"mailto:\" + email;\n },\n account: function(login) {\n return \"/profile/\" + login;\n },\n user: function(login) {\n return \"/profile/\" + login + \"/me\";\n }\n };\n\n}).call(this);\n\n})();\n//@ sourceURL=helpers/urls");minispade.register('models', "(function() {(function() {\nminispade.require('models/extensions');\nminispade.require('models/account');\nminispade.require('models/artifact');\nminispade.require('models/branch');\nminispade.require('models/build');\nminispade.require('models/commit');\nminispade.require('models/hook');\nminispade.require('models/job');\nminispade.require('models/repository');\nminispade.require('models/sponsor');\nminispade.require('models/user');\nminispade.require('models/worker');\n\n}).call(this);\n\n})();\n//@ sourceURL=models");minispade.register('models/account', "(function() {(function() {\nminispade.require('travis/model');\n\n this.Travis.Account = Travis.Model.extend({\n primaryKey: 'login',\n login: DS.attr('string'),\n name: DS.attr('string'),\n type: DS.attr('string'),\n reposCount: DS.attr('number'),\n urlGithub: (function() {\n return \"http://github.com/\" + (this.get('login'));\n }).property()\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/account");minispade.register('models/artifact', "(function() {(function() {\nminispade.require('travis/model');\n\n this.Travis.Artifact = Travis.Model.extend({\n body: DS.attr('string'),\n init: function() {\n this._super.apply(this, arguments);\n return this.set('queue', Ember.A([]));\n },\n append: function(body) {\n if (this.get('isLoaded')) {\n return this.set('body', this.get('body') + body);\n } else {\n return this.get('queue').pushObject(body);\n }\n },\n recordDidLoad: (function() {\n var queue;\n if (this.get('isLoaded')) {\n queue = this.get('queue');\n if (queue.get('length') > 0) {\n return this.append(queue.toArray().join(''));\n }\n }\n }).observes('isLoaded')\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/artifact");minispade.register('models/branch', "(function() {(function() {\nminispade.require('travis/model');\n\n this.Travis.Branch = Travis.Model.extend(Travis.Helpers, {\n repositoryId: DS.attr('number'),\n commitId: DS.attr('number'),\n number: DS.attr('number'),\n branch: DS.attr('string'),\n message: DS.attr('string'),\n result: DS.attr('number'),\n duration: DS.attr('number'),\n startedAt: DS.attr('string'),\n finishedAt: DS.attr('string'),\n commit: DS.belongsTo('Travis.Commit'),\n repository: (function() {\n if (this.get('repositoryId')) {\n return Travis.Repository.find(this.get('repositoryId'));\n }\n }).property('repositoryId'),\n updateTimes: function() {\n this.notifyPropertyChange('started_at');\n return this.notifyPropertyChange('finished_at');\n }\n });\n\n this.Travis.Branch.reopenClass({\n byRepositoryId: function(id) {\n return this.find({\n repository_id: id\n });\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/branch");minispade.register('models/build', "(function() {(function() {\nminispade.require('travis/model');\n\n this.Travis.Build = Travis.Model.extend(Travis.DurationCalculations, {\n eventType: DS.attr('string'),\n repositoryId: DS.attr('number'),\n commitId: DS.attr('number'),\n state: DS.attr('string'),\n number: DS.attr('number'),\n branch: DS.attr('string'),\n message: DS.attr('string'),\n result: DS.attr('number'),\n _duration: DS.attr('number', {\n key: 'duration'\n }),\n startedAt: DS.attr('string', {\n key: 'started_at'\n }),\n finishedAt: DS.attr('string', {\n key: 'finished_at'\n }),\n repository: DS.belongsTo('Travis.Repository'),\n commit: DS.belongsTo('Travis.Commit'),\n jobs: DS.hasMany('Travis.Job', {\n key: 'job_ids'\n }),\n config: (function() {\n return Travis.Helpers.compact(this.get('data.config'));\n }).property('data.config'),\n isMatrix: (function() {\n return this.get('data.job_ids.length') > 1;\n }).property('data.job_ids.length'),\n requiredJobs: (function() {\n return this.get('jobs').filter(function(data) {\n return !data.get('allowFailure');\n });\n }).property('jobs.@each.allowFailure'),\n allowedFailureJobs: (function() {\n return this.get('jobs').filter(function(data) {\n return data.get('allowFailure');\n });\n }).property('jobs.@each.allowFailure'),\n configKeys: (function() {\n var config, headers, key, keys;\n if (!(config = this.get('config'))) {\n return [];\n }\n keys = $.intersect($.keys(config), Travis.CONFIG_KEYS);\n headers = (function() {\n var _i, _len, _ref, _results;\n _ref = ['build.job', 'build.duration', 'build.finished_at'];\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n key = _ref[_i];\n _results.push(I18n.t(key));\n }\n return _results;\n })();\n return $.map(headers.concat(keys), function(key) {\n return $.camelize(key);\n });\n }).property('config')\n });\n\n this.Travis.Build.reopenClass({\n byRepositoryId: function(id, parameters) {\n return this.find($.extend(parameters || {}, {\n repository_id: id,\n orderBy: 'number DESC'\n }));\n },\n olderThanNumber: function(id, build_number) {\n return this.find({\n url: \"/builds\",\n repository_id: id,\n after_number: build_number\n });\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/build");minispade.register('models/commit', "(function() {(function() {\nminispade.require('travis/model');\n\n this.Travis.Commit = Travis.Model.extend({\n buildId: DS.attr('number'),\n sha: DS.attr('string'),\n branch: DS.attr('string'),\n message: DS.attr('string'),\n compareUrl: DS.attr('string'),\n authorName: DS.attr('string'),\n authorEmail: DS.attr('string'),\n committerName: DS.attr('string'),\n committerEmail: DS.attr('string'),\n build: DS.belongsTo('Travis.Build', {\n key: 'buildId'\n })\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/commit");minispade.register('models/extensions', "(function() {(function() {\n\n Travis.DurationCalculations = Ember.Mixin.create({\n duration: (function() {\n var duration;\n if (duration = this.get('_duration')) {\n return duration;\n } else {\n return Travis.Helpers.durationFrom(this.get('startedAt'), this.get('finishedAt'));\n }\n }).property('_duration', 'finishedAt', 'startedAt'),\n updateTimes: function() {\n this.notifyPropertyChange('_duration');\n return this.notifyPropertyChange('finished_at');\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/extensions");minispade.register('models/hook', "(function() {(function() {\nminispade.require('travis/model');\n\n this.Travis.Hook = Travis.Model.extend({\n name: DS.attr('string'),\n ownerName: DS.attr('string'),\n description: DS.attr('string'),\n active: DS.attr('boolean'),\n account: (function() {\n return this.get('slug').split('/')[0];\n }).property('slug'),\n slug: (function() {\n return \"\" + (this.get('ownerName')) + \"/\" + (this.get('name'));\n }).property('ownerName', 'name'),\n urlGithub: (function() {\n return \"http://github.com/\" + (this.get('slug'));\n }).property(),\n urlGithubAdmin: (function() {\n return \"http://github.com/\" + (this.get('slug')) + \"/admin/hooks#travis_minibucket\";\n }).property(),\n toggle: function() {\n var transaction;\n transaction = this.get('store').transaction();\n transaction.add(this);\n this.set('active', !this.get('active'));\n return transaction.commit();\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/hook");minispade.register('models/job', "(function() {(function() {\nminispade.require('travis/model');\n\n this.Travis.Job = Travis.Model.extend(Travis.DurationCalculations, {\n repositoryId: DS.attr('number'),\n buildId: DS.attr('number'),\n commitId: DS.attr('number'),\n logId: DS.attr('number'),\n queue: DS.attr('string'),\n state: DS.attr('string'),\n number: DS.attr('string'),\n result: DS.attr('number'),\n _duration: DS.attr('number', {\n key: 'duration'\n }),\n startedAt: DS.attr('string'),\n finishedAt: DS.attr('string'),\n allowFailure: DS.attr('boolean', {\n key: 'allow_failure'\n }),\n repository: DS.belongsTo('Travis.Repository', {\n key: 'repository_id'\n }),\n build: DS.belongsTo('Travis.Build', {\n key: 'build_id'\n }),\n commit: DS.belongsTo('Travis.Commit', {\n key: 'commit_id'\n }),\n log: DS.belongsTo('Travis.Artifact', {\n key: 'log_id'\n }),\n isQueued: (function() {}).property('state'),\n config: (function() {\n return Travis.Helpers.compact(this.get('data.config'));\n }).property('data.config'),\n sponsor: (function() {\n return this.get('data.sponsor');\n }).property('data.sponsor'),\n configValues: (function() {\n var config;\n if (config = this.get('config')) {\n return $.values($.only.apply(config, Travis.CONFIG_KEYS));\n } else {\n return [];\n }\n }).property('config'),\n appendLog: function(text) {\n var log;\n if (log = this.get('log')) {\n return log.append(text);\n }\n },\n subscribe: function() {\n var id;\n if (id = this.get('id')) {\n return Travis.app.pusher.subscribe(\"job-\" + id);\n }\n },\n onStateChange: (function() {\n if (this.get('state') === 'finished') {\n return Travis.app.pusher.unsubscribe(\"job-\" + (this.get('id')));\n }\n }).observes('state')\n });\n\n this.Travis.Job.reopenClass({\n queued: function(queue) {\n this.find();\n return Travis.app.store.filter(this, function(job) {\n var queued;\n queued = ['created', 'queued'].indexOf(job.get('state')) !== -1;\n return queued && job.get('queue') === (\"builds.\" + queue);\n });\n },\n findMany: function(ids) {\n return Travis.app.store.findMany(this, ids);\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/job");minispade.register('models/repository', "(function() {(function() {\nminispade.require('travis/expandable_record_array');\nminispade.require('travis/model');\n\n this.Travis.Repository = Travis.Model.extend({\n slug: DS.attr('string'),\n description: DS.attr('string'),\n lastBuildId: DS.attr('number'),\n lastBuildNumber: DS.attr('string'),\n lastBuildResult: DS.attr('number'),\n lastBuildStartedAt: DS.attr('string'),\n lastBuildFinishedAt: DS.attr('string'),\n lastBuild: DS.belongsTo('Travis.Build'),\n builds: (function() {\n var array, builds, id;\n id = this.get('id');\n builds = Travis.Build.byRepositoryId(id, {\n event_type: 'push'\n });\n array = Travis.ExpandableRecordArray.create({\n type: Travis.Build,\n content: Ember.A([]),\n store: this.get('store')\n });\n array.load(builds);\n return array;\n }).property(),\n pullRequests: (function() {\n var array, builds, id;\n id = this.get('id');\n builds = Travis.Build.byRepositoryId(id, {\n event_type: 'pull_request'\n });\n array = Travis.ExpandableRecordArray.create({\n type: Travis.Build,\n content: Ember.A([]),\n store: this.get('store')\n });\n array.load(builds);\n return array;\n }).property(),\n branches: (function() {\n return Travis.Branch.byRepositoryId(this.get('id'));\n }).property(),\n owner: (function() {\n return (this.get('slug') || '').split('/')[0];\n }).property('slug'),\n name: (function() {\n return (this.get('slug') || '').split('/')[1];\n }).property('slug'),\n lastBuildDuration: (function() {\n var duration;\n duration = this.get('data.last_build_duration');\n if (!duration) {\n duration = Travis.Helpers.durationFrom(this.get('lastBuildStartedAt'), this.get('lastBuildFinishedAt'));\n }\n return duration;\n }).property('data.last_build_duration', 'lastBuildStartedAt', 'lastBuildFinishedAt'),\n sortOrder: (function() {\n var lastBuildFinishedAt;\n if (lastBuildFinishedAt = this.get('lastBuildFinishedAt')) {\n return -new Date(lastBuildFinishedAt).getTime();\n } else {\n return -new Date('9999').getTime() - parseInt(this.get('lastBuildId'));\n }\n }).property('lastBuildFinishedAt', 'lastBuildId'),\n stats: (function() {\n var _this = this;\n return this.get('_stats') || $.get(\"https://api.github.com/repos/\" + (this.get('slug')), function(data) {\n _this.set('_stats', data);\n return _this.notifyPropertyChange('stats');\n }) && {};\n }).property(),\n select: function() {\n return Travis.Repository.select(this.get('id'));\n },\n updateTimes: function() {\n return this.notifyPropertyChange('lastBuildDuration');\n }\n });\n\n this.Travis.Repository.reopenClass({\n recent: function() {\n return this.find();\n },\n ownedBy: function(login) {\n return this.find({\n owner_name: login,\n orderBy: 'name'\n });\n },\n search: function(query) {\n return this.find({\n search: query,\n orderBy: 'name'\n });\n },\n bySlug: function(slug) {\n var repo;\n repo = $.select(this.find().toArray(), function(repo) {\n return repo.get('slug') === slug;\n });\n if (repo.length > 0) {\n return repo;\n } else {\n return this.find({\n slug: slug\n });\n }\n },\n select: function(id) {\n return this.find().forEach(function(repository) {\n return repository.set('selected', repository.get('id') === id);\n });\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/repository");minispade.register('models/sponsor', "(function() {(function() {\nminispade.require('travis/model');\n\n this.Travis.Sponsor = Travis.Model.extend({\n type: DS.attr('string'),\n url: DS.attr('string'),\n link: DS.attr('string'),\n image: (function() {\n return \"/images/sponsors/\" + (this.get('data.image'));\n }).property('data.image')\n });\n\n Travis.Sponsor.reopenClass({\n decks: function() {\n return this.platinum().concat(this.gold());\n },\n platinum: function() {\n var platinum, sponsor, _i, _len, _results;\n platinum = this.byType('platinum').toArray();\n _results = [];\n for (_i = 0, _len = platinum.length; _i < _len; _i++) {\n sponsor = platinum[_i];\n _results.push([sponsor]);\n }\n return _results;\n },\n gold: function() {\n var gold, _results;\n gold = this.byType('gold').toArray();\n _results = [];\n while (gold.length > 0) {\n _results.push(gold.splice(0, 2));\n }\n return _results;\n },\n links: function() {\n return this.byType('silver');\n },\n byType: function() {\n var types;\n types = Array.prototype.slice.apply(arguments);\n return Travis.Sponsor.filter(function(sponsor) {\n return types.indexOf(sponsor.get('type')) !== -1;\n });\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/sponsor");minispade.register('models/user', "(function() {(function() {\nminispade.require('travis/ajax');\nminispade.require('travis/model');\n\n this.Travis.User = Travis.Model.extend(Travis.Ajax, {\n name: DS.attr('string'),\n email: DS.attr('string'),\n login: DS.attr('string'),\n token: DS.attr('string'),\n locale: DS.attr('string'),\n gravatarId: DS.attr('string'),\n isSyncing: DS.attr('boolean'),\n syncedAt: DS.attr('string'),\n repoCount: DS.attr('number'),\n init: function() {\n if (this.get('isSyncing')) {\n this.poll();\n }\n this._super();\n return Ember.run.next(this, function() {\n var transaction;\n transaction = this.get('store').transaction();\n return transaction.add(this);\n });\n },\n urlGithub: (function() {\n return \"https://github.com/\" + (this.get('login'));\n }).property(),\n updateLocale: function(locale) {\n var observer, self, transaction;\n this.setWithSession('locale', locale);\n transaction = this.get('transaction');\n transaction.commit();\n self = this;\n observer = function() {\n if (!self.get('isSaving')) {\n self.removeObserver('isSaving', observer);\n transaction = self.get('store').transaction();\n return transaction.add(self);\n }\n };\n return this.addObserver('isSaving', observer);\n },\n type: (function() {\n return 'user';\n }).property(),\n sync: function() {\n this.post('/users/sync');\n this.setWithSession('isSyncing', true);\n return this.poll();\n },\n poll: function() {\n var _this = this;\n return this.ajax('/users', 'get', {\n success: function(data) {\n if (data.user.is_syncing) {\n return Ember.run.later(_this, _this.poll.bind(_this), 3000);\n } else {\n _this.set('isSyncing', false);\n return _this.setWithSession('syncedAt', data.user.synced_at);\n }\n }\n });\n },\n setWithSession: function(name, value) {\n var user;\n this.set(name, value);\n user = JSON.parse(typeof sessionStorage !== \"undefined\" && sessionStorage !== null ? sessionStorage.getItem('travis.user') : void 0);\n user[$.underscore(name)] = this.get(name);\n return typeof sessionStorage !== \"undefined\" && sessionStorage !== null ? sessionStorage.setItem('travis.user', JSON.stringify(user)) : void 0;\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/user");minispade.register('models/worker', "(function() {(function() {\nminispade.require('travis/model');\n\n this.Travis.Worker = Travis.Model.extend({\n state: DS.attr('string'),\n name: DS.attr('string'),\n host: DS.attr('string'),\n lastSeenAt: DS.attr('string'),\n payload: (function() {\n return this.get('data.payload');\n }).property('data.payload'),\n number: (function() {\n return this.get('name').match(/\\d+$/)[0];\n }).property('name'),\n isWorking: (function() {\n return this.get('state') === 'working';\n }).property('state'),\n repository: (function() {\n return Travis.Repository.find(this.get('payload.repository.id'));\n }).property('payload.repository.id'),\n job_id: (function() {\n return this.get('payload.job.id');\n }).property('payload.job.id'),\n job: (function() {\n return Travis.Job.find(this.get('job_id'));\n }).property('job_id')\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=models/worker");minispade.register('pusher', "(function() {(function() {\n\n Travis.Pusher = function(config) {\n if (config) {\n this.init(config);\n }\n return this;\n };\n\n $.extend(Travis.Pusher, {\n CHANNELS: ['common'],\n CHANNEL_PREFIX: ''\n });\n\n $.extend(Travis.Pusher.prototype, {\n active_channels: [],\n init: function(config) {\n var channel, _i, _len, _ref, _results;\n Pusher.warn = this.warn.bind(this);\n this.pusher = new Pusher(config.key);\n _ref = Travis.Pusher.CHANNELS;\n _results = [];\n for (_i = 0, _len = _ref.length; _i < _len; _i++) {\n channel = _ref[_i];\n _results.push(this.subscribe(channel));\n }\n return _results;\n },\n subscribe: function(channel) {\n var _this = this;\n if (this.pusher && this.active_channels.indexOf(channel) === -1) {\n this.active_channels.push(channel);\n return this.pusher.subscribe(this.prefix(channel)).bind_all(function(event, data) {\n return _this.receive(event, data);\n });\n }\n },\n unsubscribe: function(channel) {\n var ix;\n ix = this.active_channels.indexOf(channel);\n if (this.pusher && ix === -1) {\n this.active_channels.splice(ix, 1);\n return this.pusher.unsubscribe(this.prefix(channel));\n }\n },\n prefix: function(channel) {\n return \"\" + Travis.Pusher.CHANNEL_PREFIX + channel;\n },\n receive: function(event, data) {\n if (event.substr(0, 6) === 'pusher') {\n return;\n }\n if (data.id) {\n data = this.normalize(event, data);\n }\n return Ember.run.next(function() {\n return Travis.app.store.receive(event, data);\n });\n },\n normalize: function(event, data) {\n switch (event) {\n case 'build:started':\n case 'build:finished':\n return data;\n case 'job:created':\n case 'job:started':\n case 'job:finished':\n case 'job:log':\n if (data.queue) {\n data.queue = data.queue.replace('builds.', '');\n }\n return {\n job: data\n };\n case 'worker:added':\n case 'worker:updated':\n case 'worker:removed':\n return {\n worker: data\n };\n }\n },\n warn: function(type, warning) {\n if (!this.ignoreWarning(warning)) {\n return console.warn(warning);\n }\n },\n ignoreWarning: function(warning) {\n var message, _ref;\n if (message = (_ref = warning.data) != null ? _ref.message : void 0) {\n return message.indexOf('Existing subscription') === 0 || message.indexOf('No current subscription') === 0;\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=pusher");minispade.register('routes', "(function() {(function() {\n\n Travis.Router = Ember.Router.extend({\n location: 'history',\n enableLogging: true,\n initialState: 'loading',\n goToRoot: Ember.Route.transitionTo('root.home.show'),\n goToStats: Ember.Route.transitionTo('root.stats'),\n showRepository: Ember.Route.transitionTo('root.home.repository.show'),\n showBuilds: Ember.Route.transitionTo('root.home.repository.builds.index'),\n showBuild: Ember.Route.transitionTo('root.home.repository.builds.show'),\n showPullRequests: Ember.Route.transitionTo('root.home.repository.pullRequests'),\n showBranches: Ember.Route.transitionTo('root.home.repository.branches'),\n showJob: Ember.Route.transitionTo('root.home.repository.job'),\n showProfile: Ember.Route.transitionTo('root.profile'),\n showAccount: Ember.Route.transitionTo('root.profile.account'),\n showUserProfile: Ember.Route.transitionTo('root.profile.account.profile'),\n signedIn: function() {\n return !!Travis.app.get('auth.user');\n },\n requiresAuth: function(path) {\n return path === '/profile' && !this.signedIn();\n },\n loading: Ember.Route.extend({\n routePath: function(router, path) {\n router.set('lastAttemptedPath', path);\n if (router.requiresAuth(path)) {\n return router.send('showUnauthenticated');\n } else {\n return router.send('showAuthenticated');\n }\n }\n }),\n showUnauthenticated: Ember.State.transitionTo('root.home.show'),\n showAuthenticated: Ember.State.transitionTo('authenticated.index'),\n authenticated: Ember.Route.extend({\n index: Ember.Route.extend({\n connectOutlets: function(router) {\n var path;\n router.transitionTo('root');\n path = router.get('lastAttemptedPath');\n if (path && path !== '/') {\n return router.route(path);\n }\n }\n })\n }),\n root: Ember.Route.extend({\n initialState: 'home',\n loading: Ember.State.extend(),\n stats: Ember.Route.extend({\n route: '/stats',\n connectOutlets: function(router) {\n router.get('applicationController').connectOutlet('statsLayout');\n $('body').attr('id', 'stats');\n router.get('statsLayoutController').connectOutlet('top', 'top');\n return router.get('statsLayoutController').connectOutlet('main', 'stats');\n }\n }),\n profile: Ember.Route.extend({\n initialState: 'index',\n route: '/profile',\n connectOutlets: function(router) {\n router.get('applicationController').connectOutlet('profileLayout');\n $('body').attr('id', 'profile');\n router.get('accountsController').set('content', Travis.Account.find());\n router.get('profileLayoutController').connectOutlet('top', 'top');\n return router.get('profileLayoutController').connectOutlet('left', 'accounts');\n },\n index: Ember.Route.extend({\n route: '/',\n connectOutlets: function(router) {\n router.get('profileLayoutController').connectOutlet('main', 'profile');\n return router.get('profileController').activate('hooks');\n }\n }),\n account: Ember.Route.extend({\n initialState: 'index',\n route: '/:login',\n connectOutlets: function(router, account) {\n var params;\n if (account) {\n params = {\n login: account.get('login')\n };\n return router.get('profileController').setParams(params);\n } else {\n return router.send('showProfile');\n }\n },\n deserialize: function(router, params) {\n return router.get('accountsController').findByLogin(params.login);\n },\n serialize: function(router, account) {\n if (account) {\n return {\n login: account.get('login')\n };\n } else {\n return {};\n }\n },\n index: Ember.Route.extend({\n route: '/',\n connectOutlets: function(router) {\n return router.get('profileController').activate('hooks');\n }\n }),\n profile: Ember.Route.extend({\n route: '/profile',\n connectOutlets: function(router) {\n return router.get('profileController').activate('user');\n }\n })\n })\n }),\n home: Ember.Route.extend({\n initialState: 'show',\n route: '/',\n connectOutlets: function(router) {\n router.get('applicationController').connectOutlet('home');\n $('body').attr('id', 'home');\n router.get('homeController').connectOutlet('left', 'repositories');\n router.get('homeController').connectOutlet('right', 'sidebar');\n router.get('homeController').connectOutlet('top', 'top');\n return router.get('homeController').connectOutlet('main', 'repository');\n },\n show: Ember.Route.extend({\n route: '/',\n connectOutlets: function(router) {\n return router.get('repositoryController').activate('index');\n }\n }),\n repository: Ember.Route.extend({\n initialState: 'show',\n route: '/:owner/:name',\n connectOutlets: function(router, repository) {\n return router.get('repositoryController').set('repository', repository);\n },\n deserialize: function(router, params) {\n var deferred, observer, repos, slug;\n slug = \"\" + params.owner + \"/\" + params.name;\n repos = Travis.Repository.bySlug(slug);\n deferred = $.Deferred();\n observer = function() {\n if (repos.get('isLoaded')) {\n repos.removeObserver('isLoaded', observer);\n return deferred.resolve(repos.objectAt(0));\n }\n };\n repos.addObserver('isLoaded', observer);\n return deferred.promise();\n },\n serialize: function(router, repository) {\n if (repository) {\n return {\n owner: repository.get('owner'),\n name: repository.get('name')\n };\n } else {\n return {};\n }\n },\n show: Ember.Route.extend({\n route: '/',\n connectOutlets: function(router) {\n return router.get('repositoryController').activate('current');\n }\n }),\n builds: Ember.Route.extend({\n route: '/builds',\n initialState: 'index',\n index: Ember.Route.extend({\n route: '/',\n connectOutlets: function(router, repository) {\n return router.get('repositoryController').activate('builds');\n }\n }),\n show: Ember.Route.extend({\n route: '/:build_id',\n connectOutlets: function(router, build) {\n if (!build.get) {\n build = Travis.Build.find(build);\n }\n router.get('repositoryController').set('build', build);\n return router.get('repositoryController').activate('build');\n },\n serialize: function(router, build) {\n if (build.get) {\n return {\n build_id: build.get('id')\n };\n } else {\n return {\n build_id: build\n };\n }\n },\n deserialize: function(router, params) {\n var build, deferred, observer;\n build = Travis.Build.find(params.build_id);\n deferred = $.Deferred();\n observer = function() {\n if (build.get('id')) {\n build.removeObserver('id', observer);\n return deferred.resolve(build);\n }\n };\n build.addObserver('id', observer);\n return deferred.promise();\n }\n })\n }),\n pullRequests: Ember.Route.extend({\n route: '/pull_requests',\n connectOutlets: function(router, repository) {\n return router.get('repositoryController').activate('pull_requests');\n }\n }),\n branches: Ember.Route.extend({\n route: '/branches',\n connectOutlets: function(router, repository) {\n return router.get('repositoryController').activate('branches');\n }\n }),\n job: Ember.Route.extend({\n route: '/jobs/:job_id',\n connectOutlets: function(router, job) {\n if (!job.get) {\n job = Travis.Job.find(job);\n }\n router.get('repositoryController').set('job', job);\n return router.get('repositoryController').activate('job');\n },\n serialize: function(router, job) {\n if (job.get) {\n return {\n job_id: job.get('id')\n };\n } else {\n return {\n job_id: job\n };\n }\n },\n deserialize: function(router, params) {\n var deferred, job, observer;\n job = Travis.Job.find(params.job_id);\n deferred = $.Deferred();\n observer = function() {\n if (job.get('id')) {\n job.removeObserver('id', observer);\n return deferred.resolve(job);\n }\n };\n job.addObserver('id', observer);\n return deferred.promise();\n }\n })\n })\n })\n })\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=routes");minispade.register('slider', "(function() {(function() {\n\n this.Travis.Slider = function() {\n if ((typeof localStorage !== \"undefined\" && localStorage !== null ? localStorage.getItem('travis.maximized') : void 0) === 'true') {\n this.minimize();\n }\n return this;\n };\n\n $.extend(Travis.Slider.prototype, {\n persist: function() {\n return typeof localStorage !== \"undefined\" && localStorage !== null ? localStorage.setItem('travis.maximized', this.isMinimized()) : void 0;\n },\n isMinimized: function() {\n return $('body').hasClass('maximized');\n },\n minimize: function() {\n return $('body').addClass('maximized');\n },\n toggle: function() {\n var element;\n $('body').toggleClass('maximized');\n this.persist();\n element = $('');\n $('#top .profile').append(element);\n return Em.run.later((function() {\n return element.remove();\n }), 10);\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=slider");minispade.register('store', "(function() {(function() {\n var DATA_PROXY,\n __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };\nminispade.require('store/rest_adapter');\n\n DATA_PROXY = {\n get: function(name) {\n return this.savedData[name];\n }\n };\n\n Travis.Store = DS.Store.extend({\n revision: 4,\n adapter: Travis.RestAdapter.create(),\n merge: function(type, id, hash) {\n var clientId, data, dataCache, primaryKey, record, recordCache, typeMap;\n if (hash === void 0) {\n hash = id;\n primaryKey = type.proto().primaryKey;\n Ember.assert(\"A data hash was loaded for a record of type \" + type.toString() + \" but no primary key '\" + primaryKey + \"' was provided.\", hash[primaryKey]);\n id = hash[primaryKey];\n }\n typeMap = this.typeMapFor(type);\n dataCache = typeMap.cidToHash;\n clientId = typeMap.idToCid[id];\n recordCache = this.get('recordCache');\n if (clientId !== void 0) {\n if (data = dataCache[clientId]) {\n $.extend(data, hash);\n } else {\n dataCache[clientId] = hash;\n }\n if (record = recordCache[clientId]) {\n record.send('didChangeData');\n }\n } else {\n clientId = this.find(type, id).get('clientId');\n }\n if (clientId) {\n DATA_PROXY.savedData = hash;\n this.updateRecordArrays(type, clientId, DATA_PROXY);\n return {\n id: id,\n clientId: clientId\n };\n }\n },\n receive: function(event, data) {\n var job, mappings, name, type, _ref;\n _ref = event.split(':'), name = _ref[0], type = _ref[1];\n mappings = this.adapter.get('mappings');\n type = mappings[name];\n if (event === 'job:log') {\n if (job = this.find(Travis.Job, data['job']['id'])) {\n return job.appendLog(data['job']['_log']);\n }\n } else if (data[type.singularName()]) {\n return this._loadOne(this, type, data);\n } else if (data[type.pluralName()]) {\n return this._loadMany(this, type, data);\n } else {\n if (!type) {\n throw \"can't load data for \" + name;\n }\n }\n },\n _loadOne: function(store, type, json) {\n var root;\n root = type.singularName();\n this.adapter.sideload(store, type, json, root);\n this.merge(type, json[root]);\n return this._updateAssociations(type, root, json[root]);\n },\n _loadMany: function(store, type, json) {\n var root;\n root = type.pluralName();\n this.adapter.sideload(store, type, json, root);\n return this.loadMany(type, json[root]);\n },\n _updateAssociations: function(type, name, data) {\n var _this = this;\n return Em.get(type, 'associationsByName').forEach(function(key, meta) {\n var clientId, dataProxy, id, ids, parent, _ref;\n if (meta.kind === 'belongsTo') {\n id = data[\"\" + key + \"_id\"];\n if (clientId = _this.typeMapFor(meta.type).idToCid[id]) {\n if (parent = _this.findByClientId(meta.type, clientId, id)) {\n dataProxy = parent.get('data');\n if (ids = dataProxy.get(\"\" + name + \"_ids\")) {\n if (_ref = data.id, __indexOf.call(ids, _ref) < 0) {\n ids.pushObject(data.id);\n }\n return parent.send('didChangeData');\n }\n }\n }\n }\n });\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=store");minispade.register('store/fixture_adapter', "(function() {(function() {\n\n this.Travis.FixtureAdapter = DS.Adapter.extend({\n find: function(store, type, id) {\n var fixtures;\n fixtures = type.FIXTURES;\n Ember.assert(\"Unable to find fixtures for model type \" + type.toString(), !!fixtures);\n if (fixtures.hasLoaded) {\n return;\n }\n return setTimeout((function() {\n store.loadMany(type, fixtures);\n return fixtures.hasLoaded = true;\n }), 300);\n },\n findMany: function() {\n return this.find.apply(this, arguments);\n },\n findAll: function(store, type) {\n var fixtures, ids;\n fixtures = type.FIXTURES;\n Ember.assert(\"Unable to find fixtures for model type \" + type.toString(), !!fixtures);\n ids = fixtures.map(function(item, index, self) {\n return item.id;\n });\n return store.loadMany(type, ids, fixtures);\n },\n findQuery: function(store, type, params, array) {\n var fixture, fixtures, hashes, key, matches, value;\n fixtures = type.FIXTURES;\n Ember.assert(\"Unable to find fixtures for model type \" + type.toString(), !!fixtures);\n hashes = (function() {\n var _i, _len, _results;\n _results = [];\n for (_i = 0, _len = fixtures.length; _i < _len; _i++) {\n fixture = fixtures[_i];\n matches = (function() {\n var _results1;\n _results1 = [];\n for (key in params) {\n value = params[key];\n _results1.push(key === 'orderBy' || fixture[key] === value);\n }\n return _results1;\n })();\n if (matches.reduce(function(a, b) {\n return a && b;\n })) {\n _results.push(fixture);\n } else {\n _results.push(null);\n }\n }\n return _results;\n })();\n return array.load(hashes.compact());\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=store/fixture_adapter");minispade.register('store/rest_adapter', "(function() {(function() {\nminispade.require('travis/ajax');\nminispade.require('models');\n\n this.Travis.RestAdapter = DS.RESTAdapter.extend(Travis.Ajax, {\n mappings: {\n repositories: Travis.Repository,\n repository: Travis.Repository,\n builds: Travis.Build,\n build: Travis.Build,\n commits: Travis.Commit,\n commit: Travis.Commit,\n jobs: Travis.Job,\n job: Travis.Job,\n account: Travis.Account,\n accounts: Travis.Account,\n worker: Travis.Worker,\n workers: Travis.Worker\n },\n plurals: {\n repository: 'repositories',\n build: 'builds',\n branch: 'branches',\n job: 'jobs',\n worker: 'workers',\n profile: 'profile'\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=store/rest_adapter");minispade.register('tailing', "(function() {(function() {\n\n this.Travis.Tailing = function() {\n this.position = $(window).scrollTop();\n $(window).scroll(this.onScroll.bind(this));\n return this;\n };\n\n $.extend(Travis.Tailing.prototype, {\n options: {\n timeout: 200\n },\n run: function() {\n this.autoScroll();\n this.positionButton();\n if (this.active()) {\n return Ember.run.later(this.run.bind(this), this.options.timeout);\n }\n },\n toggle: function(event) {\n if (this.active()) {\n return this.stop();\n } else {\n return this.start();\n }\n },\n active: function() {\n return $('#tail').hasClass('active');\n },\n start: function() {\n $('#tail').addClass('active');\n return this.run();\n },\n stop: function() {\n return $('#tail').removeClass('active');\n },\n autoScroll: function() {\n var log, logBottom, win, winBottom;\n if (!this.active()) {\n return;\n }\n win = $(window);\n log = $('#log');\n logBottom = log.offset().top + log.outerHeight() + 40;\n winBottom = win.scrollTop() + win.height();\n if (logBottom - winBottom > 0) {\n return win.scrollTop(logBottom - win.height());\n }\n },\n onScroll: function() {\n var position;\n this.positionButton();\n position = $(window).scrollTop();\n if (position < this.position) {\n this.stop();\n }\n return this.position = position;\n },\n positionButton: function() {\n var max, offset, tail;\n tail = $('#tail');\n if (tail.length === 0) {\n return;\n }\n offset = $(window).scrollTop() - $('#log').offset().top;\n max = $('#log').height() - $('#tail').height() + 5;\n if (offset > max) {\n offset = max;\n }\n if (offset > 0) {\n return tail.css({\n top: offset - 2\n });\n } else {\n return tail.css({\n top: 0\n });\n }\n }\n });\n\n}).call(this);\n\n})();\n//@ sourceURL=tailing");minispade.register('views', "(function() {(function() {\nminispade.require('ext/ember/namespace');\n\n this.Travis.reopen({\n View: Em.View.extend({\n popup: function(event) {\n return $(\"#\" + event.target.name).toggleClass('display');\n }\n })\n });\n\n this.Travis.reopen({\n HomeView: Travis.View.extend({\n templateName: 'layouts/home'\n }),\n ProfileLayoutView: Travis.View.extend({\n templateName: 'layouts/profile'\n }),\n StatsLayoutView: Travis.View.extend({\n templateName: 'layouts/simple'\n }),\n ApplicationView: Travis.View.extend({\n templateName: 'application'\n })\n });\nminispade.require('views/accounts');\nminispade.require('views/build');\nminispade.require('views/job');\nminispade.require('views/repo');\nminispade.require('views/profile');\nminispade.require('views/sidebar');\nminispade.require('views/stats');\nminispade.require('views/top');\n\n}).call(this);\n\n})();\n//@ sourceURL=views");minispade.register('views/accounts', "(function() {(function() {\n\n this.Travis.reopen({\n AccountsView: Travis.View.extend({\n tabBinding: 'controller.tab',\n templateName: 'profile/accounts',\n classAccounts: (function() {\n if (this.get('tab') === 'accounts') {\n return 'active';\n }\n }).property('tab')\n }),\n AccountsListView: Em.CollectionView.extend({\n elementId: 'accounts',\n accountBinding: 'content',\n tagName: 'ul',\n emptyView: Ember.View.extend({\n template: Ember.Handlebars.compile('
%@%@
\\n'.fmt(path, path, number, number, line);\n });\n return result.trim();\n },\n deansi: function(log) {\n var ansi, text;\n log = log.replace(/\\r\\r/g, '\\r').replace(/\\033\\[K\\r/g, '\\r').replace(/^.*\\r(?!$)/gm, '').replace(/\u001b\\[2K/g, '').replace(/\\033\\(B/g, \"\");\n ansi = ansiparse(log);\n text = '';\n ansi.forEach(function(part) {\n var classes;\n classes = [];\n part.foreground && classes.push(part.foreground);\n part.background && classes.push('bg-' + part.background);\n part.bold && classes.push('bold');\n part.italic && classes.push('italic');\n return text += (classes.length ? '' + part.text + '' : part.text);\n });\n return text.replace(/\\033/g, '');\n },\n fold: function(log) {\n log = this.unfold(log);\n $.each(Travis.Log.FOLDS, function(name, pattern) {\n return log = log.replace(pattern, function() {\n return '\");\n foundHelper = helpers['t'];\n stack1 = foundHelper ? foundHelper.call(depth0, \"builds.name\", {hash:{},contexts:[depth0],data:data}) : helperMissing.call(depth0, \"t\", \"builds.name\", {hash:{},contexts:[depth0],data:data});\n data.buffer.push(escapeExpression(stack1) + \" | \\n\");\n foundHelper = helpers['t'];\n stack1 = foundHelper ? foundHelper.call(depth0, \"builds.commit\", {hash:{},contexts:[depth0],data:data}) : helperMissing.call(depth0, \"t\", \"builds.commit\", {hash:{},contexts:[depth0],data:data});\n data.buffer.push(escapeExpression(stack1) + \" | \\n\");\n foundHelper = helpers['t'];\n stack1 = foundHelper ? foundHelper.call(depth0, \"builds.message\", {hash:{},contexts:[depth0],data:data}) : helperMissing.call(depth0, \"t\", \"builds.message\", {hash:{},contexts:[depth0],data:data});\n data.buffer.push(escapeExpression(stack1) + \" | \\n\");\n foundHelper = helpers['t'];\n stack1 = foundHelper ? foundHelper.call(depth0, \"builds.duration\", {hash:{},contexts:[depth0],data:data}) : helperMissing.call(depth0, \"t\", \"builds.duration\", {hash:{},contexts:[depth0],data:data});\n data.buffer.push(escapeExpression(stack1) + \" | \\n\");\n foundHelper = helpers['t'];\n stack1 = foundHelper ? foundHelper.call(depth0, \"builds.finished_at\", {hash:{},contexts:[depth0],data:data}) : helperMissing.call(depth0, \"t\", \"builds.finished_at\", {hash:{},contexts:[depth0],data:data});\n data.buffer.push(escapeExpression(stack1) + \" | \\n
---|
\\n \");\n stack1 = helpers.view.call(depth0, \"view.ShowMoreButton\", {hash:{},contexts:[depth0],data:data});\n data.buffer.push(escapeExpression(stack1) + \"\\n
\\n\");\n return buffer;}\nfunction program2(depth0,data) {\n \n var buffer = '', stack1;\n data.buffer.push(\"\\n \");\n stack1 = {};\n stack1['contextBinding'] = \"build\";\n stack1 = helpers.view.call(depth0, \"Travis.BuildsItemView\", {hash:stack1,inverse:self.noop,fn:self.program(3, program3, data),contexts:[depth0],data:data});\n if(stack1 || stack1 === 0) { data.buffer.push(stack1); }\n data.buffer.push(\"\\n \");\n return buffer;}\nfunction program3(depth0,data) {\n \n var buffer = '', stack1, foundHelper;\n data.buffer.push(\"\\n