Commit 4ee78e5834e60a3fa4e2f10b0760a40f02cd1b31

made the ruby git-daemon support options and moved things around a bit on the class

Commit diff

app/models/repository.rb

 
3030 end
3131
3232 def self.find_by_path(path)
33 repo_name, project_name = (path.split('/') - GitoriousConfig['repository_base_path'].split('/')).reverse
33 base_path = path.gsub(/^#{Regexp.escape(GitoriousConfig['repository_base_path'])}/, "")
34 repo_name, project_name = base_path.split("/").reverse
3435
3536 project = Project.find_by_slug!(project_name)
3637 project.repositories.find_by_name(repo_name.sub(/\.git/, ""))
toggle raw diff

script/git-daemon

 
44require 'daemons'
55require 'geoip'
66require 'socket'
7require "optparse"
78
89ENV["RAILS_ENV"] ||= "production"
910require File.dirname(__FILE__)+'/../config/environment'
1011
1112Rails.configuration.log_level = :info # Disable debug
13ActiveRecord::Base.logger = nil
14ActiveRecord::Base.allow_concurrency = true
15ActiveRecord::Base.clear_active_connections!
1216
1317BASE_PATH = File.expand_path(GitoriousConfig['repository_base_path'])
1418
2121$children_active = 0
2222
2323module Git
24
25class Daemon
26 include Daemonize
27
28 def self.start
29 new
30 end
31
32 def initialize
33 daemonize(File.join(RAILS_ROOT, "log", "git-daemon.log"))
24 class Daemon
25 include Daemonize
3426
35 @geoip = GeoIP.new(File.join(RAILS_ROOT, "data", "GeoIP.dat"))
36 trap "CLD" do
37 pid = Process.wait
38 $children_reaped += 1
39 log(pid, "Disconnected. (status=#{$?.exitstatus})")
40
41 $children_reaped = $children_active = 0 if $children_reaped == $children_active
27 SERVICE_REGEXP = /(\w{4})(git-[\w-]+)\s(.+)\x0host=([\w\.\-]+)/.freeze
28
29 def initialize(options)
30 @options = options
31 @geoip = GeoIP.new(File.join(RAILS_ROOT, "data", "GeoIP.dat"))
4232 end
4333
44 port = 9418
45 server = TCPServer.new('localhost', port)
46 service_regexp = /(\w{4})(git-[\w-]+)\s(.+)\x0host=([\w\.\-]+)/.freeze
47 while session = server.accept
48 $children_active += 1
49
50 if $children_active - $children_reaped > MAX_CHILDREN
51 log(Process.pid, "too many active children #{$children_active - $children_reaped}/#{MAX_CHILDREN}")
52 session.close
53 # we didn't actually do the fork, so decrease the count
54 $children_active -= 1
55 next
34 def start
35 if @options[:daemonize]
36 daemonize(@options[:logfile])
5637 end
38 @socket = TCPServer.new(@options[:host], @options[:port])
39 log(Process.pid, "Listening on #{@options[:host]}:#{@options[:port]}...")
40 run
41 end
5742
58 line = session.recv(1000)
59 timeout = 30
60 if line =~ service_regexp
61 code = $1
62 service = $2
63 base_path = $3
64 host = $4
65
66 path = "#{BASE_PATH}/#{base_path}"
67 if !File.join(File.expand_path(path)).index(BASE_PATH) == 0 || !File.directory?(path)
68 log(Process.pid, "Invalid path: #{base_path}")
43 def run
44 while session = @socket.accept
45 $children_active += 1
46
47 if $children_active - $children_reaped > MAX_CHILDREN
48 log(Process.pid, "too many active children #{$children_active - $children_reaped}/#{MAX_CHILDREN}")
6949 session.close
7050 $children_active -= 1
7151 next
7252 end
53
54 line = session.recv(1000)
55 timeout = 30
56 if line =~ SERVICE_REGEXP
57 code = $1
58 service = $2
59 base_path = $3
60 host = $4
7361
74 if !File.exist?(File.join(path, "git-daemon-export-ok"))
75 session.close
76 $children_active -= 1
77 next
78 end
62 path = File.expand_path("#{BASE_PATH}/#{base_path}")
63 if !path.index(BASE_PATH) == 0 || !File.directory?(path)
64 log(Process.pid, "Invalid path: #{base_path}")
65 session.close
66 $children_active -= 1
67 next
68 end
69
70 if !File.exist?(File.join(path, "git-daemon-export-ok"))
71 session.close
72 $children_active -= 1
73 next
74 end
7975
80 Dir.chdir(path) do
81 cmd = "git-upload-pack --strict --timeout=#{timeout} ."
76 Dir.chdir(path) do
77 cmd = "git-upload-pack --strict --timeout=#{timeout} ."
8278
83 fork do
84 repository = nil
85 begin
86 ActiveRecord::Base.allow_concurrency = true
87 repository = ::Repository.find_by_path(path)
88 rescue Exception
89 end
90 pid = Process.pid
91 ip_family, port, name, ip = session.peeraddr
92 log(pid, "Connection from #{ip} for #{path.inspect}")
79 fork do
80 repository = nil
81
82 begin
83 repository = ::Repository.find_by_path(path)
84 rescue => e
85 log(Process.pid, "AR error: #{e.class.name} #{e.message}:\n #{e.backtrace.join("\n ")}")
86 end
87
88 pid = Process.pid
89 ip_family, port, name, ip = session.peeraddr
90 log(pid, "Connection from #{ip} for #{path.inspect}")
9391
94 $stdout.reopen(session)
95 $stdin.reopen(session)
96 session.close
92 $stdout.reopen(session)
93 $stdin.reopen(session)
94 session.close
9795
98 if repository
99 if ip_family == "AF_INET6"
100 repository.cloned_from(ip)
96 if repository
97 if ip_family == "AF_INET6"
98 repository.cloned_from(ip)
99 else
100 localization = @geoip.country(ip)
101 repository.cloned_from(ip, localization[3], localization[5])
102 end
101103 else
102 localization = @geoip.country(ip)
103 repository.cloned_from(ip, localization[3], localization[5])
104 log(pid, "Cannot find repository: #{path}")
104105 end
105 else
106 log(pid, "Cannot find repository: #{path}")
107 end
108106
109 exec(cmd)
110 $children_reaped += 1
111 exit!
107 exec(cmd)
108 $children_reaped += 1
109 exit!
110 end
112111 end
112 else
113 $stderr.puts "Invalid request: #{line}"
114 session.close
115 $children_active -= 1
116 next
113117 end
114 else
115 $stderr.puts "Invalid request: #{line}"
116 session.close
117 $children_active -= 1
118 next
119118 end
120119 end
121 end
122120
123 def log(pid, msg)
124 $stderr.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} [#{pid}] #{msg}"
121 def handle_stop(signal)
122 log(Process.pid, "Received #{signal}, exiting..")
123 exit 0
124 end
125
126 def handle_cld
127 pid = Process.wait
128 $children_reaped += 1
129 log(pid, "Disconnected. (status=#{$?.exitstatus})")
130
131 if $children_reaped == $children_active
132 $children_reaped = 0
133 $children_active = 0
134 end
135 end
136
137 def log(pid, msg)
138 $stderr.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} [#{pid}] #{msg}"
139 end
140
125141 end
126142end
127143
128end
144options = {
145 :port => 9418,
146 :host => "localhost",
147 :logfile => File.join(RAILS_ROOT, "log", "git-daemon.log"),
148 :daemonize => false
149
150}
129151
130trap "SIGINT" do
131 $stderr.puts "Exiting..."
132 exit 0
133end
152OptionParser.new do |opts|
153 opts.banner = "Usage: #{$0} start|stop [options]"
154
155 opts.on("-p", "--port", Integer, "Port to listen on") do |o|
156 options[:port] = o
157 end
158
159 opts.on("-h", "--host", "Host to listen on") do |o|
160 options[:host] = o
161 end
162
163 opts.on("-l", "--logfile", "File to log to") do |o|
164 options[:logfile] = o
165 end
166
167 opts.on("-d", "--daemonize", "Daemonize or run in foreground (default)") do |o|
168 options[:daemonize] = o
169 end
170
171 # opts.on("-e", "--environment", "RAILS_ENV to use") do |o|
172 # options[:port] = o
173 # end
174end.parse!
175
176#puts options.inspect
177
178@git_daemon = Git::Daemon.new(options)
179
180trap("SIGKILL") { @git_daemon.handle_stop("SIGKILL") }
181trap("TERM") { @git_daemon.handle_stop("TERM") }
182trap("SIGINT") { @git_daemon.handle_stop("SIGINT") }
183trap("CLD") { @git_daemon.handle_cld }
184
185@git_daemon.start
134186
135Git::Daemon.start
187#Git::Daemon.start
toggle raw diff