class Netrc

Constants

VERSION
WINDOWS

Attributes

new_item_prefix[RW]

Public Class Methods

default_path() click to toggle source
# File lib/netrc.rb, line 5
def self.default_path
  if WINDOWS
    File.join(ENV['USERPROFILE'].gsub("\\","/"), "_netrc")
  else
    File.join(ENV["HOME"], ".netrc")
  end
end
lex(lines) click to toggle source
# File lib/netrc.rb, line 25
def self.lex(lines)
  tokens = []
  for line in lines
    content, comment = line.split(%r(\s*#.*)/)
    content.each_char do |char|
      case char
      when %r\s/
        if tokens.last && tokens.last[-1..-1] =~ %r\s/
          tokens.last << char
        else
          tokens << char
        end
      else
        if tokens.last && tokens.last[-1..-1] =~ %r\S/
          tokens.last << char
        else
          tokens << char
        end
      end
    end
    if comment
      tokens << comment
    end
  end
  tokens
end
new(path, data) click to toggle source
# File lib/netrc.rb, line 101
def initialize(path, data)
  @new_item_prefix = ''
  @path = path
  @pre, @data = data
end
parse(ts) click to toggle source

Returns two values, a header and a list of items. Each item is a 7-tuple, containing:

  • machine keyword (including trailing whitespace+comments)

  • machine name

  • login keyword (including surrounding whitespace+comments)

  • login

  • password keyword (including surrounding whitespace+comments)

  • password

  • trailing chars

This lets us change individual fields, then write out the file with all its original formatting.

# File lib/netrc.rb, line 67
def self.parse(ts)
  cur, item = [], []

  def ts.take
    if count < 1
      raise Error, "unexpected EOF"
    end
    shift
  end

  def ts.readto
    l = []
    while count > 0 && ! yield(self[0])
      l << shift
    end
    return l.join
  end

  pre = ts.readto{|t| t == "machine"}
  while ts.count > 0
    cur << ts.take + ts.readto{|t| ! skip?(t)}
    cur << ts.take
    cur << ts.readto{|t| t == "login"} + ts.take + ts.readto{|t| ! skip?(t)}
    cur << ts.take
    cur << ts.readto{|t| t == "password"} + ts.take + ts.readto{|t| ! skip?(t)}
    cur << ts.take
    cur << ts.readto{|t| t == "machine"}
    item << cur
    cur = []
  end

  [pre, item]
end
read(path=default_path) click to toggle source

Reads path and parses it as a .netrc file. If path doesn't exist, returns an empty object.

# File lib/netrc.rb, line 15
def self.read(path=default_path)
  perm = File.stat(path).mode & 0777
  if perm != 0600 && !(WINDOWS)
    raise Error, "Permission bits for '#{path}' should be 0600, but are "+perm.to_s(8)
  end
  new(path, parse(lex(File.readlines(path))))
rescue Errno::ENOENT
  new(path, parse(lex([])))
end
skip?(s) click to toggle source
# File lib/netrc.rb, line 52
def self.skip?(s)
  s =~ %r^\s/
end

Public Instance Methods

[](k) click to toggle source
# File lib/netrc.rb, line 109
def [](k)
  if item = @data.detect {|datum| datum[1] == k}
    [item[3], item[5]]
  end
end
[]=(k, info) click to toggle source
# File lib/netrc.rb, line 115
def []=(k, info)
  if item = @data.detect {|datum| datum[1] == k}
    item[3], item[5] = info
  else
    @data << new_item(k, info[0], info[1])
  end
end
count() click to toggle source
# File lib/netrc.rb, line 123
def count
  @data.count
end
delete(key) click to toggle source
# File lib/netrc.rb, line 127
def delete(key)
  datum = nil
  for value in @data
    if value[1] == key
      datum = value
      break
    end
  end
  @data.delete(datum)
end
each(&block) click to toggle source
# File lib/netrc.rb, line 138
def each(&block)
  @data.each(&block)
end
new_item(m, l, p) click to toggle source
# File lib/netrc.rb, line 142
def new_item(m, l, p)
  [new_item_prefix+"machine ", m, "\n  login ", l, "\n  password ", p, "\n"]
end
save() click to toggle source
# File lib/netrc.rb, line 146
def save
  File.open(@path, 'w', 0600) {|file| file.print(unparse)}
end
unparse() click to toggle source
# File lib/netrc.rb, line 150
def unparse
  @pre + @data.map(&:join).join
end