diff --git a/spec/atom-portable-spec.coffee b/spec/atom-portable-spec.coffee index 4665621ff..eaf919170 100644 --- a/spec/atom-portable-spec.coffee +++ b/spec/atom-portable-spec.coffee @@ -1,9 +1,29 @@ path = require "path" fs = require 'fs-plus' temp = require "temp" -rimraf = require "rimraf" AtomPortable = require "../src/browser/atom-portable" +describe "Set Portable Mode on #win32", -> + portableAtomHomePath = path.join(path.dirname(process.execPath), "..", ".atom") + portableAtomHomeNaturallyExists = fs.existsSync(portableAtomHomePath) + portableAtomHomeBackupPath = "#{portableAtomHomePath}.temp" + + beforeEach -> + fs.renameSync(portableAtomHomePath, portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomePath) + + afterEach -> + if portableAtomHomeNaturallyExists + fs.renameSync(portableAtomHomeBackupPath, portableAtomHomePath) if not fs.existsSync(portableAtomHomePath) + else + fs.removeSync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath) + fs.removeSync(portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomeBackupPath) + + it "creates a portable home directory", -> + expect(fs.existsSync(portableAtomHomePath)).toBe false + + AtomPortable.setPortable(process.env.ATOM_HOME) + expect(fs.existsSync(portableAtomHomePath)).toBe true + describe "Check for Portable Mode", -> describe "Windows", -> describe "with ATOM_HOME environment variable", -> @@ -23,8 +43,8 @@ describe "Check for Portable Mode", -> if portableAtomHomeNaturallyExists fs.renameSync(portableAtomHomeBackupPath, portableAtomHomePath) if not fs.existsSync(portableAtomHomePath) else - rimraf.sync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath) - rimraf.sync(portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomeBackupPath) + fs.removeSync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath) + fs.removeSync(portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomeBackupPath) describe "with .atom directory sibling to exec", -> beforeEach -> @@ -35,7 +55,7 @@ describe "Check for Portable Mode", -> describe "without .atom directory sibling to exec", -> beforeEach -> - rimraf.sync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath) + fs.removeSync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath) it "returns false", -> expect(AtomPortable.isPortableInstall("win32", environmentAtomHome)).toBe false diff --git a/src/browser/atom-portable.coffee b/src/browser/atom-portable.coffee index a8cbd2d41..06ca6865e 100644 --- a/src/browser/atom-portable.coffee +++ b/src/browser/atom-portable.coffee @@ -8,6 +8,9 @@ class AtomPortable execDirectoryPath = path.dirname(process.execPath) path.join(execDirectoryPath, '..', '.atom') + @setPortable: (existingAtomHome) -> + fs.copySync(existingAtomHome, @getPortableAtomHomePath()) + @isPortableInstall: (platform, environmentAtomHome, defaultHome) -> return false unless platform is 'win32' return false if environmentAtomHome diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 48485486b..ca9d7e3ae 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -12,15 +12,14 @@ yargs = require 'yargs' console.log = require 'nslog' start = -> - setupAtomHome() + args = parseCommandLine() + setupAtomHome(args) setupCompileCache() return if handleStartupEventWithSquirrel() # NB: This prevents Win10 from showing dupe items in the taskbar app.setAppUserModelId('com.squirrel.atom.atom') - args = parseCommandLine() - addPathToOpen = (event, pathToOpen) -> event.preventDefault() args.pathsToOpen.push(pathToOpen) @@ -57,13 +56,25 @@ handleStartupEventWithSquirrel = -> setupCrashReporter = -> crashReporter.start(productName: 'Atom', companyName: 'GitHub') -setupAtomHome = -> +setupAtomHome = ({setPortable}) -> return if process.env.ATOM_HOME + atomHome = path.join(app.getHomeDir(), '.atom') AtomPortable = require './atom-portable' - atomHome = AtomPortable.getPortableAtomHomePath() if AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome) + + if setPortable and not AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome) + try + AtomPortable.setPortable(atomHome) + catch error + console.log("Failed copying portable directory '#{atomHome}' to '#{AtomPortable.getPortableAtomHomePath()}'") + console.log("#{error.message} #{error.stack}") + + if AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome) + atomHome = AtomPortable.getPortableAtomHomePath() + try atomHome = fs.realpathSync(atomHome) + process.env.ATOM_HOME = atomHome setupCompileCache = -> @@ -102,6 +113,7 @@ parseCommandLine = -> options.boolean('profile-startup').describe('profile-startup', 'Create a profile of the startup execution time.') options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the Atom source directory and enable dev-mode.') options.boolean('safe').describe('safe', 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.') + options.boolean('portable').describe('portable', 'Set portable mode. Copies the ~/.atom folder to be a sibling of the installed Atom location if a .atom folder is not already there.') options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.') options.string('timeout').describe('timeout', 'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).') options.alias('v', 'version').boolean('v').describe('v', 'Print the version.') @@ -131,6 +143,7 @@ parseCommandLine = -> profileStartup = args['profile-startup'] urlsToOpen = [] devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH ? path.join(app.getHomeDir(), 'github', 'atom') + setPortable = args.portable if args['resource-path'] devMode = true @@ -151,6 +164,6 @@ parseCommandLine = -> {resourcePath, devResourcePath, pathsToOpen, urlsToOpen, executedFrom, test, version, pidToKillWhenClosed, devMode, safeMode, newWindow, - logFile, socketPath, profileStartup, timeout} + logFile, socketPath, profileStartup, timeout, setPortable} start()