diff --git a/atom.gyp b/atom.gyp index 907219da59f..300b577fb95 100644 --- a/atom.gyp +++ b/atom.gyp @@ -39,6 +39,7 @@ 'atom/common/api/lib/screen.coffee', 'atom/common/api/lib/shell.coffee', 'atom/common/lib/init.coffee', + 'atom/common/lib/asar.coffee', 'atom/renderer/lib/chrome-api.coffee', 'atom/renderer/lib/init.coffee', 'atom/renderer/lib/inspector.coffee', diff --git a/atom/browser/lib/init.coffee b/atom/browser/lib/init.coffee index d25179c1ba4..c1f8b779ba8 100644 --- a/atom/browser/lib/init.coffee +++ b/atom/browser/lib/init.coffee @@ -80,7 +80,7 @@ setImmediate -> # Set application's desktop name. if packageJson.desktopName? app.setDesktopName packageJson.desktopName - else + else app.setDesktopName '#{app.getName()}.desktop' # Load the chrome extension support. diff --git a/atom/common/api/atom_api_asar.cc b/atom/common/api/atom_api_asar.cc index 44fcfafd31a..525af42d1cc 100644 --- a/atom/common/api/atom_api_asar.cc +++ b/atom/common/api/atom_api_asar.cc @@ -21,7 +21,7 @@ class Archive : public mate::Wrappable { static asar::ArchiveFactory archive_factory; scoped_refptr archive = archive_factory.GetOrCreate(path); if (!archive) - return args->ThrowError("Invalid asar archive"); + return v8::False(args->isolate()); return (new Archive(archive))->GetWrapper(args->isolate()); } @@ -34,7 +34,7 @@ class Archive : public mate::Wrappable { const base::FilePath& path) { asar::Archive::FileInfo info; if (!archive_->GetFileInfo(path, &info)) - return args->ThrowError("Can not find file"); + return v8::False(args->isolate()); mate::Dictionary dict(args->isolate(), v8::Object::New(args->isolate())); dict.Set("size", info.size); dict.Set("offset", info.offset); @@ -46,7 +46,7 @@ class Archive : public mate::Wrappable { const base::FilePath& path) { asar::Archive::Stats stats; if (!archive_->Stat(path, &stats)) - return args->ThrowError("Can not find file"); + return v8::False(args->isolate()); mate::Dictionary dict(args->isolate(), v8::Object::New(args->isolate())); dict.Set("size", stats.size); dict.Set("offset", stats.offset); diff --git a/atom/common/lib/asar.coffee b/atom/common/lib/asar.coffee new file mode 100644 index 00000000000..9d35deeffb3 --- /dev/null +++ b/atom/common/lib/asar.coffee @@ -0,0 +1,64 @@ +asar = process.atomBinding 'asar' +fs = require 'fs' +path = require 'path' + +# Separate asar package's path from full path. +splitPath = (p) -> + components = p.split path.sep + for c, i in components by -1 + if path.extname(c) is '.asar' + asarPath = components.slice(0, i + 1).join path.sep + filePath = components.slice(i + 1).join path.sep + return [true, asarPath, filePath] + return [false, p] + +# Convert asar archive's Stats object to fs's Stats object. +asarStatsToFsStats = (stats) -> + { + size: stats.size + isFile: -> stats.isFile + isDirectory: -> stats.isDirectory + isSymbolicLink: -> stats.isLink + isBlockDevice: -> false + isCharacterDevice: -> false + isFIFO: -> false + isSocket: -> false + } + +# Override fs APIs. +statSync = fs.statSync +fs.statSync = (p) -> + [isAsar, asarPath, filePath] = splitPath p + return statSync p unless isAsar + + archive = asar.createArchive asarPath + throw new Error("Invalid package #{asarPath}") unless archive + + stats = archive.stat filePath + throw new Error("#{filePath} not found in #{asarPath}") unless stats + + asarStatsToFsStats stats + +stat = fs.stat +fs.stat = (p, callback) -> + [isAsar, asarPath, filePath] = splitPath p + return stat p, callback unless isAsar + + archive = asar.createArchive asarPath + return callback throw new Error("Invalid package #{asarPath}") unless archive + + stats = asar.createArchive(asarPath).stat filePath + return callback new Error("#{filePath} not found in #{asarPath}") unless stats + + callback undefined, asarStatsToFsStats stats + +statSyncNoException = fs.statSyncNoException +fs.statSyncNoException = (p) -> + [isAsar, asarPath, filePath] = splitPath p + return statSyncNoException p unless isAsar + + archive = asar.createArchive asarPath + return false unless archive + stats = asar.createArchive(asarPath).stat filePath + return false unless stats + asarStatsToFsStats stats diff --git a/atom/common/lib/init.coffee b/atom/common/lib/init.coffee index 0b4b2c224ac..c85fb65a958 100644 --- a/atom/common/lib/init.coffee +++ b/atom/common/lib/init.coffee @@ -33,3 +33,6 @@ global.clearImmediate = timers.clearImmediate if process.type is 'browser' global.setTimeout = wrapWithActivateUvLoop timers.setTimeout global.setInterval = wrapWithActivateUvLoop timers.setInterval + +# Add support for asar packages. +require './asar'