git-webby 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|