Module: Portless::Hosts

Defined in:
lib/portless/hosts.rb

Overview

/etc/hosts management for resolvers that don't special-case .localhost (Safari, custom TLDs). Chrome/Firefox/Edge auto-resolve *.localhost, so this is a fallback. Entries live in a fenced, idempotent block. Mirrors portless's hosts.ts.

Class Method Summary collapse

Class Method Details

.build_block(hostnames) ⇒ Object



31
32
33
34
35
# File 'lib/portless/hosts.rb', line 31

def build_block(hostnames)
  return "" if hostnames.empty?
  lines = hostnames.uniq.map { |h| "127.0.0.1\t#{h}" }
  [ Constants::HOSTS_BEGIN, *lines, Constants::HOSTS_END ].join("\n")
end

.cleanObject



27
28
29
# File 'lib/portless/hosts.rb', line 27

def clean
  write(strip_block(read))
end

.fileObject

PORTLESS_HOSTS_FILE overrides the target (tests; unusual setups).



14
15
16
17
18
19
# File 'lib/portless/hosts.rb', line 14

def file
  override = ENV["PORTLESS_HOSTS_FILE"]
  return override unless override.to_s.empty?

  Constants::WINDOWS ? File.join(ENV.fetch("SystemRoot", "C:/Windows"), "System32/drivers/etc/hosts") : "/etc/hosts"
end

.readObject



41
42
43
# File 'lib/portless/hosts.rb', line 41

def read
  File.exist?(file) ? File.read(file) : ""
end

.strip_block(text) ⇒ Object



37
38
39
# File 'lib/portless/hosts.rb', line 37

def strip_block(text)
  text.gsub(/\n*#{Regexp.escape(Constants::HOSTS_BEGIN)}.*?#{Regexp.escape(Constants::HOSTS_END)}\n*/m, "\n")
end

.sync(hostnames) ⇒ Object

Replace the managed block with one 127.0.0.1 line per hostname.



22
23
24
25
# File 'lib/portless/hosts.rb', line 22

def sync(hostnames)
  block = build_block(hostnames)
  write(strip_block(read) + (block.empty? ? "" : "\n#{block}\n"))
end

.write(content) ⇒ Object



45
46
47
48
49
# File 'lib/portless/hosts.rb', line 45

def write(content)
  File.write(file, content.gsub(/\n{3,}/, "\n\n"))
rescue Errno::EACCES
  raise Error, "writing #{file} needs root — re-run via sudo (rb-portless hosts sync)"
end