jorp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+
2
+ source "https://rubygems.org"
3
+
4
+ gem 'listen'
5
+ gem 'highline'
6
+ gem 'net-ssh'
7
+ gem 'net-scp'
@@ -0,0 +1,19 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ highline (1.6.15)
5
+ jruby-pageant (1.1.1)
6
+ listen (0.5.3)
7
+ net-scp (1.0.4)
8
+ net-ssh (>= 1.99.1)
9
+ net-ssh (2.6.0)
10
+ jruby-pageant (>= 1.1.1)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ highline
17
+ listen
18
+ net-scp
19
+ net-ssh
@@ -0,0 +1,4 @@
1
+ jorp
2
+ ====
3
+
4
+ A SSH wrapper for local text editors
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ require 'jorp'
5
+ Jorp::App.new(ARGV, $0).run
@@ -0,0 +1,14 @@
1
+
2
+ Gem::Specification.new do |s|
3
+ s.name = 'jorp'
4
+ s.version = '1.0.0'
5
+ s.date = '2012-10-16'
6
+ s.summary = 'A SSH wrapper for local text editors'
7
+ s.description = 'Jorp lets you edit remote files using local editors'
8
+ s.authors = [ 'Stewart Ulm' ]
9
+ s.email = 'stewart.ulm@gmail.com'
10
+ s.homepage = 'http://github.com/stewartspeak/jorp'
11
+ s.files = `git ls-files`.split("\n")
12
+ s.executables = [ 'jorp' ]
13
+ s.require_paths = [ 'lib' ]
14
+ end
@@ -0,0 +1,69 @@
1
+ # encoding: utf-8
2
+
3
+ require 'bundler/setup'
4
+ require 'optparse'
5
+ require 'jorp/sudo_adaptor'
6
+ require 'jorp/basic_adaptor'
7
+ require 'jorp/remote_adaptor'
8
+
9
+ module Jorp
10
+
11
+ DEFAULT_OPTIONS = {
12
+ :username => (ENV['USER']),
13
+ :editor => (ENV['JORP_EDITOR'] || ENV['EDITOR'] || 'subl -w'),
14
+ :hostname => ENV['JORP_HOST'],
15
+ :sudo => false,
16
+ }
17
+
18
+ class App
19
+
20
+ def initialize(args, bin_path)
21
+ @original_args = args.clone
22
+ @bin_path = bin_path
23
+ process_args(args)
24
+ end
25
+
26
+ def process_args(args)
27
+ @options = DEFAULT_OPTIONS.clone
28
+ parser = OptionParser.new(args) do |opts|
29
+ opts.banner = 'jorp [options] [file]'
30
+ opts.program_name = 'Jorp'
31
+ opts.version = '0.1'
32
+ opts.on('-s', '--sudo') { @options[:sudo] = true }
33
+ opts.on('-e', '--editor [command]') {|e| @options[:editor] = e }
34
+ opts.on('-u', '--username [username]') {|u| @options[:username] = u }
35
+ opts.on('-h', '--host [hostname]') {|h| @options[:hostname] = h }
36
+ end
37
+ parser.load(File.expand_path('~/.jorp'))
38
+ parser.parse!
39
+ if ARGV.length != 1
40
+ puts parser
41
+ exit -1
42
+ end
43
+ @options[:path] = args[0]
44
+ end
45
+
46
+ def run
47
+ if @options[:hostname].nil?
48
+ if @options[:sudo]
49
+ @adaptor = SudoAdaptor.new(@options[:path])
50
+ else
51
+ @adaptor = BasicAdaptor.new(@options[:path])
52
+ end
53
+ else
54
+ puts "Using remote host: \"#{@options[:hostname]}\""
55
+ if @options[:sudo]
56
+ @adaptor = RemoteAdaptor.new(@options[:hostname], @options[:path], @options[:username])
57
+ else
58
+ @adaptor = RemoteAdaptor.new(@options[:hostname], @options[:path], @options[:username])
59
+ end
60
+ end
61
+ @adaptor.connect
62
+ system("#{@options[:editor]} \"#{@adaptor.proxy_path}\"")
63
+ @adaptor.disconnect
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
@@ -0,0 +1,23 @@
1
+ # encoding: utf-8
2
+
3
+ module Jorp
4
+
5
+ class BasicAdaptor
6
+
7
+ def initialize(path)
8
+ @path = path
9
+ end
10
+
11
+ def connect
12
+ end
13
+
14
+ def disconnect
15
+ end
16
+
17
+ def proxy_path
18
+ @path
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ module Jorp
4
+
5
+ class FileListener
6
+
7
+ end
8
+
9
+ end
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tmpdir'
4
+ require 'pty'
5
+ require 'expect'
6
+ require 'listen'
7
+ require 'net/ssh'
8
+ require 'net/scp'
9
+
10
+ module Jorp
11
+
12
+ class RemoteAdaptor
13
+
14
+ def initialize(hostname, path, username)
15
+ @hostname = hostname
16
+ @path = path
17
+ @username = username
18
+ @proxy_directory = Dir.mktmpdir('jorp')
19
+ @proxy_path = File.join(@proxy_directory, File.basename(@path))
20
+ end
21
+
22
+ def upload(connection)
23
+ begin
24
+ copier = Net::SCP.new(connection)
25
+ copier.upload!(@proxy_path, @path)
26
+ rescue Exception => e
27
+ puts "ERROR: " + e
28
+ end
29
+ end
30
+
31
+ def download(connection)
32
+ begin
33
+ copier = Net::SCP.new(connection)
34
+ copier.download!(@path, @proxy_path)
35
+ rescue Exception => e
36
+ puts "ERROR: " + e
37
+ end
38
+ end
39
+
40
+ def connect
41
+ connection = Net::SSH.start(@hostname, @username)
42
+ download(connection)
43
+ Thread.new do
44
+ begin
45
+ Listen.to(@proxy_directory, :filter => /^#{Regexp.escape(File.basename(@proxy_path))}$/) do
46
+ upload(connection)
47
+ end
48
+ rescue Exception => e
49
+ puts "An error occurred: " + e.inspect
50
+ end
51
+ end
52
+ end
53
+
54
+ def disconnect
55
+ FileUtils.remove_entry_secure(@proxy_directory)
56
+ end
57
+
58
+ def proxy_path
59
+ @proxy_path
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ module Jorp
4
+
5
+ class Sudo
6
+
7
+ def initialize()
8
+ end
9
+
10
+ def prompt
11
+ password = nil
12
+ begin
13
+ PTY.spawn("sudo -k -p ENTER_PASSWORD whoami") do |input, output, pid|
14
+ loop do
15
+ response = input.expect(/^ENTER_PASSWORD/)
16
+ if response.nil? || response.length == 0
17
+ raise IOError.new
18
+ end
19
+ output.puts(password = HighLine.ask("Enter password: ") {|q| q.echo = false })
20
+ input.expect(/^(Sorry, try again|root$)/) do |matches|
21
+ if (matches[1] =~ /^Sorry, try again/)
22
+ password = nil
23
+ puts("Sorry, try again.")
24
+ end
25
+ end
26
+ break unless password.nil?
27
+ end
28
+ end
29
+ rescue
30
+ @password = nil
31
+ end
32
+ @password = password
33
+ end
34
+
35
+ def exec(command)
36
+ PTY.spawn("sudo -k -p ENTER_PASSWORD #{command}") do |input, output, pid|
37
+ input.expect(/^ENTER_PASSWORD/)
38
+ output.puts(@password)
39
+ while (response = input.gets)
40
+ # no-op
41
+ end
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ end
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ require 'tmpdir'
4
+ require 'pty'
5
+ require 'expect'
6
+ require 'highline/import'
7
+ require 'listen'
8
+ require 'jorp/sudo'
9
+
10
+ module Jorp
11
+
12
+ class SudoAdaptor
13
+
14
+ def initialize(path)
15
+ @source_path = path
16
+ @proxy_directory = Dir.mktmpdir('jorp')
17
+ @proxy_path = File.join(@proxy_directory, File.basename(@source_path))
18
+ FileUtils.touch(@proxy_path)
19
+ end
20
+
21
+ def connect
22
+ sudo = Sudo.new
23
+ if sudo.prompt
24
+ sudo.exec("cp \"#{@source_path}\" \"#{@proxy_path}\"")
25
+ Thread.new do
26
+ begin
27
+ Listen.to(@proxy_directory, :filter => /^#{Regexp.escape(File.basename(@proxy_path))}$/) do
28
+ sudo.exec("cp -p \"#{proxy_path}\" \"#{@source_path}\"")
29
+ end
30
+ rescue Exception => e
31
+ # log this error
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ def disconnect
38
+ FileUtils.remove_entry_secure(@proxy_directory)
39
+ end
40
+
41
+ def proxy_path
42
+ @proxy_path
43
+ end
44
+
45
+ end
46
+
47
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jorp
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Stewart Ulm
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-10-16 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Jorp lets you edit remote files using local editors
22
+ email: stewart.ulm@gmail.com
23
+ executables:
24
+ - jorp
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - .gitignore
31
+ - Gemfile
32
+ - Gemfile.lock
33
+ - README.md
34
+ - bin/jorp
35
+ - jorp.gemspec
36
+ - lib/jorp.rb
37
+ - lib/jorp/basic_adaptor.rb
38
+ - lib/jorp/listener.rb
39
+ - lib/jorp/remote_adaptor.rb
40
+ - lib/jorp/sudo.rb
41
+ - lib/jorp/sudo_adaptor.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/stewartspeak/jorp
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.6
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: A SSH wrapper for local text editors
72
+ test_files: []
73
+