gitolite 0.0.1.alpha
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/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +30 -0
- data/README.rdoc +22 -0
- data/Rakefile +2 -0
- data/gitolite.gemspec +24 -0
- data/lib/gitolite.rb +6 -0
- data/lib/gitolite/config.rb +123 -0
- data/lib/gitolite/gitolite_admin.rb +82 -0
- data/lib/gitolite/ssh_key.rb +68 -0
- data/lib/gitolite/version.rb +3 -0
- data/spec/config_spec.rb +4 -0
- data/spec/configs/complicated.conf +298 -0
- data/spec/configs/simple.conf +5 -0
- data/spec/gitolite_admin_spec.rb +4 -0
- data/spec/keys/bob.pub +1 -0
- data/spec/keys/bob@desktop.pub +1 -0
- data/spec/keys/bob@zilla.com.pub +1 -0
- data/spec/keys/bob@zilla.com@desktop.pub +1 -0
- data/spec/keys/jakub123.pub +1 -0
- data/spec/keys/jakub123@foo.net.pub +1 -0
- data/spec/keys/joe@sch.ool.edu.pub +1 -0
- data/spec/keys/joe@sch.ool.edu@desktop.pub +1 -0
- data/spec/spec_helper.rb +0 -0
- data/spec/ssh_key_spec.rb +124 -0
- metadata +121 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
gitolite (0.1.0)
|
5
|
+
grit (~> 2.4.1)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: http://rubygems.org/
|
9
|
+
specs:
|
10
|
+
diff-lcs (1.1.2)
|
11
|
+
grit (2.4.1)
|
12
|
+
diff-lcs (~> 1.1)
|
13
|
+
mime-types (~> 1.15)
|
14
|
+
mime-types (1.16)
|
15
|
+
rspec (2.4.0)
|
16
|
+
rspec-core (~> 2.4.0)
|
17
|
+
rspec-expectations (~> 2.4.0)
|
18
|
+
rspec-mocks (~> 2.4.0)
|
19
|
+
rspec-core (2.4.0)
|
20
|
+
rspec-expectations (2.4.0)
|
21
|
+
diff-lcs (~> 1.1.2)
|
22
|
+
rspec-mocks (2.4.0)
|
23
|
+
|
24
|
+
PLATFORMS
|
25
|
+
ruby
|
26
|
+
x86-mingw32
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
gitolite!
|
30
|
+
rspec (~> 2.4.0)
|
data/README.rdoc
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
= gitolite - Coming soon
|
2
|
+
|
3
|
+
This gem is designed to provide a Ruby interface to the {gitolite}[https://github.com/sitaramc/gitolite] git backend system. I am aiming to provide all management functionality that is available via the gitolite-admin repository (like SSH keys, repository permissions, etc)
|
4
|
+
|
5
|
+
== Requirements
|
6
|
+
* Ruby 1.9.2 or higher
|
7
|
+
* a working {gitolite}[https://github.com/sitaramc/gitolite] installation
|
8
|
+
* the <tt>gitolite-admin</tt> repository checked out locally
|
9
|
+
|
10
|
+
== Installation
|
11
|
+
|
12
|
+
gem install gitolite
|
13
|
+
|
14
|
+
== Usage
|
15
|
+
|
16
|
+
== Caveats
|
17
|
+
=== 1.8.x compatibility
|
18
|
+
This gem should work properly on Ruby 1.8.x with the exception of deny rules. In order to fully support Ruby < 1.9.x, an ordered Hash is required, such as the one implemented by ActiveSupport. Support will be added if there appears to be a demand for it.
|
19
|
+
|
20
|
+
== Documentation
|
21
|
+
|
22
|
+
== Future
|
data/Rakefile
ADDED
data/gitolite.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "gitolite/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "gitolite"
|
7
|
+
s.version = Gitolite::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Stafford Brunk"]
|
10
|
+
s.email = ["wingrunr21@gmail.com"]
|
11
|
+
s.homepage = "https://www.github.com/wingrunr21/gitolite"
|
12
|
+
s.summary = %q{A Ruby gem for manipulating the gitolite git backend via the gitolite-admin repository.}
|
13
|
+
s.description = %q{This gem is designed to provide a Ruby interface to the gitolite git backend system. This gem aims to provide all management functionality that is available via the gitolite-admin repository (like SSH keys, repository permissions, etc)}
|
14
|
+
|
15
|
+
s.rubyforge_project = "gitolite"
|
16
|
+
|
17
|
+
s.add_development_dependency "rspec", "~> 2.4.0"
|
18
|
+
s.add_dependency "grit", "~> 2.4.1"
|
19
|
+
|
20
|
+
s.files = `git ls-files`.split("\n")
|
21
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
22
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
end
|
data/lib/gitolite.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
module Gitolite
|
2
|
+
class Config
|
3
|
+
attr_accessor :repos, :groups
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
@repos = {}
|
7
|
+
@groups = Hash.new { |k,v| k[v] = [] }
|
8
|
+
process_config(config)
|
9
|
+
end
|
10
|
+
|
11
|
+
#Represents a repo inside the gitolite configuration. The name, permissions, and git config
|
12
|
+
#options are all encapsulated in this class
|
13
|
+
class Repo
|
14
|
+
ALLOWED_PERMISSIONS = ['C', 'R', 'RW', 'RW+', 'RWC', 'RW+C', 'RWD', 'RW+D', 'RWCD', 'RW+CD', '-']
|
15
|
+
|
16
|
+
attr_accessor :permissions, :name, :config
|
17
|
+
|
18
|
+
def initialize(name)
|
19
|
+
@name = name
|
20
|
+
@permissions = Hash.new {|k,v| k[v] = Hash.new{|k2, v2| k2[v2] = [] }}
|
21
|
+
@config = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_permission(perm, refex, users)
|
25
|
+
if ALLOWED_PERMISSIONS.include? perm
|
26
|
+
@permissions[perm][refex].concat users
|
27
|
+
else
|
28
|
+
raise InvalidPermissionError, "#{perm} is not in the allowed list of permissions!"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def set_git_config(key, value)
|
33
|
+
@config[key] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
def unset_git_config(key)
|
37
|
+
@config.delete(key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
@name
|
42
|
+
end
|
43
|
+
|
44
|
+
#Gets raised if a permission that isn't in the allowed
|
45
|
+
#list is passed in
|
46
|
+
class InvalidPermissionError < RuntimeError
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
#Based on
|
52
|
+
#https://github.com/sitaramc/gitolite/blob/pu/src/gl-compile-conf#cleanup_conf_line
|
53
|
+
def cleanup_config_line(line)
|
54
|
+
#remove comments, even those that happen inline
|
55
|
+
line.gsub!(/^((".*?"|[^#"])*)#.*/) {|m| m=$1}
|
56
|
+
|
57
|
+
#fix whitespace
|
58
|
+
line.gsub!('=', ' = ')
|
59
|
+
line.gsub!(/\s+/, ' ')
|
60
|
+
line.strip!
|
61
|
+
end
|
62
|
+
|
63
|
+
def process_config(config)
|
64
|
+
context = [] #will store our context for permissions or config declarations
|
65
|
+
|
66
|
+
#Read each line of our config
|
67
|
+
File.open(config, 'r').each do |l|
|
68
|
+
|
69
|
+
line = cleanup_config_line(l)
|
70
|
+
next if line.empty? #lines are empty if we killed a comment
|
71
|
+
|
72
|
+
case line.strip
|
73
|
+
#found a repo definition
|
74
|
+
when /^repo (.*)/
|
75
|
+
#Empty our current context
|
76
|
+
context = []
|
77
|
+
|
78
|
+
repos = $1.split
|
79
|
+
repos.each do |r|
|
80
|
+
context << r
|
81
|
+
|
82
|
+
@repos[r] = Repo.new(r) unless @repos.has_key? r
|
83
|
+
end
|
84
|
+
#repo permissions
|
85
|
+
when /^(-|C|R|RW\+?(?:C?D?|D?C?)) (.* )?= (.+)/
|
86
|
+
perm = $1
|
87
|
+
refex = $2 || ""
|
88
|
+
users = $3.split
|
89
|
+
|
90
|
+
context.each do |c|
|
91
|
+
@repos[c].add_permission(perm, refex, users)
|
92
|
+
end
|
93
|
+
#repo git config
|
94
|
+
when /^config (.+) = ?(.*)/
|
95
|
+
key = $1
|
96
|
+
value = $2
|
97
|
+
|
98
|
+
context.each do |c|
|
99
|
+
@repos[c].set_git_config(key, value)
|
100
|
+
end
|
101
|
+
#group definition
|
102
|
+
when /^(@\S+) = ?(.*)/
|
103
|
+
group = $1
|
104
|
+
users = $2.split
|
105
|
+
|
106
|
+
@groups[group].concat users
|
107
|
+
@groups[group].uniq!
|
108
|
+
#gitweb definition
|
109
|
+
when /^(\S+)(?: "(.*?)")? = "(.*)"$/
|
110
|
+
#ignore gitweb right now
|
111
|
+
puts line
|
112
|
+
when /^include "(.+)"/
|
113
|
+
#ignore includes for now
|
114
|
+
else
|
115
|
+
puts "The following line cannot be processed:"
|
116
|
+
puts "'#{line}'"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Gitolite
|
2
|
+
class GitoliteAdmin
|
3
|
+
attr_accessor :gl_admin, :ssh_keys, :config
|
4
|
+
|
5
|
+
CONF = "/conf/gitolite.conf"
|
6
|
+
KEYDIR = "/keydir"
|
7
|
+
|
8
|
+
#Intialize with the path to
|
9
|
+
#the gitolite-admin repository
|
10
|
+
def initialize(path, options = {})
|
11
|
+
@gl_admin = Grit::Repo.new(path)
|
12
|
+
|
13
|
+
@path = path
|
14
|
+
@conf = options[:conf] || CONF
|
15
|
+
@keydir = options[:keydir] || KEYDIR
|
16
|
+
|
17
|
+
@ssh_keys = load_keys(File.join(@path, @keydir))
|
18
|
+
@config = Config.new(File.join(@path, @conf))
|
19
|
+
end
|
20
|
+
|
21
|
+
#Writes all aspects out to the file system
|
22
|
+
#will also stage all changes
|
23
|
+
def save
|
24
|
+
#Process config file
|
25
|
+
|
26
|
+
#Process ssh keys
|
27
|
+
files = list_keys(File.join(@path, @keydir)).map{|f| File.basename f}
|
28
|
+
keys = @ssh_keys.values.map{|f| f.map {|t| t.filename}}.flatten
|
29
|
+
|
30
|
+
#Remove all keys we don't have a record for
|
31
|
+
to_remove = (files - keys).map { |f| File.join(@keydir, f)}
|
32
|
+
@gl_admin.remove(to_remove) unless to_remove.empty?
|
33
|
+
|
34
|
+
#Write all keys to files, overwriting existing keys
|
35
|
+
keys.each do |key|
|
36
|
+
File.open(key, "w") do |f|
|
37
|
+
f.write key.to_s
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#commits all staged changes and pushes back
|
43
|
+
#to origin
|
44
|
+
def apply
|
45
|
+
status = @gl_admin.status
|
46
|
+
end
|
47
|
+
|
48
|
+
#Calls save and apply in order
|
49
|
+
def save_and_apply
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_key(key)
|
53
|
+
raise "Key must be of type Gitolite::SSHKey!" unless key.instance_of? Gitolite::SSHKey
|
54
|
+
@ssh_keys[key.owner] << key
|
55
|
+
end
|
56
|
+
|
57
|
+
def rm_key(key)
|
58
|
+
@ssh_keys[key.owner].delete key
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
#Loads all .pub files in the gitolite-admin
|
63
|
+
#keydir directory
|
64
|
+
def load_keys(path)
|
65
|
+
keys = Hash.new {|k,v| k[v] = []}
|
66
|
+
|
67
|
+
list_keys(path).each do |key|
|
68
|
+
new_key = SSHKey.from_file(File.join(path, key))
|
69
|
+
owner = new_key.owner
|
70
|
+
|
71
|
+
keys[owner] << new_key
|
72
|
+
end
|
73
|
+
|
74
|
+
keys
|
75
|
+
end
|
76
|
+
|
77
|
+
def list_keys(path)
|
78
|
+
Dir.chdir(path)
|
79
|
+
Dir.glob("**/*.pub")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Gitolite
|
2
|
+
#Models an SSH key within gitolite
|
3
|
+
#provides support for multikeys
|
4
|
+
#
|
5
|
+
#Types of multi keys:
|
6
|
+
# bob.pub => username: bob
|
7
|
+
# bob@desktop.pub => username: bob, location: desktop
|
8
|
+
# bob@email.com.pub => username: bob@email.com
|
9
|
+
# bob@email.com@desktop.pub => username: bob@email.com, location: desktop
|
10
|
+
|
11
|
+
class SSHKey
|
12
|
+
attr_accessor :owner, :location, :type, :blob, :email
|
13
|
+
|
14
|
+
def initialize(type, blob, email, owner = nil, location = "")
|
15
|
+
@type = type
|
16
|
+
@blob = blob
|
17
|
+
@email = email
|
18
|
+
|
19
|
+
@owner = owner || email
|
20
|
+
@location = location
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.from_file(key)
|
24
|
+
|
25
|
+
raise "#{key} does not exist!" unless File.exists?(key)
|
26
|
+
|
27
|
+
#Get our owner and location
|
28
|
+
File.basename(key) =~ /^(\w+(?:@(?:\w+\.)+\D{2,4})?)(?:@(\w+))?.pub$/i
|
29
|
+
owner = $1
|
30
|
+
location = $2 || ""
|
31
|
+
|
32
|
+
#Get parts of the key
|
33
|
+
type, blob, email = File.read(key).split
|
34
|
+
|
35
|
+
#If the key didn't have an email, just use the owner
|
36
|
+
if email.nil?
|
37
|
+
email = owner
|
38
|
+
end
|
39
|
+
|
40
|
+
self.new(type, blob, email, owner, location)
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
[@type, @blob, @email].join(' ')
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_file(filename)
|
48
|
+
File.open(filename, "w") do |f|
|
49
|
+
f.write (self.to_s)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def filename
|
54
|
+
file = @owner
|
55
|
+
file += "@#{@location}" unless @location.empty?
|
56
|
+
file += ".pub"
|
57
|
+
end
|
58
|
+
|
59
|
+
def ==(key)
|
60
|
+
@type == key.type &&
|
61
|
+
@blob == key.blob &&
|
62
|
+
@email == key.email &&
|
63
|
+
@owner == key.owner &&
|
64
|
+
@location == key.location
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,298 @@
|
|
1
|
+
# example conf file for gitolite
|
2
|
+
|
3
|
+
# ----------------------------------------------------------------------------
|
4
|
+
# overall syntax:
|
5
|
+
# - everything is space-separated; no commas, semicolons, etc (except in
|
6
|
+
# the description string for gitweb)
|
7
|
+
# - comments in the normal shell-ish style; no surprises there
|
8
|
+
# - there are NO continuation lines of any kind
|
9
|
+
# - user/repo names as simple as possible; they must start with an
|
10
|
+
# alphanumeric, but after that they can also contain ".", "_", "-".
|
11
|
+
# - usernames can optionally be followed by an "@" and a domainname
|
12
|
+
# containing at least one "." (this allows you to use an email
|
13
|
+
# address as someone's username)
|
14
|
+
# - reponames can contain "/" characters (this allows you to
|
15
|
+
# put your repos in a tree-structure for convenience)
|
16
|
+
|
17
|
+
# objectives, over and above gitosis:
|
18
|
+
# - simpler syntax
|
19
|
+
# - easier gitweb/daemon control
|
20
|
+
# - specify who can push a branch/tag
|
21
|
+
# - specify who can rewind a branch/rewrite a tag
|
22
|
+
|
23
|
+
# ----------------------------------------------------------------------------
|
24
|
+
|
25
|
+
# GROUPS
|
26
|
+
# ------
|
27
|
+
|
28
|
+
# syntax:
|
29
|
+
# @groupname = [one or more names]
|
30
|
+
|
31
|
+
# groups let you club (user or group) names together for convenience
|
32
|
+
|
33
|
+
# * a group is like a #define in C except that it can *accumulate* values
|
34
|
+
# * the config file is parsed in a single-pass, so later *additions* to a
|
35
|
+
# group name cannot affect earlier *uses* of it
|
36
|
+
|
37
|
+
# The following examples should illustrate all this:
|
38
|
+
|
39
|
+
# you can have a group of people...
|
40
|
+
@staff = sitaram some_dev another-dev
|
41
|
+
|
42
|
+
# ...or a group of repos
|
43
|
+
@oss_repos = gitolite linux git perl rakudo entrans vkc
|
44
|
+
|
45
|
+
# ...or even a group of refexes
|
46
|
+
@important = master$ QA_done refs/tags/v[0-9]
|
47
|
+
# (see later for what "refex"s are; I'm only mentioning it
|
48
|
+
# here to emphasise that you can group them too)
|
49
|
+
|
50
|
+
# even sliced and diced differently
|
51
|
+
@admins = sitaram admin2
|
52
|
+
# notice that sitaram is in 2 groups (staff and admins)
|
53
|
+
|
54
|
+
# if you repeat a group name in another definition line, the
|
55
|
+
# new ones get added to the old ones (they accumulate)
|
56
|
+
@staff = au.thor
|
57
|
+
# so now "@staff" expands to all 4 names
|
58
|
+
|
59
|
+
# groups can include other groups, and the included group will
|
60
|
+
# be expanded to whatever value it currently has
|
61
|
+
@interns = indy james
|
62
|
+
@staff = bob @interns
|
63
|
+
# "@staff" expands to 7 names now
|
64
|
+
@interns = han
|
65
|
+
# "@interns" now has 3 names in it, but note that this does
|
66
|
+
# not change @staff
|
67
|
+
|
68
|
+
# REPO AND BRANCH PERMISSIONS
|
69
|
+
# ---------------------------
|
70
|
+
|
71
|
+
# syntax:
|
72
|
+
# start line:
|
73
|
+
# repo [one or more repos and/or repo groups]
|
74
|
+
# followed by one or more permissions lines:
|
75
|
+
# (C|R|RW|RW+|RWC|RW+C|RWD|RW+D|RWCD|RW+CD) [zero or more refexes] = [one or more users]
|
76
|
+
|
77
|
+
# there are 6 types of permissions: R, RW, and RW+ are simple (the "+" means
|
78
|
+
# permission to "rewind" -- force push a non-fast forward to -- a branch).
|
79
|
+
# The *standalone* C permission pertains to creating a REPO and is described
|
80
|
+
# in doc/wildcard-repositories.mkd. The C and D *suffixes* to the RW/RW+
|
81
|
+
# permissions pertain to creating or deleting a BRANCH, and are described in
|
82
|
+
# doc/3-faq-tips-etc.mkd, in the sections on "separating push and create
|
83
|
+
# rights" and "separating delete and rewind rights" respectively.
|
84
|
+
|
85
|
+
# how permissions are matched:
|
86
|
+
# - user, repo, and access (W or +) are known. For that combination, if
|
87
|
+
# any of the refexes match the refname being updated, the push succeeds.
|
88
|
+
# If none of them match, it fails
|
89
|
+
|
90
|
+
# what's a refex? a regex to match against the ref being updated (get it?)
|
91
|
+
# See next section for more on refexes
|
92
|
+
|
93
|
+
# BASIC PERMISSIONS (repo level only; apply to all branches/tags in repo)
|
94
|
+
|
95
|
+
# most important rule of all -- specify who can make changes
|
96
|
+
# to *this* file take effect
|
97
|
+
repo gitolite-admin
|
98
|
+
RW+ = @admins
|
99
|
+
|
100
|
+
# "@all" is a special, predefined, group name of all users
|
101
|
+
# (everyone who has a pubkey in keydir)
|
102
|
+
repo testing
|
103
|
+
RW+ = @all
|
104
|
+
|
105
|
+
# this repo is visible to staff but only sitaram can write to it
|
106
|
+
repo gitolite
|
107
|
+
R = @staff
|
108
|
+
RW+ = sitaram
|
109
|
+
|
110
|
+
# you can split up access rules for a repo for convenience
|
111
|
+
# (notice that @oss_repos contains gitolite also)
|
112
|
+
repo @oss_repos
|
113
|
+
R = @all
|
114
|
+
|
115
|
+
# set permissions to all repos. *Please* do see
|
116
|
+
# doc/3-faq-tips-etc.mkd for notes on this feature
|
117
|
+
repo @all
|
118
|
+
RW+ = @admins
|
119
|
+
|
120
|
+
# SPECIFYING AND USING A REFEX
|
121
|
+
|
122
|
+
# - refexes are specified in perl regex syntax
|
123
|
+
# - refexes are prefix-matched (they are internally anchored with "^"
|
124
|
+
# before being used), which means a refex like "refs/tags/v[0-9]"
|
125
|
+
# matches anything *starting with* that pattern. There may be text
|
126
|
+
# after it (example: refs/tags/v4-r3/p7), and it will still match
|
127
|
+
|
128
|
+
# ADVANCED PERMISSIONS USING REFEXES
|
129
|
+
|
130
|
+
# - if no refex appears, the rule applies to all refs in that repo
|
131
|
+
# - a refex is automatically prefixed by "refs/heads/" if it doesn't start
|
132
|
+
# with "refs/" (so tags have to be explicitly named as
|
133
|
+
# refs/tags/pattern)
|
134
|
+
|
135
|
+
# here's the example from
|
136
|
+
# Documentation/howto/update-hook-example.txt:
|
137
|
+
|
138
|
+
# refs/heads/master junio
|
139
|
+
# +refs/heads/pu junio
|
140
|
+
# refs/heads/cogito$ pasky
|
141
|
+
# refs/heads/bw/.* linus
|
142
|
+
# refs/heads/tmp/.* .*
|
143
|
+
# refs/tags/v[0-9].* junio
|
144
|
+
|
145
|
+
# and here're the equivalent gitolite refexes
|
146
|
+
repo git
|
147
|
+
RW = bobzilla
|
148
|
+
RW master = junio
|
149
|
+
RW+ pu = junio
|
150
|
+
RW cogito$ = pasky
|
151
|
+
RW bw/ = linus
|
152
|
+
RW tmp/ = @all
|
153
|
+
RW refs/tags/v[0-9] = junio
|
154
|
+
|
155
|
+
# DENY/EXCLUDE RULES
|
156
|
+
|
157
|
+
# ***IMPORTANT NOTES ABOUT "DENY" RULES***:
|
158
|
+
|
159
|
+
# - deny rules do NOT affect read access. They only apply to write access.
|
160
|
+
#
|
161
|
+
# - when using deny rules, the order of your rules starts to matter, where
|
162
|
+
# earlier it did not. The first matching rule applies, where "matching" is
|
163
|
+
# defined as either permitting the operation you're attempting (`W` or `+`),
|
164
|
+
# which results in success, or a "deny" (`-`), which results in failure.
|
165
|
+
# (As before, a fallthrough also results in failure).
|
166
|
+
|
167
|
+
# in the example above, you cannot easily say "anyone can write any tag,
|
168
|
+
# except version tags can only be written by junio". The following might look
|
169
|
+
# like it works but it doesn't:
|
170
|
+
|
171
|
+
# RW refs/tags/v[0-9] = junio
|
172
|
+
# RW refs/tags/ = junio linus pasky @others
|
173
|
+
|
174
|
+
# if you use "deny" rules, however, you can do this (a "deny" rule just uses
|
175
|
+
# "-" instead of "R" or "RW" or "RW+" in the permission field)
|
176
|
+
|
177
|
+
RW refs/tags/v[0-9] = junio
|
178
|
+
- refs/tags/v[0-9] = linus pasky @others
|
179
|
+
RW refs/tags/ = junio linus pasky @others
|
180
|
+
|
181
|
+
# FILE/DIR NAME BASED RESTRICTIONS
|
182
|
+
# --------------------------------
|
183
|
+
|
184
|
+
# Here's a hopefully self-explanatory example. Assume the project has the
|
185
|
+
# following contents at the top level: a README, a "doc/" directory, and an
|
186
|
+
# "src/" directory.
|
187
|
+
|
188
|
+
repo foo
|
189
|
+
RW+ = lead_dev # rule 1
|
190
|
+
RW = dev1 dev2 dev3 dev4 # rule 2
|
191
|
+
|
192
|
+
RW NAME/ = lead_dev # rule 3
|
193
|
+
RW NAME/doc/ = dev1 dev2 # rule 4
|
194
|
+
RW NAME/src/ = dev1 dev2 dev3 dev4 # rule 5
|
195
|
+
|
196
|
+
# Notes
|
197
|
+
|
198
|
+
# - the "NAME/" is part of the syntax; think of it as a keyword if you like.
|
199
|
+
# The rest of it is treated as a refex to match against each file being
|
200
|
+
# touched (see "SPECIFYING AND USING A REFEX" above for details)
|
201
|
+
|
202
|
+
# - file/dir NAME-based restrictions are *in addition* to normal (branch-name
|
203
|
+
# based) restrictions; they are not a *replacement* for them. This is why
|
204
|
+
# rule #2 (or something like it, maybe with a more specific branch-name) is
|
205
|
+
# needed; without it, dev1/2/3/4 cannot push any branches.
|
206
|
+
|
207
|
+
# - if a repo has *any* NAME/ rules, then NAME-based restrictions are checked
|
208
|
+
# for *all* users. This is why rule 3 is needed, even though we don't
|
209
|
+
# actually have any NAME-based restrictions on lead_dev. Notice the pattern
|
210
|
+
# on rule 3.
|
211
|
+
|
212
|
+
# - *each* file touched by the commits being pushed is checked against those
|
213
|
+
# rules. So, lead_dev can push changes to any files, dev1/2 can push
|
214
|
+
# changes to files in "doc/" and "src/" (but not the top level README), and
|
215
|
+
# dev3/4 can only push changes to files in "src/".
|
216
|
+
|
217
|
+
# GITWEB AND DAEMON STUFF
|
218
|
+
# -----------------------
|
219
|
+
|
220
|
+
# No specific syntax for gitweb and daemon access; just make the repo readable
|
221
|
+
# ("R" access) to the special users "gitweb" and "daemon"
|
222
|
+
|
223
|
+
# make "@oss_repos" (all 7 of them!) accessible via git daemon
|
224
|
+
repo @oss_repos
|
225
|
+
R = daemon
|
226
|
+
|
227
|
+
# make the two *large* repos accessible via gitweb
|
228
|
+
repo linux perl
|
229
|
+
R = gitweb
|
230
|
+
|
231
|
+
# REPO OWNER/DESCRIPTION LINE FOR GITWEB
|
232
|
+
|
233
|
+
# syntax, one of:
|
234
|
+
# reponame = "some description string in double quotes"
|
235
|
+
# reponame "owner name" = "some description string in double quotes"
|
236
|
+
|
237
|
+
# note: setting a description also gives gitweb access; you do not have to
|
238
|
+
# give gitweb access as described above if you're specifying a description
|
239
|
+
|
240
|
+
gitolite "Sitaram Chamarty" = "fast, secure, access control for git in a corporate environment"
|
241
|
+
|
242
|
+
# REPO SPECIFIC GITCONFIG
|
243
|
+
# -----------------------
|
244
|
+
|
245
|
+
# update 2010-02-06; this won't work unless the rc file has the right
|
246
|
+
# settings; please see comments around the variable $GL_GITCONFIG_KEYS in
|
247
|
+
# conf/example.gitolite.rc for details and security information.
|
248
|
+
|
249
|
+
# (Thanks to teemu dot matilainen at iki dot fi)
|
250
|
+
|
251
|
+
# this should be specified within a "repo" stanza
|
252
|
+
|
253
|
+
# syntax:
|
254
|
+
# config sectionname.keyname = [optional value_string]
|
255
|
+
|
256
|
+
# example usage: if you placed a hook in hooks/common that requires
|
257
|
+
# configuration information that is specific to each repo, you could do this:
|
258
|
+
|
259
|
+
repo gitolite
|
260
|
+
config hooks.mailinglist = gitolite-commits@example.tld
|
261
|
+
config hooks.emailprefix = "[gitolite] "
|
262
|
+
config foo.bar = ""
|
263
|
+
config foo.baz =
|
264
|
+
|
265
|
+
# This does either a plain "git config section.key value" (for the first 3
|
266
|
+
# examples above) or "git config --unset-all section.key" (for the last
|
267
|
+
# example). Other forms (--add, the value_regex, etc) are not supported.
|
268
|
+
|
269
|
+
# INCLUDE SOME OTHER FILE
|
270
|
+
# -----------------------
|
271
|
+
|
272
|
+
include "foo.conf"
|
273
|
+
|
274
|
+
# this includes the contents of $GL_ADMINDIR/conf/foo.conf here
|
275
|
+
|
276
|
+
# Notes:
|
277
|
+
# - the include statement is not allowed inside delegated fragments for
|
278
|
+
# security reasons.
|
279
|
+
# - you can also use an absolute path if you like, although in the interests
|
280
|
+
# of cloning the admin-repo sanely you should avoid doing this!
|
281
|
+
|
282
|
+
# EXTERNAL COMMAND HELPERS -- RSYNC
|
283
|
+
# ---------------------------------
|
284
|
+
|
285
|
+
# If $RSYNC_BASE is non-empty, the following config entries come into play
|
286
|
+
# (otherwise they are ignored):
|
287
|
+
|
288
|
+
# a "fake" git repository to collect rsync rules. Gitolite does not
|
289
|
+
# auto-create any repo whose name starts with EXTCMD/
|
290
|
+
repo EXTCMD/rsync
|
291
|
+
# grant permissions to files/dirs within the $RSYNC_BASE tree. A leading
|
292
|
+
# NAME/ is required as a prefix; the actual path starts after that. Matching
|
293
|
+
# follows the same rules as given in "FILE/DIR NAME BASED RESTRICTIONS" above
|
294
|
+
RW NAME/ = sitaram
|
295
|
+
RW NAME/foo/ = user1
|
296
|
+
R NAME/bar/ = user2
|
297
|
+
# just to remind you that these are perl regexes, not shell globs
|
298
|
+
RW NAME/baz/.*/*.c = user3
|
data/spec/keys/bob.pub
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6EFlh48tzCnepmggd09sUEM4m1zH3Fs/X6XWm1MAkEnMsD5hFGjkcNabDM8vq9zIRZ05YC6Gxo2plstAf+X4Y636+hyFvbDONB9mRP7DxJhFRaBScSFH60jeTz4ue2ExH3xA1JkaHMcV5vooUqG4BW8Vy/sz8wt/s0aIg9xqkrPOnfvqwunZ/zFUNyL8tC1HY3zGUkRzEVd2yRKaI+DGyRsh8HuYIb2X3NQ0YsU3uGGud7ObmxDbM7WGniyxRVK3lYCvgnTjvdPGi7Xx9QNQz53zLFbklGPZSfpFFHS84qR0Rd/+MnpT50FODhTmXHZtZF1eik09z63GW3YVt4PGoQ== bob@zilla.com
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAwZc2kw4Bc8Kksp0XBiDR/rDrUAmv2THB9OVbRwJ7TEelU8OFJqCx1syjdjAgS+LE3K5d5xtDMYRlxE2hkl8V6EySY9Q35qWqaqhmS8erZap0qiCWM5vlzxWFKOpnhQdNbNjA7a7FSTDT6ThOC9sTCJfMvNdBiiUUGGDE48AvtwtF3er24h8w7J5623AICfOdhfPAFavTO6/QpeHRe8QOkbBJ2oaJDer4rDetgtBUgHXh3jANgD2ICRFd9l5eCozkDCISFJ6Xg2Eq8gMJ2DKj3BSzBpRPiAJ1YVsr/cBzGxRVRPS6Go485E2r7l7zAsE1t/t6eRUU4W5ZeopxD4GUXQ== bob@zilla.com
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAu1cY+0C5QV/0mcdobqS673BVlT7weW1lZKp83v8kTYHJJ8NLKixnPf4VePUoE5IMdmWMHNtAtSCG+X/Gdo/2VBHWbZ/O2mC2WSYH0u/nk+Bw0l30/vbV0wP3rcapY42BiMl/H0CPuxql99SBcVJoAaKkxJ4uvyR/hQ+mEmSIYz7mD11opCC6owmWm7R5Sdf2UGXzYXHwu5G9DdIE+QcmYbLkltCBHwa17syoM5QtetbHc/S/wbudrLclJXPHJ0xEtJMhGEHzNJndwYpOA4R61O+phIXIwdtdBeCAxAQyb9hf+qrOBaMfXyFn/WF0ov8hAnKDWWKg74e4ZHYJ2qPSRw== bob@zilla.com
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAsRofYfjAUdw0McxGpLTxBbZyKN05HGY19ZIjEQmBPUe2Skt1i/SLwIYzTzKv6vEgAdT9SwmCsO/jpDY/ZM+MhWy4okBisn04yIHCW10q4+YNo2WatzttEa1W+hC58nKtoq/0HkvPVdoeOZxcNtpjvgvkrXH2zdmX7xnA1AAWtqRNkRYWPKjiojkg92aqmJLISSIDeZs2wvXbFO3BJhkvyr3W60cinKhGBBscvdCYUi5pb9dXIFhEEqRf1JkT5CEmF3p4GqSt4/L79nR0LV45grS4NbcN+fCnjWZ8PQhmJ+WPLKkydgR1YvobeY7zDHdHJXWLhsPa+SjwI3WfzrB+GQ== bob@zilla.com
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAvtAkUG0e/dgqzb9Vtj6mspYCueII5U/gx3fnpIb2j8ng/ZJPPLYIb2UCwHdFBj/VZerKiJn6epJRi8qj4ddC4Z/LPNgjn06gbjAAubyb2Lki/XSvizpP6j4OtRnt/Vf17n1hyUKN0OAQmSaf1DoXsvWHpb64U7WxbY3Z3XLdJlqtIXW0vr3X13RKx6JZDGM2re/1ymZ5SJZT/KTruqtC42Yu4C2ktSa+JRh82+jALGy/5A/o1lsCziCSE/+iycVNM9hSfbwGTC1AVT1WO2BiQlduUL3tk4XyMEjlOXF2K4FobcBhLTrNtLc24vnlx5HkcBmuubq7x6g1pw4znwItgQ== jakub123@foo.net
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArDPbrc0rP+Pux38Y14rMkgbPHo7iY89/VG80BH8dXVB1nisFHgY6zJdSPJ3zrEm1j81Hc7tZvd3FGjOKP8Ae02/J8O4WaVdB5pMo81YxQWu3eV6nD7x7AIeZEBauK7zV3eqyxTZ/V0oBd7e9VKMukxoiv+RXlXdItpH0md3bpQ3IreFjfaBrFnX0QLdGx0CjimKtMNOU7yKRlvuGcrvMoRtXSUzssAUtjmy8cRabBqZyJVOFrk6MhE1VpcAEE47Sb2ovFgfx5w4kA7mRAz6jO+MAM5go0lGoK26WrR9p/ZXuhmmdjQMPdSCssGQxni657vLp3F7PGV2AG35M58IwuQ==
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAu9Y0aeYzlF/e/JZDYr4s/BmCnU5WATugdxnEDboTFgSt0rIZ3P+93m+wchGgP/GzspHa/gSIBBjDBwmzPlhdNieJdiNyJ0n0BvUWOBlI3wNQLU+wdqa1UwxQyPZNSplxyzhcsIgD6kPqYR9JE6Yga7QUnJdP/vAB+XtMoZlc+CVKjxLrjijSHX57WJ0bSXwKtYVHtgCGtJ1mmAZV/q64SR3mqEwB7WG0BTNwT0ruHRk4Zg/EpuutStYGne23/1FBSrfMirQCEneTiLOO/vAibWLzTRWSVyRT9YJYeH0Cp5dXnu3MqPL6+PhaP+iDtx6Vo/h2jeCJZpJUJb7dX9nl/Q== joe@sch.ool.edu
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAt6+DWErgYKwCLQ+1DiD05iZc1FFgU2n+QXSqAOIjU5O2FKVgGU5JLOGydidOUK/vWRrPmS045Iv4BxTPIUPMLjn9lBjUkY7ZxfJb5aSW+9zwE/5/073DswRwHVZuxsxfScgqkwenTjN6bbM+qnASn+b6yxfRLmp86IzIXxKp2EiJ4Anw/9oUxre/K25WemTo8eUfKLfTS+z0KLSs1C9TJpO/MkDkHiv1S2wcnduA+nVcbSo7MuxrVDdQIQcDf0gKwwLwxtvKZXtUWC3Ji9kn3F86aRVBuMcl068t+UbbKvLc0BKo7RFMQ+nHXHosu1GJBwal+wWygbBksTk+92hRGQ== joe@sch.ool.edu
|
data/spec/spec_helper.rb
ADDED
File without changes
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'gitolite/ssh_key'
|
2
|
+
include Gitolite
|
3
|
+
|
4
|
+
describe Gitolite::SSHKey do
|
5
|
+
describe '#owner' do
|
6
|
+
it 'owner should be bob for bob.pub' do
|
7
|
+
key = File.join(File.dirname(__FILE__),'keys', 'bob.pub')
|
8
|
+
s = SSHKey.new(key)
|
9
|
+
s.owner.should == 'bob'
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'owner should be bob for bob@desktop.pub' do
|
13
|
+
key = File.join(File.dirname(__FILE__),'keys', 'bob@desktop.pub')
|
14
|
+
s = SSHKey.new(key)
|
15
|
+
s.owner.should == 'bob'
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'owner should be bob@zilla.com for bob@zilla.com.pub' do
|
19
|
+
key = File.join(File.dirname(__FILE__),'keys', 'bob@zilla.com.pub')
|
20
|
+
s = SSHKey.new(key)
|
21
|
+
s.owner.should == 'bob@zilla.com'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'owner should be bob@zilla.com for bob@zilla.com@desktop.pub' do
|
25
|
+
key = File.join(File.dirname(__FILE__),'keys', 'bob@zilla.com@desktop.pub')
|
26
|
+
s = SSHKey.new(key)
|
27
|
+
s.owner.should == 'bob@zilla.com'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'owner should be jakub123 for jakub123.pub' do
|
31
|
+
key = File.join(File.dirname(__FILE__),'keys', 'jakub123.pub')
|
32
|
+
s = SSHKey.new(key)
|
33
|
+
s.owner.should == 'jakub123'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'owner should be jakub123@foo.net for jakub123@foo.net.pub' do
|
37
|
+
key = File.join(File.dirname(__FILE__),'keys', 'jakub123@foo.net.pub')
|
38
|
+
s = SSHKey.new(key)
|
39
|
+
s.owner.should == 'jakub123@foo.net'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'owner should be joe@sch.ool.edu for joe@sch.ool.edu' do
|
43
|
+
key = File.join(File.dirname(__FILE__),'keys', 'joe@sch.ool.edu.pub')
|
44
|
+
s = SSHKey.new(key)
|
45
|
+
s.owner.should == 'joe@sch.ool.edu'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'owner should be joe@sch.ool.edu for joe@sch.ool.edu@desktop.pub' do
|
49
|
+
key = File.join(File.dirname(__FILE__),'keys', 'joe@sch.ool.edu@desktop.pub')
|
50
|
+
s = SSHKey.new(key)
|
51
|
+
s.owner.should == 'joe@sch.ool.edu'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#location' do
|
56
|
+
it 'location should be "" for bob.pub' do
|
57
|
+
key = File.join(File.dirname(__FILE__),'keys', 'bob.pub')
|
58
|
+
s = SSHKey.new(key)
|
59
|
+
s.location.should == ''
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'location should be "desktop" for bob@desktop.pub' do
|
63
|
+
key = File.join(File.dirname(__FILE__),'keys', 'bob@desktop.pub')
|
64
|
+
s = SSHKey.new(key)
|
65
|
+
s.location.should == 'desktop'
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'location should be "" for bob@zilla.com.pub' do
|
69
|
+
key = File.join(File.dirname(__FILE__),'keys', 'bob@zilla.com.pub')
|
70
|
+
s = SSHKey.new(key)
|
71
|
+
s.location.should == ''
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'location should be "desktop" for bob@zilla.com@desktop.pub' do
|
75
|
+
key = File.join(File.dirname(__FILE__),'keys', 'bob@zilla.com@desktop.pub')
|
76
|
+
s = SSHKey.new(key)
|
77
|
+
s.location.should == 'desktop'
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'location should be "" for jakub123.pub' do
|
81
|
+
key = File.join(File.dirname(__FILE__),'keys', 'jakub123.pub')
|
82
|
+
s = SSHKey.new(key)
|
83
|
+
s.location.should == ''
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'location should be "" for jakub123@foo.net.pub' do
|
87
|
+
key = File.join(File.dirname(__FILE__),'keys', 'jakub123@foo.net.pub')
|
88
|
+
s = SSHKey.new(key)
|
89
|
+
s.location.should == ''
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'location should be "" for joe@sch.ool.edu' do
|
93
|
+
key = File.join(File.dirname(__FILE__),'keys', 'joe@sch.ool.edu.pub')
|
94
|
+
s = SSHKey.new(key)
|
95
|
+
s.location.should == ''
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'location should be "desktop" for joe@sch.ool.edu@desktop.pub' do
|
99
|
+
key = File.join(File.dirname(__FILE__),'keys', 'joe@sch.ool.edu@desktop.pub')
|
100
|
+
s = SSHKey.new(key)
|
101
|
+
s.location.should == 'desktop'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe '#keys' do
|
106
|
+
it 'should load ssh key properly' do
|
107
|
+
key = File.join(File.dirname(__FILE__),'keys', 'bob.pub')
|
108
|
+
s = SSHKey.new(key)
|
109
|
+
parts = File.read(key).split #should get type, blob, email
|
110
|
+
|
111
|
+
s.type.should == parts[0]
|
112
|
+
s.blob.should == parts[1]
|
113
|
+
s.email.should == parts[2]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#email' do
|
118
|
+
it 'should use owner if email is missing' do
|
119
|
+
key = File.join(File.dirname(__FILE__),'keys', 'jakub123@foo.net.pub')
|
120
|
+
s = SSHKey.new(key)
|
121
|
+
s.owner.should == s.email
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gitolite
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: true
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- alpha
|
10
|
+
version: 0.0.1.alpha
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Stafford Brunk
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-30 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 2
|
31
|
+
- 4
|
32
|
+
- 0
|
33
|
+
version: 2.4.0
|
34
|
+
type: :development
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: grit
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
segments:
|
45
|
+
- 2
|
46
|
+
- 4
|
47
|
+
- 1
|
48
|
+
version: 2.4.1
|
49
|
+
type: :runtime
|
50
|
+
version_requirements: *id002
|
51
|
+
description: This gem is designed to provide a Ruby interface to the gitolite git backend system. This gem aims to provide all management functionality that is available via the gitolite-admin repository (like SSH keys, repository permissions, etc)
|
52
|
+
email:
|
53
|
+
- wingrunr21@gmail.com
|
54
|
+
executables: []
|
55
|
+
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files: []
|
59
|
+
|
60
|
+
files:
|
61
|
+
- .gitignore
|
62
|
+
- Gemfile
|
63
|
+
- Gemfile.lock
|
64
|
+
- README.rdoc
|
65
|
+
- Rakefile
|
66
|
+
- gitolite.gemspec
|
67
|
+
- lib/gitolite.rb
|
68
|
+
- lib/gitolite/config.rb
|
69
|
+
- lib/gitolite/gitolite_admin.rb
|
70
|
+
- lib/gitolite/ssh_key.rb
|
71
|
+
- lib/gitolite/version.rb
|
72
|
+
- spec/config_spec.rb
|
73
|
+
- spec/configs/complicated.conf
|
74
|
+
- spec/configs/simple.conf
|
75
|
+
- spec/gitolite_admin_spec.rb
|
76
|
+
- spec/keys/bob.pub
|
77
|
+
- spec/keys/bob@desktop.pub
|
78
|
+
- spec/keys/bob@zilla.com.pub
|
79
|
+
- spec/keys/bob@zilla.com@desktop.pub
|
80
|
+
- spec/keys/jakub123.pub
|
81
|
+
- spec/keys/jakub123@foo.net.pub
|
82
|
+
- spec/keys/joe@sch.ool.edu.pub
|
83
|
+
- spec/keys/joe@sch.ool.edu@desktop.pub
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
- spec/ssh_key_spec.rb
|
86
|
+
has_rdoc: true
|
87
|
+
homepage: https://www.github.com/wingrunr21/gitolite
|
88
|
+
licenses: []
|
89
|
+
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
segments:
|
101
|
+
- 0
|
102
|
+
version: "0"
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ">"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
segments:
|
109
|
+
- 1
|
110
|
+
- 3
|
111
|
+
- 1
|
112
|
+
version: 1.3.1
|
113
|
+
requirements: []
|
114
|
+
|
115
|
+
rubyforge_project: gitolite
|
116
|
+
rubygems_version: 1.3.7
|
117
|
+
signing_key:
|
118
|
+
specification_version: 3
|
119
|
+
summary: A Ruby gem for manipulating the gitolite git backend via the gitolite-admin repository.
|
120
|
+
test_files: []
|
121
|
+
|