git-webby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +74 -0
- data/Rakefile +44 -0
- data/doc/releases/v0.1.0.rdoc +11 -0
- data/git-webby.gemspec +32 -0
- data/lib/git/webby.rb +145 -0
- data/lib/git/webby/http_backend.rb +248 -0
- data/lib/git/webby/version.rb +14 -0
- data/test/config_test.rb +30 -0
- data/test/fixtures/config.yml +7 -0
- data/test/fixtures/htpasswd +4 -0
- data/test/fixtures/mycode.git/HEAD +1 -0
- data/test/fixtures/mycode.git/config +4 -0
- data/test/fixtures/mycode.git/description +1 -0
- data/test/fixtures/mycode.git/hooks/applypatch-msg.sample +15 -0
- data/test/fixtures/mycode.git/hooks/commit-msg.sample +24 -0
- data/test/fixtures/mycode.git/hooks/post-commit.sample +8 -0
- data/test/fixtures/mycode.git/hooks/post-receive.sample +15 -0
- data/test/fixtures/mycode.git/hooks/post-update.sample +8 -0
- data/test/fixtures/mycode.git/hooks/pre-applypatch.sample +14 -0
- data/test/fixtures/mycode.git/hooks/pre-commit.sample +46 -0
- data/test/fixtures/mycode.git/hooks/pre-rebase.sample +169 -0
- data/test/fixtures/mycode.git/hooks/prepare-commit-msg.sample +36 -0
- data/test/fixtures/mycode.git/hooks/update.sample +128 -0
- data/test/fixtures/mycode.git/info/exclude +6 -0
- data/test/fixtures/mycode.git/info/refs +3 -0
- data/test/fixtures/mycode.git/objects/02/83eb96425444e17b97182e1ba9f216cc67c132 +0 -0
- data/test/fixtures/mycode.git/objects/03/9927042df267a1bc606fc4485b7a79b6a9e3cd +1 -0
- data/test/fixtures/mycode.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
- data/test/fixtures/mycode.git/objects/5e/54a0767e0c380f3baab17938d68c7f464cf171 +1 -0
- data/test/fixtures/mycode.git/objects/71/6e9568eed27d5ee4378b3ecf6dd095a547bde9 +1 -0
- data/test/fixtures/mycode.git/objects/be/118435b9d908fd4a689cd8b0cc98059911a31a +0 -0
- data/test/fixtures/mycode.git/objects/db/aefcb5bde664671c73b99515c386dcbc7f22b6 +0 -0
- data/test/fixtures/mycode.git/objects/eb/669b878d2013ac70aa5dee75e6357ea81d16ea +0 -0
- data/test/fixtures/mycode.git/objects/ed/10cfcf72862e140c97fe899cba2a55f4cb4c20 +0 -0
- data/test/fixtures/mycode.git/objects/info/packs +2 -0
- data/test/fixtures/mycode.git/objects/pack/pack-40a8636b62258fffd78ec1e8d254116e72d385a9.idx +0 -0
- data/test/fixtures/mycode.git/objects/pack/pack-40a8636b62258fffd78ec1e8d254116e72d385a9.pack +0 -0
- data/test/fixtures/mycode.git/packed-refs +4 -0
- data/test/fixtures/mycode.git/refs/heads/master +1 -0
- data/test/fixtures/mycode.git/refs/tags/v0.1.0 +1 -0
- data/test/helpers.rb +67 -0
- data/test/htpasswd_test.rb +68 -0
- data/test/http_backend_authentication_test.rb +69 -0
- data/test/http_backend_test.rb +134 -0
- metadata +134 -0
data/README.rdoc
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
= Git-Webby - Web smarty for Git
|
2
|
+
|
3
|
+
== DESCRIPTION
|
4
|
+
|
5
|
+
This project was inspired in the {Grack}[http://github.com/schacon/grack]
|
6
|
+
Smart-HTTP server handler (written by
|
7
|
+
{Scott Chacon}[http://github.com/schacon]) but developed using
|
8
|
+
{Sinatra}[http://www.sinatrarb.com] and aims replace the original
|
9
|
+
`git-http-backend` including new features.
|
10
|
+
|
11
|
+
The main goal of the <b>Git-Webby</b> is implement the following useful features.
|
12
|
+
|
13
|
+
- Smart-HTTP, based on _git-http-backend_.
|
14
|
+
- Authentication flexible based on database or configuration file like .+htpasswd+.
|
15
|
+
- API to get information about repository.
|
16
|
+
|
17
|
+
== SINOPSIS
|
18
|
+
|
19
|
+
Install the Git-Webby using {Rubygems}[http://rubygems.org/gems/git-webby].
|
20
|
+
|
21
|
+
gem install git-webby
|
22
|
+
|
23
|
+
Or fork the project hosted on {Github}[http://github.com/codigorama/git-webby].
|
24
|
+
|
25
|
+
git clone https://github.com/codigorama/git-webby.git
|
26
|
+
...
|
27
|
+
cd git-webby
|
28
|
+
rake install
|
29
|
+
|
30
|
+
Configure your Rackup file (<tt>config.ru</tt>) using the following instructions:
|
31
|
+
|
32
|
+
# config.ru
|
33
|
+
require "git/webby"
|
34
|
+
|
35
|
+
Git::Webby::HttpBackend.configure do |server|
|
36
|
+
server.project_root = "/home/git/repositories"
|
37
|
+
server.git_path = "/usr/bin/git"
|
38
|
+
server.get_any_file = true
|
39
|
+
server.upload_pack = true
|
40
|
+
server.receive_pack = false
|
41
|
+
server.authenticate = true
|
42
|
+
end
|
43
|
+
|
44
|
+
$ rackup --port 2011 --daemonize
|
45
|
+
$ git clone http://localhost:2011/mycode.git
|
46
|
+
|
47
|
+
You can use the <tt>.netrc</tt> for improve your connection. Put this:
|
48
|
+
|
49
|
+
machine <host> login <username> password <password>
|
50
|
+
|
51
|
+
The Git-Webby is under development, so there are still many improvements to be
|
52
|
+
made. Please, help us to improve the project with your feedback to
|
53
|
+
{issues}[http://github.com/codigorama/git-webby] or sending email to
|
54
|
+
{opensource@codigorama.com}[mailto:opensource@codigorama.com].
|
55
|
+
|
56
|
+
Discuss in {Google Groups}[http://groups.google.com/group/git-webby].
|
57
|
+
|
58
|
+
== AUTHORS
|
59
|
+
|
60
|
+
Written by Hallison Batista <hallison@codigorama.com>.
|
61
|
+
|
62
|
+
== BUGS
|
63
|
+
|
64
|
+
If you find a bug, please report it at the Git-Webby project's
|
65
|
+
{issues tracker}[http://github.com/codigorama/git-webby] on Github.
|
66
|
+
|
67
|
+
== LICENSE
|
68
|
+
|
69
|
+
Git-Webby is Copyright (c) 2011 Hallison Batista, Codigorama.
|
70
|
+
|
71
|
+
It is free software, and may be redistributed under the terms specified in
|
72
|
+
LICENSE.txt.
|
73
|
+
|
74
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#:nopkg:
|
2
|
+
ENV["RUBYLIB"] = "#{File.dirname(__FILE__)}/lib"
|
3
|
+
ENV["RUBYOPT"] = "-rubygems"
|
4
|
+
#:
|
5
|
+
|
6
|
+
require "git/webby"
|
7
|
+
|
8
|
+
def spec
|
9
|
+
@spec ||= Gem::Specification.load("git-webby.gemspec")
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Run tests"
|
13
|
+
task :test, [:file] do |spec, args|
|
14
|
+
Dir["test/#{args.file}*_test.rb"].each do |file|
|
15
|
+
sh "ruby #{file}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "API Documentation (RDoc)"
|
20
|
+
task :doc do
|
21
|
+
sh "rdoc -o doc/api -H -f hanna -m README.rdoc"
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "Build #{spec.file_name}"
|
25
|
+
task :build => "#{spec.name}.gemspec" do
|
26
|
+
sh "gem build #{spec.name}.gemspec"
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "Release #{spec.file_name}"
|
30
|
+
task :release do
|
31
|
+
sh "gem push #{spec.file_name}"
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Install gem file #{spec.file_name}"
|
35
|
+
task :install => :build do
|
36
|
+
sh "gem install -l #{spec.file_name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Uninstall gem #{spec.name} v#{spec.version}"
|
40
|
+
task :uninstall do
|
41
|
+
sh "gem uninstall -l #{spec.name} -v #{spec.version}"
|
42
|
+
end
|
43
|
+
|
44
|
+
task :default => :test
|
@@ -0,0 +1,11 @@
|
|
1
|
+
== Git-Webby v0.1.0
|
2
|
+
|
3
|
+
Implementation of the basic features:
|
4
|
+
|
5
|
+
- Smart-HTTP implementation.
|
6
|
+
- Authentication using +htpasswd+ features (only crypt algorithm).
|
7
|
+
- Basic configuration in Rackup file.
|
8
|
+
|
9
|
+
This is a beta version. For more informations about this release,
|
10
|
+
please visit <http://github.com/codigorama/git-webby>.
|
11
|
+
|
data/git-webby.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "git/webby"
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.platform = Gem::Platform::RUBY
|
5
|
+
spec.name = "git-webby"
|
6
|
+
spec.summary = "Git Web implementation of the Smart HTTP and other features"
|
7
|
+
spec.authors = ["Hallison Batista"]
|
8
|
+
spec.email = "hallison@codigorama.com"
|
9
|
+
spec.homepage = "http://github.com/codigorama/git-webby"
|
10
|
+
spec.rubyforge_project = spec.name
|
11
|
+
spec.version = Git::Webby::VERSION
|
12
|
+
spec.date = Git::Webby::RELEASE
|
13
|
+
spec.test_files = spec.files.select{ |path| path =~ /^test\/.*/ }
|
14
|
+
spec.require_paths = ["lib"]
|
15
|
+
spec.files = %x[git ls-files].split.reject do |out|
|
16
|
+
out =~ %r{^\.} || out =~ %r{/^doc/api/}
|
17
|
+
end
|
18
|
+
spec.description = <<-end.gsub /^ /,''
|
19
|
+
Git::Webby is a implementation of the several features:
|
20
|
+
- Smart HTTP which works like as git-http-backend.
|
21
|
+
- Show info pages about the projects.
|
22
|
+
end
|
23
|
+
spec.post_install_message = <<-end.gsub(/^[ ]{4}/,'')
|
24
|
+
#{'-'*78}
|
25
|
+
Git::Webby v#{spec.version}
|
26
|
+
|
27
|
+
Thanks for use Git::Webby.
|
28
|
+
#{'-'*78}
|
29
|
+
end
|
30
|
+
spec.add_dependency "sinatra", ">= 1.0"
|
31
|
+
end
|
32
|
+
|
data/lib/git/webby.rb
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
# See <b>Git::Webby</b> for documentation.
|
2
|
+
module Git
|
3
|
+
|
4
|
+
# Internal requirements
|
5
|
+
require "git/webby/version"
|
6
|
+
|
7
|
+
# The main goal of the <b>Git::Webby</b> is implement the following useful
|
8
|
+
# features.
|
9
|
+
#
|
10
|
+
# - Smart-HTTP, based on _git-http-backend_.
|
11
|
+
# - Authentication flexible based on database or configuration file like <tt>.htpasswd</tt>.
|
12
|
+
# - API to get information about repository.
|
13
|
+
module Webby
|
14
|
+
|
15
|
+
module RepositoryUtils # :nodoc:
|
16
|
+
def project_path_to(*args)
|
17
|
+
File.join(settings.project_root.to_s, *(args.map(&:to_s)))
|
18
|
+
end
|
19
|
+
|
20
|
+
def git_dir(name)
|
21
|
+
unless name =~ /\w\.git/ # not bare directory
|
22
|
+
File.join(name, ".git")
|
23
|
+
else
|
24
|
+
name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def path_to(name, *args)
|
29
|
+
project_path_to(git_dir(name), *args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def read_file(dirname, *file)
|
33
|
+
File.read(path_to(dirname, *file))
|
34
|
+
end
|
35
|
+
|
36
|
+
def chdir(dirname, &block)
|
37
|
+
Dir.chdir(path_to(dirname), &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def git_cli(command, *args)
|
41
|
+
%Q[#{settings.git_path} #{args.unshift(command.to_s.gsub("_","-")).compact.join(" ")}]
|
42
|
+
end
|
43
|
+
|
44
|
+
def git_run(command, *args)
|
45
|
+
%x[#{git_cli command, *args}]
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
# This class configure the needed variables used by application.
|
51
|
+
#
|
52
|
+
# For HTTP-Backend configuration
|
53
|
+
#
|
54
|
+
# The following attributes was necessary by +http_backend+:
|
55
|
+
#
|
56
|
+
# *project_root* :: Directory that contains all git repositories.
|
57
|
+
# *git_path* :: Path to git command line program.
|
58
|
+
# *get_any_file* :: Like <tt>http.getanyfile</tt> configuration.
|
59
|
+
# *upload_pack* :: Like <tt>http.uploadpack</tt> configuration.
|
60
|
+
# *receive_pack* :: Like <tt>http.receivepack</tt> configuration.
|
61
|
+
class Config
|
62
|
+
|
63
|
+
# Configuration for HTTP Backend variables
|
64
|
+
attr_accessor :http_backend
|
65
|
+
|
66
|
+
def initialize(attributes = {}) # :yields: config
|
67
|
+
attributes.each do |key, value|
|
68
|
+
self.send("#{key}=", value) if self.respond_to? key
|
69
|
+
end
|
70
|
+
yield self if block_given?
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.load_file(file)
|
74
|
+
require "yaml"
|
75
|
+
new(YAML.load_file(file))
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
class Htgroup #:nodoc:
|
81
|
+
require "webrick/httpauth/htgroup"
|
82
|
+
|
83
|
+
def initialize(file)
|
84
|
+
@handler = WEBrick::HTTPAuth::Htgroup.new(file)
|
85
|
+
yield self if block_given?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class Htpasswd #:nodoc:
|
90
|
+
require "webrick/httpauth/htpasswd"
|
91
|
+
|
92
|
+
def initialize(file)
|
93
|
+
@handler = WEBrick::HTTPAuth::Htpasswd.new(file)
|
94
|
+
yield self if block_given?
|
95
|
+
end
|
96
|
+
|
97
|
+
def find(username)
|
98
|
+
password = @handler.get_passwd(nil, username, false)
|
99
|
+
if block_given?
|
100
|
+
yield password ? [password, password[0,2]] : [nil, nil]
|
101
|
+
else
|
102
|
+
password
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def authenticated?(username, password)
|
107
|
+
self.find username do |crypted, salt|
|
108
|
+
crypted && salt && crypted == password.crypt(salt)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def create(username, password)
|
113
|
+
@handler.set_passwd(nil, username, password)
|
114
|
+
end
|
115
|
+
alias update create
|
116
|
+
|
117
|
+
def destroy(username)
|
118
|
+
@handler.delete_passwd(nil, username)
|
119
|
+
end
|
120
|
+
|
121
|
+
def include?(username)
|
122
|
+
users.include? username
|
123
|
+
end
|
124
|
+
|
125
|
+
def size
|
126
|
+
users.size
|
127
|
+
end
|
128
|
+
|
129
|
+
def write!
|
130
|
+
@handler.flush
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def users
|
136
|
+
@handler.each{|username, password| username }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Applications
|
141
|
+
autoload :HttpBackend, "git/webby/http_backend"
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
@@ -0,0 +1,248 @@
|
|
1
|
+
module Git::Webby
|
2
|
+
|
3
|
+
module HttpBackendUtils #:nodoc:
|
4
|
+
|
5
|
+
include RepositoryUtils
|
6
|
+
|
7
|
+
def repository
|
8
|
+
params[:repository]
|
9
|
+
end
|
10
|
+
|
11
|
+
def content_type_for_git(name, *suffixes)
|
12
|
+
content_type("application/x-git-#{name}-#{suffixes.compact.join("-")}")
|
13
|
+
end
|
14
|
+
|
15
|
+
def service_request?
|
16
|
+
not params[:service].nil?
|
17
|
+
end
|
18
|
+
|
19
|
+
# select_service feature
|
20
|
+
def service
|
21
|
+
@service = params[:service]
|
22
|
+
return false if @service.nil?
|
23
|
+
return false if @service[0, 4] != "git-"
|
24
|
+
@service = @service.gsub("git-", "")
|
25
|
+
end
|
26
|
+
|
27
|
+
# pkt_write feature
|
28
|
+
def packet_write(line)
|
29
|
+
(line.size + 4).to_s(base=16).rjust(4, "0") + line
|
30
|
+
end
|
31
|
+
|
32
|
+
# pkt_flush feature
|
33
|
+
def packet_flush
|
34
|
+
"0000"
|
35
|
+
end
|
36
|
+
|
37
|
+
# hdr_nocache feature
|
38
|
+
def header_nocache
|
39
|
+
headers "Expires" => "Fri, 01 Jan 1980 00:00:00 GMT",
|
40
|
+
"Pragma" => "no-cache",
|
41
|
+
"Cache-Control" => "no-cache, max-age=0, must-revalidate"
|
42
|
+
end
|
43
|
+
|
44
|
+
# hdr_cache_forever feature
|
45
|
+
def header_cache_forever
|
46
|
+
now = Time.now
|
47
|
+
headers "Date" => now.to_s,
|
48
|
+
"Expires" => (now + 31536000).to_s,
|
49
|
+
"Cache-Control" => "public, max-age=31536000"
|
50
|
+
end
|
51
|
+
|
52
|
+
# select_getanyfile feature
|
53
|
+
def read_any_file
|
54
|
+
unless settings.get_any_file
|
55
|
+
halt 403, "Unsupported service: getanyfile"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# get_text_file feature
|
60
|
+
def read_text_file(repository, *file)
|
61
|
+
read_any_file
|
62
|
+
header_nocache
|
63
|
+
content_type "text/plain"
|
64
|
+
read_file(repository, *file)
|
65
|
+
end
|
66
|
+
|
67
|
+
# get_loose_object feature
|
68
|
+
def send_loose_object(repository, hash_prefix, hash_suffix)
|
69
|
+
read_any_file
|
70
|
+
header_cache_forever
|
71
|
+
content_type_for_git :loose, :object
|
72
|
+
send_file(path_to(repository, "objects", hash_prefix, hash_suffix))
|
73
|
+
end
|
74
|
+
|
75
|
+
# get_pack_file and get_idx_file
|
76
|
+
def send_pack_idx_file(repository, pack, idx = false)
|
77
|
+
read_any_file
|
78
|
+
header_cache_forever
|
79
|
+
content_type_for_git :packed, :objects, (idx ? :toc : nil)
|
80
|
+
send_file(path_to(repository, "objects", "pack", pack))
|
81
|
+
end
|
82
|
+
|
83
|
+
def send_info_packs(repository)
|
84
|
+
read_any_file
|
85
|
+
header_nocache
|
86
|
+
content_type "text/plain; charset=utf-8"
|
87
|
+
send_file(path_to(repository, "objects", "info", "packs"))
|
88
|
+
end
|
89
|
+
|
90
|
+
# run_service feature
|
91
|
+
def run_advertisement(repository, service)
|
92
|
+
header_nocache
|
93
|
+
content_type_for_git service, :advertisement
|
94
|
+
chdir repository do
|
95
|
+
response.body = ""
|
96
|
+
response.body += packet_write("# service=git-#{service}\n")
|
97
|
+
response.body += packet_flush
|
98
|
+
response.body += git_run(service, "--stateless-rpc --advertise-refs .")
|
99
|
+
response.finish
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def run_process(repository, service)
|
104
|
+
content_type_for_git service, :result
|
105
|
+
input = request.body.read
|
106
|
+
command = git_cli(service, "--stateless-rpc .")
|
107
|
+
chdir repository do
|
108
|
+
# This source has extracted from Grack written by Scott Chacon.
|
109
|
+
IO.popen(command, File::RDWR) do |pipe|
|
110
|
+
pipe.write(input)
|
111
|
+
while !pipe.eof?
|
112
|
+
block = pipe.read(8192) # 8M at a time
|
113
|
+
response.write block # steam it to the client
|
114
|
+
end
|
115
|
+
end # IO
|
116
|
+
response.finish
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end # HttpBackendUtils
|
121
|
+
|
122
|
+
module HttpBackendAuthentication #:nodoc:
|
123
|
+
|
124
|
+
def htpasswd
|
125
|
+
@htpasswd ||= Htpasswd.new(project_path_to("htpasswd"))
|
126
|
+
end
|
127
|
+
|
128
|
+
def authentication
|
129
|
+
@authentication ||= Rack::Auth::Basic::Request.new request.env
|
130
|
+
end
|
131
|
+
|
132
|
+
def authenticated?
|
133
|
+
request.env["REMOTE_USER"] && request.env["git.webby.authenticated"]
|
134
|
+
end
|
135
|
+
|
136
|
+
def authenticate(username, password)
|
137
|
+
checked = [ username, password ] == authentication.credentials
|
138
|
+
validated = authentication.provided? && authentication.basic?
|
139
|
+
granted = htpasswd.authenticated? username, password
|
140
|
+
if checked and validated and granted
|
141
|
+
request.env["git.webby.authenticated"] = true
|
142
|
+
request.env["REMOTE_USER"] = authentication.username
|
143
|
+
else
|
144
|
+
nil
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def unauthorized!(realm = Git::Webby::info)
|
149
|
+
headers "WWW-Authenticate" => %(Basic realm="#{realm}")
|
150
|
+
throw :halt, [ 401, "Authorization Required" ]
|
151
|
+
end
|
152
|
+
|
153
|
+
def bad_request!
|
154
|
+
throw :halt, [ 400, "Bad Request" ]
|
155
|
+
end
|
156
|
+
|
157
|
+
def authenticate!
|
158
|
+
return if authenticated?
|
159
|
+
unauthorized! unless authentication.provided?
|
160
|
+
bad_request! unless authentication.basic?
|
161
|
+
unauthorized! unless authenticate(*authentication.credentials)
|
162
|
+
request.env["REMOTE_USER"] = authentication.username
|
163
|
+
end
|
164
|
+
|
165
|
+
def access_granted?(username, password)
|
166
|
+
authenticated? || authenticate(username, password)
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
require "sinatra/base"
|
172
|
+
|
173
|
+
# The Smart HTTP handler server. This is the main Web application which respond to following requests:
|
174
|
+
#
|
175
|
+
# <repo.git>/HEAD :: HEAD contents
|
176
|
+
# <repo.git>/info/refs :: Text file that contains references.
|
177
|
+
# <repo.git>/objects/info/* :: Text file that contains all list of packets, alternates or http-alternates.
|
178
|
+
# <repo.git>/objects/*/* :: Git objects, packets or indexes.
|
179
|
+
# <repo.git>/upload-pack :: Post an upload packets.
|
180
|
+
# <repo.git>/receive-pack :: Post a receive packets.
|
181
|
+
#
|
182
|
+
# See ::configure for more details.
|
183
|
+
class HttpBackend < Sinatra::Base
|
184
|
+
|
185
|
+
helpers HttpBackendUtils
|
186
|
+
|
187
|
+
set :project_root, File.expand_path("#{File.dirname(__FILE__)}/git")
|
188
|
+
set :git_path, "/usr/bin/git"
|
189
|
+
set :get_any_file, true
|
190
|
+
set :upload_pack, true
|
191
|
+
set :receive_pack, false
|
192
|
+
set :authenticate, false
|
193
|
+
|
194
|
+
def self.configure(*envs, &block)
|
195
|
+
super(*envs, &block)
|
196
|
+
self
|
197
|
+
end
|
198
|
+
|
199
|
+
before do
|
200
|
+
authenticate! if settings.authenticate
|
201
|
+
end
|
202
|
+
|
203
|
+
# implements the get_text_file function
|
204
|
+
get "/:repository/HEAD" do |repository|
|
205
|
+
read_text_file(repository, "HEAD")
|
206
|
+
end
|
207
|
+
|
208
|
+
# implements the get_info_refs function
|
209
|
+
get "/:repository/info/refs" do |repository|
|
210
|
+
if service_request? # by URL query parameters
|
211
|
+
run_advertisement repository, service
|
212
|
+
else
|
213
|
+
read_text_file(repository, :info, :refs)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# implements the get_text_file and get_info_packs functions
|
218
|
+
get %r{/(.*?)/objects/info/(packs|alternates|http-alternates)$} do |repository, file|
|
219
|
+
if file == "packs"
|
220
|
+
send_info_packs(repository)
|
221
|
+
else
|
222
|
+
read_text_file(repository, :objects, :info, file)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# implements the get_loose_object function
|
227
|
+
get %r{/(.*?)/objects/([0-9a-f]{2})/([0-9a-f]{38})$} do |repository, prefix, suffix|
|
228
|
+
send_loose_object(repository, prefix, suffix)
|
229
|
+
end
|
230
|
+
|
231
|
+
# implements the get_pack_file and get_idx_file functions
|
232
|
+
get %r{/(.*?)/objects/pack/(pack-[0-9a-f]{40}.(pack|idx))$} do |repository, pack, ext|
|
233
|
+
send_pack_idx_file(repository, pack, ext == "idx")
|
234
|
+
end
|
235
|
+
|
236
|
+
# implements the service_rpc function
|
237
|
+
post "/:repository/:service" do |repository, rpc|
|
238
|
+
run_process repository, service
|
239
|
+
end
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
helpers HttpBackendAuthentication
|
244
|
+
|
245
|
+
end # HttpBackend
|
246
|
+
|
247
|
+
end # Git::Webby
|
248
|
+
|