diff --git a/spec/spec-helper.coffee b/spec/spec-helper.coffee index a902fc2b4..db907b685 100644 --- a/spec/spec-helper.coffee +++ b/spec/spec-helper.coffee @@ -18,6 +18,7 @@ atom.themes.loadBaseStylesheets() atom.themes.requireStylesheet '../static/jasmine' fixturePackagesPath = path.resolve(__dirname, './fixtures/packages') +atom.packages.packageDirPaths.unshift(fixturePackagesPath) atom.keymap.loadBundledKeymaps() [bindingSetsToRestore, bindingSetsByFirstKeystrokeToRestore] = [] @@ -50,7 +51,9 @@ beforeEach -> bindingSetsByFirstKeystrokeToRestore = _.clone(keymap.bindingSetsByFirstKeystroke) # reset config before each spec; don't load or save from/to `config.json` - config = new Config() + config = new Config + resourcePath: window.resourcePath + configDirPath: atom.getConfigDirPath() config.packageDirPaths.unshift(fixturePackagesPath) spyOn(config, 'load') spyOn(config, 'save') diff --git a/src/atom-application.coffee b/src/atom-application.coffee index b54b99bfa..2d3bb244f 100644 --- a/src/atom-application.coffee +++ b/src/atom-application.coffee @@ -51,7 +51,7 @@ class AtomApplication version: null constructor: (options) -> - {@resourcePath, @version} = options + {@resourcePath, @version, @devMode} = options global.atomApplication = this @pidsToOpenWindows = {} @@ -147,7 +147,7 @@ class AtomApplication app.on 'open-url', (event, urlToOpen) => event.preventDefault() - @openUrl(urlToOpen) + @openUrl({urlToOpen, @devMode}) autoUpdater.on 'ready-for-update-on-quit', (event, version, quitAndUpdateCallback) => event.preventDefault() @@ -251,9 +251,11 @@ class AtomApplication console.log("Killing process #{pid} failed: #{error.code}") delete @pidsToOpenWindows[pid] - # Private: Handles an atom:// url. + # Private: Open an atom:// url. # - # Currently only supports atom://session/ urls. + # The host of the URL being opened is assumed to be the package name + # responsible for opening the URL. A new window will be created with + # that package's `urlMain` as the bootstrap script. # # * options # + urlToOpen: @@ -261,15 +263,25 @@ class AtomApplication # + devMode: # Boolean to control the opened window's dev mode. openUrl: ({urlToOpen, devMode}) -> - parsedUrl = url.parse(urlToOpen) - if parsedUrl.host is 'session' - sessionId = parsedUrl.path.split('/')[1] - console.log "Joining session #{sessionId}" - if sessionId - bootstrapScript = 'collaboration/lib/bootstrap' - new AtomWindow({bootstrapScript, @resourcePath, sessionId, devMode}) + unless @packages? + PackageManager = require './package-manager' + fsUtils = require './fs-utils' + @packages = new PackageManager + configDirPath: fsUtils.absolute('~/.atom') + devMode: devMode + resourcePath: @resourcePath + + packageName = url.parse(urlToOpen).host + pack = _.find @packages.getAvailablePackageMetadata(), ({name}) -> name is packageName + if pack? + if pack.urlMain + packagePath = @packages.resolvePackagePath(packageName) + bootstrapScript = path.resolve(packagePath, pack.urlMain) + new AtomWindow({bootstrapScript, @resourcePath, devMode, urlToOpen}) + else + console.log "Package '#{pack.name}' does not have a url main: #{urlToOpen}" else - console.log "Opening unknown url #{urlToOpen}" + console.log "Opening unknown url: #{urlToOpen}" # Private: Opens up a new {AtomWindow} to run specs within. # diff --git a/src/atom.coffee b/src/atom.coffee index 07569171e..f4ce8e441 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -27,6 +27,9 @@ class Atom initialize: -> @unsubscribe() + {devMode, resourcePath} = atom.getLoadSettings() + configDirPath = @getConfigDirPath() + Config = require './config' Keymap = require './keymap' PackageManager = require './package-manager' @@ -35,7 +38,7 @@ class Atom ThemeManager = require './theme-manager' ContextMenuManager = require './context-menu-manager' - @packages = new PackageManager() + @packages = new PackageManager({devMode, configDirPath, resourcePath}) #TODO Remove once packages have been updated to not touch atom.packageStates directly @__defineGetter__ 'packageStates', => @packages.packageStates @@ -43,8 +46,8 @@ class Atom @subscribe @packages, 'loaded', => @watchThemes() @themes = new ThemeManager() - @contextMenu = new ContextMenuManager(@getLoadSettings().devMode) - @config = new Config() + @contextMenu = new ContextMenuManager(devMode) + @config = new Config({configDirPath, resourcePath}) @pasteboard = new Pasteboard() @keymap = new Keymap() @syntax = deserialize(@getWindowState('syntax')) ? new Syntax() @@ -213,6 +216,10 @@ class Atom getHomeDirPath: -> app.getHomeDir() + # Public: Get the directory path to Atom's configuration area. + getConfigDirPath: -> + @configDirPath ?= fsUtils.absolute('~/.atom') + getWindowStatePath: -> switch @windowMode when 'spec' diff --git a/src/config.coffee b/src/config.coffee index 1b2466381..f6104747f 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -7,8 +7,6 @@ path = require 'path' async = require 'async' pathWatcher = require 'pathwatcher' -configDirPath = fsUtils.absolute("~/.atom") - # Public: Used to access all of Atom's configuration details. # # A global instance of this class is available to all plugins which can be @@ -35,27 +33,26 @@ class Config configFileHasErrors: null # Private: Created during initialization, available as `global.config` - constructor: -> - @configDirPath = configDirPath - @bundledKeymapsDirPath = path.join(resourcePath, "keymaps") - @nodeModulesDirPath = path.join(resourcePath, "node_modules") + constructor: ({@configDirPath, @resourcePath}={}) -> + @bundledKeymapsDirPath = path.join(@resourcePath, "keymaps") + @nodeModulesDirPath = path.join(@resourcePath, "node_modules") @bundledPackageDirPaths = [@nodeModulesDirPath] @lessSearchPaths = [ - path.join(resourcePath, 'static', 'variables') - path.join(resourcePath, 'static') + path.join(@resourcePath, 'static', 'variables') + path.join(@resourcePath, 'static') ] - @packageDirPaths = [path.join(configDirPath, "packages")] + @packageDirPaths = [path.join(@configDirPath, "packages")] if atom.getLoadSettings().devMode - @packageDirPaths.unshift(path.join(configDirPath, "dev", "packages")) + @packageDirPaths.unshift(path.join(@configDirPath, "dev", "packages")) @userPackageDirPaths = _.clone(@packageDirPaths) - @userStoragePath = path.join(configDirPath, "storage") + @userStoragePath = path.join(@configDirPath, "storage") @defaultSettings = core: _.clone(require('./root-view').configDefaults) editor: _.clone(require('./editor').configDefaults) @settings = {} - @configFilePath = fsUtils.resolve(configDirPath, 'config', ['json', 'cson']) - @configFilePath ?= path.join(configDirPath, 'config.cson') + @configFilePath = fsUtils.resolve(@configDirPath, 'config', ['json', 'cson']) + @configFilePath ?= path.join(@configDirPath, 'config.cson') # Private: initializeConfigDirectory: (done) -> @@ -67,7 +64,7 @@ class Config fsUtils.copy(sourcePath, destinationPath, callback) queue.drain = done - templateConfigDirPath = fsUtils.resolve(window.resourcePath, 'dot-atom') + templateConfigDirPath = fsUtils.resolve(@resourcePath, 'dot-atom') onConfigDirFile = (sourcePath) => relativePath = sourcePath.substring(templateConfigDirPath.length + 1) destinationPath = path.join(@configDirPath, relativePath) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index cc08c6f56..a2f026b2d 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -8,7 +8,11 @@ module.exports = class PackageManager _.extend @prototype, EventEmitter - constructor: -> + constructor: ({configDirPath, devMode, @resourcePath}) -> + @packageDirPaths = [path.join(configDirPath, "packages")] + if devMode + @packageDirPaths.unshift(path.join(configDirPath, "dev", "packages")) + @loadedPackages = {} @activePackages = {} @packageStates = {} @@ -83,10 +87,10 @@ class PackageManager resolvePackagePath: (name) -> return name if fsUtils.isDirectorySync(name) - packagePath = fsUtils.resolve(config.packageDirPaths..., name) + packagePath = fsUtils.resolve(@packageDirPaths..., name) return packagePath if fsUtils.isDirectorySync(packagePath) - packagePath = path.join(window.resourcePath, 'node_modules', name) + packagePath = path.join(@resourcePath, 'node_modules', name) return packagePath if @isInternalPackage(packagePath) isInternalPackage: (packagePath) -> @@ -108,11 +112,11 @@ class PackageManager getAvailablePackagePaths: -> packagePaths = [] - for packageDirPath in config.packageDirPaths + for packageDirPath in @packageDirPaths for packagePath in fsUtils.listSync(packageDirPath) packagePaths.push(packagePath) if fsUtils.isDirectorySync(packagePath) - for packagePath in fsUtils.listSync(path.join(window.resourcePath, 'node_modules')) + for packagePath in fsUtils.listSync(path.join(@resourcePath, 'node_modules')) packagePaths.push(packagePath) if @isInternalPackage(packagePath) _.uniq(packagePaths) @@ -122,8 +126,8 @@ class PackageManager getAvailablePackageMetadata: -> packages = [] - for packagePath in atom.getAvailablePackagePaths() + for packagePath in @getAvailablePackagePaths() name = path.basename(packagePath) - metadata = atom.getLoadedPackage(name)?.metadata ? Package.loadMetadata(packagePath, true) + metadata = @getLoadedPackage(name)?.metadata ? Package.loadMetadata(packagePath, true) packages.push(metadata) packages