git-lighttp 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +11 -0
  3. data/Makefile +41 -0
  4. data/README.pt-BR.rdoc +81 -0
  5. data/README.rdoc +75 -0
  6. data/Rakefile +50 -0
  7. data/doc/releases/v0.1.0.rdoc +11 -0
  8. data/doc/releases/v0.2.0.rdoc +24 -0
  9. data/doc/releases/v0.3.0.rdoc +13 -0
  10. data/git-lighttp.gemspec +25 -0
  11. data/lib/git/lighttp.rb +365 -0
  12. data/lib/git/lighttp/extensions.rb +73 -0
  13. data/lib/git/lighttp/http_backend.rb +178 -0
  14. data/lib/git/lighttp/treeish.rb +28 -0
  15. data/lib/git/lighttp/version.rb +26 -0
  16. data/test/all.rb +12 -0
  17. data/test/config_test.rb +43 -0
  18. data/test/fixtures/config.yml +13 -0
  19. data/test/fixtures/htgroup +3 -0
  20. data/test/fixtures/htpasswd +4 -0
  21. data/test/fixtures/mycode.git/HEAD +1 -0
  22. data/test/fixtures/mycode.git/config +4 -0
  23. data/test/fixtures/mycode.git/description +1 -0
  24. data/test/fixtures/mycode.git/hooks/applypatch-msg.sample +15 -0
  25. data/test/fixtures/mycode.git/hooks/commit-msg.sample +24 -0
  26. data/test/fixtures/mycode.git/hooks/post-commit.sample +8 -0
  27. data/test/fixtures/mycode.git/hooks/post-receive.sample +15 -0
  28. data/test/fixtures/mycode.git/hooks/post-update.sample +8 -0
  29. data/test/fixtures/mycode.git/hooks/pre-applypatch.sample +14 -0
  30. data/test/fixtures/mycode.git/hooks/pre-commit.sample +46 -0
  31. data/test/fixtures/mycode.git/hooks/pre-rebase.sample +169 -0
  32. data/test/fixtures/mycode.git/hooks/prepare-commit-msg.sample +36 -0
  33. data/test/fixtures/mycode.git/hooks/update.sample +128 -0
  34. data/test/fixtures/mycode.git/info/exclude +6 -0
  35. data/test/fixtures/mycode.git/info/refs +3 -0
  36. data/test/fixtures/mycode.git/objects/02/83eb96425444e17b97182e1ba9f216cc67c132 +0 -0
  37. data/test/fixtures/mycode.git/objects/03/9927042df267a1bc606fc4485b7a79b6a9e3cd +1 -0
  38. data/test/fixtures/mycode.git/objects/0d/eed0a56fa8f5f2a788d58b3ea235afd547b828 +2 -0
  39. data/test/fixtures/mycode.git/objects/4b/825dc642cb6eb9a060e54bf8d69288fbee4904 +0 -0
  40. data/test/fixtures/mycode.git/objects/5e/54a0767e0c380f3baab17938d68c7f464cf171 +1 -0
  41. data/test/fixtures/mycode.git/objects/63/9b96262e7e19ca2169575e797b234098b8a72e +0 -0
  42. data/test/fixtures/mycode.git/objects/71/6e9568eed27d5ee4378b3ecf6dd095a547bde9 +1 -0
  43. data/test/fixtures/mycode.git/objects/b6/f3f0fabeaaaaf2db22b8ef98f59115baec7ef9 +0 -0
  44. data/test/fixtures/mycode.git/objects/be/118435b9d908fd4a689cd8b0cc98059911a31a +0 -0
  45. data/test/fixtures/mycode.git/objects/db/aefcb5bde664671c73b99515c386dcbc7f22b6 +0 -0
  46. data/test/fixtures/mycode.git/objects/eb/669b878d2013ac70aa5dee75e6357ea81d16ea +0 -0
  47. data/test/fixtures/mycode.git/objects/ed/10cfcf72862e140c97fe899cba2a55f4cb4c20 +0 -0
  48. data/test/fixtures/mycode.git/objects/ed/1c3a255ab3fce056dc31cd82df9f61a4d9fa22 +0 -0
  49. data/test/fixtures/mycode.git/objects/info/alternates +0 -0
  50. data/test/fixtures/mycode.git/objects/info/http-alternates +0 -0
  51. data/test/fixtures/mycode.git/objects/info/packs +2 -0
  52. data/test/fixtures/mycode.git/objects/pack/pack-40a8636b62258fffd78ec1e8d254116e72d385a9.idx +0 -0
  53. data/test/fixtures/mycode.git/objects/pack/pack-40a8636b62258fffd78ec1e8d254116e72d385a9.pack +0 -0
  54. data/test/fixtures/mycode.git/packed-refs +4 -0
  55. data/test/fixtures/mycode.git/refs/heads/master +1 -0
  56. data/test/fixtures/mycode.git/refs/tags/v0.1.0 +1 -0
  57. data/test/helpers.rb +53 -0
  58. data/test/htgroup_test.rb +29 -0
  59. data/test/htpasswd_test.rb +63 -0
  60. data/test/http_backend_authentication_test.rb +61 -0
  61. data/test/http_backend_test.rb +123 -0
  62. data/test/project_handler_test.rb +45 -0
  63. data/test/treeish_test.rb +33 -0
  64. metadata +121 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c42b6bc5a9164165905fec6ee9a64e010d18cd52
4
+ data.tar.gz: 6886a3e0b6f059e483b43c4e1c34541fbba8976b
5
+ SHA512:
6
+ metadata.gz: dc3f5819df08305540b53233b4159c47dab26b73c5fe6f7b238303b27dae7496f397d61e1f06a4f8cd4e71d603e76ae97729dfa2534a8b3b612a7f4c287833ca
7
+ data.tar.gz: 4eaec72837984539df8bc799f7eb0a1f42c69bdfc2e552e780297dc374cdad305489c33ee649e7f5a53e8c1c09212a2dda680d220c8312371da9b9867bd571b6
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'sinatra'
4
+ gem 'json'
5
+
6
+ group :coding do
7
+ gem 'minitest'
8
+ gem 'minitest-rg'
9
+ gem 'rack-test'
10
+ end
11
+
data/Makefile ADDED
@@ -0,0 +1,41 @@
1
+ .SHELL: /bin/sh
2
+
3
+ name = git-lighttp
4
+ version = 0.3.0
5
+ specfile = $(name).gemspec
6
+ package = $(name)-$(version).gem
7
+
8
+ ctags = '/.*alias(_method)?[[:space:]]+:([[:alnum:]_=!?]+),?[[:space:]]+:([[:alnum:]_=!]+)/\\2/f/'
9
+
10
+ all:: check
11
+
12
+ ctags:
13
+ ctags --recurse=yes --tag-relative=yes --totals=yes --extra=+f --fields=+iaS --regex-ruby=$(ctags)
14
+
15
+ clean:
16
+ rm -rf $(name)-*.gem
17
+ rm -rf *.lock
18
+ rm -rf doc/api/**
19
+
20
+ check:
21
+ ruby test/all.rb
22
+
23
+ docs:
24
+ rdoc -o doc/api -H -f fivefish -m README.rdoc
25
+
26
+ build:
27
+ gem $@ $(specfile)
28
+
29
+ dist: build
30
+
31
+ push: build
32
+ gem $@ $(package)
33
+
34
+ release: push
35
+
36
+ install: build
37
+ gem $@ --local $(package)
38
+
39
+ uninstall: build
40
+ gem $@ $(package) -v$(version)
41
+
data/README.pt-BR.rdoc ADDED
@@ -0,0 +1,81 @@
1
+ = Git-Lighttp - Web mais esperta para o Git
2
+
3
+ {<img src="https://badge.fury.io/rb/git-lighttp.svg" alt="Gem Version" />}[https://badge.fury.io/rb/git-lighttp]
4
+
5
+ == DESCRIÇÃO
6
+
7
+ Este projeto foi inspirado no {Grack}[http://github.com/schacon/grack], um
8
+ servidor de processos Smart-HTTP (escrito por
9
+ {Scott Chacon}[http://github.com/schacon]), mas projetado usando
10
+ {Sinatra}[http://www.sinatrarb.com] e visa substituir o `git-http-backend`
11
+ original incluindo novas funcionalidades.
12
+
13
+ O objetivo principal do <b>Git-Lighttp</b> é implementar as seguintes
14
+ funcionalidades:
15
+
16
+ - Smart-HTTP, baseado no _git-http-backend_.
17
+ - Autenticação flexível baseado em banco de dados ou arquivo de configuração
18
+ como <tt>.htpasswd</tt>.
19
+ - API para obter informações sobre o repositório (_Treeish_).
20
+
21
+ == SINOPSE
22
+
23
+ Instale o Git-Lighttp usando {Rubygems}[http://rubygems.org/gems/git-lighttp].
24
+
25
+ gem install git-lighttp
26
+
27
+ Ou faça um _checkout_ do projeto hospedado no
28
+ {Github}[http://github.com/hallison/git-lighttp].
29
+
30
+ git clone https://github.com/hallison/git-lighttp.git
31
+ ...
32
+ cd git-lighttp
33
+ rake install
34
+
35
+ Configure o arquivo Rackup (<tt>config.ru</tt>) usando as seguintes instruções:
36
+
37
+ # config.ru
38
+ require "git/lighttp"
39
+
40
+ Git::Lighttp::HttpBackend.configure do |server|
41
+ server.project_root = "/home/git/repositories"
42
+ server.git_path = "/usr/bin/git"
43
+ server.get_any_file = true
44
+ server.upload_pack = true
45
+ server.receive_pack = false
46
+ server.authenticate = true
47
+ end
48
+
49
+ $ rackup --port 2011 --daemonize
50
+ $ git clone http://localhost:2011/mycode.git
51
+
52
+ Você poderá usar o arquivo <tt>.netrc</tt> para melhorar sua conexão. Coloque
53
+ isso:
54
+
55
+ machine <servidor> login <usuario> password <senha>
56
+
57
+ O Git-Lighttp está em desenvolvimento, então ainda há muitas melhorias a serem
58
+ feitas. Por favor, nos ajude a melhorar o projeto enviando seu comentário nos
59
+ {problemas}[http://github.com/hallison/git-lighttp/issues] encontrados ou
60
+ enviando um email para
61
+ {hallisonbatista@gmail.com}[mailto:hallisonbatista@gmail.com].
62
+
63
+ Discuta no {Google Groups}[http://groups.google.com/group/git-lighttp].
64
+
65
+ == AUTORES
66
+
67
+ Escrito por Hallison Batista <hallisonbatista@gmail.com>.
68
+
69
+ == ERROS
70
+
71
+ Se você encontrar um erro, por favor, informe no
72
+ {gerenciador de erros}[http://github.com/hallison/git-lighttp] do projeto
73
+ Git-Lighttp no Github.
74
+
75
+ == LICENÇA
76
+
77
+ Git-Lighttp é Copyright (c) 2011-2015 Hallison Batista.
78
+
79
+ Este é um _software_ livre e pode ser redistribuído sob os termos
80
+ especificados em LICENSE.txt.
81
+
data/README.rdoc ADDED
@@ -0,0 +1,75 @@
1
+ = Git-Lighttp - Web smarty for Git
2
+
3
+ {<img src="https://badge.fury.io/rb/git-lighttp.svg" alt="Gem Version" />}[https://badge.fury.io/rb/git-lighttp]
4
+
5
+ == DESCRIPTION
6
+
7
+ This project was inspired in the {Grack}[http://github.com/schacon/grack]
8
+ Smart-HTTP server handler (written by
9
+ {Scott Chacon}[http://github.com/schacon]) but developed using
10
+ {Sinatra}[http://www.sinatrarb.com] and aims replace the original
11
+ `git-http-backend` including new features.
12
+
13
+ The main goal of the <b>Git-Lighttp</b> is implement the following useful features.
14
+
15
+ - Smart-HTTP, based on _git-http-backend_.
16
+ - Authentication flexible based on database or configuration file like .+htpasswd+.
17
+ - API to get information about repository (_Treeish_).
18
+
19
+ == SINOPSIS
20
+
21
+ Install the Git-Lighttp using {Rubygems}[http://rubygems.org/gems/git-lighttp].
22
+
23
+ gem install git-lighttp
24
+
25
+ Or checkout the project hosted on {Github}[http://github.com/hallison/git-lighttp].
26
+
27
+ git clone https://github.com/hallison/git-lighttp.git
28
+ ...
29
+ cd git-lighttp
30
+ rake install
31
+
32
+ Configure the Rackup file (<tt>config.ru</tt>) using the following instructions:
33
+
34
+ # config.ru
35
+ require "git/lighttp"
36
+
37
+ Git::Lighttp::HttpBackend.configure do |server|
38
+ server.project_root = "/home/git/repositories"
39
+ server.git_path = "/usr/bin/git"
40
+ server.get_any_file = true
41
+ server.upload_pack = true
42
+ server.receive_pack = false
43
+ server.authenticate = true
44
+ end
45
+
46
+ $ rackup --port 2011 --daemonize
47
+ $ git clone http://localhost:2011/mycode.git
48
+
49
+ You can use the <tt>.netrc</tt> for improve your connection. Put this:
50
+
51
+ machine <host> login <username> password <password>
52
+
53
+ The Git-Lighttp is under development, so there are still many improvements to be
54
+ made. Please, help us to improve the project sending your feedback to
55
+ {issues}[http://github.com/hallison/git-lighttp] or sending email to
56
+ {hallisonbatista@gmail.com}[mailto:hallisonbatista@gmail.com].
57
+
58
+ Discuss in {Google Groups}[http://groups.google.com/group/git-lighttp].
59
+
60
+ == AUTHORS
61
+
62
+ Written by Hallison Batista <hallisonbatista@gmail.com>.
63
+
64
+ == BUGS
65
+
66
+ If you find a bug, please report it at the Git-Lighttp project's
67
+ {issues tracker}[http://github.com/hallison/git-lighttp] on Github.
68
+
69
+ == LICENSE
70
+
71
+ Git-Lighttp is Copyright (c) 2011-2015 Hallison Batista.
72
+
73
+ This is free software, and may be redistributed under the terms specified in
74
+ LICENSE.txt.
75
+
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require "git/lighttp"
2
+
3
+ def spec
4
+ @spec ||= Gem::Specification.load("git-lighttp.gemspec")
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :test, [:file] do |spec, args|
9
+ Dir["test/#{args.file}*_test.rb"].each do |file|
10
+ sh "ruby #{file}"
11
+ end
12
+ end
13
+
14
+ desc "API Documentation (RDoc)"
15
+ task :doc do
16
+ sh "rdoc -o doc/api -H -f hanna -m README.rdoc"
17
+ end
18
+
19
+ desc "Build tags"
20
+ task :tags do
21
+ rbalias = '/.*alias(_method)?[[:space:]]+:([[:alnum:]_=!?]+),?[[:space:]]+:([[:alnum:]_=!]+)/\\2/f/'
22
+ sh "ctags", "--recurse=yes",
23
+ "--tag-relative=yes",
24
+ "--totals=yes",
25
+ "--extra=+f",
26
+ "--fields=+iaS",
27
+ "--regex-ruby="+rbalias
28
+ end
29
+
30
+ desc "Build #{spec.file_name}"
31
+ task :build => "#{spec.name}.gemspec" do
32
+ sh "gem build #{spec.name}.gemspec"
33
+ end
34
+
35
+ desc "Release #{spec.file_name}"
36
+ task :release => :build do
37
+ sh "gem push #{spec.file_name}"
38
+ end
39
+
40
+ desc "Install gem file #{spec.file_name}"
41
+ task :install => :build do
42
+ sh "gem install -l #{spec.file_name}"
43
+ end
44
+
45
+ desc "Uninstall gem #{spec.name} v#{spec.version}"
46
+ task :uninstall do
47
+ sh "gem uninstall #{spec.name} -v #{spec.version}"
48
+ end
49
+
50
+ task :default => :test
@@ -0,0 +1,11 @@
1
+ == Git-Lighttp 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/hallison/git-lighttp>.
11
+
@@ -0,0 +1,24 @@
1
+ == Git-Lighttp v0.2.0
2
+
3
+ Implementation of viewer for browsing of source code:
4
+
5
+ - Fixes in tasks.
6
+ - Adding of classes for handle repositories.
7
+ - Improvements in all helpers.
8
+ - Base controller for shared settings
9
+ - The project handler has been improved to find a repository and run the
10
+ command line for get files and informations.
11
+ - The HTTP Backend class has been updated for use the new changes in project
12
+ handler.
13
+ - Fixes in RPC service to POST git-upload-pack
14
+ - The repository was passed as current directory instead of the full path.
15
+ - Adding of tree in project handler
16
+ - Adding of viewer for browsing of source code
17
+ - The recursive tree has been removed for improve performance.
18
+ - Small improvements in helpers and tests.
19
+
20
+ This is a beta version. For more informations about this release,
21
+ please visit <http://github.com/codigorama/git-lighttp>.
22
+
23
+
24
+
@@ -0,0 +1,13 @@
1
+ == Git-Lighttp v0.3.0
2
+
3
+ Improvements and new features.
4
+
5
+ - Fixes in the Sinatra compatibility.
6
+ - Improvements in the treeish middleware.
7
+ - HTTP group support.
8
+ - The configuration can be made the rack-way, using the class itself.
9
+ - The project renamed from Git-Webby to Git-Lighttp.
10
+
11
+ This is a beta version. For more informations about this release,
12
+ please visit <http://github.com/hallison/git-lighttp>.
13
+
@@ -0,0 +1,25 @@
1
+ require "git/lighttp"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.platform = Gem::Platform::RUBY
5
+ spec.name = "git-lighttp"
6
+ spec.summary = "Git Web implementation of the Light (Smart) HTTP and other features"
7
+ spec.authors = ["Hallison Batista"]
8
+ spec.email = "hallisonbatista@gmail.com"
9
+ spec.homepage = "http://github.com/hallison/git-lighttp"
10
+ spec.rubyforge_project = spec.name
11
+ spec.version = Git::Lighttp::VERSION
12
+ spec.date = Git::Lighttp::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::Lighttp 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.add_dependency "sinatra"
24
+ end
25
+
@@ -0,0 +1,365 @@
1
+ # Standard requirements
2
+ require "yaml"
3
+
4
+ # 3rd part requirements
5
+ require "sinatra/base"
6
+ require "json"
7
+
8
+ # Internal requirements
9
+ require "git/lighttp/extensions"
10
+ require "git/lighttp/version"
11
+
12
+ # See <b>Git::Lighttp</b> for documentation.
13
+ module Git
14
+
15
+ # The main goal of the <b>Git::Lighttp</b> is implement the following useful
16
+ # features.
17
+ #
18
+ # - Smart-HTTP, based on _git-http-backend_.
19
+ # - Authentication flexible based on database or configuration file like <tt>.htpasswd</tt>.
20
+ # - API to get information about repository.
21
+ #
22
+ # This class configure the needed variables used by application. See
23
+ # Config::DEFAULTS for the values will be initialized by default.
24
+ #
25
+ # Basically, the +default+ attribute set the values that will be necessary
26
+ # by all applications.
27
+ #
28
+ # The HTTP-Backend application is configured by +http_backend+ attribute
29
+ # to set the Git RCP CLI. More details about this feature, see the
30
+ # {git-http-backend official
31
+ # page}[http://www.kernel.org/pub/software/scm/git/docs/git-http-backend.html]
32
+ #
33
+ # For tree view (JSON API) just use the attribute +treeish+.
34
+ #
35
+ # [*default*]
36
+ # Default configuration. All attributes will be used by all modular
37
+ # applications.
38
+ #
39
+ # *project_root* ::
40
+ # Sets the root directory where repositories have been
41
+ # placed.
42
+ # *git_path* ::
43
+ # Path to the git command line.
44
+ #
45
+ # [*treeish*]
46
+ # Configuration for Treeish JSON API.
47
+ #
48
+ # *authenticate* ::
49
+ # Sets if the tree view server requires authentication.
50
+ #
51
+ # [*http_backend*]
52
+ # HTTP-Backend configuration.
53
+ #
54
+ # *authenticate* ::
55
+ # Sets if authentication is required.
56
+ #
57
+ # *get_any_file* ::
58
+ # Like +http.getanyfile+.
59
+ #
60
+ # *upload_pack* ::
61
+ # Like +http.uploadpack+.
62
+ #
63
+ # *receive_pack* ::
64
+ # Like +http.receivepack+.
65
+ module Lighttp
66
+
67
+ class ProjectHandler #:nodoc:
68
+
69
+ # Path to git comamnd
70
+ attr_reader :path
71
+
72
+ attr_reader :project_root
73
+
74
+ attr_reader :repository
75
+
76
+ def initialize(project_root, path = "/usr/bin/git")
77
+ @repository = nil
78
+ @path = check_path(File.expand_path(path))
79
+ @project_root = check_path(File.expand_path(project_root))
80
+ end
81
+
82
+ def path_to(*args)
83
+ File.join(@repository || @project_root, *(args.compact.map(&:to_s)))
84
+ end
85
+
86
+ def repository=(name)
87
+ @repository = check_path(path_to(name))
88
+ end
89
+
90
+ def cli(command, *args)
91
+ %Q[#{@path} #{args.unshift(command.to_s.gsub("_","-")).compact.join(" ")}]
92
+ end
93
+
94
+ def run(command, *args)
95
+ chdir{ %x[#{cli command, *args}] }
96
+ end
97
+
98
+ def read_file(*file)
99
+ File.read(path_to(*file))
100
+ end
101
+
102
+ def loose_object_path(*hash)
103
+ path_to(:objects, *hash)
104
+ end
105
+
106
+ def pack_idx_path(pack)
107
+ path_to(:objects, :pack, pack)
108
+ end
109
+
110
+ def info_packs_path
111
+ path_to(:objects, :info, :packs)
112
+ end
113
+
114
+ def tree(ref = "HEAD", path = "")
115
+ list = run("ls-tree --abbrev=6 --full-tree --long #{ref}:#{path}")
116
+ if list
117
+ tree = []
118
+ list.scan %r{^(\d{3})(\d)(\d)(\d) (\w.*?) (.{6})[ \t]{0,}(.*?)\t(.*?)\n}m do
119
+ object = {
120
+ :ftype => ftype[$1],
121
+ :fperm => "#{fperm[$2.to_i]}#{fperm[$3.to_i]}#{fperm[$4.to_i]}",
122
+ :otype => $5.to_sym,
123
+ :ohash => $6,
124
+ :fsize => fsize($7, 2),
125
+ :fname => $8
126
+ }
127
+ object[:objects] = nil if object[:otype] == :tree
128
+ tree << object
129
+ end
130
+ tree
131
+ else
132
+ nil
133
+ end
134
+ end
135
+
136
+ private
137
+
138
+ def repository_path(name)
139
+ bare = name =~ /\w\.git/ ? name : %W[#{name} .git]
140
+ check_path(path_to(*bare))
141
+ end
142
+
143
+ def check_path(path)
144
+ path && !path.empty? && File.ftype(path) && path
145
+ end
146
+
147
+ def chdir(&block)
148
+ Dir.chdir(@repository || @project_root, &block)
149
+ end
150
+
151
+ def ftype
152
+ { "120" => "l", "100" => "-", "040" => "d" }
153
+ end
154
+
155
+ def fperm
156
+ [ "---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx" ]
157
+ end
158
+
159
+ def fsize(str, scale = 1)
160
+ units = [ :b, :kb, :mb, :gb, :tb ]
161
+ value = str.to_f
162
+ size = 0.0
163
+ units.each_index do |i|
164
+ size = value / 1024**i
165
+ return [format("%.#{scale}f", size).to_f, units[i].to_s.upcase] if size <= 10
166
+ end
167
+ end
168
+
169
+ end
170
+
171
+ class Htpasswd #:nodoc:
172
+
173
+ def initialize(file)
174
+ require "webrick/httpauth/htpasswd"
175
+ @handler = WEBrick::HTTPAuth::Htpasswd.new(file)
176
+ yield self if block_given?
177
+ end
178
+
179
+ def find(username) #:yield: password, salt
180
+ password = @handler.get_passwd(nil, username, false)
181
+ if block_given?
182
+ yield password ? [password, password[0,2]] : [nil, nil]
183
+ else
184
+ password
185
+ end
186
+ end
187
+
188
+ def authenticated?(username, password)
189
+ self.find username do |crypted, salt|
190
+ crypted && salt && crypted == password.crypt(salt)
191
+ end
192
+ end
193
+
194
+ def create(username, password)
195
+ @handler.set_passwd(nil, username, password)
196
+ end
197
+ alias update create
198
+
199
+ def destroy(username)
200
+ @handler.delete_passwd(nil, username)
201
+ end
202
+
203
+ def include?(username)
204
+ users.include? username
205
+ end
206
+
207
+ def size
208
+ users.size
209
+ end
210
+
211
+ def write!
212
+ @handler.flush
213
+ end
214
+
215
+ private
216
+
217
+ def users
218
+ @handler.each{|username, password| username }
219
+ end
220
+ end
221
+
222
+ class Htgroup #:nodoc:
223
+
224
+ def initialize(file)
225
+ require "webrick/httpauth/htgroup"
226
+ WEBrick::HTTPAuth::Htgroup.class_eval do
227
+ attr_reader :group
228
+ end
229
+ @handler = WEBrick::HTTPAuth::Htgroup.new(file)
230
+ yield self if block_given?
231
+ end
232
+
233
+ def members(group)
234
+ @handler.members(group)
235
+ end
236
+
237
+ def groups(username)
238
+ @handler.group.select do |group, members|
239
+ members.include? username
240
+ end.keys
241
+ end
242
+
243
+ end
244
+
245
+ module GitHelpers #:nodoc:
246
+
247
+ def git
248
+ @git ||= ProjectHandler.new(settings.project_root, settings.git_path)
249
+ end
250
+
251
+ def repository
252
+ git.repository ||= (params[:repository] || params[:captures].first)
253
+ git
254
+ end
255
+
256
+ def content_type_for_git(name, *suffixes)
257
+ content_type("application/x-git-#{name}-#{suffixes.compact.join("-")}")
258
+ end
259
+
260
+ end
261
+
262
+ module AuthenticationHelpers #:nodoc:
263
+
264
+ def htpasswd
265
+ @htpasswd ||= Htpasswd.new(git.path_to("htpasswd"))
266
+ end
267
+
268
+ def authentication
269
+ @authentication ||= Rack::Auth::Basic::Request.new request.env
270
+ end
271
+
272
+ def authenticated?
273
+ request.env["REMOTE_USER"] && request.env["git.lighttp.authenticated"]
274
+ end
275
+
276
+ def authenticate(username, password)
277
+ checked = [ username, password ] == authentication.credentials
278
+ validated = authentication.provided? && authentication.basic?
279
+ granted = htpasswd.authenticated? username, password
280
+ if checked and validated and granted
281
+ request.env["git.lighttp.authenticated"] = true
282
+ request.env["REMOTE_USER"] = authentication.username
283
+ else
284
+ nil
285
+ end
286
+ end
287
+
288
+ def unauthorized!(realm = Git::Lighttp::info)
289
+ headers "WWW-Authenticate" => %(Basic realm="#{realm}")
290
+ throw :halt, [ 401, "Authorization Required" ]
291
+ end
292
+
293
+ def bad_request!
294
+ throw :halt, [ 400, "Bad Request" ]
295
+ end
296
+
297
+ def authenticate!
298
+ return if authenticated?
299
+ unauthorized! unless authentication.provided?
300
+ bad_request! unless authentication.basic?
301
+ unauthorized! unless authenticate(*authentication.credentials)
302
+ request.env["REMOTE_USER"] = authentication.username
303
+ end
304
+
305
+ def access_granted?(username, password)
306
+ authenticated? || authenticate(username, password)
307
+ end
308
+
309
+ end # AuthenticationHelpers
310
+
311
+ # Servers
312
+ autoload :HttpBackend, "git/lighttp/http_backend"
313
+ autoload :Treeish, "git/lighttp/treeish"
314
+
315
+ class << self
316
+
317
+ def config
318
+ @config ||= {
319
+ :default => {
320
+ :project_root => "/home/git",
321
+ :git_path => "/usr/bin/git"
322
+ },
323
+ :treeish => {
324
+ :authenticate => false
325
+ },
326
+ :http_backend => {
327
+ :authenticate => true,
328
+ :get_any_file => true,
329
+ :upload_pack => true,
330
+ :receive_pack => false
331
+ }
332
+ }.to_struct
333
+ end
334
+
335
+ # Configure Git::Lighttp modules using keys. See Config for options.
336
+ def configure(&block)
337
+ yield config
338
+ config
339
+ end
340
+
341
+ def load_config_file(file)
342
+ YAML.load_file(file).to_struct.each_pair do |app, options|
343
+ options.each_pair do |option, value|
344
+ config[app][option] = value
345
+ end
346
+ end
347
+ config
348
+ rescue IndexError => error
349
+ abort "configuration option not found"
350
+ end
351
+
352
+ end
353
+
354
+ class Application < Sinatra::Base #:nodoc:
355
+
356
+ set :project_root, lambda { Git::Lighttp.config.default.project_root }
357
+ set :git_path, lambda { Git::Lighttp.config.default.git_path }
358
+
359
+ mime_type :json, "application/json"
360
+
361
+ end
362
+
363
+ end
364
+
365
+ end