From 0fc2f70dc5d162f370d9487c7ca1ddd706b3569b Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Mon, 21 Oct 2013 16:26:18 -0700 Subject: [PATCH 01/21] :memo: Throughly document BufferedNodeProcess --- src/buffered-node-process.coffee | 37 ++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/buffered-node-process.coffee b/src/buffered-node-process.coffee index 6325004de..f2f59e274 100644 --- a/src/buffered-node-process.coffee +++ b/src/buffered-node-process.coffee @@ -1,23 +1,46 @@ BufferedProcess = require './buffered-process' path = require 'path' -# Public: Like BufferedProcess, but accepts a node script instead of an -# executable, on Unix which allows running scripts and executables, this seems -# unnecessary, but on Windows we have to separate scripts from executables since -# it doesn't support shebang strings. +# Public: Like {BufferedProcess}, but accepts a Node script instead of an +# executable. +# +# This may seem unnecessary but on Windows we have to have separate executables +# for each script without this since Windows doesn't support shebang strings. module.exports = class BufferedNodeProcess extends BufferedProcess + # Executes the given Node script. + # + # * options + # + command: + # The path to the Javascript script to execute. + # + args: + # The array of arguments to pass to the script (optional). + # + options: + # The options Object to pass to Node's `ChildProcess.spawn` (optional). + # + stdout: + # The callback that receives a single argument which contains the + # standard output of the script. The callback is called as data is + # received but it's buffered to ensure only complete lines are passed + # until the source stream closes. After the source stream has closed + # all remaining data is sent in a final call (optional). + # + stderr: + # The callback that receives a single argument which contains the + # standard error of the script. The callback is called as data is + # received but it's buffered to ensure only complete lines are passed + # until the source stream closes. After the source stream has closed + # all remaining data is sent in a final call. + # + exit: + # The callback which receives a single argument containing the exit + # status (optional). constructor: ({command, args, options, stdout, stderr, exit}) -> node = if process.platform is 'darwin' - # On OS X we use the helper process to run script, because it doesn't - # create an icon on the Dock. + # Use a helper to prevent an icon from appearing on the Dock path.resolve(process.resourcesPath, '..', 'Frameworks', 'Atom Helper.app', 'Contents', 'MacOS', 'Atom Helper') else process.execPath - # Tell atom-shell to run like upstream node. options ?= {} options.env ?= Object.create(process.env) options.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = 1 From ffbce2020e5e58a67ebef06207fe6bbce385cb8c Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Mon, 21 Oct 2013 16:31:15 -0700 Subject: [PATCH 02/21] Note that stderr is optional --- src/buffered-node-process.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/buffered-node-process.coffee b/src/buffered-node-process.coffee index f2f59e274..a98734506 100644 --- a/src/buffered-node-process.coffee +++ b/src/buffered-node-process.coffee @@ -28,7 +28,7 @@ class BufferedNodeProcess extends BufferedProcess # standard error of the script. The callback is called as data is # received but it's buffered to ensure only complete lines are passed # until the source stream closes. After the source stream has closed - # all remaining data is sent in a final call. + # all remaining data is sent in a final call (optional). # + exit: # The callback which receives a single argument containing the exit # status (optional). From 814ab4e9807d9849f0a0f4ad3624c49ecddbabad Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Mon, 21 Oct 2013 16:32:10 -0700 Subject: [PATCH 03/21] :memo: Throughly document BufferedProcess. --- src/buffered-process.coffee | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/buffered-process.coffee b/src/buffered-process.coffee index d726d7b29..3a555c3b6 100644 --- a/src/buffered-process.coffee +++ b/src/buffered-process.coffee @@ -1,28 +1,35 @@ ChildProcess = require 'child_process' -path = require 'path' -_ = require 'underscore-plus' -# Public: A wrapper which provides buffering for ChildProcess. +# Public: A wrapper which provides line buffering for Node's ChildProcess. module.exports = class BufferedProcess process: null killed: false - # Executes the given command. + # Executes the given executable. # # * options # + command: - # The command to execute. + # The path to the executable to execute. # + args: - # The arguments for the given command. + # The array of arguments to pass to the script (optional). # + options: - # The options to pass to ChildProcess. + # The options Object to pass to Node's `ChildProcess.spawn` (optional). # + stdout: - # The callback to receive stdout data. + # The callback that receives a single argument which contains the + # standard output of the script. The callback is called as data is + # received but it's buffered to ensure only complete lines are passed + # until the source stream closes. After the source stream has closed + # all remaining data is sent in a final call (optional). # + stderr: - # The callback to receive stderr data. + # The callback that receives a single argument which contains the + # standard error of the script. The callback is called as data is + # received but it's buffered to ensure only complete lines are passed + # until the source stream closes. After the source stream has closed + # all remaining data is sent in a final call (optional). # + exit: - # The callback to receive exit status. + # The callback which receives a single argument containing the exit + # status (optional). constructor: ({command, args, options, stdout, stderr, exit}={}) -> options ?= {} @process = ChildProcess.spawn(command, args, options) From 6ed3bb48f2329a0ab3c11681465e717a6e2fcdac Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Mon, 21 Oct 2013 16:35:59 -0700 Subject: [PATCH 04/21] Remove 'fs' require and use 'fsUtils' instead --- src/directory.coffee | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/directory.coffee b/src/directory.coffee index 41c0a9663..a11dab6a9 100644 --- a/src/directory.coffee +++ b/src/directory.coffee @@ -1,4 +1,3 @@ -fs = require 'fs' path = require 'path' fsUtils = require './fs-utils' pathWatcher = require 'pathwatcher' @@ -41,7 +40,7 @@ class Directory getRealPath: -> unless @realPath? try - @realPath = fs.realpathSync(@path) + @realPath = fsUtils.realpathSync(@path) catch e @realPath = @path @realPath @@ -82,9 +81,9 @@ class Directory files = [] for entryPath in fsUtils.listSync(@path) try - stat = fs.lstatSync(entryPath) + stat = fsUtils.lstatSync(entryPath) symlink = stat.isSymbolicLink() - stat = fs.statSync(entryPath) if symlink + stat = fsUtils.statSync(entryPath) if symlink catch e continue if stat.isDirectory() From 58ef0f417679a226a7b6d97cd9341bbad5a862d8 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Mon, 21 Oct 2013 16:54:52 -0700 Subject: [PATCH 05/21] :memo: Refine Directory's documentation --- src/directory.coffee | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/directory.coffee b/src/directory.coffee index a11dab6a9..b8a11dd3f 100644 --- a/src/directory.coffee +++ b/src/directory.coffee @@ -17,7 +17,7 @@ class Directory # * path: # A {String} representing the file directory # + symlink: - # A {Boolean} indicating if the path is a symlink + # A {Boolean} indicating if the path is a symlink (defaults to false). constructor: (@path, @symlink=false) -> @on 'first-contents-changed-subscription-will-be-added', => @subscribeToNativeChangeEvents() @@ -29,14 +29,16 @@ class Directory getBaseName: -> path.basename(@path) - # Public: Returns the directory's path. + # Public: Returns the directory's symbolic path. # - # FIXME what is the difference between real path and path? + # This may include unfollowed symlinks or relative directory entries. Or it + # may be fully resolved, it depends on what you give it. getPath: -> @path - # Public: Returns this directory's real path. + # Public: Returns this directory's completely resolved path. # - # FIXME what is the difference between real path and path? + # All relative directory entries are removed and symlinks are resolved to + # their final destination. getRealPath: -> unless @realPath? try @@ -45,7 +47,8 @@ class Directory @realPath = @path @realPath - # Public: Returns whether the given path is inside this directory. + # Public: Returns whether the given path (real or symbolic) is inside this + # directory. contains: (pathToCheck) -> return false unless pathToCheck From d0ed2a87cd5de08396e99d452755bc4970f5521d Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Tue, 22 Oct 2013 15:46:04 -0700 Subject: [PATCH 06/21] :memo: Remove curly braces for core objects --- src/directory.coffee | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/directory.coffee b/src/directory.coffee index b8a11dd3f..8492e4616 100644 --- a/src/directory.coffee +++ b/src/directory.coffee @@ -12,17 +12,19 @@ class Directory path: null realPath: null - # Public: Configures an new Directory instance, no files are accessed. + # Public: Configures a new Directory instance, no files are accessed. # # * path: - # A {String} representing the file directory + # A String containing the absolute path to the directory. # + symlink: - # A {Boolean} indicating if the path is a symlink (defaults to false). + # A Boolean indicating if the path is a symlink (defaults to false). constructor: (@path, @symlink=false) -> @on 'first-contents-changed-subscription-will-be-added', => + # Triggered by emissary, when a new contents-changed listener attaches @subscribeToNativeChangeEvents() @on 'last-contents-changed-subscription-removed', => + # Triggered by emissary, when the last contents-changed listener detaches @unsubscribeFromNativeChangeEvents() # Public: Returns the basename of the directory. @@ -78,7 +80,7 @@ class Directory # # Note: It follows symlinks. # - # Returns an {Array} of {Files}. + # Returns an Array of {Files}. getEntries: -> directories = [] files = [] From 8503a53fec89d403d685c05ed01905fbeb73e772 Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Tue, 22 Oct 2013 15:46:21 -0700 Subject: [PATCH 07/21] :memo: Update documentation for file.coffee --- src/file.coffee | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/file.coffee b/src/file.coffee index bb1673136..5e7895410 100644 --- a/src/file.coffee +++ b/src/file.coffee @@ -5,10 +5,10 @@ Q = require 'q' _ = require 'underscore-plus' fsUtils = require './fs-utils' -# Public: Represents an individual file in the editor. +# Public: Represents an individual file. # -# This class shouldn't be created directly, instead you should create a -# {Directory} and access the {File} objects that it creates. +# You should probably create a {Directory} and access the {File} objects that +# it creates, rather than instantiating the {File} class directly. module.exports = class File Emitter.includeInto(this) @@ -16,10 +16,10 @@ class File path: null cachedContents: null - # Private: Creates a new file. + # Public: Creates a new file. # # * path: - # A String representing the file path + # A String containing the absolute path to the file # * symlink: # A Boolean indicating if the path is a symlink (default: false) constructor: (@path, @symlink=false) -> @@ -27,15 +27,18 @@ class File @handleEventSubscriptions() + # Private: Subscribes to file system notifications when necessary. handleEventSubscriptions: -> eventNames = ['contents-changed', 'moved', 'removed'] subscriptionsAdded = eventNames.map (eventName) -> "first-#{eventName}-subscription-will-be-added" @on subscriptionsAdded.join(' '), => + # Only subscribe when a listener of eventName attaches (triggered by emissary) @subscribeToNativeChangeEvents() if @exists() subscriptionsRemoved = eventNames.map (eventName) -> "last-#{eventName}-subscription-removed" @on subscriptionsRemoved.join(' '), => + # Detach when the last listener of eventName detaches (triggered by emissary) subscriptionsEmpty = _.every eventNames, (eventName) => @getSubscriptionCount(eventName) is 0 @unsubscribeFromNativeChangeEvents() if subscriptionsEmpty @@ -100,7 +103,7 @@ class File promise.then (contents) => @cachedContents = contents - # Public: Returns whether a file exists. + # Public: Returns whether the file exists. exists: -> fsUtils.exists(@getPath()) From b288a5c68f188cd05bfbc5687e480e37b893df2a Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Wed, 23 Oct 2013 14:52:27 -0700 Subject: [PATCH 08/21] :memo: Provide detailed docs on fsUtils --- src/fs-utils.coffee | 189 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 150 insertions(+), 39 deletions(-) diff --git a/src/fs-utils.coffee b/src/fs-utils.coffee index 19e16d7db..0d08b0eaf 100644 --- a/src/fs-utils.coffee +++ b/src/fs-utils.coffee @@ -7,9 +7,22 @@ rimraf = require 'rimraf' path = require 'path' # Public: Useful extensions to node's built-in fs module +# +# Important, this extends Node's builtin in ['fs' module][fs], which means that you +# can do anything that you can do with Node's 'fs' module plus a few extra +# functions that we've found to be helpful. +# +# [fs]: http://nodejs.org/api/fs.html fsExtensions = - # Make the given path absolute by resolving it against the - # current working directory. + # Public: Make the given path absolute by resolving it against the current + # working directory. + # + # * relativePath: + # The String containing the relative path. If the path is prefixed with + # '~', it will be expanded to the current user's home directory. + # + # Returns the absolute path or the relative path if it's unable to determine + # it's realpath. absolute: (relativePath) -> return null unless relativePath? @@ -25,11 +38,12 @@ fsExtensions = catch e relativePath - # Returns true if a file or folder at the specified path exists. + # Public: Returns true if a file or folder at the specified path exists. exists: (pathToCheck) -> + # TODO: rename to existsSync pathToCheck? and fs.statSyncNoException(pathToCheck) isnt false - # Returns true if the specified path is a directory that exists. + # Public: Returns true if the given path exists and is a directory. isDirectorySync: (directoryPath) -> return false unless directoryPath?.length > 0 if stat = fs.statSyncNoException(directoryPath) @@ -37,6 +51,7 @@ fsExtensions = else false + # Public: Asynchronously checks that the given path exists and is a directory. isDirectory: (directoryPath, done) -> return done(false) unless directoryPath?.length > 0 fs.exists directoryPath, (exists) -> @@ -49,7 +64,7 @@ fsExtensions = else done(false) - # Returns true if the specified path is a regular file that exists. + # Public: Returns true if the specified path exists and is a file. isFileSync: (filePath) -> return false unless filePath?.length > 0 if stat = fs.statSyncNoException(filePath) @@ -57,7 +72,7 @@ fsExtensions = else false - # Returns true if the specified path is executable. + # Public: Returns true if the specified path is executable. isExecutableSync: (pathToCheck) -> return false unless pathToCheck?.length > 0 if stat = fs.statSyncNoException(pathToCheck) @@ -65,8 +80,14 @@ fsExtensions = else false - # Returns an array with the paths of the files and folders - # contained in the directory path. + # Public: Returns an Array with the paths of the files and directories + # contained within the directory path. It is not recursive. + # + # * rootPath: + # The absolute path to the directory to list. + # * extensions: + # An array of extensions to filter the results by. If none are given, none + # are filtered (optional). listSync: (rootPath, extensions) -> return [] unless @isDirectorySync(rootPath) paths = fs.readdirSync(rootPath) @@ -74,6 +95,16 @@ fsExtensions = paths = paths.map (childPath) -> path.join(rootPath, childPath) paths + # Public: Asynchronously lists the files and directories in the given path. + # The listing is not recursive. + # + # * rootPath: + # The absolute path to the directory to list. + # * extensions: + # An array of extensions to filter the results by. If none are given, none + # are filtered (optional) + # * callback: + # The function to call list: (rootPath, rest...) -> extensions = rest.shift() if rest.length > 1 done = rest.shift() @@ -85,6 +116,7 @@ fsExtensions = paths = paths.map (childPath) -> path.join(rootPath, childPath) done(null, paths) + # Private: Returns only the paths which end with one of the given extensions. filterExtensions: (paths, extensions) -> extensions = extensions.map (ext) -> if ext is '' @@ -93,6 +125,7 @@ fsExtensions = '.' + ext.replace(/^\./, '') paths.filter (pathToCheck) -> _.include(extensions, path.extname(pathToCheck)) + # Deprecated: No one currently uses this. listTreeSync: (rootPath) -> paths = [] onPath = (childPath) -> @@ -101,22 +134,34 @@ fsExtensions = @traverseTreeSync(rootPath, onPath, onPath) paths + # Public: Moves the file or directory to the target synchronously. move: (source, target) -> + # TODO: This should be renamed to moveSync fs.renameSync(source, target) - # Remove the file or directory at the given path. + # Public: Removes the file or directory at the given path synchronously. remove: (pathToRemove) -> + # TODO: This should be renamed to removeSync rimraf.sync(pathToRemove) - # Open, read, and close a file, returning the file's contents. + # Public: Open, read, and close a file, returning the file's contents + # synchronously. read: (filePath) -> + # TODO: This should be renamed to readSync fs.readFileSync(filePath, 'utf8') - # Open, write, flush, and close a file, writing the given content. + # Public: Open, write, flush, and close a file, writing the given content + # synchronously. + # + # It also creates the necessary parent directories. writeSync: (filePath, content) -> mkdirp.sync(path.dirname(filePath)) fs.writeFileSync(filePath, content) + # Public: Open, write, flush, and close a file, writing the given content + # asynchronously. + # + # It also creates the necessary parent directories. write: (filePath, content, callback) -> mkdirp path.dirname(filePath), (error) -> if error? @@ -124,6 +169,7 @@ fsExtensions = else fs.writeFile(filePath, content, callback) + # Public: Copies the given path asynchronously. copy: (sourcePath, destinationPath, done) -> mkdirp path.dirname(destinationPath), (error) -> if error? @@ -145,11 +191,23 @@ fsExtensions = sourceStream.pipe(destinationStream) - # Create a directory at the specified path including any missing parent - # directories. + # Public: Create a directory at the specified path including any missing + # parent directories synchronously. makeTree: (directoryPath) -> + # TODO: rename to makeTreeSync mkdirp.sync(directoryPath) if directoryPath and not @exists(directoryPath) + # Public: Recursively walk the given path and execute the given functions + # synchronously. + # + # * rootPath: + # The String containing the directory to recurse into. + # * onFile: + # The function to execute on each file, receives a single argument the + # absolute path. + # * onDirectory: + # The function to execute on each directory, receives a single argument the + # absolute path (defaults to onFile) traverseTreeSync: (rootPath, onFile, onDirectory=onFile) -> return unless @isDirectorySync(rootPath) @@ -167,6 +225,17 @@ fsExtensions = traverse(rootPath, onFile, onDirectory) + # Public: Recursively walk the given path and execute the given functions + # asynchronously. + # + # * rootPath: + # The String containing the directory to recurse into. + # * onFile: + # The function to execute on each file, receives a single argument the + # absolute path. + # * onDirectory: + # The function to execute on each directory, receives a single argument the + # absolute path (defaults to onFile) traverseTree: (rootPath, onFile, onDirectory, onDone) -> fs.readdir rootPath, (error, files) -> if error @@ -194,10 +263,28 @@ fsExtensions = queue.drain = onDone queue.push(path.join(rootPath, file)) for file in files + # Public: Hashes the contents of the given file. + # + # * pathToDigest: + # The String containing the absolute path. + # + # Returns a String containing the MD5 hexadecimal hash. md5ForPath: (pathToDigest) -> contents = fs.readFileSync(pathToDigest) require('crypto').createHash('md5').update(contents).digest('hex') + # Public: Finds a relative path among the given array of paths. + # + # * loadPaths: + # An Array of absolute and relative paths to search. + # * pathToResolve: + # The string containing the path to resolve. + # * extensions: + # An array of extensions to pass to {resolveExtensions} in which case + # pathToResolve should not contain an extension (optional). + # + # Returns the absolute path of the file to be resolved if it's found and + # undefined otherwise. resolve: (args...) -> extensions = args.pop() if _.isArray(_.last(args)) pathToResolve = args.pop() @@ -218,10 +305,22 @@ fsExtensions = return @absolute(candidatePath) if @exists(candidatePath) undefined + # Deprecated: resolveOnLoadPath: (args...) -> loadPaths = Module.globalPaths.concat(module.paths) @resolve(loadPaths..., args...) + # Public: Finds the first file in the given path which matches the extension + # in the order given. + # + # * pathToResolve: + # The String containing relative or absolute path of the file in question + # without the extension or '.'. + # * extensions: + # The ordered Array of extensions to try. + # + # Returns the absolute path of the file if it exists with any of the given + # extensions, otherwise it's undefined. resolveExtension: (pathToResolve, extensions) -> for extension in extensions if extension == "" @@ -231,6 +330,7 @@ fsExtensions = return @absolute(pathWithExtension) if @exists(pathWithExtension) undefined + # Public: Returns true for extensions associated with compressed files. isCompressedExtension: (ext) -> _.indexOf([ '.gz' @@ -240,6 +340,7 @@ fsExtensions = '.zip' ], ext, true) >= 0 + # Public: Returns true for extensions associated with image files. isImageExtension: (ext) -> _.indexOf([ '.gif' @@ -249,9 +350,27 @@ fsExtensions = '.tiff' ], ext, true) >= 0 + # Public: Returns true for extensions associated with pdf files. isPdfExtension: (ext) -> ext is '.pdf' + # Public: Returns true for extensions associated with binary files. + isBinaryExtension: (ext) -> + _.indexOf([ + '.DS_Store' + '.a' + '.o' + '.so' + '.woff' + ], ext, true) >= 0 + + # Public: Returns true for files named similarily to 'README' + isReadmePath: (readmePath) -> + extension = path.extname(readmePath) + base = path.basename(readmePath, extension).toLowerCase() + base is 'readme' and (extension is '' or @isMarkdownExtension(extension)) + + # Private: Used by isReadmePath. isMarkdownExtension: (ext) -> _.indexOf([ '.markdown' @@ -262,24 +381,30 @@ fsExtensions = '.ron' ], ext, true) >= 0 - isBinaryExtension: (ext) -> - _.indexOf([ - '.DS_Store' - '.a' - '.o' - '.so' - '.woff' - ], ext, true) >= 0 + # Public: Reads and returns CSON, JSON or Plist files and returns the + # corresponding Object. + readObjectSync: (objectPath) -> + CSON = require 'season' + if CSON.isObjectPath(objectPath) + CSON.readFileSync(objectPath) + else + @readPlistSync(objectPath) - isReadmePath: (readmePath) -> - extension = path.extname(readmePath) - base = path.basename(readmePath, extension).toLowerCase() - base is 'readme' and (extension is '' or @isMarkdownExtension(extension)) + # Public: Reads and returns CSON, JSON or Plist files and calls the specified + # callback with the corresponding Object. + readObject: (objectPath, done) -> + CSON = require 'season' + if CSON.isObjectPath(objectPath) + CSON.readFile(objectPath, done) + else + @readPlist(objectPath, done) + # Private: Used by readObjectSync. readPlistSync: (plistPath) -> plist = require 'plist' plist.parseStringSync(@read(plistPath)) + # Private: Used by readObject. readPlist: (plistPath, done) -> plist = require 'plist' fs.readFile plistPath, 'utf8', (error, contents) -> @@ -291,18 +416,4 @@ fsExtensions = catch parseError done(parseError) - readObjectSync: (objectPath) -> - CSON = require 'season' - if CSON.isObjectPath(objectPath) - CSON.readFileSync(objectPath) - else - @readPlistSync(objectPath) - - readObject: (objectPath, done) -> - CSON = require 'season' - if CSON.isObjectPath(objectPath) - CSON.readFile(objectPath, done) - else - @readPlist(objectPath, done) - module.exports = _.extend({}, fs, fsExtensions) From 378a7135b791c89f935201d764672cfe66c8e051 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 23 Oct 2013 15:53:50 -0700 Subject: [PATCH 09/21] Add missing at sign before getFocusedWindowSize Closes atom/collaboration#22 --- src/browser/atom-application.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 304c4709d..f0fa4126b 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -300,7 +300,7 @@ class AtomApplication if pack.urlMain packagePath = @packages.resolvePackagePath(packageName) bootstrapScript = path.resolve(packagePath, pack.urlMain) - new AtomWindow({bootstrapScript, @resourcePath, devMode, urlToOpen, initialSize: getFocusedWindowSize()}) + new AtomWindow({bootstrapScript, @resourcePath, devMode, urlToOpen, initialSize: @getFocusedWindowSize()}) else console.log "Package '#{pack.name}' does not have a url main: #{urlToOpen}" else From 2d30ec84bb0e6073e5ee3ec83b8da191bc338033 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 23 Oct 2013 16:12:25 -0700 Subject: [PATCH 10/21] Upgrade to tree-view@0.21.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 45fce7732..a01b7de13 100644 --- a/package.json +++ b/package.json @@ -106,7 +106,7 @@ "timecop": "0.7.0", "to-the-hubs": "0.8.0", "toml": "0.3.0", - "tree-view": "0.20.0", + "tree-view": "0.21.0", "visual-bell": "0.3.0", "whitespace": "0.7.0", "wrap-guide": "0.4.0", From 1b8f8cd9142e26149663ec0db4df3faedac2073d Mon Sep 17 00:00:00 2001 From: Matt Colyer Date: Wed, 23 Oct 2013 16:16:30 -0700 Subject: [PATCH 11/21] :memo: Clarify git-utils.coffee --- src/git.coffee | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/git.coffee b/src/git.coffee index eb1c6f42f..67436594e 100644 --- a/src/git.coffee +++ b/src/git.coffee @@ -74,6 +74,7 @@ class Git @subscribeToBuffer(buffer) for buffer in project.getBuffers() @subscribe project, 'buffer-created', (buffer) => @subscribeToBuffer(buffer) + # Private: Subscribes to buffer events. subscribeToBuffer: (buffer) -> bufferStatusHandler = => if path = buffer.getPath() @@ -82,8 +83,8 @@ class Git @subscribe buffer, 'reloaded', bufferStatusHandler @subscribe buffer, 'destroyed', => @unsubscribe(buffer) - # Public: Destroy this `Git` object. This destroys any tasks and - # subscriptions and releases the underlying libgit2 repository handle. + # Public: Destroy this `Git` object. This destroys any tasks and subscriptions + # and releases the underlying libgit2 repository handle. destroy: -> if @statusTask? @statusTask.terminate() @@ -114,7 +115,8 @@ class Git # Public: Returns the status of a single path in the repository. # - # * path: A String defining a relative path + # * path: + # A String defining a relative path # # Returns a {Number}, FIXME representing what? getPathStatus: (path) -> @@ -128,24 +130,23 @@ class Git @emit 'status-changed', path, pathStatus pathStatus - # Public: Determines if the given path is ignored. + # Public: Returns true if the given path is ignored. isPathIgnored: (path) -> @getRepo().isIgnored(@relativize(path)) - # Public: Determine if the given status indicates modification. + # Public: Returns true if the given status indicates modification. isStatusModified: (status) -> @getRepo().isStatusModified(status) - # Public: Determine if the given path is modified. + # Public: Returns true if the given path is modified. isPathModified: (path) -> @isStatusModified(@getPathStatus(path)) - # Public: Determine if the given status indicates a new path. + # Public: Returns true if the given status indicates a new path. isStatusNew: (status) -> @getRepo().isStatusNew(status) - # Public: Determine if the given path is new. + # Public: Returns true if the given path is new. isPathNew: (path) -> @isStatusNew(@getPathStatus(path)) - # Public: Is the project at the root of this repository? - # - # Returns true if at the root, false if in a subfolder of the repository. + # Public: Returns true if at the root, false if in a subfolder of the + # repository. isProjectAtRoot: -> @projectAtRoot ?= project.relativize(@getWorkingDirectory()) is '' @@ -170,9 +171,10 @@ class Git # git checkout HEAD -- # ``` # - # path - The String path to checkout + # * path: + # The String path to checkout # - # Returns a {Boolean} that's `true` if the method was successful. + # Returns a Boolean that's true if the method was successful. checkoutHead: (path) -> headCheckedOut = @getRepo().checkoutHead(@relativize(path)) @getPathStatus(path) if headCheckedOut @@ -180,10 +182,12 @@ class Git # Public: Checks out a branch in your repository. # - # reference - The {String} reference to checkout - # create - A {Boolean} value which, if `true` creates the new reference if it doesn't exist. + # * reference: + # The String reference to checkout + # * create: + # A Boolean value which, if true creates the new reference if it doesn't exist. # - # Returns a {Boolean} that's `true` if the method was successful. + # Returns a Boolean that's true if the method was successful. checkoutReference: (reference, create) -> @getRepo().checkoutReference(reference, create) @@ -204,7 +208,7 @@ class Git # * path: # The String path to check # - # Returns a {Boolean}. + # Returns a Boolean. isSubmodule: (path) -> @getRepo().isSubmodule(@relativize(path)) # Public: Retrieves the status of a directory. @@ -252,7 +256,7 @@ class Git # Returns a String. getUpstreamBranch: -> @getRepo().getUpstreamBranch() - # Public: ? + # Public: Returns the current SHA for the given reference. getReferenceTarget: (reference) -> @getRepo().getReferenceTarget(reference) # Public: Gets all the local and remote references. @@ -261,13 +265,15 @@ class Git # can be an array of strings containing the reference names. getReferences: -> @getRepo().getReferences() - # Public: ? + # Public: Returns the number of commits behind the current branch is from the + # default remote branch. getAheadBehindCount: (reference) -> @getRepo().getAheadBehindCount(reference) - # Public: ? + # Public: Returns true if the given branch exists. hasBranch: (branch) -> @getReferenceTarget("refs/heads/#{branch}")? - # Private: + # Private: Refreshes the current git status in an outside process and + # asynchronously updates the relevant properties. refreshStatus: -> @statusTask = Task.once require.resolve('./repository-status-handler'), @getPath(), ({statuses, upstream, branch}) => statusesUnchanged = _.isEqual(statuses, @statuses) and _.isEqual(upstream, @upstream) and _.isEqual(branch, @branch) From ca26d53db1d6fd14b606216673a7e45819a8a8e2 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 23 Oct 2013 16:31:24 -0700 Subject: [PATCH 12/21] Upgrade to collaboration@0.29.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a01b7de13..a5d941571 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "autoflow": "0.5.0", "bookmarks": "0.8.0", "bracket-matcher": "0.7.0", - "collaboration": "0.28.0", + "collaboration": "0.29.0", "command-logger": "0.6.0", "command-palette": "0.5.0", "dev-live-reload": "0.11.0", From f21e8e3aa4f962657768fa27b5b18be57e6098fa Mon Sep 17 00:00:00 2001 From: Adam Roben Date: Thu, 24 Oct 2013 08:48:05 -0400 Subject: [PATCH 13/21] Get rid of ANSI escape sequences in Constructicon output Passing --no-color to grunt should get rid of these. --- script/constructicon/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/constructicon/build b/script/constructicon/build index e3d40044b..2d077a573 100755 --- a/script/constructicon/build +++ b/script/constructicon/build @@ -8,7 +8,7 @@ set -ex cd "$(dirname "$0")/../.." rm -fr node_modules ./script/bootstrap -./node_modules/.bin/grunt --build-dir="$BUILT_PRODUCTS_DIR" deploy +./node_modules/.bin/grunt --no-color --build-dir="$BUILT_PRODUCTS_DIR" deploy echo "TARGET_BUILD_DIR=$BUILT_PRODUCTS_DIR" echo "FULL_PRODUCT_NAME=Atom.app" From 6f47010a7297ba45501de3b739d9a75087b3d266 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 24 Oct 2013 09:52:51 -0700 Subject: [PATCH 14/21] Upgrade to language-javascript@0.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a5d941571..01a588fff 100644 --- a/package.json +++ b/package.json @@ -120,7 +120,7 @@ "language-html": "0.1.0", "language-hyperlink": "0.2.0", "language-java": "0.1.0", - "language-javascript": "0.1.0", + "language-javascript": "0.2.0", "language-json": "0.1.0", "language-less": "0.1.0", "language-make": "0.1.0", From c1b0ba2773eb9254b8d128ee6ab89c4d0cc1f5bb Mon Sep 17 00:00:00 2001 From: probablycorey Date: Thu, 24 Oct 2013 10:56:26 -0700 Subject: [PATCH 15/21] Check for cmake dependency before building Atom --- script/bootstrap | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/script/bootstrap b/script/bootstrap index f87a8c8b1..078aa8fad 100755 --- a/script/bootstrap +++ b/script/bootstrap @@ -1,5 +1,6 @@ #!/usr/bin/env node var safeExec = require('./utils/child-process-wrapper.js').safeExec; +var exec = require('child_process').exec; var path = require('path'); // Executes an array of commands one by one. @@ -17,6 +18,15 @@ function joinCommands() { return Array.prototype.slice.call(arguments, 0).join(commandSeparator); } +function checkDependencies() { + exec("cmake -h", function(error) { + if (error) { + console.error("Error: cmake is required to build Atom.") + process.exit(1); + } + }); +} + var echoNewLine = process.platform == 'win32' ? 'echo.' : 'echo'; var commands = [ 'git submodule --quiet sync', @@ -27,5 +37,6 @@ var commands = [ 'node vendor/apm/bin/apm install --silent', ]; +checkDependencies() process.chdir(path.dirname(__dirname)); executeCommands(commands, process.exit); From 48fbdc69fb0f2cdc34bdd11edd7a429ab2cd69a7 Mon Sep 17 00:00:00 2001 From: probablycorey Date: Thu, 24 Oct 2013 14:43:05 -0700 Subject: [PATCH 16/21] Update collaboration version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 01a588fff..72bf5af3a 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "autoflow": "0.5.0", "bookmarks": "0.8.0", "bracket-matcher": "0.7.0", - "collaboration": "0.29.0", + "collaboration": "0.30.0", "command-logger": "0.6.0", "command-palette": "0.5.0", "dev-live-reload": "0.11.0", From 3e584f29b1efa873dd2affab12ea6a82934c89e7 Mon Sep 17 00:00:00 2001 From: Ben Ogle Date: Thu, 24 Oct 2013 15:17:29 -0700 Subject: [PATCH 17/21] Upgrade to find-and-replace@0.32.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 72bf5af3a..7c270dcdd 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "dev-live-reload": "0.11.0", "editor-stats": "0.5.0", "exception-reporting": "0.5.0", - "find-and-replace": "0.31.0", + "find-and-replace": "0.32.0", "fuzzy-finder": "0.15.0", "gfm": "0.5.0", "git-diff": "0.12.0", From feff67457d8111a49cba62cfa09101cf55a84ced Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 24 Oct 2013 18:43:22 -0700 Subject: [PATCH 18/21] :non-potable_water: Include namespace when canceling subscription Emissary does not clear our namespace listeners when calling off with only the event name and the handler. --- src/config.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index 18cbf2692..02ada675d 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -211,12 +211,12 @@ class Config previousValue = _.clone(value) callback(value, {previous}) - subscription = { cancel: => @off 'updated', updateCallback } - @on "updated.#{keyPath.replace(/\./, '-')}", updateCallback + eventName = "updated.#{keyPath.replace(/\./, '-')}" + subscription = { cancel: => @off eventName, updateCallback } + @on eventName, updateCallback callback(value) if options.callNow ? true subscription - # Public: Unobserve all callbacks on a given key # # keyPath - The {String} name of the key to unobserve From 29646cdff8dc5655527f4d78ebcd8e12e724e844 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 24 Oct 2013 18:58:43 -0700 Subject: [PATCH 19/21] :lipstick: Use Date.now --- src/window-bootstrap.coffee | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/window-bootstrap.coffee b/src/window-bootstrap.coffee index 15da3237e..6d94e4dc0 100644 --- a/src/window-bootstrap.coffee +++ b/src/window-bootstrap.coffee @@ -1,5 +1,5 @@ # Like sands through the hourglass, so are the days of our lives. -startTime = new Date().getTime() +startTime = Date.now() require './window' @@ -7,4 +7,4 @@ Atom = require './atom' window.atom = new Atom() window.setUpEnvironment('editor') window.startEditorWindow() -console.log "Window load time: #{new Date().getTime() - startTime}ms" +console.log "Window load time: #{Date.now() - startTime}ms" From 6460cbe2881dac535e555c1e18802eb90e6d0604 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 25 Oct 2013 08:36:32 -0700 Subject: [PATCH 20/21] Upgrade to command-palette@0.6.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c270dcdd..cb984d161 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "bracket-matcher": "0.7.0", "collaboration": "0.30.0", "command-logger": "0.6.0", - "command-palette": "0.5.0", + "command-palette": "0.6.0", "dev-live-reload": "0.11.0", "editor-stats": "0.5.0", "exception-reporting": "0.5.0", From 53547b5a8d91e5911bb3af8fe6823753b9f79c9a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 25 Oct 2013 09:12:22 -0700 Subject: [PATCH 21/21] Trigger commands on rootView when body is active element --- src/window-event-handler.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/window-event-handler.coffee b/src/window-event-handler.coffee index 5ee711be3..429cecdc9 100644 --- a/src/window-event-handler.coffee +++ b/src/window-event-handler.coffee @@ -14,7 +14,11 @@ class WindowEventHandler @reloadRequested = false @subscribe ipc, 'command', (command, args...) -> - $(document.activeElement).trigger(command, args...) + activeElement = document.activeElement + # Use root view if body has focus + if activeElement is document.body and atom.rootView? + activeElement = atom.rootView + $(activeElement).trigger(command, args...) @subscribe ipc, 'context-command', (command, args...) -> $(atom.contextMenu.activeElement).trigger(command, args...)