diff --git a/TODO.md b/TODO.md index b5e185c..b3f3bc0 100644 --- a/TODO.md +++ b/TODO.md @@ -9,3 +9,5 @@ - [x] When deserializing localFiles, check to see if the file is deleted and if so remove it. - [x] Display more information in "Show downloaded files" - [x] Store when files are downloaded + - [ ] Handle SFTP "expected" errors like PERMISSION_DENIED when navigating + - [ ] Add a "Remote File Modified" warning based on timestamp diff --git a/lib/main.coffee b/lib/main.coffee index 17b4da1..cbf9ec4 100644 --- a/lib/main.coffee +++ b/lib/main.coffee @@ -2,6 +2,8 @@ _ = require 'underscore-plus' # Import needed to register deserializer RemoteEditEditor = require './model/remote-edit-editor' + + # Deferred requirements OpenFilesView = null HostView = null @@ -99,6 +101,8 @@ module.exports = atom.commands.add('atom-workspace', 'remote-edit:create-file', => @createFilesView().createFile()) atom.commands.add('atom-workspace', 'remote-edit:rename-folder-file', => @createFilesView().renameFolderFile()) atom.commands.add('atom-workspace', 'remote-edit:remove-folder-file', => @createFilesView().deleteFolderFile()) + atom.commands.add('atom-workspace', 'remote-edit:cut-folder-file', => @createFilesView().copycutFolderFile(true)) + atom.commands.add('atom-workspace', 'remote-edit:paste-folder-file', => @createFilesView().pasteFolderFile()) deactivate: -> @ipdw?.destroy() @@ -134,7 +138,7 @@ module.exports = @filesView initializeIpdwIfNecessary: -> - if atom.config.get 'remote-edit.notifications' + if atom.config.get 'remote-edit2.notifications' stop = false for editor in atom.workspace.getTextEditors() when !stop if editor instanceof RemoteEditEditor @@ -145,7 +149,7 @@ module.exports = if @ipdw is undefined InterProcessDataWatcher ?= require './model/inter-process-data-watcher' fs = require 'fs-plus' - @ipdw = new InterProcessDataWatcher(fs.absolute(atom.config.get('remote-edit.defaultSerializePath'))) + @ipdw = new InterProcessDataWatcher(fs.absolute(atom.config.get('remote-edit2.defaultSerializePath'))) else @ipdw diff --git a/lib/model/ftp-host.coffee b/lib/model/ftp-host.coffee index 16c1a6b..d3abbee 100644 --- a/lib/model/ftp-host.coffee +++ b/lib/model/ftp-host.coffee @@ -69,7 +69,7 @@ module.exports = #################### # Overridden methods getConnectionString: (connectionOptions) -> - if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (keytar?) + if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (keytar?) keytarPassword = keytar.getPassword(@getServiceNamePassword(), @getServiceAccount()) _.extend({host: @hostname, port: @port, user: @username, password: keytarPassword}, connectionOptions) else @@ -110,7 +110,7 @@ module.exports = async.filter(objects, ((item, callback) -> callback(item?)), ((result) -> callback(null, result))) (objects, callback) -> objects.push(new RemoteFile((path + "/.."), false, true, false, null, null, null)) - if atom.config.get 'remote-edit.showHiddenFiles' + if atom.config.get 'remote-edit2.showHiddenFiles' callback(null, objects) else async.filter(objects, ((item, callback) -> item.isHidden(callback)), ((result) -> callback(null, result))) @@ -165,7 +165,7 @@ module.exports = @port localFiles: localFile.serialize() for localFile in @localFiles @usePassword - @password + password: new Buffer(@password).toString("base64") @lastOpenDirectory } @@ -173,6 +173,7 @@ module.exports = tmpArray = [] tmpArray.push(LocalFile.deserialize(localFile, host: this)) for localFile in params.localFiles params.localFiles = tmpArray + params.password = new Buffer(params.password, "base64").toString("utf8") params createFolder: (folderpath, callback) -> diff --git a/lib/model/host.coffee b/lib/model/host.coffee index 35f2d57..4345a41 100644 --- a/lib/model/host.coffee +++ b/lib/model/host.coffee @@ -14,10 +14,10 @@ module.exports = constructor: (@alias = null, @hostname, @directory = "/", @username = osenv.user(), @port, @localFiles = [], @usePassword, @lastOpenDirectory) -> @emitter = new Emitter @searchKey = @hostname - atom.config.observe "remote-edit.filterHostsUsing", (settings) => + atom.config.observe 'remote-edit2.filterHostsUsing', (settings) => @searchKey = @getSearchKey(settings) ? @searchKey - if atom.config.get 'remote-edit.clearFileList' + if atom.config.get 'remote-edit2.clearFileList' _.each(@localFiles, (val) => @removeLocalFile(val) ) diff --git a/lib/model/inter-process-data.coffee b/lib/model/inter-process-data.coffee index 4d8f73e..8517a39 100644 --- a/lib/model/inter-process-data.coffee +++ b/lib/model/inter-process-data.coffee @@ -34,7 +34,7 @@ module.exports = for host in @hostList @addSubscriptionToHost(host) - if atom.config.get 'remote-edit.notifications' + if atom.config.get 'remote-edit2.notifications' RemoteEditEditor ?= require '../model/remote-edit-editor' @disposables.add atom.workspace.observeTextEditors((editor) => @@ -69,7 +69,7 @@ module.exports = @hostList = _.reject(@hostList, ((val) -> val == host)) @emitter.emit 'did-change' - if atom.config.get 'remote-edit.notifications' + if atom.config.get 'remote-edit2.notifications' @disposables.add host.onInfo (info) => atom.notifications.add(info.type, info.message) addNewHost: (host) -> diff --git a/lib/model/remote-edit-editor.coffee b/lib/model/remote-edit-editor.coffee index 80e68c3..5fe1430 100644 --- a/lib/model/remote-edit-editor.coffee +++ b/lib/model/remote-edit-editor.coffee @@ -71,7 +71,7 @@ module.exports = @initiateUpload() initiateUpload: -> - if atom.config.get 'remote-edit.uploadOnSave' + if atom.config.get 'remote-edit2.uploadOnSave' @upload() else Dialog ?= require '../view/dialog' diff --git a/lib/model/sftp-host.coffee b/lib/model/sftp-host.coffee index 261070a..0da55cd 100644 --- a/lib/model/sftp-host.coffee +++ b/lib/model/sftp-host.coffee @@ -29,6 +29,10 @@ module.exports = protocol: "sftp" constructor: (@alias = null, @hostname, @directory, @username, @port = "22", @localFiles = [], @usePassword = false, @useAgent = true, @usePrivateKey = false, @password, @passphrase, @privateKeyPath, @lastOpenDirectory) -> + # Default to /home/ which is the most common case... + if @directory == "" + @directory = "/home/#{@username}" + super( @alias, @hostname, @directory, @username, @port, @localFiles, @usePassword, @lastOpenDirectory) getConnectionStringUsingAgent: -> @@ -38,8 +42,8 @@ module.exports = username: @username, } - if atom.config.get('remote-edit.agentToUse') != 'Default' - _.extend(connectionString, {agent: atom.config.get('remote-edit.agentToUse')}) + if atom.config.get('remote-edit2.agentToUse') != 'Default' + _.extend(connectionString, {agent: atom.config.get('remote-edit2.agentToUse')}) else if process.platform == "win32" _.extend(connectionString, {agent: 'pageant'}) else @@ -48,7 +52,7 @@ module.exports = connectionString getConnectionStringUsingKey: -> - if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (keytar?) + if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (keytar?) keytarPassphrase = keytar.getPassword(@getServiceNamePassphrase(), @getServiceAccount()) {host: @hostname, port: @port, username: @username, privateKey: @getPrivateKey(@privateKeyPath), passphrase: keytarPassphrase} else @@ -56,7 +60,7 @@ module.exports = getConnectionStringUsingPassword: -> - if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (keytar?) + if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (keytar?) keytarPassword = keytar.getPassword(@getServiceNamePassword(), @getServiceAccount()) {host: @hostname, port: @port, username: @username, password: keytarPassword} else @@ -113,6 +117,7 @@ module.exports = else callback(null) (callback) => + console.debug "Real Host Connect..." @connection = new ssh2() @connection.on 'error', (err) => @emitter.emit 'info', {message: "Error occured when connecting to sftp://#{@username}@#{@hostname}:#{@port}", type: 'error'} @@ -127,29 +132,35 @@ module.exports = ) isConnected: -> - @connection? and @connection._state == 'authenticated' + @connection? and @connection._sock and @connection._sock.writable and @connection._sshstream and @connection._sshstream.writable getFilesMetadata: (path, callback) -> async.waterfall([ (callback) => @connection.sftp(callback) - (sftp, callback) -> + (sftp, callback) => + # temp store in this so we can close it when we are done... + @tmp_sftp = sftp sftp.readdir(path, callback) (files, callback) => + # ... and now we are done! + @tmp_sftp.end() async.map(files, ((file, callback) => callback(null, @createRemoteFileFromFile(path, file))), callback) (objects, callback) -> objects.push(new RemoteFile((path + "/.."), false, true, false, null, null, null)) - if atom.config.get 'remote-edit.showHiddenFiles' + if atom.config.get 'remote-edit2.showHiddenFiles' callback(null, objects) else async.filter(objects, ((item, callback) -> item.isHidden(callback)), ((result) -> callback(null, result))) ], (err, result) => if err? @emitter.emit('info', {message: "Error occured when reading remote directory sftp://#{@username}@#{@hostname}:#{@port}:#{path}", type: 'error'} ) - console.error err if err? + console.error err + console.error err.code callback?(err) else callback?(err, (result.sort (a, b) -> return if a.name.toLowerCase() >= b.name.toLowerCase() then 1 else -1)) + ) getFile: (localFile, callback) -> @@ -162,6 +173,7 @@ module.exports = ], (err, sftp) => @emitter.emit('info', {message: "Error when reading remote file sftp://#{@username}@#{@hostname}:#{@port}#{localFile.remoteFile.path}", type: 'error'}) if err? @emitter.emit('info', {message: "Successfully read remote file sftp://#{@username}@#{@hostname}:#{@port}#{localFile.remoteFile.path}", type: 'success'}) if !err? + sftp?.end() callback?(err, localFile) ) @@ -171,18 +183,23 @@ module.exports = (callback) => @connection.sftp(callback) (sftp, callback) -> + @tmp_sftp = sftp sftp.fastPut(localFile.path, localFile.remoteFile.path, callback) + (callback) -> + @tmp_sftp.end() + callback() ], (err) => if err? @emitter.emit('info', {message: "Error occured when writing remote file sftp://#{@username}@#{@hostname}:#{@port}#{localFile.remoteFile.path}", type: 'error'}) console.error err if err? else @emitter.emit('info', {message: "Successfully wrote remote file sftp://#{@username}@#{@hostname}:#{@port}#{localFile.remoteFile.path}", type: 'success'}) - @close() + callback?(err) ) serializeParams: -> + tmp = if @password then @password else "" { @alias @hostname @@ -193,7 +210,7 @@ module.exports = @useAgent @usePrivateKey @usePassword - @password + password: new Buffer(tmp).toString("base64") @passphrase @privateKeyPath @lastOpenDirectory @@ -203,4 +220,116 @@ module.exports = tmpArray = [] tmpArray.push(LocalFile.deserialize(localFile, host: this)) for localFile in params.localFiles params.localFiles = tmpArray + params.password = new Buffer(params.password, "base64").toString("utf8") params + + # Create the folder and call the callback. The callback will be called + # for both erroe cases (1st arg) and success (2nd arg is the path) + createFolder: (folderpath, callback) -> + @emitter.emit 'info', {message: "Creating remote directory at sftp://#{@username}@#{@hostname}:#{@port}#{folderpath}", type: 'info'} + async.waterfall([ + (callback) => + @connection.sftp(callback) + (sftp, callback) -> + sftp.mkdir(folderpath, callback) + sftp.end() + callback(null, folderpath) + ], (err) => + if err? + @emitter.emit('info', {message: "Error occured while creating remote directory sftp://#{@username}@#{@hostname}:#{@port}#{folderpath}", type: 'error'}) + console.error err if err? + else + @emitter.emit('info', {message: "Successfully created directory sftp://#{@username}@#{@hostname}:#{@port}#{folderpath}", type: 'success'}) + callback(err) + ) + + + createFile: (filepath, callback) -> + @emitter.emit 'info', {message: "Creating remote file at sftp://#{@username}@#{@hostname}:#{@port}#{filepath}", type: 'info'} + async.waterfall([ + (callback) => + @connection.sftp(callback) + (sftp, callback) => + @tmp_sftp = sftp + sftp.exists(filepath, callback) + (callback) => + @tmp_sftp.writeFile(filepath, "", callback) + (callback) => + @tmp_sftp.end() + callback() + ], (err) => + if err? + if err == true + @emitter.emit('info', {message: "Fle ftp://#{@username}@#{@hostname}:#{@port}#{filepath} already exists", type: 'error'}) + else + @emitter.emit('info', {message: "Error occurred while creating remote file ftp://#{@username}@#{@hostname}:#{@port}#{filepath}", type: 'error'}) + console.error err if err? + else + @emitter.emit('info', {message: "Successfully wrote remote file ftp://#{@username}@#{@hostname}:#{@port}#{filepath}", type: 'success'}) + callback?(err) + ) + + + deleteFolderFile: (deletepath, isFolder, callback) -> + async.waterfall([ + (callback) => + @connection.sftp(callback) + (sftp, callback) => + @tmp_sftp = sftp + if isFolder + sftp.rmdir(deletepath, callback) + else + sftp.unlink(deletepath, callback) + (callback) => + @tmp_sftp.end() + callback(null) + ], (err) => + if err? + @emitter.emit('info', {message: "Error occurred when deleting remote folder/file sftp://#{@username}@#{@hostname}:#{@port}#{deletepath}", type: 'error'}) + console.error err if err? + else + @emitter.emit('info', {message: "Successfully deleted remote folder/file sftp://#{@username}@#{@hostname}:#{@port}#{deletepath}", type: 'success'}) + callback?(err) + ) + + # Rename jsut constructs paths and calls moveFolderFile which is more generic + renameFolderFile: (path, oldName, newName, isFolder, callback) => + if oldName == newName + @emitter.emit('info', {message: "The new name is same as the old", type: 'error'}) + return + oldPath = path + "/" + oldName + newPath = path + "/" + newName + @moveFolderFile(oldPath, newPath, isFolder, callback) + + moveFolderFile: (oldPath, newPath, isFolder, callback) -> + async.waterfall([ + (callback) => + @connection.sftp(callback) + (sftp, callback) => + @tmp_sftp = sftp + if isFolder + sftp.readdir(newPath, callback) + else + sftp.exists(newPath, callback) + ], (err, result) => + console.log result + if (isFolder and result != undefined) or (!isFolder and err==true) + @emitter.emit('info', {message: "#{if isFolder then 'Folder' else 'File'} already exists", type: 'error'}) + @tmp_sftp.end() + return + + async.waterfall([ + (callback) => + @tmp_sftp.rename(oldPath, newPath, callback) + (callback) => + @tmp_sftp.end() + callback() + ], (err) => + if err? + @emitter.emit('info', {message: "Error occurred when renaming remote folder/file sftp://#{@username}@#{@hostname}:#{@port}#{oldPath}", type: 'error'}) + console.error err if err? + else + @emitter.emit('info', {message: "Successfully renamed remote folder/file sftp://#{@username}@#{@hostname}:#{@port}#{oldPath}", type: 'success'}) + callback?(err) + ) + ) diff --git a/lib/view/files-view.coffee b/lib/view/files-view.coffee index 117b69e..393734e 100644 --- a/lib/view/files-view.coffee +++ b/lib/view/files-view.coffee @@ -1,5 +1,6 @@ -{$, $$, View} = require 'atom-space-pen-views' -{CompositeDisposable, Emitter} = require 'atom' +{$, $$, TextEditorView} = require 'atom-space-pen-views' +{View} = require 'space-pen' +{CompositeDisposable, Emitter, TextEditor} = require 'atom' LocalFile = require '../model/local-file' Dialog = require './dialog' @@ -21,26 +22,61 @@ module.exports = @content: -> @div class: 'remote-edit-tree-view remote-edit-resizer tool-panel', 'data-show-on-right-side': false, => @div class: 'remote-edit-scroller order--center', => - @div class: 'remote-edit-info focusable-panel', tabindex: -1, click: 'clickInfo', => + @div class: 'remote-edit-info focusable-panel', click: 'clickInfo', => @p class: 'remote-edit-server', => @span class: 'remote-edit-server-type inline-block', 'FTP:' @span class: 'remote-edit-server-alias inline-block highlight', outlet: 'server_alias', 'unknown' @p class: 'remote-edit-folder text-bold', => @span 'Folder: ' @span outlet: 'server_folder', 'unknown' + # @tag 'atom-text-editor', 'mini': true, class: 'native-key-bindings', outlet: 'filter' + # Gettext does not exist cause there is no model behind this... + @input class: 'remote-edit-filter-text native-key-bindings', tabindex: 1, outlet: 'filter' + # @subview 'filter', new SimpleTextView(mini: true, password: true) @div class: 'remote-edit-scroller', outlet: 'scroller', => @ol class: 'list-tree full-menu focusable-panel', tabindex: -1, outlet: 'list' @div class: 'remote-edit-message', outlet: 'message' @div class: 'remote-edit-resize-handle', outlet: 'resizeHandle' + doFilter: (e) -> + switch e.keyCode + when 13 + toOpen = @filter.val() + if @filter.val()[0] == "." or @filter.val()[0] != "/" + toOpen = @path + "/" + @filter.val() + + @openDirectory(toOpen, (err) => + if err? + @setError("Could not open location") + else + @filter.val("") + ) + return + + # Hide the elements that do not match the filter's value + console.debug "checking for " + @filter.val() + if @filter.val().length > 0 + @list.find('li span').each (index, item) => + if ! $(item).text().match(@filter.val()) + $(item).addClass('hidden') + else + $(item).removeClass('hidden') + else + @list.find('li span').removeClass('hidden') + + e.preventDefault() + + initialize: (@host) -> @emitter = new Emitter @disposables = new CompositeDisposable @listenForEvents() + @cutPasteBuffer = {} connect: (connectionOptions = {}, connect_path = false) -> - dir = upath.normalize(if connect_path then connect_path else if atom.config.get('remote-edit.rememberLastOpenDirectory') and @host.lastOpenDirectory? then @host.lastOpenDirectory else @host.directory) + console.debug "re-connecting (FilesView::connect) to #{connect_path}" + dir = upath.normalize(if connect_path then connect_path else if atom.config.get('remote-edit2.rememberLastOpenDirectory') and @host.lastOpenDirectory? then @host.lastOpenDirectory else @host.directory) async.waterfall([ (callback) => if @host.usePassword and !connectionOptions.password? @@ -74,6 +110,7 @@ module.exports = @setError("You do not have read permission to what you've specified as the default directory! See the console for more info.") else if err.code is 2 and @path is @host.lastOpenDirectory # no such file, can occur if lastOpenDirectory is used and the dir has been removed + console.debug "No such file, can occur if lastOpenDirectory is used and the dir has been removed" @host.lastOpenDirectory = undefined @connect(connectionOptions) else if @host.usePassword and (err.code == 530 or err.level == "connection-ssh") @@ -130,13 +167,16 @@ module.exports = (callback) => @host.getFilesMetadata(dir, callback) (items, callback) => - items = _.sortBy(items, 'isFile') if atom.config.get 'remote-edit.foldersOnTop' + items = _.sortBy(items, 'isFile') if atom.config.get 'remote-edit2.foldersOnTop' @setItems(items) callback(undefined, undefined) ], (err, result) => - @updatePath(dir) - @populateInfo() - @setError(err) if err? + if ! err + @updatePath(dir) + @populateInfo() + else + @setError(err) if err? + callback?(err, result) ) @@ -187,13 +227,20 @@ module.exports = openFile: (file) => dtime = moment().format("HH:mm:ss DD/MM/YY") + async.waterfall([ + (callback) => + if !@host.isConnected() + @setMessage("Connecting...") + @host.connect(callback) + else + callback(null) (callback) => @getDefaultSaveDirForHostAndFile(file, callback) (savePath, callback) => savePath = savePath + path.sep + dtime.replace(/([^a-z0-9\s]+)/gi, '').replace(/([\s]+)/gi, '-') + "_" + file.name localFile = new LocalFile(savePath, file, dtime, @host) - @host.getFile(localFile, callback) + uri = path.normalize(savePath) filePane = atom.workspace.paneForURI(uri) if filePane @@ -223,20 +270,25 @@ module.exports = atom.workspace.open(uri, split: 'left') ) - openDirectory: (dir) => + openDirectory: (dir, callback) => dir = upath.normalize(dir) async.waterfall([ (callback) => if !@host.isConnected() - @connect({}, dir) - callback(null) + @setMessage("Connecting...") + @host.connect(callback) + else + callback(null) (callback) => @host.invalidate() - @populate(dir) - ], (err, savePath) -> - callback(err, savePath) + @populate(dir, callback) + ], (err) -> + callback?(err) ) + # + # Called on event listener to handle all actions of the file list + # confirmed: (item) -> async.waterfall([ (callback) => @@ -251,7 +303,7 @@ module.exports = @host.invalidate() @populate(item.path) else if item.isLink - if atom.config.get('remote-edit.followLinks') + if atom.config.get('remote-edit2.followLinks') @populate(item.path) else @openFile(item) @@ -296,6 +348,8 @@ module.exports = @on 'mousedown', '.remote-edit-resize-handle', (e) => @resizeStarted(e) + @filter.on "keyup", (e) => @doFilter(e) + @disposables.add atom.commands.add 'atom-workspace', 'filesview:open', => item = @getSelectedItem() if item.isFile @@ -313,7 +367,7 @@ module.exports = @list.empty() if @items.length - for item in items + for item in @items itemView = $(@viewForItem(item)) itemView.data('select-list-item', item) @list.append(itemView) @@ -386,6 +440,43 @@ module.exports = else throw new Error("Not implemented yet!") + copycutFolderFile: (cut=false) => + if @selectedItem and @selectedItem.name and @selectedItem.name != '.' + @cutPasteBuffer = { + name: @selectedItem.name + oldPath: @path + "/" + @selectedItem.name + isDir: @selectedItem.isDir + cut: cut + } + + pasteFolderFile: () => + if !@cutPasteBuffer or !@cutPasteBuffer.oldPath or @cutPasteBuffer.oldPath == '.' + @setError("Nothing to paste") + return + + # Construct the new path using the old name + @cutPasteBuffer.newPath = @path + '/' + @cutPasteBuffer.name + + # We only support cut... copying a folder we need to do recursive stuff... + if !@cutPasteBuffer.cut + throw new Error("Copy is Not implemented yet!") + + if typeof @host.moveFolderFile == 'function' + if @selectedItem and @selectedItem.name and @selectedItem.name != '.' + async.waterfall([ + (newname, callback) => + @deselect() + @host.moveFolderFile(@cutPasteBuffer.oldPath, @cutPasteBuffer.newPath, @cutPasteBuffer.isDir, () => + @openDirectory(@path) + # reset buffer + @cutPasteBuffer = {} + ) + ], (err, result) => + @openDirectory(@path) + ) + else + throw new Error("Not implemented yet!") + deselect: () -> @list.find('li.selected').removeClass('selected'); diff --git a/lib/view/host-view.coffee b/lib/view/host-view.coffee index a6b6a94..d93f63d 100644 --- a/lib/view/host-view.coffee +++ b/lib/view/host-view.coffee @@ -85,14 +85,14 @@ module.exports = @port.setText(@host.port ? "") - if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (keytar?) + if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (keytar?) keytarPassword = keytar.getPassword(@host.getServiceNamePassword(), @host.getServiceAccount()) @password.setText(keytarPassword ? "") else @password.setText(@host.password ? "") - @privateKeyPath.setText(@host.privateKeyPath ? atom.config.get('remote-edit.sshPrivateKeyPath')) - if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (@host instanceof SftpHost) and (keytar?) + @privateKeyPath.setText(@host.privateKeyPath ? atom.config.get('remote-edit2.sshPrivateKeyPath')) + if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (@host instanceof SftpHost) and (keytar?) keytarPassphrase = keytar.getPassword(@host.getServiceNamePassphrase(), @host.getServiceAccount()) @privateKeyPassphrase.setText(keytarPassphrase ? "") else @@ -156,29 +156,29 @@ module.exports = if @privateKeyButton.hasClass('selected') @host.privateKeyPath = fs.absolute(@privateKeyPath.getText()) - if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (@privateKeyPassphrase.getText().length > 0) and (keytar?) + if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (@privateKeyPassphrase.getText().length > 0) and (keytar?) keytar.replacePassword(@host.getServiceNamePassphrase(), @host.getServiceAccount(), @privateKeyPassphrase.getText()) @host.passphrase = "***** keytar *****" - else if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (@privateKeyPassphrase.getText().length is 0) + else if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (@privateKeyPassphrase.getText().length is 0) keytar.deletePassword(@host.getServiceNamePassphrase(), @host.getServiceAccount()) @host.passphrase = "" else @host.passphrase = @privateKeyPassphrase.getText() if @passwordButton.hasClass('selected') - if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (@password.getText().length > 0) and (keytar?) + if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (@password.getText().length > 0) and (keytar?) keytarResult = keytar.replacePassword(@host.getServiceNamePassword(), @host.getServiceAccount(), @password.getText()) @host.password = "***** keytar *****" - else if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (@password.getText().length is 0) and (keytar?) + else if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (@password.getText().length is 0) and (keytar?) keytar.deletePassword(@host.getServiceNamePassword(), @host.getServiceAccount()) @host.password = "" else @host.password = @password.getText() else if @host instanceof FtpHost @host.usePassword = true - if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (@password.getText().length > 0) and (keytar?) + if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (@password.getText().length > 0) and (keytar?) keytarResult = keytar.replacePassword(@host.getServiceNamePassword(), @host.getServiceAccount(), @password.getText()) @host.password = "***** keytar *****" - else if atom.config.get('remote-edit.storePasswordsUsingKeytar') and (@password.getText().length is 0) and (keytar?) + else if atom.config.get('remote-edit2.storePasswordsUsingKeytar') and (@password.getText().length is 0) and (keytar?) keytar.deletePassword(@host.getServiceNamePassword(), @host.getServiceAccount()) @host.password = "" else diff --git a/menus/remote-edit.cson b/menus/remote-edit.cson index a1fc1b6..ad2d465 100644 --- a/menus/remote-edit.cson +++ b/menus/remote-edit.cson @@ -25,4 +25,8 @@ {'label': 'Create file', 'command': 'remote-edit:create-file'} {'label': 'Rename', 'command': 'remote-edit:rename-folder-file'} {'label': 'Remove folder/file', 'command': 'remote-edit:remove-folder-file'} + {'type': 'separator'} + #{'label': 'Copy', 'command': 'remote-edit:copy-folder-file'} + {'label': 'Cut', 'command': 'remote-edit:cut-folder-file'} + {'label': 'Paste', 'command': 'remote-edit:paste-folder-file'} ] diff --git a/package.json b/package.json index 7fefbd4..4f32d9f 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { "name": "remote-edit2", "main": "./lib/main.coffee", - "version": "3.0.0", + "version": "3.0.1", "description": "Browse and edit remote files using SFTP and FTP", "homepage": "https://github.com/duxet/remote-edit2", "repository": { "type": "git", - "url": "https://github.com/duxet/remote-edit2.git" + "url": "https://github.com/urban-1/remote-edit2.git" }, "bugs": { - "url": "https://github.com/duxet/remote-edit2/issues" + "url": "https://github.com/urban-1/remote-edit2/issues" }, "license": "MIT", "author": { @@ -24,7 +24,7 @@ "async": "<2.0.0", "file-size": ">=0.0.5", "moment": ">=2.7.0", - "ssh2": "~0.4.7", + "ssh2": ">=0.5.2", "serializable": ">=1.0.0", "string-hash": ">=1.1.0", "osenv": ">=0.1.0", @@ -52,5 +52,10 @@ "remote", "edit", "sync" - ] + ], + "apmInstallSource": { + "type": "git", + "source": "https://github.com/urban-1/remote-edit2.git", + "sha": "e3145de753e29cccb33023a6220bfdadd6f30713" + } } diff --git a/spec/remote-edit-spec.coffee b/spec/remote-edit-spec.coffee index 1a1a880..31915ae 100644 --- a/spec/remote-edit-spec.coffee +++ b/spec/remote-edit-spec.coffee @@ -11,7 +11,7 @@ describe "remote-edit:", -> workspaceElement = atom.views.getView(atom.workspace) activationPromise = null - atom.config.set 'remote-edit.defaultSerializePath', "#{fixture.getSerializePath()}" + atom.config.set 'remote-edit2.defaultSerializePath', "#{fixture.getSerializePath()}" waitsForPromise -> atom.workspace.open()