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 ADDED
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in gitolite.gemspec
4
+ gemspec
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
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
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,6 @@
1
+ module Gitolite
2
+ require 'grit'
3
+ require 'gitolite/ssh_key'
4
+ require 'gitolite/config'
5
+ require 'gitolite/gitolite_admin'
6
+ end
@@ -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
+
@@ -0,0 +1,3 @@
1
+ module Gitolite
2
+ VERSION = "0.0.1.alpha"
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'gitolite/config'
2
+
3
+ describe Gitolite::Config do
4
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ repo gitolite-admin
2
+ RW+ = bobzilla
3
+
4
+ repo testing
5
+ RW+ = @all
@@ -0,0 +1,4 @@
1
+ require 'gitolite/gitolite_admin'
2
+
3
+ describe Gitolite::GitoliteAdmin do
4
+ end
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
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
+