ghost 1.0.0.pre → 1.0.0.pre.2

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.
data/README.md CHANGED
@@ -65,6 +65,11 @@ Command
65
65
  Listing 1 host(s):
66
66
  staging-server.local -> 64.233.167.99
67
67
 
68
+ With RVM you need to add `rvmsudo` before the command:
69
+
70
+ $ rvmsudo ghost add mydevsite.local
71
+ [Adding] mydevsite.local -> 127.0.0.1
72
+
68
73
  Library
69
74
  -------
70
75
 
@@ -77,23 +82,37 @@ Installation
77
82
 
78
83
  sudo gem install ghost
79
84
 
85
+ If you are using RVM:
86
+
87
+ gem install ghost
88
+
80
89
  Contributors
81
90
  ============
82
91
 
83
- If this list is ever out of date, you can get full contributor list with `git log --format='%aN (%ae)' | sort -u`
92
+ If this list is ever out of date, you can get full contributor list
93
+ with `git log --format='%aN (%ae)' | sort -u` or from [here](https://github.com/bjeanes/ghost/graphs/contributors).
84
94
 
85
95
  * [Alkesh Vaghmaria](https://github.com/alkesh)
86
96
  * [Andrei Serdeliuc](https://github.com/extraordinaire)
87
97
  * [Ben Hoskings](https://github.com/benhoskings)
88
- * [Bodaniel Jeanes](https://github.com/bjeanes)
89
- * [Courtois Simon](https://github.com/simonc)
98
+ * [Bo Jeanes](https://github.com/bjeanes)
99
+ * [David Warkentin](https://github.com/ev0rtex)
100
+ * [Duncan Beevers](https://github.com/duncanbeevers)
90
101
  * [Felipe Coury](https://github.com/fcoury)
102
+ * [Finn Smith](https://github.com/finn)
103
+ * [Geoff Wagstaff](https://github.com/TheDeveloper)
104
+ * [Johannes Thoenes](https://github.com/jthoenes)
91
105
  * [Justin Mazzi](https://github.com/jmazzi)
92
106
  * [Lars Fronius](https://github.com/LarsFronius)
93
107
  * [Lee Jensen](https://github.com/outerim)
108
+ * [Luiz Galaviz](https://github.com/MGalv)
109
+ * [Luiz Rocha](https://github.com/lsdr)
94
110
  * [Mitchell Riley](https://github.com/mitchellvriley)
111
+ * [Noah Kantrowitz](https://github.com/coderanger)
95
112
  * [Ryan Bigg](https://github.com/radar)
96
113
  * [Sam Beam](https://github.com/sbeam)
114
+ * [Simon Courtois](https://github.com/simonc)
115
+ * [Turadg Aleahmad](https://github.com/turadg)
97
116
 
98
117
  Legal Stuff
99
118
  ===========
@@ -0,0 +1,25 @@
1
+ Ghost::Cli.task :set do
2
+ desc "Add a host or modify the IP of an existing host"
3
+ def perform(host, ip = nil)
4
+ host = Ghost::Host.new(*[host, ip].compact)
5
+ Ghost.store.set(host)
6
+ puts "[Setting] #{host.name} -> #{host.ip}"
7
+ rescue Ghost::Host::NotResolvable
8
+ abort "Unable to resolve IP address for target host #{ip.inspect}."
9
+ end
10
+
11
+ help do
12
+ <<-EOF.unindent
13
+ Usage: ghost set <local host name> [<remote host name>|<IP address>]
14
+
15
+ #{desc}.
16
+
17
+ If a second parameter is not provided, it defaults to 127.0.0.1
18
+
19
+ Examples:
20
+ ghost set my-localhost # points to 127.0.0.1
21
+ ghost set google.dev google.com # points to the IP of google.com
22
+ ghost set router 192.168.1.1 # points to 192.168.1.1
23
+ EOF
24
+ end
25
+ end
@@ -2,21 +2,19 @@ require 'set'
2
2
 
3
3
  require 'ghost/host'
4
4
  require 'ghost/tokenized_file'
5
+ require 'resolv'
5
6
 
6
7
  module Ghost
7
8
  module Store
8
9
  # TODO: A lot of this duplicates Resolv::Hosts in Ruby stdlib.
9
10
  # Can that be modifiied to use tokens in place of this?
10
11
  class HostsFileStore
11
- attr_accessor :path, :file
12
+ attr_accessor :path, :file, :strict
12
13
 
13
- # TODO: Support windows locations:
14
- # Windows 95/98/Me c:\windows\hosts
15
- # Windows NT/2000/XP Pro c:\winnt\system32\drivers\etc\hosts
16
- # Windows XP Home c:\windows\system32\drivers\etc\hosts
17
- def initialize(path = "/etc/hosts")
14
+ def initialize(path = Resolv::Hosts::DefaultFileName)
18
15
  self.path = path
19
16
  self.file = Ghost::TokenizedFile.new(path, "# ghost start", "# ghost end")
17
+ self.strict = true
20
18
  end
21
19
 
22
20
  def add(host)
@@ -28,6 +26,16 @@ module Ghost
28
26
  true
29
27
  end
30
28
 
29
+ def set(host)
30
+ sync do |buffer|
31
+ delete_host host, buffer
32
+ buffer[host.ip] << host.name
33
+ buffer_changed!
34
+ end
35
+
36
+ true
37
+ end
38
+
31
39
  def all
32
40
  sync do |buffer|
33
41
  buffer.map do |ip, hosts|
@@ -41,17 +49,34 @@ module Ghost
41
49
  end
42
50
 
43
51
  def delete(host)
44
- result = SortedSet.new
45
52
  sync do |buffer|
46
- buffer.each do |ip, names|
47
- names.dup.each do |name|
48
- next unless host.match(name)
49
- next if host.respond_to?(:ip) && host.ip != ip
53
+ delete_host host, buffer, :strict
54
+ end
55
+ end
56
+
57
+ def purge(host)
58
+ sync do |buffer|
59
+ delete_host host, buffer
60
+ end
61
+ end
50
62
 
51
- result << Ghost::Host.new(name, ip)
52
- names.delete(name)
53
- buffer_changed!
63
+ def delete_host(host, buffer, strict = false)
64
+ result = SortedSet.new
65
+ buffer.each do |ip, names|
66
+ names.each do |name|
67
+ if host.kind_of? Host
68
+ next unless host.name == name
69
+ elsif host.kind_of? String
70
+ next unless host == name
71
+ else
72
+ next unless host.match(name)
54
73
  end
74
+
75
+ next if host.respond_to?(:ip) && host.ip != ip && strict
76
+
77
+ result << Ghost::Host.new(name, ip)
78
+ names.delete(name)
79
+ buffer_changed!
55
80
  end
56
81
  end
57
82
  result.to_a
@@ -1,3 +1,3 @@
1
1
  module Ghost
2
- VERSION = "1.0.0.pre"
2
+ VERSION = "1.0.0.pre.2"
3
3
  end
@@ -14,6 +14,7 @@ describe Ghost::Cli, :type => :cli do
14
14
  export Export all hosts in /etc/hosts format
15
15
  import Import hosts in /etc/hosts format
16
16
  list Show all (or a filtered) list of hosts
17
+ set Add a host or modify the IP of an existing host
17
18
 
18
19
  See 'ghost help <task>' for more information on a specific task.
19
20
  EOF
@@ -34,7 +34,10 @@ describe Ghost::Store::HostsFileStore do
34
34
  before { write(contents) }
35
35
 
36
36
  it 'manages the default file of /etc/hosts when no file path is provided' do
37
- described_class.new.path.should == "/etc/hosts"
37
+ previous_hosts_location = Resolv::Hosts::DefaultFileName
38
+ Resolv::Hosts::DefaultFileName = "hosts_location"
39
+ described_class.new.path.should == "hosts_location"
40
+ Resolv::Hosts::DefaultFileName = previous_hosts_location
38
41
  end
39
42
 
40
43
  it 'manages the file at the provided path when given' do
@@ -276,6 +279,95 @@ describe Ghost::Store::HostsFileStore do
276
279
  end
277
280
  end
278
281
 
282
+ describe "#set" do
283
+ let(:host) { Ghost::Host.new("github.com", "127.0.0.1") }
284
+
285
+ context 'with existing ghost-managed hosts in the file' do
286
+ let(:contents) do
287
+ <<-EOF.gsub(/^\s+/,'')
288
+ 127.0.0.1 localhost localhost.localdomain
289
+ # ghost start
290
+ 192.168.1.1 github.com
291
+ 192.168.1.2 github.com
292
+ # ghost end
293
+ EOF
294
+ end
295
+
296
+ context 'when setting the host to an IP' do
297
+ it 'replaces all instances of that hostname with a single entry for that IP' do
298
+ store.set(host)
299
+ read.should == <<-EOF.gsub(/^\s+/,'')
300
+ 127.0.0.1 localhost localhost.localdomain
301
+ # ghost start
302
+ 127.0.0.1 github.com
303
+ # ghost end
304
+ EOF
305
+ end
306
+
307
+ it 'returns true' do
308
+ store.set(host).should be_true
309
+ end
310
+ end
311
+ end
312
+ end
313
+
314
+ describe "#purge" do
315
+ context 'with existing ghost-managed hosts in the file' do
316
+ let(:contents) do
317
+ <<-EOF.gsub(/^\s+/,'')
318
+ 127.0.0.1 localhost localhost.localdomain
319
+ # ghost start
320
+ 127.0.0.1 google.com
321
+ 127.0.0.2 gooogle.com
322
+ 192.168.1.1 github.com
323
+ # ghost end
324
+ EOF
325
+ end
326
+
327
+ context 'when purging one of the ghost entries' do
328
+ context 'using a Ghost::Host to identify host' do
329
+ context 'and the IP does not match an entry' do
330
+ let(:host) { Ghost::Host.new("google.com", "127.0.0.2") }
331
+
332
+ it 'returns array of removed hosts' do
333
+ store.purge(host).should == [Ghost::Host.new('google.com', '127.0.0.1')]
334
+ end
335
+
336
+ it 'removes the host from the file' do
337
+ store.purge(host)
338
+ read.should == <<-EOF.gsub(/^\s+/,'')
339
+ 127.0.0.1 localhost localhost.localdomain
340
+ # ghost start
341
+ 127.0.0.2 gooogle.com
342
+ 192.168.1.1 github.com
343
+ # ghost end
344
+ EOF
345
+ end
346
+ end
347
+
348
+ context 'and the IP matches an entry' do
349
+ let(:host) { Ghost::Host.new("google.com", "127.0.0.1") }
350
+
351
+ it 'returns array of removed hosts' do
352
+ store.purge(host).should == [Ghost::Host.new('google.com', '127.0.0.1')]
353
+ end
354
+
355
+ it 'removes the host from the file' do
356
+ store.purge(host)
357
+ read.should == <<-EOF.gsub(/^\s+/,'')
358
+ 127.0.0.1 localhost localhost.localdomain
359
+ # ghost start
360
+ 127.0.0.2 gooogle.com
361
+ 192.168.1.1 github.com
362
+ # ghost end
363
+ EOF
364
+ end
365
+ end
366
+ end
367
+ end
368
+ end
369
+ end
370
+
279
371
  describe "#empty" do
280
372
  context 'with no ghost-managed hosts in the file' do
281
373
  it 'returns false' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ghost
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre
4
+ version: 1.0.0.pre.2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,41 +9,56 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-05 00:00:00.000000000Z
12
+ date: 2012-11-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: unindent
16
- requirement: &70100277448360 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - =
19
+ - - '='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '1.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70100277448360
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - '='
28
+ - !ruby/object:Gem::Version
29
+ version: '1.0'
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: rspec
27
- requirement: &70100277447880 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
- - - =
35
+ - - '='
31
36
  - !ruby/object:Gem::Version
32
37
  version: 2.9.0
33
38
  type: :development
34
39
  prerelease: false
35
- version_requirements: *70100277447880
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 2.9.0
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: rake
38
- requirement: &70100277447400 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
- - - =
51
+ - - '='
42
52
  - !ruby/object:Gem::Version
43
53
  version: 0.9.2.2
44
54
  type: :development
45
55
  prerelease: false
46
- version_requirements: *70100277447400
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2.2
47
62
  description: Allows you to create, list, and modify local hostnames on POSIX systems
48
63
  (e.g. Mac OS X and Linux) and Windows
49
64
  email: me@bjeanes.com
@@ -62,6 +77,7 @@ files:
62
77
  - lib/ghost/cli/task/help.rb
63
78
  - lib/ghost/cli/task/import.rb
64
79
  - lib/ghost/cli/task/list.rb
80
+ - lib/ghost/cli/task/set.rb
65
81
  - lib/ghost/cli/task.rb
66
82
  - lib/ghost/cli.rb
67
83
  - lib/ghost/host.rb
@@ -107,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
123
  version: 1.3.1
108
124
  requirements: []
109
125
  rubyforge_project: ghost
110
- rubygems_version: 1.8.10
126
+ rubygems_version: 1.8.23
111
127
  signing_key:
112
128
  specification_version: 3
113
129
  summary: Allows you to create, list, and modify local hostnames