blaggard 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +2 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +66 -0
- data/README.md +84 -0
- data/Rakefile +20 -0
- data/bin/blaggard +55 -0
- data/blaggard.gemspec +18 -0
- data/config.yml.example +9 -0
- data/install.txt +60 -0
- data/lib/blaggard.rb +33 -0
- data/lib/blaggard/advertisement.rb +92 -0
- data/lib/blaggard/auth.rb +37 -0
- data/lib/blaggard/bundle.rb +20 -0
- data/lib/blaggard/console.rb +3 -0
- data/lib/blaggard/git.rb +82 -0
- data/lib/blaggard/group_config.rb +123 -0
- data/lib/blaggard/group_finder.rb +28 -0
- data/lib/blaggard/server.rb +311 -0
- data/script/console +7 -0
- data/spec/advertisement_spec.rb +81 -0
- data/spec/fixtures/spec_repo.git/FETCH_HEAD +2 -0
- data/spec/fixtures/spec_repo.git/HEAD +1 -0
- data/spec/fixtures/spec_repo.git/HEAD_TRACKER +1 -0
- data/spec/fixtures/spec_repo.git/config +53 -0
- data/spec/fixtures/spec_repo.git/index +0 -0
- data/spec/fixtures/spec_repo.git/logs/HEAD +7 -0
- data/spec/fixtures/spec_repo.git/logs/refs/heads/br2 +2 -0
- data/spec/fixtures/spec_repo.git/logs/refs/heads/master +2 -0
- data/spec/fixtures/spec_repo.git/logs/refs/heads/not-good +1 -0
- data/spec/fixtures/spec_repo.git/logs/refs/remotes/origin/HEAD +1 -0
- data/spec/fixtures/spec_repo.git/logs/refs/remotes/test/master +2 -0
- data/spec/fixtures/spec_repo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 +0 -0
- data/spec/fixtures/spec_repo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 +0 -0
- data/spec/fixtures/spec_repo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 +0 -0
- data/spec/fixtures/spec_repo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd +0 -0
- data/spec/fixtures/spec_repo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd +0 -0
- data/spec/fixtures/spec_repo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 +0 -0
- data/spec/fixtures/spec_repo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b +0 -0
- data/spec/fixtures/spec_repo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 +0 -0
- data/spec/fixtures/spec_repo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d +0 -0
- data/spec/fixtures/spec_repo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 +0 -0
- data/spec/fixtures/spec_repo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 +0 -0
- data/spec/fixtures/spec_repo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc +0 -0
- data/spec/fixtures/spec_repo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 +0 -0
- data/spec/fixtures/spec_repo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +2 -0
- data/spec/fixtures/spec_repo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 +0 -0
- data/spec/fixtures/spec_repo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea +0 -0
- data/spec/fixtures/spec_repo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 +0 -0
- data/spec/fixtures/spec_repo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +2 -0
- data/spec/fixtures/spec_repo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a +0 -0
- data/spec/fixtures/spec_repo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af +1 -0
- data/spec/fixtures/spec_repo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 +0 -0
- data/spec/fixtures/spec_repo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d +0 -0
- data/spec/fixtures/spec_repo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 +0 -0
- data/spec/fixtures/spec_repo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe +2 -0
- data/spec/fixtures/spec_repo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 +1 -0
- data/spec/fixtures/spec_repo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 +0 -0
- data/spec/fixtures/spec_repo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 +2 -0
- data/spec/fixtures/spec_repo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +3 -0
- data/spec/fixtures/spec_repo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +2 -0
- data/spec/fixtures/spec_repo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 +3 -0
- data/spec/fixtures/spec_repo.git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd +0 -0
- data/spec/fixtures/spec_repo.git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 +0 -0
- data/spec/fixtures/spec_repo.git/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 +0 -0
- data/spec/fixtures/spec_repo.git/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 +2 -0
- data/spec/fixtures/spec_repo.git/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 +0 -0
- data/spec/fixtures/spec_repo.git/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 +3 -0
- data/spec/fixtures/spec_repo.git/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd +3 -0
- data/spec/fixtures/spec_repo.git/objects/d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 +0 -0
- data/spec/fixtures/spec_repo.git/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f +0 -0
- data/spec/fixtures/spec_repo.git/objects/d7/1aab4f9b04b45ce09bcaa636a9be6231474759 +0 -0
- data/spec/fixtures/spec_repo.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
- data/spec/fixtures/spec_repo.git/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 +0 -0
- data/spec/fixtures/spec_repo.git/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 +0 -0
- data/spec/fixtures/spec_repo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 +0 -0
- data/spec/fixtures/spec_repo.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 +0 -0
- data/spec/fixtures/spec_repo.git/objects/fd/093bff70906175335656e6ce6ae05783708765 +0 -0
- data/spec/fixtures/spec_repo.git/objects/fd/4959ce7510db09d4d8217fa2d1780413e05a09 +0 -0
- data/spec/fixtures/spec_repo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx +0 -0
- data/spec/fixtures/spec_repo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack +0 -0
- data/spec/fixtures/spec_repo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx +0 -0
- data/spec/fixtures/spec_repo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack +0 -0
- data/spec/fixtures/spec_repo.git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx +0 -0
- data/spec/fixtures/spec_repo.git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack +0 -0
- data/spec/fixtures/spec_repo.git/packed-refs +3 -0
- data/spec/fixtures/spec_repo.git/refs/heads/br2 +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/cannot-fetch +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/chomped +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/haacked +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/master +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/not-good +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/packed-test +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/subtrees +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/test +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/track-local +1 -0
- data/spec/fixtures/spec_repo.git/refs/heads/trailing +1 -0
- data/spec/fixtures/spec_repo.git/refs/notes/fanout +1 -0
- data/spec/fixtures/spec_repo.git/refs/remotes/test/master +1 -0
- data/spec/fixtures/spec_repo.git/refs/tags/master-r1 +1 -0
- data/spec/fixtures/spec_repo.git/refs/tags/master-r2 +1 -0
- data/spec/fixtures/spec_repo.git/refs/tags/test-r1 +1 -0
- data/spec/fixtures/spec_repo.git/refs/tags/test-r2 +1 -0
- data/spec/git_spec.rb +23 -0
- data/spec/group_config_spec.rb +64 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/support/test_env.rb +17 -0
- metadata +197 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 31aab3cfdcd15e952475d87c6504c1258e579183
|
4
|
+
data.tar.gz: d24471bf40000af22e5a0ac0dffd6700abe086f3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8842ba4475ce9b8b5cbfa7689af39db5974f33525e3f8b9085d55843b9413e926fc3dee55b2254626f2d8ae7f269d0d85ac6d3465f84a7257fdaf0c9d5a9215c
|
7
|
+
data.tar.gz: bccc8d1cdfcb61f22da3ef9c735380341e6d8785f7c2dd4ed7b78cf27574ff89401dda9aff0baac2c359a916be5ff27cdd83a9cced3387d4c643454c2ce38271
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem "rack", "~> 1.5.2"
|
4
|
+
gem "rake"
|
5
|
+
gem "thor"
|
6
|
+
gem "coveralls", :require => false
|
7
|
+
|
8
|
+
group :test do
|
9
|
+
gem "test"
|
10
|
+
gem "rspec"
|
11
|
+
gem "rack-test", "~> 0.6.2"
|
12
|
+
gem "mocha"
|
13
|
+
gem "simplecov", :require => false # Disable for ruby 1.8
|
14
|
+
#gem "rcov", :require => false # Enable for ruby 1.8
|
15
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
coveralls (0.7.11)
|
5
|
+
multi_json (~> 1.10)
|
6
|
+
rest-client (>= 1.6.8, < 2)
|
7
|
+
simplecov (~> 0.9.1)
|
8
|
+
term-ansicolor (~> 1.3)
|
9
|
+
thor (~> 0.19.1)
|
10
|
+
diff-lcs (1.2.5)
|
11
|
+
docile (1.1.5)
|
12
|
+
metaclass (0.0.4)
|
13
|
+
mime-types (2.4.3)
|
14
|
+
mocha (1.1.0)
|
15
|
+
metaclass (~> 0.0.1)
|
16
|
+
multi_json (1.10.1)
|
17
|
+
netrc (0.10.3)
|
18
|
+
rack (1.5.2)
|
19
|
+
rack-test (0.6.3)
|
20
|
+
rack (>= 1.0)
|
21
|
+
rake (10.4.2)
|
22
|
+
rest-client (1.7.3)
|
23
|
+
mime-types (>= 1.16, < 3.0)
|
24
|
+
netrc (~> 0.7)
|
25
|
+
rspec (3.2.0)
|
26
|
+
rspec-core (~> 3.2.0)
|
27
|
+
rspec-expectations (~> 3.2.0)
|
28
|
+
rspec-mocks (~> 3.2.0)
|
29
|
+
rspec-core (3.2.1)
|
30
|
+
rspec-support (~> 3.2.0)
|
31
|
+
rspec-expectations (3.2.0)
|
32
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
33
|
+
rspec-support (~> 3.2.0)
|
34
|
+
rspec-mocks (3.2.1)
|
35
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
36
|
+
rspec-support (~> 3.2.0)
|
37
|
+
rspec-support (3.2.2)
|
38
|
+
rubytest (0.8.1)
|
39
|
+
simplecov (0.9.2)
|
40
|
+
docile (~> 1.1.0)
|
41
|
+
multi_json (~> 1.0)
|
42
|
+
simplecov-html (~> 0.9.0)
|
43
|
+
simplecov-html (0.9.0)
|
44
|
+
term-ansicolor (1.3.0)
|
45
|
+
tins (~> 1.0)
|
46
|
+
test (1.0.0)
|
47
|
+
rubytest
|
48
|
+
thor (0.19.1)
|
49
|
+
tins (1.3.4)
|
50
|
+
|
51
|
+
PLATFORMS
|
52
|
+
ruby
|
53
|
+
|
54
|
+
DEPENDENCIES
|
55
|
+
coveralls
|
56
|
+
mocha
|
57
|
+
rack (~> 1.5.2)
|
58
|
+
rack-test (~> 0.6.2)
|
59
|
+
rake
|
60
|
+
rspec
|
61
|
+
simplecov
|
62
|
+
test
|
63
|
+
thor
|
64
|
+
|
65
|
+
BUNDLED WITH
|
66
|
+
1.10.4
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
#<div style='text-align:center'> Blaggard</div>
|
2
|
+
### <div style='text-align:center'> A Ruby/Rack Git Smart-HTTP Server Handler that implements a branch-level access control layer</div>
|
3
|
+
========================================
|
4
|
+
|
5
|
+
This project is a fork of [Grack](https://github.com/schacon/grack). Please refer to documentation and license on grack's README. The name came from the acronym **B**ranch **L**evel **A**ccess **C**ontrol for **G**it which obviously expands into Blaggard since everyone wants to be a pirate...arrrr!
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
To run as an executable:
|
10
|
+
|
11
|
+
gem install blaggard
|
12
|
+
cp $BLAGGARD_PATH/config.yml.example ~/config.yml
|
13
|
+
|
14
|
+
# Edit ~/config.yml's project_root value to point to you repo's directory
|
15
|
+
|
16
|
+
blaggard start ~/config.yml
|
17
|
+
git clone localhost:8080/my_repo.git
|
18
|
+
|
19
|
+
To run as a mounted bundle in routes.rb of another Rack application:
|
20
|
+
|
21
|
+
mount Blaggard::Bundle.new({
|
22
|
+
git_path: /bin/git,
|
23
|
+
project_root: path/to/repos,
|
24
|
+
upload_pack: true,
|
25
|
+
receive_pack: true,
|
26
|
+
use_acl: true
|
27
|
+
}), at: '/'
|
28
|
+
|
29
|
+
## Config
|
30
|
+
|
31
|
+
Blaggard keeps all information about access control within the repo itself as an object. To create a config file, use the command line interface:
|
32
|
+
|
33
|
+
blaggard config path/to/repo path/to/config.yml
|
34
|
+
|
35
|
+
The config.yml is a list of group objects that correspond to the following format:
|
36
|
+
|
37
|
+
group_name:
|
38
|
+
# read and write must start with : to be parsed into symbols
|
39
|
+
:read:
|
40
|
+
# an array of branches that a group can read (clone, fetch, etc)
|
41
|
+
- refs/heads/readable1
|
42
|
+
- refs/heads/readable2
|
43
|
+
:write:
|
44
|
+
# an array of branches a group can write to (push, etc)
|
45
|
+
- refs/heads/writeable1
|
46
|
+
|
47
|
+
another_group:
|
48
|
+
# even if a group has no privileges you must still include an
|
49
|
+
# empty array
|
50
|
+
:read: []
|
51
|
+
# if a group has access to all branches (ie. admin)
|
52
|
+
:write:
|
53
|
+
- refs/heads/*
|
54
|
+
|
55
|
+
The command line executable should let you know if your config file is both parsable and if there are any errors, what groups those errors belong to.
|
56
|
+
|
57
|
+
## Testing
|
58
|
+
|
59
|
+
To run unit tests:
|
60
|
+
|
61
|
+
rake test
|
62
|
+
|
63
|
+
To run an interactive Pry console with all libraries loaded run:
|
64
|
+
|
65
|
+
rake console
|
66
|
+
|
67
|
+
The test repository located at `spec/fixtures/spec_repo.git` is copied into a temp location before the tests and therefore the tests are dependent upon it staying the same. If you use this repo for testing in the console, just copy it to another directory and edit the startup config.yml to reflect that repo path.
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
## Contribution
|
72
|
+
|
73
|
+
1. Take a look at the Issues
|
74
|
+
2. Write a fix, making sure all tests run
|
75
|
+
3. Submit a Pull Request
|
76
|
+
4. Rejoice!
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
task :default => :test
|
2
|
+
|
3
|
+
desc "Run the tests."
|
4
|
+
task :test do
|
5
|
+
system "bundle exec rspec spec"
|
6
|
+
end
|
7
|
+
|
8
|
+
task :console do
|
9
|
+
system "./script/console"
|
10
|
+
end
|
11
|
+
|
12
|
+
namespace :blaggard do
|
13
|
+
desc "Start Blaggard"
|
14
|
+
task :start do
|
15
|
+
system "./script/server"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc "Start everything."
|
20
|
+
multitask :start => [ 'blaggard:start' ]
|
data/bin/blaggard
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
libdir = File.absolute_path( File.join( File.dirname(__FILE__), '../lib' ) )
|
3
|
+
$LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
4
|
+
|
5
|
+
require 'blaggard'
|
6
|
+
require 'thor'
|
7
|
+
|
8
|
+
class BlaggardCLI < Thor
|
9
|
+
include Blaggard
|
10
|
+
desc "config <repo> <config_file>", "add a YAML config file to the repository"
|
11
|
+
def config(repo, config)
|
12
|
+
repo = File.absolute_path(repo)
|
13
|
+
if Dir.entries(repo).include? ".git"
|
14
|
+
repo = "#{repo}/.git"
|
15
|
+
end
|
16
|
+
meta = Blaggard::GroupConfig.new(repo)
|
17
|
+
begin
|
18
|
+
data = YAML.load(File.read(config))
|
19
|
+
rescue
|
20
|
+
raise Blaggard::GroupConfigError, "#{config} not a valid YAML file"
|
21
|
+
end
|
22
|
+
data.each do |group_name, value|
|
23
|
+
unless value[:read].instance_of?(Array) && value[:write].instance_of?(Array)
|
24
|
+
raise Blaggard::GroupConfigError, "#{group_name} not a valid group structure. Groups must include :read: [] and :write: []"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
meta.groups = data
|
28
|
+
meta.write_to_git
|
29
|
+
puts meta.read_from_git
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "start [config.yml]", "starts the blaggard server. Optionally pass in a config file. If you don't it will run on localhost:8080"
|
33
|
+
def start(config = nil)
|
34
|
+
require 'rack'
|
35
|
+
if config
|
36
|
+
conf_data = YAML.load( File.read(config) )
|
37
|
+
else
|
38
|
+
conf_data = YAML.load( File.read(File.absolute_path("config.yml")))
|
39
|
+
end
|
40
|
+
puts "Starting server at project root: #{conf_data[:project_root]}"
|
41
|
+
app = Blaggard::App.new(conf_data)
|
42
|
+
|
43
|
+
protected_app = Rack::Auth::Basic.new(app) do |username, password|
|
44
|
+
# make call to LDAP to authenticate
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
pretty_protected_app = Rack::ShowStatus.new(Rack::ShowExceptions.new(protected_app))
|
49
|
+
|
50
|
+
Rack::Server.start :app => pretty_protected_app,
|
51
|
+
:Port => app.config[:port] || 8080,
|
52
|
+
:Host => app.config[:host] || 'localhost'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
BlaggardCLI.start(ARGV)
|
data/blaggard.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'blaggard'
|
3
|
+
s.version = '1.0.0'
|
4
|
+
s.date = '2013-06-02'
|
5
|
+
s.summary = "This is a fork of Grack that adds Branch Level Access control and LDAP Authentication"
|
6
|
+
s.description = "This is a fork of Grack that adds Branch Level Access control and LDAP Authentication. This was designed to be used in conjuction with Qualcomm's ChipCode web application"
|
7
|
+
s.authors = ['Scott Chacon', 'Dawa Ometto', 'Ryan Canty']
|
8
|
+
s.email = 'jrcanty@gmail.com'
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.executables << 'blaggard'
|
11
|
+
s.homepage = "https://github.com/onetwopunch/blaggard"
|
12
|
+
s.license = 'MIT'
|
13
|
+
|
14
|
+
s.add_development_dependency('rspec')
|
15
|
+
s.add_dependency('rack')
|
16
|
+
s.add_dependency('thor')
|
17
|
+
|
18
|
+
end
|
data/config.yml.example
ADDED
data/install.txt
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
Installation
|
2
|
+
========================
|
3
|
+
|
4
|
+
** This documentation is not finished yet. I haven't tested all of
|
5
|
+
these and it's obviously incomplete - these are currently just notes.
|
6
|
+
|
7
|
+
FastCGI
|
8
|
+
---------------------------------------
|
9
|
+
Here is an example config from lighttpd server:
|
10
|
+
----
|
11
|
+
# main fastcgi entry
|
12
|
+
$HTTP["url"] =~ "^/myapp/.+$" {
|
13
|
+
fastcgi.server = ( "/myapp" =>
|
14
|
+
( "localhost" =>
|
15
|
+
( "bin-path" => "/var/www/localhost/cgi-bin/dispatch.fcgi",
|
16
|
+
"docroot" => "/var/www/localhost/htdocs/myapp",
|
17
|
+
"host" => "127.0.0.1",
|
18
|
+
"port" => 1026,
|
19
|
+
"check-local" => "disable"
|
20
|
+
)
|
21
|
+
)
|
22
|
+
)
|
23
|
+
} # HTTP[url]
|
24
|
+
----
|
25
|
+
You can use the examples/dispatch.fcgi file as your dispatcher.
|
26
|
+
|
27
|
+
(Example Apache setup?)
|
28
|
+
|
29
|
+
Installing in a Java application server
|
30
|
+
---------------------------------------
|
31
|
+
# install Warbler
|
32
|
+
$ sudo gem install warbler
|
33
|
+
$ cd gitsmart
|
34
|
+
$ (edit config.ru)
|
35
|
+
$ warble
|
36
|
+
$ cp gitsmart.war /path/to/java/autodeploy/dir
|
37
|
+
|
38
|
+
Unicorn
|
39
|
+
---------------------------------------
|
40
|
+
With Unicorn (http://unicorn.bogomips.org/) you can just run 'unicorn'
|
41
|
+
in the directory with the config.ru file.
|
42
|
+
|
43
|
+
Thin
|
44
|
+
---------------------------------------
|
45
|
+
thin.yml
|
46
|
+
---
|
47
|
+
pid: /home/deploy/myapp/server/thin.pid
|
48
|
+
log: /home/deploy/myapp/logs/thin.log
|
49
|
+
timeout: 30
|
50
|
+
port: 7654
|
51
|
+
max_conns: 1024
|
52
|
+
chdir: /home/deploy/myapp/site_files
|
53
|
+
rackup: /home/deploy/myapp/server/config.ru
|
54
|
+
max_persistent_conns: 512
|
55
|
+
environment: production
|
56
|
+
address: 127.0.0.1
|
57
|
+
servers: 1
|
58
|
+
daemonize: true
|
59
|
+
|
60
|
+
|
data/lib/blaggard.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'rack/request'
|
3
|
+
require 'rack/response'
|
4
|
+
require 'rack/utils'
|
5
|
+
require 'time'
|
6
|
+
require 'rack'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
require 'blaggard/git'
|
10
|
+
require 'blaggard/server'
|
11
|
+
require 'blaggard/group_config'
|
12
|
+
require 'blaggard/advertisement'
|
13
|
+
require 'blaggard/auth'
|
14
|
+
require 'blaggard/bundle'
|
15
|
+
require 'blaggard/group_finder'
|
16
|
+
|
17
|
+
|
18
|
+
module Blaggard
|
19
|
+
def self.app_root
|
20
|
+
File.absolute_path(File.join(__FILE__, "../.."))
|
21
|
+
end
|
22
|
+
class App
|
23
|
+
def initialize(config = nil)
|
24
|
+
@server = Blaggard::Server.new(config)
|
25
|
+
end
|
26
|
+
def config
|
27
|
+
@server.config
|
28
|
+
end
|
29
|
+
def call(env)
|
30
|
+
@server.call env
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Blaggard
|
2
|
+
class Advertisement
|
3
|
+
def initialize(repo_path, groups, service)
|
4
|
+
@git = Blaggard::Git.new(repo_path)
|
5
|
+
@meta = Blaggard::GroupConfig.new(repo_path)
|
6
|
+
@groups = groups
|
7
|
+
@repo_path = repo_path
|
8
|
+
@service = service
|
9
|
+
@priv = service == "upload-pack" ? :read : :write
|
10
|
+
refs_hash
|
11
|
+
end
|
12
|
+
|
13
|
+
def raw_refs
|
14
|
+
@raw_refs ||= @git.execute(%W(#{@service} --stateless-rpc --advertise-refs #{@repo_path})).split("\n")
|
15
|
+
@first_ref_line ||= @raw_refs.first + "\n" # head_ref\0capabilities
|
16
|
+
@pk_end ||= @raw_refs.last
|
17
|
+
@raw_refs
|
18
|
+
end
|
19
|
+
|
20
|
+
def accessible_tags
|
21
|
+
@tags || begin
|
22
|
+
tags = accessible_branches.map{ |branch| @git.tags_on_branch(branch)}.flatten.compact
|
23
|
+
tags.map{ |tag| "refs/tags/#{tag}"}.uniq
|
24
|
+
rescue
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def accessible_branches
|
30
|
+
@branches || begin
|
31
|
+
branches = @meta.branches(@groups, @priv)
|
32
|
+
|
33
|
+
if branches.include? "refs/heads/*"
|
34
|
+
return refs_hash.keys.select{ |ref| ref.start_with? "refs/heads/"}
|
35
|
+
end
|
36
|
+
branches
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def refs_hash
|
41
|
+
# To access the refs quicker, put them in a hash where the ref name is the key
|
42
|
+
@refs_hash ||= Hash[ raw_refs[1..-2].collect { |v| ary = v.split; [ary.last, ary.first] } ]
|
43
|
+
end
|
44
|
+
|
45
|
+
def update_head
|
46
|
+
#sort refs by time since the most recent will be the HEAD if the user doesn't have access
|
47
|
+
# to the actual head
|
48
|
+
refs = @git.time_ordered_refs & accessible_branches
|
49
|
+
new_head = refs.first
|
50
|
+
line = @first_ref_line.gsub(/symref\=HEAD\:(.*?) /, "symref=HEAD:#{new_head} ")
|
51
|
+
|
52
|
+
new_sha = refs_hash[new_head]
|
53
|
+
line = line.gsub(/[a-f0-9]{44}/, new_sha)
|
54
|
+
update_line_length(line)
|
55
|
+
end
|
56
|
+
|
57
|
+
def update_line_length(line)
|
58
|
+
# Each line contains 4 bytes of line length followed by the ref followed by the branch name
|
59
|
+
# When HEAD is not accessible we need to update the line length of the first ref which includes
|
60
|
+
# all the capabilities
|
61
|
+
|
62
|
+
# Len should be (line.length - 4) to account for the first 4 bytes, but Ruby parses the \0 as
|
63
|
+
# unicode \u0000 which adds back 4 characters.
|
64
|
+
len = line.encode('utf-8').length
|
65
|
+
hex = "%04x" % len
|
66
|
+
return "#{hex}#{line[4..-1]}"
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def can_access_head?
|
71
|
+
head_file = File.join(@repo_path, 'HEAD')
|
72
|
+
ref = File.open(head_file, &:readline).split.last rescue (return false)
|
73
|
+
@groups.each do |group|
|
74
|
+
return true if @meta.can_access_branch?(group, @priv, ref)
|
75
|
+
end
|
76
|
+
return false
|
77
|
+
end
|
78
|
+
|
79
|
+
def advertise
|
80
|
+
# Construct the new advertisement using the updated head and only the
|
81
|
+
# branches accessible to the user
|
82
|
+
# TODO: We need a quick way to get only the tags for the accessible branches.
|
83
|
+
result = can_access_head? ? @first_ref_line : update_head
|
84
|
+
result += accessible_branches.map{ |branch| "#{refs_hash[branch]} #{branch}" }.join("\n")
|
85
|
+
result += "\n" unless accessible_tags.empty?
|
86
|
+
result += accessible_tags.map{ |tag| "#{refs_hash[tag]} #{tag}" }.join("\n")
|
87
|
+
result += "\n#{@pk_end}"
|
88
|
+
|
89
|
+
return result
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|