Handle not ready repos
[gitorious.git] / config / git-proxymachine.rb
blobd010b326c5305bfb015f2291b122ed267f90d5ce
1 # encoding: utf-8
2 #--
3 #   Copyright (C) 2011-2014 Gitorious AS
5 #   This program is free software: you can redistribute it and/or modify
6 #   it under the terms of the GNU Affero General Public License as published by
7 #   the Free Software Foundation, either version 3 of the License, or
8 #   (at your option) any later version.
10 #   This program is distributed in the hope that it will be useful,
11 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 #   GNU Affero General Public License for more details.
15 #   You should have received a copy of the GNU Affero General Public License
16 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 #++
19 # Run with `env RAILS_ENV="development" proxymachine -c config/git-proxymachine.rb`
21 ENV["RAILS_ENV"] ||= "production"
22 require File.dirname(__FILE__) + "/../config/environment" unless defined?(Rails)
24 class GitRouter
25   # Lookup the real repository path based on +path+
26   def self.lookup_repository(path)
27     LOGGER.info "Looking up #{path.inspect}"
28     ActiveRecord::Base.verify_active_connections!
29     ::Repository.find_by_path(path)
30   end
32   def self.error_message(msg)
33     message = ["\n----------------------------------------------"]
34     message << msg
35     message << "----------------------------------------------\n"
36     sideband_message(message.join("\n"))
37   end
39   def self.sideband_message(message, channel = 2)
40     msg = "%s%s" % [channel.chr, message]
41     "%04x%s" % [msg.length+4, msg]
42   end
44   def self.header_tag(path)
45     host = Gitorious.host
46     header_data = "git-upload-pack /#{path}\000host=#{host}\000"
47     "%04x%s" % [header_data.length+4, header_data]
48   end
49 end
51 # Do the proxying to the proper host, and send the real path onwards
52 # to the backend git-daemon
53 remote_host = ENV['GIT_DAEMON_PORT_9418_TCP_ADDR'] || 'localhost'
54 remote_port = ENV['GIT_DAEMON_PORT_9418_TCP_PORT'] || 9400
55 remote = "#{remote_host}:#{remote_port}"
57 proxy do |data|
58   if data =~ /^....(git\-upload\-pack|git\ upload\-pack)\s(.+)\x00host=(.+)\x00/
59     service, path, host = $1, $2, $3
60     if repository = GitRouter.lookup_repository(path)
61       {
62         :remote => remote,
63         :data => GitRouter.header_tag(repository.hashed_path + ".git")
64       }
65     else
66       { :close => GitRouter.error_message("Cannot find repository #{path}") }
67     end
68   elsif data =~ /^....(git\-receive\-pack|git\ receive\-pack)/
69     {
70       :close => GitRouter.error_message("The git:// protocol is read-only.\n\n" +
71         "Please use the push url as listed on the repository page.")
72     }
73   else
74     { :noop => true }
75   end
76 end