rhosts 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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