sshfsmount 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 15c81068a30c8ed5a61b3fcc19d7a6503036762d
4
- data.tar.gz: '0943c0fbd855d60f5c349c29cba4fd209ab89e03'
3
+ metadata.gz: 0f9330ebd590ac3a49fb68f3166a18f1e8666ca5
4
+ data.tar.gz: 6ad40fe249ba8b6a82f365fae9518e9b351972d3
5
5
  SHA512:
6
- metadata.gz: fdc671ab26209081bd02081aba7515a56c7fecbc6ea6e4162cc5866678e9323abe8db71d0d208f7dc6c426e72c329632c7652a989d58f3157db31a5c0e644fc2
7
- data.tar.gz: a2a64b1d2500f7889fd46646f7e0e46c7a1c529a059fb8fcca7a456d987504766e5209c0d4c032ff169906c4615ea9ef9542a90aefb4d60922fcb038fbda03ec
6
+ metadata.gz: 31eac3dbd23722dbacb13dc2d15e0e5495870d758c0a87eaab7e2eadba5b382b83b336f248f6eb04afa5582120e55da270e217eb90193cc9ea15dcfb65c834a9
7
+ data.tar.gz: d42f434f5a1d99b9099b9e9ec6a97737c5cd83089381fe2ca40429d6ea6fa4678fea67e66c72b517463a6558da83444ffca9dfd5dc3ca3db86d8bafe0b8a00d2
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![Build Status](https://travis-ci.org/nomoon/sshfsmount.svg?branch=master)](https://travis-ci.org/nomoon/sshfsmount)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/nomoon/sshfsmount/badge.svg?branch=master)](https://coveralls.io/github/nomoon/sshfsmount?branch=master)
5
5
  [![Dependency Status](https://gemnasium.com/badges/github.com/nomoon/sshfsmount.svg)](https://gemnasium.com/github.com/nomoon/sshfsmount)
6
+ [![Gem Version](https://badge.fury.io/rb/sshfsmount.svg)](https://badge.fury.io/rb/sshfsmount)
6
7
 
7
8
  A simple front-end CLI to SSHFS.
8
9
 
@@ -1,156 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "gli"
5
- require "json"
6
- require "shellwords"
7
- require "fileutils"
8
-
9
4
  require "sshfsmount"
10
-
11
- #
12
- # Basic SSHFS flags
13
- #
14
- SSHFS_FLAGS = [
15
- "-o local",
16
- "-o workaround=nonodelaysrv",
17
- "-o transform_symlinks",
18
- "-o idmap=user",
19
- "-C",
20
- ].freeze
21
-
22
- #
23
- # Locate config file.
24
- #
25
- CONFIG_FILE = [
26
- File.join(Dir.home, ".sshfsmount.json"),
27
- File.join(Dir.home, ".config", "sshfsmount.json"),
28
- File.join(Dir.home, ".config", "sshfsmount", "sshfsmount.json"),
29
- ].select { |f| File.exist?(f) }.first.freeze
30
-
31
- #
32
- # Parse config file
33
- #
34
- CONFIG = (begin
35
- if CONFIG_FILE.nil?
36
- STDERR.puts "No config file found"
37
- {}
38
- else
39
- JSON.parse(File.read(CONFIG_FILE), symbolize_names: true)
40
- end
41
- rescue JSON::ParserError => e
42
- STDERR.puts "Parse error in config file `#{CONFIG_FILE}`: #{e}"
43
- {}
44
- end).freeze
45
-
46
- #
47
- # Create Mount-point Directory
48
- #
49
- def mkmountpoint(name)
50
- local = File.expand_path(name)
51
- if !Dir.exist?(local)
52
- STDERR.puts "Creating mount-point directory #{local}"
53
- FileUtils.mkdir_p(local)
54
- elsif !Dir.empty?(local)
55
- raise "Mount point #{local} already exists and is not empty"
56
- elsif VERBOSE
57
- STDERR.puts "Mount-point directory #{local} already exists and is empty"
58
- end
59
- local
60
- end
61
-
62
- #
63
- # Delete mount-point directory
64
- #
65
- def rmmountpoint(name)
66
- local = File.expand_path(name)
67
- if !Dir.exist?(local)
68
- STDERR.puts "Mount-point directory not found" if VERBOSE
69
- elsif !Dir.empty?(local)
70
- raise "Mount-point directory #{local} is not empty"
71
- else
72
- STDERR.puts "Deleting mount-point directory #{local}"
73
- FileUtils.rmdir(local)
74
- end
75
- local
76
- end
77
-
78
- #
79
- # Mount an SSHFS volume
80
- #
81
- def mount(mount_name, params)
82
- local = mkmountpoint(params[:local])
83
- volname = params[:volname] || mount_name
84
- p_remote = Shellwords.escape(params[:remote])
85
- p_local = Shellwords.escape(local)
86
- p_volname = Shellwords.escape(volname)
87
- port = (params[:port] || 22).to_i
88
- cmd = "/usr/local/bin/sshfs #{p_remote} #{p_local} " \
89
- "-o volname=\"#{p_volname}\" #{SSHFS_FLAGS.join(' ')} -p #{port}"
90
- pgrep = `pgrep -f \"#{cmd}\"`
91
- unless pgrep.empty?
92
- raise "SSHFS process for #{mount_name} running already (PID: #{pgrep.strip}, " \
93
- "Mount-point: #{p_local})"
94
- end
95
- puts "Mounting #{params[:remote]} to #{params[:local]} as \"#{volname}\""
96
- STDERR.puts "> #{cmd}" if VERBOSE
97
- system(cmd)
98
- end
99
-
100
- #
101
- # Unmount an SSHFS volume
102
- #
103
- def unmount(mount_name, params)
104
- local = File.expand_path(params[:local])
105
- p_local = Shellwords.escape(local)
106
- cmd = "diskutil unmount #{p_local}"
107
- pgrep = `pgrep -f \"#{p_local}\"`
108
- if pgrep.empty?
109
- raise "No SSHFS process found with the mount-point for #{mount_name} (#{p_local})"
110
- end
111
- puts "Unmounting #{local}"
112
- STDERR.puts "> #{cmd}" if VERBOSE
113
- system(cmd)
114
- rmmountpoint(local)
115
- end
116
-
117
- #
118
- # GLI command-line app definition
119
- #
120
- include GLI::App
121
-
122
- program_desc "A simple front-end CLI to SSHFS"
123
- version Sshfsmount::VERSION
124
-
125
- switch %i[u unmount], desc: "Unmount the volume", negatable: false
126
- switch %i[v verbose], desc: "Show verbose output", negatable: false
127
-
128
- desc "List active SSHFS processes"
129
- command :active do |c|
130
- c.action do
131
- system("pgrep -fl sshfs")
132
- end
133
- end
134
-
135
- #
136
- # Define commands from data-file
137
- #
138
- extant_commands = commands.keys
139
- CONFIG.reject { |name, _| extant_commands.include?(name) }.each do |mount_name, params|
140
- desc "mount #{params[:remote]} to #{params[:local]}"
141
- command mount_name do |c|
142
- c.switch %i[u unmount], desc: "Unmount the volume", negatable: false
143
- c.switch %i[v verbose], desc: "Show verbose output", negatable: false
144
- c.action do |global_options, cmd_options|
145
- VERBOSE = global_options[:v] || cmd_options[:v]
146
- if global_options[:u] || cmd_options[:u]
147
- unmount(mount_name, params)
148
- else
149
- mount(mount_name, params)
150
- end
151
- end
152
- end
153
- end
5
+ require "sshfsmount/cli"
154
6
 
155
7
  # Run the GLI app
156
- exit run(ARGV)
8
+ exit Sshfsmount::CLI.run(ARGV)
@@ -1,7 +1,164 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "json"
4
+ require "shellwords"
5
+ require "pathname"
6
+
3
7
  require "sshfsmount/version"
4
8
 
5
9
  module Sshfsmount
6
- # Your code goes here...
10
+ #
11
+ # Basic SSHFS flags
12
+ #
13
+ SSHFS_FLAGS = [
14
+ "-o local",
15
+ "-o workaround=nonodelaysrv",
16
+ "-o transform_symlinks",
17
+ "-o idmap=user",
18
+ "-C",
19
+ ].freeze
20
+
21
+ module_function
22
+
23
+ def verbose
24
+ @verbose
25
+ end
26
+
27
+ def verbose=(val)
28
+ @verbose = val ? true : false
29
+ end
30
+
31
+ def sshfs_cmd
32
+ sshfs_cmd = `command -v sshfs`.strip
33
+ raise "sshfs command not found in path" if sshfs_cmd.empty?
34
+ sshfs_cmd
35
+ end
36
+
37
+ #
38
+ # Locate config file.
39
+ #
40
+ def find_config_file
41
+ @config_file ||= begin
42
+ [
43
+ Pathname.new(File.join(Dir.home, ".sshfsmount.json")),
44
+ Pathname.new(File.join(Dir.home, ".config", "sshfsmount.json")),
45
+ Pathname.new(File.join(Dir.home, ".config", "sshfsmount", "sshfsmount.json")),
46
+ ].select(&:file?).first
47
+ end
48
+ end
49
+
50
+ #
51
+ # Parse config file
52
+ #
53
+ def config
54
+ @config ||= begin
55
+ config_file = find_config_file
56
+ if config_file.nil?
57
+ STDERR.puts "No config file found"
58
+ {}
59
+ else
60
+ JSON.parse(config_file.read, symbolize_names: true)
61
+ end
62
+ rescue JSON::ParserError => e
63
+ STDERR.puts "Parse error in config file `#{config_file}`: #{e}"
64
+ {}
65
+ end
66
+ end
67
+
68
+ def active_mounts
69
+ @active_mounts ||= begin
70
+ `mount`.lines.each_with_object({}) do |line, mounts|
71
+ regex = %r{^(?<remote>.+@[^:]+\:/.*?) on (?<local>/.*?) (?<options>\(\b(?:fuse|osxfuse)\b.*?\))$}
72
+ info = line.match(regex)
73
+ next if info.nil?
74
+ pid = `pgrep -f "/sshfs #{Shellwords.escape(info[:remote])} #{Shellwords.escape(info[:local])} "`.strip
75
+ pid = "None found" if pid.empty?
76
+ mounts[Pathname.new(info[:local]).expand_path] = {
77
+ local: info[:local],
78
+ remote: info[:remote],
79
+ options: info[:options],
80
+ pid: pid,
81
+ str: "#{info[:remote]} on #{info[:local]} (PID: #{pid})",
82
+ }
83
+ end
84
+ end
85
+ end
86
+
87
+ # Fails if the mount-path is already in use.
88
+ def dupe_check!(mount_name, params)
89
+ local = Pathname.new(params[:local]).expand_path
90
+ dupe = active_mounts[local]
91
+ return if dupe.nil?
92
+ raise "\"#{mount_name}\" already mounted?\n* #{dupe[:str]}"
93
+ end
94
+
95
+ #
96
+ # Create Mount-point Directory
97
+ #
98
+ def mkmountpoint(name)
99
+ local = Pathname.new(name).expand_path
100
+ if !local.exist?
101
+ STDERR.puts "Creating mount-point directory #{local}"
102
+ local.mkpath
103
+ elsif !local.directory
104
+ raise "Mount point #{local} exists and is not a directory"
105
+ elsif !local.empty?
106
+ raise "Mount point #{local} already exists and is not empty"
107
+ elsif @verbose
108
+ STDERR.puts "Mount-point directory #{local} already exists and is empty"
109
+ end
110
+ local
111
+ end
112
+
113
+ #
114
+ # Delete mount-point directory
115
+ #
116
+ def rmmountpoint(name)
117
+ local = Pathname.new(name).expand_path
118
+ if !local.exist?
119
+ STDERR.puts "Mount-point directory not found" if @verbose
120
+ elsif !local.directory?
121
+ raise "Mount point #{local} is not a directory"
122
+ elsif !local.empty?
123
+ raise "Mount-point directory #{local} is not empty"
124
+ else
125
+ STDERR.puts "Deleting mount-point directory #{local}"
126
+ local.rmdir
127
+ return true
128
+ end
129
+ end
130
+
131
+ #
132
+ # Mount an SSHFS volume
133
+ #
134
+ def mount(mount_name, params)
135
+ dupe_check!(mount_name, params)
136
+ local = mkmountpoint(params[:local])
137
+ volname = params[:volname] || mount_name
138
+ cmd = "#{sshfs_cmd} " \
139
+ "#{Shellwords.escape(params[:remote])} " \
140
+ "#{Shellwords.escape(local)} " \
141
+ "-o volname=\"#{Shellwords.escape(volname)}\" " \
142
+ "#{SSHFS_FLAGS.join(' ')} " \
143
+ "-p #{(params[:port] || 22).to_i}"
144
+ puts "Mounting \"#{mount_name}\"\n" \
145
+ " * #{params[:remote]} on #{local} as \"#{volname}\""
146
+ STDERR.puts "> #{cmd}" if @verbose
147
+ system(cmd)
148
+ end
149
+
150
+ #
151
+ # Unmount an SSHFS volume
152
+ #
153
+ def unmount(mount_name, params)
154
+ local = Pathname.new(params[:local]).expand_path
155
+ info = active_mounts[local]
156
+ raise "No active mount-point found for #{local}" if info.nil?
157
+ STDERR.puts "No active SSHFS process found for #{local}" if info[:pid] == "None found"
158
+ cmd = "umount #{Shellwords.escape(local)}"
159
+ puts "Unmounting \"#{mount_name}\" (#{local})"
160
+ STDERR.puts "> #{cmd}" if @verbose
161
+ raise "Unmount error, skipping removal of mount-point." unless system(cmd)
162
+ rmmountpoint(local)
163
+ end
7
164
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "gli"
4
+
5
+ module Sshfsmount
6
+ module CLI
7
+ extend GLI::App
8
+ #
9
+ # GLI command-line app definition
10
+ #
11
+ program_desc "A simple front-end CLI to SSHFS"
12
+ version Sshfsmount::VERSION
13
+
14
+ switch %i[u unmount], desc: "Unmount the volume", negatable: false
15
+ switch %i[v verbose], desc: "Show verbose output", negatable: false
16
+
17
+ desc "List active SSHFS processes"
18
+ command :active do |c|
19
+ c.action do
20
+ Sshfsmount.active_mounts.each_value do |data|
21
+ puts "* #{data[:str]}"
22
+ end
23
+ end
24
+ end
25
+
26
+ config = Sshfsmount.config
27
+
28
+ #
29
+ # Define commands from data-file
30
+ #
31
+ extant_commands = commands.keys
32
+ config.reject { |name, _| extant_commands.include?(name) }.each do |mount_name, params|
33
+ desc "mount #{params[:remote]} to #{params[:local]}"
34
+ command mount_name do |c|
35
+ c.switch %i[u unmount], desc: "Unmount the volume", negatable: false
36
+ c.switch %i[v verbose], desc: "Show verbose output", negatable: false
37
+ c.action do |global_options, cmd_options|
38
+ Sshfsmount.verbose = global_options[:v] || cmd_options[:v]
39
+ if global_options[:u] || cmd_options[:u]
40
+ Sshfsmount.unmount(mount_name, params)
41
+ else
42
+ Sshfsmount.mount(mount_name, params)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sshfsmount
4
- VERSION = "0.1.0".freeze
4
+ VERSION = "0.1.2".freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sshfsmount
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Bellefleur
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-25 00:00:00.000000000 Z
11
+ date: 2017-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -128,6 +128,7 @@ files:
128
128
  - bin/setup
129
129
  - exe/sshfsmount
130
130
  - lib/sshfsmount.rb
131
+ - lib/sshfsmount/cli.rb
131
132
  - lib/sshfsmount/version.rb
132
133
  - sshfsmount.gemspec
133
134
  homepage: https://github.com/nomoon/sshfsmount