Module: GitWit::Shell

Defined in:
lib/git_wit/shell.rb

Constant Summary collapse

SHELL_COMMANDS =
%w(git-upload-pack git-receive-pack git-upload-archive)
SUDO_ENV_KEYS =
%w(SSH_ORIGINAL_COMMAND GEM_HOME GEM_PATH PATH 
BUNDLE_GEMFILE RAILS_ENV)

Class Method Summary collapse

Class Method Details

.app_userObject



20
21
22
# File 'lib/git_wit/shell.rb', line 20

def self.app_user
  File.stat(rails_root).uid
end

.authenticate(username) ⇒ Object



40
41
42
# File 'lib/git_wit/shell.rb', line 40

def self.authenticate(username)
  GitWit.user_for_authentication username
end

.authenticate!(username) ⇒ Object



44
45
46
47
48
# File 'lib/git_wit/shell.rb', line 44

def self.authenticate!(username)
  user = authenticate username
  abort "Anonymous access denied" if user.nil?
  user
end

.authorize(command, user, repository) ⇒ Object



50
51
52
53
# File 'lib/git_wit/shell.rb', line 50

def self.authorize(command, user, repository)
  op = command == "git-receive-pack" ? :write : :read
  GitWit.authorize op, user, repository
end

.authorize!(command, user, repository) ⇒ Object



55
56
57
# File 'lib/git_wit/shell.rb', line 55

def self.authorize!(command, user, repository)
  abort "Unauthorized" unless authorize command, user, repository
end

.boot_appObject



30
31
32
# File 'lib/git_wit/shell.rb', line 30

def self.boot_app
  require File.expand_path File.join(rails_root, "config/environment")
end

.exec_with_sudo!(user = app_user) ⇒ Object



7
8
9
10
11
12
13
14
# File 'lib/git_wit/shell.rb', line 7

def self.exec_with_sudo!(user = app_user)
  return if running_as?(user)
  Dir.chdir rails_root
  env = SUDO_ENV_KEYS.map { |k| "#{k}=#{ENV[k]}" if ENV[k] }.compact
  env << "RAILS_ROOT=#{rails_root}" << "TERM=dumb"
  cmd = ["sudo", "-u", "##{app_user}", *env, "-s", $PROGRAM_NAME, *ARGV]
  exec *cmd
end

.parse_ssh_original_commandObject



34
35
36
37
38
# File 'lib/git_wit/shell.rb', line 34

def self.parse_ssh_original_command
  /^(?<cmd>git-[^\s]+)\s+'(?<repository>[^']+\.git)'/ =~ ENV["SSH_ORIGINAL_COMMAND"]
  abort "Uknown command #{cmd}" unless SHELL_COMMANDS.include? cmd
  [cmd, repository]
end

.rails_rootObject



24
25
26
27
28
# File 'lib/git_wit/shell.rb', line 24

def self.rails_root
  return File.expand_path(ENV["RAILS_ROOT"]) if ENV["RAILS_ROOT"]
  return File.expand_path("..", ENV["BUNDLE_GEMFILE"]) if ENV["BUNDLE_GEMFILE"]
  Dir.pwd
end

.runObject



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/git_wit/shell.rb', line 59

def self.run
  exec_with_sudo!
  boot_app
  command, repository = parse_ssh_original_command
  user = authenticate! ARGV[0]
  authorize! command, user, repository

  repo_path = File.expand_path File.join(GitWit.repositories_path, repository)
  cmd = ["git", "shell", "-c", "#{command} '#{repo_path}'"]
  Rails.logger.info "GitWit SSH command: #{cmd.join " "}"
  exec *cmd
end

.running_as?(user) ⇒ Boolean

Returns:

  • (Boolean)


16
17
18
# File 'lib/git_wit/shell.rb', line 16

def self.running_as?(user)
  Process.uid == user
end