class Gitolite::SSHKey

Models an SSH key within gitolite provides support for multikeys

Types of multi keys:

username: bob => <keydir>/bob/bob.pub
username: bob, location: desktop => <keydir>/bob/desktop/bob.pub

Attributes

blob[RW]
email[RW]
location[RW]
owner[RW]
type[RW]

Public Class Methods

delete_dir_if_empty(dir) click to toggle source
# File lib/gitolite/ssh_key.rb, line 71
def delete_dir_if_empty(dir)
  if File.directory?(dir) && Dir["#{dir}/*"].empty?
    Dir.rmdir(dir)
  end
rescue => e
  STDERR.puts("Warning: Couldn't delete empty directory: #{e.message}")
end
from_file(key) click to toggle source
# File lib/gitolite/ssh_key.rb, line 17
def from_file(key)
  raise "#{key} does not exist!" unless File.exists?(key)

  # Owner is the basename of the key
  # i.e., <owner>/<location>/<owner>.pub
  owner = File.basename(key, ".pub")

  # Location is the middle section of the path, if any
  location = self.location_from_path(File.dirname(key), owner)

  # Use string key constructor
  self.from_string(File.read(key), owner, location)
end
from_string(key_string, owner, location = "") click to toggle source

Construct a SSHKey from a string

# File lib/gitolite/ssh_key.rb, line 32
def from_string(key_string, owner, location = "")
  if owner.nil?
    raise ArgumentError, "owner was nil, you must specify an owner"
  end

  # Get parts of the key
  type, blob, email = key_string.split

  # We need at least a type or blob
  if type.nil? || blob.nil?
    raise ArgumentError, "'#{key_string}' is not a valid SSH key string"
  end

  # If the key didn't have an email, just use the owner
  if email.nil?
    email = owner
  end

  self.new(type, blob, email, owner, location)
end
location_from_path(path, owner) click to toggle source

Parse the key path above the key to be read. As we can omit the location, there are two possible options:

  1. Location is empty. Path is <keydir>/<owner>/

  2. Location is non-empty. Path is <keydir>/<owner>/<location>

We test this by checking the parent of the given path. If it equals owner, a location was set. This allows the daft case of e.g., using <keydir>/bob/bob/bob.pub.

# File lib/gitolite/ssh_key.rb, line 62
def location_from_path(path, owner)
  keyroot = File.dirname(path)
  if File.basename(keyroot) == owner
    File.basename(path)
  else
    ''
  end
end
new(type, blob, email, owner=nil, location = "") click to toggle source
# File lib/gitolite/ssh_key.rb, line 104
def initialize(type, blob, email, owner=nil, location = "")
  @type = type
  @blob = blob
  @email = email

  @owner = owner || email
  @location = location
end
remove(key_file, key_dir_path) click to toggle source

Remove a key given a relative path

Unlinks the key file and removes any empty parent directory below key_dir

# File lib/gitolite/ssh_key.rb, line 83
def remove(key_file, key_dir_path)

  abs_key_path = File.join(key_dir_path, key_file)
  key = self.from_file(abs_key_path)

  # Remove the file itself
  File.unlink(abs_key_path)

  key_owner_dir = File.join(key_dir_path, key.owner)

  # Remove the location, if it exists and is empty
  if key.location
    self.delete_dir_if_empty(File.join(key_owner_dir, key.location))
  end

  # Remove the owner dir, if empty
  self.delete_dir_if_empty(key_owner_dir)
end

Public Instance Methods

==(key) click to toggle source
# File lib/gitolite/ssh_key.rb, line 144
def ==(key)
  @type == key.type &&
  @blob == key.blob &&
  @email == key.email &&
  @owner == key.owner &&
  @location == key.location
end
filename() click to toggle source
# File lib/gitolite/ssh_key.rb, line 139
def filename
  [@owner, '.pub'].join
end
hash() click to toggle source
# File lib/gitolite/ssh_key.rb, line 153
def hash
  [@owner, @location, @type, @blob, @email].hash
end
relative_path() click to toggle source
# File lib/gitolite/ssh_key.rb, line 135
def relative_path
  File.join(@owner, @location, self.filename)
end
to_file(path) click to toggle source
# File lib/gitolite/ssh_key.rb, line 119
def to_file(path)
  # Ensure multi-key directory structure
  # <keydir>/<owner>/<location?>/<owner>.pub
  key_dir  = File.join(path, @owner, @location)
  key_file = File.join(key_dir, self.filename)

  # Ensure subdirs exist
  FileUtils.mkdir_p(key_dir) unless File.directory?(key_dir)

  File.open(key_file, "w") do |f|
    f.sync = true
    f.write(self.to_s)
  end
  key_file
end
to_s() click to toggle source
# File lib/gitolite/ssh_key.rb, line 114
def to_s
  [@type, @blob, @email].join(' ')
end