blaggard 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +15 -0
  5. data/Gemfile.lock +66 -0
  6. data/README.md +84 -0
  7. data/Rakefile +20 -0
  8. data/bin/blaggard +55 -0
  9. data/blaggard.gemspec +18 -0
  10. data/config.yml.example +9 -0
  11. data/install.txt +60 -0
  12. data/lib/blaggard.rb +33 -0
  13. data/lib/blaggard/advertisement.rb +92 -0
  14. data/lib/blaggard/auth.rb +37 -0
  15. data/lib/blaggard/bundle.rb +20 -0
  16. data/lib/blaggard/console.rb +3 -0
  17. data/lib/blaggard/git.rb +82 -0
  18. data/lib/blaggard/group_config.rb +123 -0
  19. data/lib/blaggard/group_finder.rb +28 -0
  20. data/lib/blaggard/server.rb +311 -0
  21. data/script/console +7 -0
  22. data/spec/advertisement_spec.rb +81 -0
  23. data/spec/fixtures/spec_repo.git/FETCH_HEAD +2 -0
  24. data/spec/fixtures/spec_repo.git/HEAD +1 -0
  25. data/spec/fixtures/spec_repo.git/HEAD_TRACKER +1 -0
  26. data/spec/fixtures/spec_repo.git/config +53 -0
  27. data/spec/fixtures/spec_repo.git/index +0 -0
  28. data/spec/fixtures/spec_repo.git/logs/HEAD +7 -0
  29. data/spec/fixtures/spec_repo.git/logs/refs/heads/br2 +2 -0
  30. data/spec/fixtures/spec_repo.git/logs/refs/heads/master +2 -0
  31. data/spec/fixtures/spec_repo.git/logs/refs/heads/not-good +1 -0
  32. data/spec/fixtures/spec_repo.git/logs/refs/remotes/origin/HEAD +1 -0
  33. data/spec/fixtures/spec_repo.git/logs/refs/remotes/test/master +2 -0
  34. data/spec/fixtures/spec_repo.git/objects/08/b041783f40edfe12bb406c9c9a8a040177c125 +0 -0
  35. data/spec/fixtures/spec_repo.git/objects/13/85f264afb75a56a5bec74243be9b367ba4ca08 +0 -0
  36. data/spec/fixtures/spec_repo.git/objects/18/1037049a54a1eb5fab404658a3a250b44335d7 +0 -0
  37. data/spec/fixtures/spec_repo.git/objects/18/10dff58d8a660512d4832e740f692884338ccd +0 -0
  38. data/spec/fixtures/spec_repo.git/objects/1a/443023183e3f2bfbef8ac923cd81c1018a18fd +0 -0
  39. data/spec/fixtures/spec_repo.git/objects/1b/8cbad43e867676df601306689fe7c3def5e689 +0 -0
  40. data/spec/fixtures/spec_repo.git/objects/1f/67fc4386b2d171e0d21be1c447e12660561f9b +0 -0
  41. data/spec/fixtures/spec_repo.git/objects/25/8f0e2a959a364e40ed6603d5d44fbb24765b10 +0 -0
  42. data/spec/fixtures/spec_repo.git/objects/27/0b8ea76056d5cad83af921837702d3e3c2924d +0 -0
  43. data/spec/fixtures/spec_repo.git/objects/2d/59075e0681f540482d4f6223a68e0fef790bc7 +0 -0
  44. data/spec/fixtures/spec_repo.git/objects/32/59a6bd5b57fb9c1281bb7ed3167b50f224cb54 +0 -0
  45. data/spec/fixtures/spec_repo.git/objects/36/97d64be941a53d4ae8f6a271e4e3fa56b022cc +0 -0
  46. data/spec/fixtures/spec_repo.git/objects/45/b983be36b73c0788dc9cbcb76cbb80fc7bb057 +0 -0
  47. data/spec/fixtures/spec_repo.git/objects/4a/202b346bb0fb0db7eff3cffeb3c70babbd2045 +2 -0
  48. data/spec/fixtures/spec_repo.git/objects/4a/23e2e65ad4e31c4c9db7dc746650bfad082679 +0 -0
  49. data/spec/fixtures/spec_repo.git/objects/4b/22b35d44b5a4f589edf3dc89196399771796ea +0 -0
  50. data/spec/fixtures/spec_repo.git/objects/52/1d87c1ec3aef9824daf6d96cc0ae3710766d91 +0 -0
  51. data/spec/fixtures/spec_repo.git/objects/5b/5b025afb0b4c913b4c338a42934a3863bf3644 +2 -0
  52. data/spec/fixtures/spec_repo.git/objects/75/057dd4114e74cca1d750d0aee1647c903cb60a +0 -0
  53. data/spec/fixtures/spec_repo.git/objects/76/3d71aadf09a7951596c9746c024e7eece7c7af +1 -0
  54. data/spec/fixtures/spec_repo.git/objects/7b/4384978d2493e851f9cca7858815fac9b10980 +0 -0
  55. data/spec/fixtures/spec_repo.git/objects/81/4889a078c031f61ed08ab5fa863aea9314344d +0 -0
  56. data/spec/fixtures/spec_repo.git/objects/84/96071c1b46c854b31185ea97743be6a8774479 +0 -0
  57. data/spec/fixtures/spec_repo.git/objects/84/9a5e34a26815e821f865b8479f5815a47af0fe +2 -0
  58. data/spec/fixtures/spec_repo.git/objects/94/4c0f6e4dfa41595e6eb3ceecdb14f50fe18162 +1 -0
  59. data/spec/fixtures/spec_repo.git/objects/9a/03079b8a8ee85a0bee58bf9be3da8b62414ed4 +0 -0
  60. data/spec/fixtures/spec_repo.git/objects/9f/13f7d0a9402c681f91dc590cf7b5470e6a77d2 +2 -0
  61. data/spec/fixtures/spec_repo.git/objects/9f/d738e8f7967c078dceed8190330fc8648ee56a +3 -0
  62. data/spec/fixtures/spec_repo.git/objects/a4/a7dce85cf63874e984719f4fdd239f5145052f +2 -0
  63. data/spec/fixtures/spec_repo.git/objects/a6/5fedf39aefe402d3bb6e24df4d4f5fe4547750 +3 -0
  64. data/spec/fixtures/spec_repo.git/objects/a7/1586c1dfe8a71c6cbf6c129f404c5642ff31bd +0 -0
  65. data/spec/fixtures/spec_repo.git/objects/a8/233120f6ad708f843d861ce2b7228ec4e3dec6 +0 -0
  66. data/spec/fixtures/spec_repo.git/objects/ae/90f12eea699729ed24555e40b9fd669da12a12 +0 -0
  67. data/spec/fixtures/spec_repo.git/objects/b2/5fa35b38051e4ae45d4222e795f9df2e43f1d1 +2 -0
  68. data/spec/fixtures/spec_repo.git/objects/b6/361fc6a97178d8fc8639fdeed71c775ab52593 +0 -0
  69. data/spec/fixtures/spec_repo.git/objects/be/3563ae3f795b2b4353bcce3a527ad0a4f7f644 +3 -0
  70. data/spec/fixtures/spec_repo.git/objects/c4/7800c7266a2be04c571c04d5a6614691ea99bd +3 -0
  71. data/spec/fixtures/spec_repo.git/objects/d0/7b0f9a8c89f1d9e74dc4fce6421dec5ef8a659 +0 -0
  72. data/spec/fixtures/spec_repo.git/objects/d6/c93164c249c8000205dd4ec5cbca1b516d487f +0 -0
  73. data/spec/fixtures/spec_repo.git/objects/d7/1aab4f9b04b45ce09bcaa636a9be6231474759 +0 -0
  74. data/spec/fixtures/spec_repo.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391 +0 -0
  75. data/spec/fixtures/spec_repo.git/objects/e7/b4ad382349ff96dd8199000580b9b1e2042eb0 +0 -0
  76. data/spec/fixtures/spec_repo.git/objects/f1/425cef211cc08caa31e7b545ffb232acb098c3 +0 -0
  77. data/spec/fixtures/spec_repo.git/objects/f6/0079018b664e4e79329a7ef9559c8d9e0378d1 +0 -0
  78. data/spec/fixtures/spec_repo.git/objects/fa/49b077972391ad58037050f2a75f74e3671e92 +0 -0
  79. data/spec/fixtures/spec_repo.git/objects/fd/093bff70906175335656e6ce6ae05783708765 +0 -0
  80. data/spec/fixtures/spec_repo.git/objects/fd/4959ce7510db09d4d8217fa2d1780413e05a09 +0 -0
  81. data/spec/fixtures/spec_repo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.idx +0 -0
  82. data/spec/fixtures/spec_repo.git/objects/pack/pack-a81e489679b7d3418f9ab594bda8ceb37dd4c695.pack +0 -0
  83. data/spec/fixtures/spec_repo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.idx +0 -0
  84. data/spec/fixtures/spec_repo.git/objects/pack/pack-d7c6adf9f61318f041845b01440d09aa7a91e1b5.pack +0 -0
  85. data/spec/fixtures/spec_repo.git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.idx +0 -0
  86. data/spec/fixtures/spec_repo.git/objects/pack/pack-d85f5d483273108c9d8dd0e4728ccf0b2982423a.pack +0 -0
  87. data/spec/fixtures/spec_repo.git/packed-refs +3 -0
  88. data/spec/fixtures/spec_repo.git/refs/heads/br2 +1 -0
  89. data/spec/fixtures/spec_repo.git/refs/heads/cannot-fetch +1 -0
  90. data/spec/fixtures/spec_repo.git/refs/heads/chomped +1 -0
  91. data/spec/fixtures/spec_repo.git/refs/heads/haacked +1 -0
  92. data/spec/fixtures/spec_repo.git/refs/heads/master +1 -0
  93. data/spec/fixtures/spec_repo.git/refs/heads/not-good +1 -0
  94. data/spec/fixtures/spec_repo.git/refs/heads/packed-test +1 -0
  95. data/spec/fixtures/spec_repo.git/refs/heads/subtrees +1 -0
  96. data/spec/fixtures/spec_repo.git/refs/heads/test +1 -0
  97. data/spec/fixtures/spec_repo.git/refs/heads/track-local +1 -0
  98. data/spec/fixtures/spec_repo.git/refs/heads/trailing +1 -0
  99. data/spec/fixtures/spec_repo.git/refs/notes/fanout +1 -0
  100. data/spec/fixtures/spec_repo.git/refs/remotes/test/master +1 -0
  101. data/spec/fixtures/spec_repo.git/refs/tags/master-r1 +1 -0
  102. data/spec/fixtures/spec_repo.git/refs/tags/master-r2 +1 -0
  103. data/spec/fixtures/spec_repo.git/refs/tags/test-r1 +1 -0
  104. data/spec/fixtures/spec_repo.git/refs/tags/test-r2 +1 -0
  105. data/spec/git_spec.rb +23 -0
  106. data/spec/group_config_spec.rb +64 -0
  107. data/spec/spec_helper.rb +42 -0
  108. data/spec/support/test_env.rb +17 -0
  109. metadata +197 -0
@@ -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
@@ -0,0 +1,5 @@
1
+ coverage/
2
+ vendor/bundle
3
+ .idea
4
+ *.yml
5
+ .bundle
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
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
@@ -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
@@ -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
+
@@ -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' ]
@@ -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)
@@ -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
@@ -0,0 +1,9 @@
1
+ :host: localhost
2
+ :port: 8080
3
+ :project_root: ./blaggard/spec/resources
4
+ :git_path: /usr/bin/git
5
+ :upload_pack: true
6
+ :receive_pack: true
7
+ :base_url: http://auth_server.com/api
8
+ :group_resource: users_groups
9
+ :use_acl: true
@@ -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
+
@@ -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