rhosts 0.0.2 → 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: aa43a36fdbc77c86d21e7de74c8bf38016e93908
4
+ data.tar.gz: 359709c1b178116b2704731a28cc3b75d2bdc027
5
+ SHA512:
6
+ metadata.gz: a88d2772c2d6f6c842f64c34e043b90e3447d63b62f8e59121bee513507d4ffccf416289e6088b311b2d95ecb66b83a8eda66467ea2f9ce1ad966bf121e04ee2
7
+ data.tar.gz: 7a2ef8048fa29442ca4f7dbdab0d026b142fb6634bcf75cacfe7cb4918c2f5dbe82b150e66ee6c972b4dd1b75bc104a3afc093c931fe8bfa16d6843acba59bd1
data/README.md CHANGED
@@ -95,3 +95,10 @@ rhosts> actives
95
95
  stg-www.example.com
96
96
 
97
97
  ```
98
+
99
+ ## advanced
100
+ You can override default settings.
101
+ You can add original rule to map/unmap.
102
+ You can define alias name to IP/host.
103
+
104
+ see .rhostsrc
@@ -10,9 +10,6 @@ module RHosts
10
10
  include RHosts::Rulable
11
11
  include RHosts::Alias
12
12
 
13
- alias_host 'exp', 'www.example.com'
14
- alias_ip 'localhost', '127.0.0.1'
15
-
16
13
  class << self
17
14
  def start
18
15
  @console = new
@@ -20,8 +17,8 @@ module RHosts
20
17
  load_default_rules
21
18
  load_run_command
22
19
 
23
- unless File.writable?(RHosts.config.hosts_file_path)
24
- STDERR.puts "Hosts file is not writable. Please check permission"
20
+ unless File.writable?(RHosts.config.hosts_file_path) and RHosts.config.sudo?
21
+ warn "Hosts file is not writable. Please check permission"
25
22
  exit 1
26
23
  end
27
24
 
@@ -1,9 +1,13 @@
1
1
  module RHosts
2
2
  class Configuration
3
- attr_accessor :hosts_file_path, :backup_dir, :make_backup
3
+ attr_accessor :hosts_file_path, :backup_dir, :make_backup, :sudo
4
4
 
5
5
  def make_backup?
6
6
  make_backup
7
7
  end
8
+
9
+ def sudo?
10
+ sudo
11
+ end
8
12
  end
9
13
  end
@@ -13,11 +13,14 @@ module RHosts
13
13
 
14
14
  def map(target)
15
15
  process(target) do |host, ip|
16
+ inactivate(host)
17
+
16
18
  unless inactives[ip].empty?
17
19
  inactives[ip].delete_if{ |h| h == host }
18
- inactives.delete(ip) if inactives[ip].empty?
19
20
  end
20
21
 
22
+ inactives.delete(ip) if inactives[ip].empty?
23
+
21
24
  actives[ip] << host
22
25
  puts "map #{host} to #{ip}"
23
26
  end
@@ -27,9 +30,10 @@ module RHosts
27
30
  process(target) do |host, ip|
28
31
  unless actives[ip].empty?
29
32
  actives[ip].delete_if{ |h| h == host }
30
- actives.delete(ip) if actives[ip].empty?
31
33
  end
32
34
 
35
+ actives.delete(ip) if actives[ip].empty?
36
+
33
37
  inactives[ip] << host
34
38
  puts "unmap #{host} from #{ip}"
35
39
  end
@@ -58,7 +62,7 @@ module RHosts
58
62
 
59
63
  ip_without_zone_index = ip.split('%')[0]
60
64
  unless IPAddress.valid?(ip_without_zone_index)
61
- STDERR.puts "#{ip} is invalid IP Address!"
65
+ warn "#{ip} is invalid IP Address!"
62
66
  next
63
67
  end
64
68
 
@@ -71,5 +75,16 @@ module RHosts
71
75
  # TODO
72
76
  # after_actions.each{ |action| action.call }
73
77
  end
78
+
79
+ def inactivate(host)
80
+ actives.each do |active_ip, active_hosts|
81
+ if active_hosts.include?(host)
82
+ active_hosts.delete(host)
83
+ actives.delete(active_ip) if active_hosts.empty?
84
+
85
+ inactives[active_ip] << host
86
+ end
87
+ end
88
+ end
74
89
  end
75
90
  end
data/lib/rhosts/filer.rb CHANGED
@@ -22,13 +22,15 @@ module RHosts
22
22
  ip_without_zone_index = ip.split('%')[0]
23
23
  next unless IPAddress.valid?(ip_without_zone_index)
24
24
 
25
- storage[ip] ||= []
26
25
  storage[ip] += hosts
27
26
  end
28
27
  end
29
28
  end
30
29
 
31
30
  [actives, inactives]
31
+ rescue
32
+ warn "hosts file load error. #{RHosts.config.hosts_file_path}"
33
+ exit
32
34
  end
33
35
 
34
36
  def backup
@@ -38,28 +40,50 @@ module RHosts
38
40
  if File.writable?(RHosts.config.backup_dir)
39
41
  FileUtils.cp(hosts_file_path, bk_file_path)
40
42
  puts "backup: #{bk_file_path}"
43
+ elsif RHosts.config.sudo?
44
+ system "sudo cp #{hosts_file_path} #{bk_file_path}"
45
+ puts "backup: #{bk_file_path}"
41
46
  else
42
- STDERR.puts "backup file is not writable. #{bk_file_path}"
43
- STDERR.puts 'So we will backup to tmp dir'
47
+ warn "backup file is not writable. #{bk_file_path}"
48
+ warn 'So we will backup to tmp dir'
44
49
  tmp = tmp_file_path
45
50
  FileUtils.cp(hosts_file_path, tmp)
46
- STDERR.puts "backup: #{tmp}"
51
+ warn "backup: #{tmp}"
47
52
  end
48
53
  end
49
54
 
50
55
  def save(actives, inactives)
51
56
  # TODO: reload hosts file if chnaged after load
52
57
  hosts_file_path = RHosts.config.hosts_file_path
53
- unless File.writable?(hosts_file_path)
54
- STDERR.puts "Hosts file is not writable. Please check permission"
55
- exit 1
56
- end
57
58
 
58
- File.open(RHosts.config.hosts_file_path, 'w') do |file|
59
- actives.each{ |ip, hosts| file.write("#{ip} #{hosts.to_a.join(' ')}\n") }
60
- inactives.each{ |ip, hosts| file.write("##{ip} #{hosts.to_a.join(' ')}\n") }
59
+ contents = []
60
+ contents += actives.map do |ip, hosts|
61
+ hosts.map do |host|
62
+ "#{ip} #{host}"
63
+ end
64
+ end.flatten
65
+ contents += inactives.map do |ip, hosts|
66
+ hosts.map do |host|
67
+ "##{ip} #{host}"
68
+ end
69
+ end.flatten
70
+
71
+ if File.writable?(hosts_file_path)
72
+ File.open(hosts_file_path, 'w') do |file|
73
+ file.write contents.join("\n")
74
+ end
75
+ puts "save: #{hosts_file_path}"
76
+ elsif RHosts.config.sudo?
77
+ tmp = tmp_file_path
78
+ File.open(tmp, 'w') do |file|
79
+ file.write contents.join("\n")
80
+ end
81
+ system "sudo mv #{tmp} #{hosts_file_path}"
82
+ puts "save: #{hosts_file_path}"
83
+ else
84
+ warn "Hosts file is not writable. Please check permission"
85
+ exit 1
61
86
  end
62
- puts "save: #{hosts_file_path}"
63
87
  end
64
88
 
65
89
  private
@@ -1,5 +1,5 @@
1
1
  module RHosts # :nodoc:
2
2
  module Version # :nodoc:
3
- STRING = '0.0.2'
3
+ STRING = '0.1.0'
4
4
  end
5
5
  end
data/lib/rhosts.rb CHANGED
@@ -25,4 +25,5 @@ RHosts.configure do |c|
25
25
  c.hosts_file_path = '/etc/hosts'
26
26
  c.backup_dir = '/etc'
27
27
  c.make_backup = true
28
+ c.sudo = false
28
29
  end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+ require 'rhosts/filer'
3
+ require 'rhosts/console/app'
4
+
5
+ describe 'ConsoleMethods' do
6
+ include RHosts::ConsoleMethods
7
+
8
+ include_context 'alias_stub'
9
+ include_context 'filer_stub'
10
+
11
+ describe '#map' do
12
+ context 'new host' do
13
+ before do
14
+ map 'localhost' => '127.0.0.1'
15
+ end
16
+
17
+ it 'mapped to actives' do
18
+ expect(actives).to eq({ '127.0.0.1' => Set.new(['localhost']) })
19
+ expect(inactives).to eq({ })
20
+ end
21
+ end
22
+
23
+ context 'duplicated host' do
24
+ before do
25
+ actives['127.0.0.1'] << 'localhost'
26
+ map 'localhost' => '127.0.0.1'
27
+ end
28
+
29
+ it 'mapped only one to actives' do
30
+ expect(actives).to eq({ '127.0.0.1' => Set.new(['localhost']) })
31
+ expect(inactives).to eq({ })
32
+ end
33
+ end
34
+
35
+ context 'unmapped host' do
36
+ before do
37
+ inactives['127.0.0.1'] << 'localhost'
38
+ map 'localhost' => '127.0.0.1'
39
+ end
40
+
41
+ it 'mapped to actives' do
42
+ expect(actives).to eq({ '127.0.0.1' => Set.new(['localhost']) })
43
+ expect(inactives).to eq({ })
44
+ end
45
+ end
46
+
47
+ context 'mapped other host' do
48
+ before do
49
+ actives['127.0.0.2'] << 'localhost'
50
+ map 'localhost' => '127.0.0.1'
51
+ end
52
+
53
+ it 'mapped to actives' do
54
+ expect(actives).to eq({ '127.0.0.1' => Set.new(['localhost']) })
55
+ expect(inactives).to eq({ '127.0.0.2' => Set.new(['localhost']) })
56
+ end
57
+ end
58
+ end
59
+
60
+ describe '#unmap' do
61
+ context 'new host' do
62
+ before do
63
+ unmap 'localhost' => '127.0.0.1'
64
+ end
65
+
66
+ it 'mapped to inactive' do
67
+ expect(actives).to eq({ })
68
+ expect(inactives).to eq({ '127.0.0.1' => Set.new(['localhost']) })
69
+ end
70
+ end
71
+
72
+ context 'duplicated host' do
73
+ before do
74
+ inactives['127.0.0.1'] << 'localhost'
75
+ unmap 'localhost' => '127.0.0.1'
76
+ end
77
+
78
+ it 'mapped only one to actives' do
79
+ expect(actives).to eq({ })
80
+ expect(inactives).to eq({ '127.0.0.1' => Set.new(['localhost']) })
81
+ end
82
+ end
83
+
84
+ context 'mapped host' do
85
+ before do
86
+ actives['127.0.0.1'] << 'localhost'
87
+ unmap 'localhost' => '127.0.0.1'
88
+ end
89
+
90
+ it 'mapped to actives' do
91
+ expect(actives).to eq({ })
92
+ expect(inactives).to eq({ '127.0.0.1' => Set.new(['localhost']) })
93
+ end
94
+ end
95
+
96
+ context 'unmapped other host' do
97
+ before do
98
+ inactives['127.0.0.2'] << 'localhost'
99
+ unmap 'localhost' => '127.0.0.1'
100
+ end
101
+
102
+ it 'mapped to actives' do
103
+ expect(actives).to eq({ })
104
+ expect(inactives).to eq({ '127.0.0.1' => Set.new(['localhost']), '127.0.0.2' => Set.new(['localhost']) })
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+ require 'rhosts/filer'
3
+ require 'stringio'
4
+
5
+ describe 'Filer' do
6
+ include_context 'capture_stderr'
7
+
8
+ context 'hosts file is not exist' do
9
+ before do
10
+ RHosts::Filer::Mock.error('read')
11
+ end
12
+
13
+ it 'should display error message and exit' do
14
+ err = capture_stderr do
15
+ expect{ RHosts::Filer.load }.to raise_error(SystemExit)
16
+ end
17
+
18
+ expect(err.chomp).to eq("hosts file load error. #{RHosts.config.hosts_file_path}")
19
+ end
20
+ end
21
+
22
+ context 'hosts file is exist' do
23
+ before do
24
+ @input = input
25
+ @output = output
26
+
27
+ RHosts::Filer::Mock.read(@input)
28
+ RHosts::Filer::Mock.writable(true)
29
+ RHosts::Filer::Mock.write(@output)
30
+
31
+ @actives, @inactives = RHosts::Filer.load
32
+ RHosts::Filer.save(@actives, @inactives)
33
+ end
34
+
35
+ context 'but empty' do
36
+ let(:input){ StringIO.new }
37
+ let(:output){ StringIO.new }
38
+
39
+ it 'should not have any mapping' do
40
+ expect(@actives).to eq({})
41
+ expect(@inactives).to eq({})
42
+ end
43
+
44
+ it 'should save nothing' do
45
+ expect(@output.string).to be_empty
46
+ end
47
+ end
48
+
49
+ context 'hosts file include active mapping' do
50
+ let(:input){ StringIO.new("127.0.0.1 localhost") }
51
+ let(:output){ StringIO.new }
52
+
53
+ it 'should be loaded as active' do
54
+ hosts = Set.new()
55
+ hosts += ['localhost']
56
+ expect(@actives).to eq({ '127.0.0.1' => hosts })
57
+ expect(@inactives).to eq({})
58
+ end
59
+
60
+ it 'should be saved as active' do
61
+ expect(@output.string).to eq(@input.string)
62
+ end
63
+ end
64
+
65
+ context 'hosts file include inactive mapping' do
66
+ let(:input){ StringIO.new("#127.0.0.1 localhost") }
67
+ let(:output){ StringIO.new }
68
+
69
+ it 'should be loaded as inactive' do
70
+ hosts = Set.new()
71
+ hosts += ['localhost']
72
+ expect(@actives).to eq({})
73
+ expect(@inactives).to eq({ '127.0.0.1' => hosts })
74
+ end
75
+
76
+ it 'should be saved as inactive' do
77
+ expect(@output.string).to eq(@input.string)
78
+ end
79
+ end
80
+ end
81
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'pry'
1
2
  require File.expand_path('../../lib/rhosts', __FILE__)
2
3
 
3
4
  # This file was generated by the `rspec --init` command. Conventionally, all
@@ -17,3 +18,5 @@ RSpec.configure do |config|
17
18
  # --seed 1234
18
19
  config.order = 'random'
19
20
  end
21
+
22
+ Dir["./spec/support/**/*.rb"].sort.each { |f| require f }
@@ -0,0 +1,4 @@
1
+ shared_context 'alias_stub' do
2
+ def alias_hosts; {} end
3
+ def alias_ips; {} end
4
+ end
@@ -0,0 +1,17 @@
1
+ # http://stackoverflow.com/questions/4459330/how-do-i-temporarily-redirect-stderr-in-ruby
2
+
3
+ require 'stringio'
4
+
5
+ shared_context 'capture_stderr' do
6
+ def capture_stderr
7
+ # The output stream must be an IO-like object. In this case we capture it in
8
+ # an in-memory IO object so we can return the string value. You can assign any
9
+ # IO object here.
10
+ previous_stderr, $stderr = $stderr, StringIO.new
11
+ yield
12
+ $stderr.string
13
+ ensure
14
+ # Restore the previous value of stderr (typically equal to STDERR).
15
+ $stderr = previous_stderr
16
+ end
17
+ end
@@ -0,0 +1,51 @@
1
+ module RHosts
2
+ module Filer
3
+ module Mock
4
+ class << self
5
+ def read(io)
6
+ open('r')
7
+ .and_yield(io)
8
+ end
9
+
10
+ def writable(bool)
11
+ File
12
+ .stub(:writable?)
13
+ .with(RHosts.config.hosts_file_path)
14
+ .and_return(bool)
15
+ end
16
+
17
+ def write(io)
18
+ open('w')
19
+ .and_yield(io)
20
+ end
21
+
22
+ def error(action)
23
+ case action
24
+ when 'read'
25
+ open('r')
26
+ .and_raise(Errno::ENOENT.new)
27
+ when 'write'
28
+ open('w')
29
+ .and_raise(Errno::ENOENT.new)
30
+ when 'writable'
31
+ File
32
+ .stub(:writable?)
33
+ .and_raise(Errno::ENOENT.new)
34
+ end
35
+ end
36
+
37
+ def reset
38
+ File.unstub(:open)
39
+ File.unstub(:writable?)
40
+ end
41
+
42
+ private
43
+ def open(mode)
44
+ File
45
+ .stub(:open)
46
+ .with(RHosts.config.hosts_file_path, mode)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ shared_context 'filer_stub' do
2
+ before do
3
+ RHosts::Filer.stub(:load).and_return(true)
4
+ RHosts::Filer.stub(:backup).and_return(true)
5
+ RHosts::Filer.stub(:save).and_return(true)
6
+ end
7
+ end
metadata CHANGED
@@ -1,46 +1,37 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: rhosts
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 2
9
- version: 0.0.2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
10
5
  platform: ruby
11
- authors:
6
+ authors:
12
7
  - Takeshi Takizawa
13
8
  autorequire:
14
9
  bindir: bin
15
10
  cert_chain: []
16
-
17
- date: 2013-06-24 00:00:00 +09:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
11
+ date: 2013-06-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
21
14
  name: ipaddress
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- none: false
25
- requirements:
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
26
17
  - - ~>
27
- - !ruby/object:Gem::Version
28
- segments:
29
- - 0
30
- - 8
31
- - 0
18
+ - !ruby/object:Gem::Version
32
19
  version: 0.8.0
33
20
  type: :runtime
34
- version_requirements: *id001
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.8.0
35
27
  description: hosts file manager
36
28
  email: TakiTake.create@gmail.com
37
- executables:
29
+ executables:
38
30
  - rhosts
39
31
  extensions: []
40
-
41
- extra_rdoc_files:
32
+ extra_rdoc_files:
42
33
  - README.md
43
- files:
34
+ files:
44
35
  - lib/rhosts.rb
45
36
  - lib/rhosts/alias.rb
46
37
  - lib/rhosts/cli.rb
@@ -53,41 +44,44 @@ files:
53
44
  - lib/rhosts/version.rb
54
45
  - License.txt
55
46
  - README.md
56
- - spec/console/app_spec.rb
47
+ - spec/lib/rhosts/console/app_spec.rb
48
+ - spec/lib/rhosts/filer_spec.rb
57
49
  - spec/spec_helper.rb
50
+ - spec/support/alias_stub.rb
51
+ - spec/support/capture_stderr.rb
52
+ - spec/support/filer_mock.rb
53
+ - spec/support/filer_stub.rb
58
54
  - bin/rhosts
59
- has_rdoc: true
60
55
  homepage: http://github.com/TakiTake/rhosts
61
- licenses:
56
+ licenses:
62
57
  - MIT
58
+ metadata: {}
63
59
  post_install_message:
64
- rdoc_options:
60
+ rdoc_options:
65
61
  - --charset=UTF-8
66
- require_paths:
62
+ require_paths:
67
63
  - lib
68
- required_ruby_version: !ruby/object:Gem::Requirement
69
- none: false
70
- requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- segments:
74
- - 0
75
- version: "0"
76
- required_rubygems_version: !ruby/object:Gem::Requirement
77
- none: false
78
- requirements:
79
- - - ">="
80
- - !ruby/object:Gem::Version
81
- segments:
82
- - 0
83
- version: "0"
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - '>='
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
84
74
  requirements: []
85
-
86
75
  rubyforge_project: rhosts
87
- rubygems_version: 1.3.7
76
+ rubygems_version: 2.0.3
88
77
  signing_key:
89
- specification_version: 3
90
- summary: rhosts-0.0.2
91
- test_files:
92
- - spec/console/app_spec.rb
78
+ specification_version: 4
79
+ summary: rhosts-0.1.0
80
+ test_files:
81
+ - spec/lib/rhosts/console/app_spec.rb
82
+ - spec/lib/rhosts/filer_spec.rb
93
83
  - spec/spec_helper.rb
84
+ - spec/support/alias_stub.rb
85
+ - spec/support/capture_stderr.rb
86
+ - spec/support/filer_mock.rb
87
+ - spec/support/filer_stub.rb
@@ -1,22 +0,0 @@
1
- require 'spec_helper'
2
- require 'rhosts/console/app'
3
-
4
- describe 'ConsoleMethods' do
5
- include RHosts::ConsoleMethods
6
-
7
- describe '#map' do
8
- before do
9
- map 'example.com' => '127.0.0.1'
10
- end
11
-
12
- after do
13
- @actives.clear
14
- @inactives.clear
15
- end
16
-
17
- it 'map example.com to 127.0.0.1' do
18
- expect(actives).to eq('127.0.0.1' => ['example.com'])
19
- expect(inactives).to eq({ })
20
- end
21
- end
22
- end