gitolite 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
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
+