rubolite 0.0.1 → 0.0.2
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 +4 -0
- data/.rspec +2 -0
- data/Guardfile +8 -0
- data/README.md +10 -1
- data/lib/rubolite/admin.rb +54 -0
- data/lib/rubolite/client.rb +55 -0
- data/lib/rubolite/parser.rb +77 -0
- data/lib/rubolite/repo.rb +15 -0
- data/lib/rubolite/ssh_key.rb +40 -0
- data/lib/rubolite/user.rb +10 -0
- data/lib/rubolite/version.rb +1 -1
- data/lib/rubolite/writer.rb +40 -0
- data/lib/rubolite.rb +7 -1
- data/rubolite.gemspec +8 -0
- data/spec/fixtures/example.pub +1 -0
- data/spec/fixtures/gitolite-conf.conf +9 -0
- data/spec/lib/rubolite/admin_spec.rb +67 -0
- data/spec/lib/rubolite/client_spec.rb +76 -0
- data/spec/lib/rubolite/parser_spec.rb +89 -0
- data/spec/lib/rubolite/repo_spec.rb +26 -0
- data/spec/lib/rubolite/ssh_key_spec.rb +34 -0
- data/spec/lib/rubolite/user_spec.rb +21 -0
- data/spec/lib/rubolite/writer_spec.rb +65 -0
- data/spec/spec_helper.rb +18 -0
- metadata +129 -4
data/.gitignore
CHANGED
data/.rspec
ADDED
data/Guardfile
ADDED
data/README.md
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
rubolite
|
2
2
|
========
|
3
3
|
|
4
|
-
Rubolite is an interface to Gitolite (https://github.com/sitaramc/gitolite)
|
4
|
+
Rubolite is an interface to Gitolite (https://github.com/sitaramc/gitolite)
|
5
|
+
|
6
|
+
This is a work in progress. It's end goal is to give a full interface to interact with Gitolite and save changes.
|
7
|
+
|
8
|
+
```
|
9
|
+
>> admin = Rubolite::Admin.new("/Users/robertross/Sites/gitolite-admin")
|
10
|
+
=> #<Rubolite::Admin:0x007f96be332de8 @path="/Users/robertross/Sites/gitolite-admin">
|
11
|
+
>> admin.parser.repos.first
|
12
|
+
=> #<Rubolite::Repo:0x007f96be347068 @name="gitolite-admin", @users=[#<Rubolite::User:0x007f96be346dc0 @name="gitolite", @permissions="RW+">]>
|
13
|
+
```
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "git"
|
2
|
+
|
3
|
+
module Rubolite
|
4
|
+
class Admin
|
5
|
+
InvalidPath = Class.new(Exception)
|
6
|
+
InvalidGitRepo = Class.new(Exception)
|
7
|
+
InvalidRepo = Class.new(Exception)
|
8
|
+
|
9
|
+
attr_reader :path, :repos
|
10
|
+
|
11
|
+
def initialize(path=nil)
|
12
|
+
@path = path if path && valid_path?(path)
|
13
|
+
end
|
14
|
+
|
15
|
+
def path=(new_path)
|
16
|
+
valid_path?(new_path)
|
17
|
+
@path = new_path
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_repo(repo)
|
21
|
+
raise InvalidRepo, "Repo not type of Rubolite::Repo, got #{repo.class}" unless repo.kind_of?(Repo)
|
22
|
+
(@repos ||= []) << repo
|
23
|
+
end
|
24
|
+
alias :<< :add_repo
|
25
|
+
|
26
|
+
def parser
|
27
|
+
@parser ||= Parser.new("#{path}/conf/gitolite.conf")
|
28
|
+
end
|
29
|
+
|
30
|
+
def writer
|
31
|
+
@writer ||= parser.writer
|
32
|
+
end
|
33
|
+
|
34
|
+
def git
|
35
|
+
@git ||= Git.open(path)
|
36
|
+
end
|
37
|
+
|
38
|
+
def repo_origin
|
39
|
+
@repo_origin ||= git.remote("origin")
|
40
|
+
end
|
41
|
+
|
42
|
+
def client
|
43
|
+
@client ||= Client.new(self)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def valid_path?(path)
|
49
|
+
raise InvalidPath, "#{path} is not a directory" unless File.directory?(path)
|
50
|
+
raise InvalidGitRepo, "#{path} is not a git repository" unless File.directory?("#{path}/.git")
|
51
|
+
true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Rubolite
|
2
|
+
class Client
|
3
|
+
attr_reader :admin, :ssh_keys
|
4
|
+
|
5
|
+
def initialize(admin)
|
6
|
+
@admin = admin
|
7
|
+
@ssh_keys = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def repos
|
11
|
+
@repos ||= admin.parser.repos
|
12
|
+
end
|
13
|
+
|
14
|
+
def groups
|
15
|
+
@groups ||= admin.parser.groups
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_group(name, users)
|
19
|
+
groups[name] = users
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_repo(repo)
|
23
|
+
repos << repo
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_ssh_key(user, ssh_key)
|
27
|
+
ssh_keys[user] = ssh_key
|
28
|
+
end
|
29
|
+
|
30
|
+
def save!
|
31
|
+
admin.writer.write!
|
32
|
+
end
|
33
|
+
|
34
|
+
def save_ssh_keys!
|
35
|
+
ssh_keys.each do |user, key|
|
36
|
+
key.write_for user, "#{admin.path}/keydir"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def commit!
|
41
|
+
admin.git.commit_all("Modified configuration by rubolite")
|
42
|
+
end
|
43
|
+
|
44
|
+
def push!
|
45
|
+
admin.git.push(admin.repo_origin)
|
46
|
+
end
|
47
|
+
|
48
|
+
def save_and_push!
|
49
|
+
save!
|
50
|
+
save_ssh_keys!
|
51
|
+
commit!
|
52
|
+
push!
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Rubolite
|
2
|
+
class Parser
|
3
|
+
attr_reader :conf_file, :repos, :groups
|
4
|
+
|
5
|
+
def initialize(conf_file)
|
6
|
+
@conf_file = conf_file
|
7
|
+
@groups = {}
|
8
|
+
parse!
|
9
|
+
end
|
10
|
+
|
11
|
+
def writer
|
12
|
+
@writer ||= Writer.new(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse_repo_line(repo_line)
|
16
|
+
if matched = repo_line.match(/repo ([\w\-\d]+)/)
|
17
|
+
matched[1]
|
18
|
+
else
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse_permissions_line(permission_line)
|
24
|
+
if matched = permission_line.match(/([R|W|\+\-]+)\s+=\s+([\@\w\d\-]+)/)
|
25
|
+
[matched[1], matched[2]]
|
26
|
+
else
|
27
|
+
[]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse_group_line(group_line)
|
32
|
+
if matched = group_line.match(/@([\w]+)\s+=\s+(.*)/)
|
33
|
+
group_name = matched[1]
|
34
|
+
names = matched[2].split(" ")
|
35
|
+
|
36
|
+
[group_name, names]
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def parse!
|
45
|
+
current_repo = nil
|
46
|
+
|
47
|
+
conf_contents.each do |line|
|
48
|
+
keyword = line.strip
|
49
|
+
case keyword
|
50
|
+
when /^repo\s/
|
51
|
+
repo_name = parse_repo_line(line)
|
52
|
+
repo = Repo.new(repo_name)
|
53
|
+
|
54
|
+
(@repos ||= []) << repo
|
55
|
+
|
56
|
+
current_repo = repo
|
57
|
+
when /^(R|W|\-)/
|
58
|
+
next unless current_repo
|
59
|
+
|
60
|
+
permissions, user = parse_permissions_line(line)
|
61
|
+
user = User.new(user, permissions)
|
62
|
+
current_repo.add_user(user)
|
63
|
+
when /^@\w/
|
64
|
+
group_name, users = parse_group_line(line)
|
65
|
+
@groups[group_name] ||= []
|
66
|
+
@groups[group_name] += users
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
self
|
71
|
+
end
|
72
|
+
|
73
|
+
def conf_contents
|
74
|
+
@conf_contents ||= File.readlines(conf_file)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Rubolite
|
2
|
+
# http://unix.stackexchange.com/questions/23590/ssh-public-key-comment-separator
|
3
|
+
# This class represents the structure of SSH public keys as defined in RFC4716
|
4
|
+
|
5
|
+
class SSHKey
|
6
|
+
attr_accessor :type, :key, :comment
|
7
|
+
|
8
|
+
def initialize(type, key, comment)
|
9
|
+
self.type = type
|
10
|
+
self.key = key
|
11
|
+
self.comment = comment
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.from_file(path)
|
15
|
+
key_contents = File.read(path)
|
16
|
+
new(*key_parts(key_contents))
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.from_string(string)
|
20
|
+
new(*key_parts(string))
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.key_parts(key_contents)
|
24
|
+
key_contents.split " "
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_for(username, directory)
|
28
|
+
File.open("#{directory}/#{username}.pub", "w") do |handle|
|
29
|
+
handle.write public_key_contents
|
30
|
+
handle.close
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def public_key_contents
|
37
|
+
[type, key, comment].join(" ")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/rubolite/version.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Rubolite
|
2
|
+
class Writer
|
3
|
+
attr_accessor :write_path
|
4
|
+
attr_reader :parser
|
5
|
+
|
6
|
+
def initialize(parser)
|
7
|
+
@parser = parser
|
8
|
+
@write_path = parser.conf_file
|
9
|
+
end
|
10
|
+
|
11
|
+
def write!
|
12
|
+
File.open(write_path, "w") do |handler|
|
13
|
+
handler.write groups
|
14
|
+
handler.write repos
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def groups
|
19
|
+
parser.groups.each_with_object([]) do |(name, users), lines|
|
20
|
+
lines << "@#{name} = #{users.join(" ")}"
|
21
|
+
end.join("\n") + "\n\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
def repos
|
25
|
+
parser.repos.each_with_object([]) do |repo, blocks|
|
26
|
+
blocks << repo_block(repo)
|
27
|
+
end.join("\n\n") + "\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
def repo_block(repo)
|
31
|
+
lines = []
|
32
|
+
lines << "repo #{repo.name}"
|
33
|
+
repo.users.each do |user|
|
34
|
+
lines << " #{user.permissions} = #{user.name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
lines.join("\n")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/rubolite.rb
CHANGED
data/rubolite.gemspec
CHANGED
@@ -16,4 +16,12 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_development_dependency "rspec", "~> 2.11.0"
|
21
|
+
gem.add_development_dependency "guard-rspec"
|
22
|
+
gem.add_development_dependency "awesome_print"
|
23
|
+
gem.add_development_dependency "pry"
|
24
|
+
gem.add_development_dependency "fakefs"
|
25
|
+
|
26
|
+
gem.add_dependency "git", "~> 1.2.5"
|
19
27
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/Zkiw2QoYtekwZUYULwQsrPJubWafiuewoP03DRn3xjwoNo0q7FE0nIw2ENODiaM8KD0+L+ax0UCdNcCiJYuzouHENBvXYxsWSk5sZicRWINJ91Jd6KZnMvCr06oObNnJKdE+7UxeC06512nBREW7xHc4urHSiBoejx8fJOUraI6Y0t+Y7l4EiugTUcZLdN3b4YNksQvv16GDnreS+0SkZKcU5zj8pIE3DRBvs8MeuK5N1oQQNkbLXLbTtBqTPfiQz7Ikj8YFaBBX8rXd66yu0sMjGImxWZjBNGPscvch/G5MGSabpRSZALWi+uN67CxJcj3vZPg6mJSxnpsXxOdZ robertross@paperwalls.local
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rubolite::Admin do
|
4
|
+
subject { Rubolite::Admin.new }
|
5
|
+
|
6
|
+
it "returns a client object" do
|
7
|
+
expect(subject.client).to be_kind_of Rubolite::Client
|
8
|
+
end
|
9
|
+
|
10
|
+
context "location" do
|
11
|
+
it "sets a location on initialization if given" do
|
12
|
+
admin = Rubolite::Admin.new("./spec/support/gitolite-admin")
|
13
|
+
expect(admin.path).to eq("./spec/support/gitolite-admin")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "sets a location for a repository" do
|
17
|
+
path_location = "./spec/support/gitolite-admin"
|
18
|
+
subject.path = path_location
|
19
|
+
expect(subject.path).to eq(path_location)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "raises an error when the path is bad" do
|
23
|
+
expect { subject.path = "./idontexist" }.to raise_error(Rubolite::Admin::InvalidPath)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "raises an error when the path given isn't a git repository" do
|
27
|
+
expect { subject.path = "./spec/support" }.to raise_error(Rubolite::Admin::InvalidGitRepo)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "does not raise an error when the path given is a valid git repository" do
|
31
|
+
expect { subject.path = "./spec/support/gitolite-admin" }.not_to raise_error(Rubolite::Admin::InvalidGitRepo)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "adding repos" do
|
36
|
+
let(:repo) { Rubolite::Repo.new }
|
37
|
+
|
38
|
+
it "adds a repo" do
|
39
|
+
subject.add_repo repo
|
40
|
+
subject.should have(1).repos
|
41
|
+
end
|
42
|
+
|
43
|
+
it "raises when trying to add a repo of a bad class" do
|
44
|
+
expect { subject.add_repo "bad" }.to raise_error(Rubolite::Admin::InvalidRepo)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "config parsing" do
|
49
|
+
it "#parser returns a parser object" do
|
50
|
+
subject.path = "./spec/support/gitolite-admin"
|
51
|
+
expect(subject.parser).to be_kind_of Rubolite::Parser
|
52
|
+
end
|
53
|
+
|
54
|
+
it "#writer returns a writer object" do
|
55
|
+
subject.path = "./spec/support/gitolite-admin"
|
56
|
+
expect(subject.writer).to be_kind_of Rubolite::Writer
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "git" do
|
61
|
+
subject { Rubolite::Admin.new("./spec/support/gitolite-admin") }
|
62
|
+
|
63
|
+
specify "#git returns a grit repo instance" do
|
64
|
+
expect(subject.git).to be_kind_of Git::Base
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rubolite::Client do
|
4
|
+
let(:admin) { Rubolite::Admin.new("./spec/support/gitolite-admin") }
|
5
|
+
subject { Rubolite::Client.new(admin) }
|
6
|
+
|
7
|
+
it "initializes with an admin object" do
|
8
|
+
expect { Rubolite::Client.new(admin) }.not_to raise_error
|
9
|
+
end
|
10
|
+
|
11
|
+
context "repos" do
|
12
|
+
it "represents repos from the parser" do
|
13
|
+
expect(subject.repos.map(&:name)).to include "gitolite-admin"
|
14
|
+
end
|
15
|
+
|
16
|
+
specify "#add_repo adds a repo" do
|
17
|
+
subject.add_repo Rubolite::Repo.new("awesome-repo")
|
18
|
+
subject.should have(3).repos
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "groups" do
|
23
|
+
specify "#add_group adds a group" do
|
24
|
+
subject.add_group "staff", ["robert", "bobby"]
|
25
|
+
subject.should have(1).groups
|
26
|
+
end
|
27
|
+
|
28
|
+
specify "#add_group adds a group with users" do
|
29
|
+
subject.add_group "staff", ["robert", "bobby"]
|
30
|
+
expect(subject.groups["staff"]).to eq %w(robert bobby)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "ssh keys" do
|
35
|
+
specify "#add_ssh_key adds an ssh key" do
|
36
|
+
subject.add_ssh_key "robert", Rubolite::SSHKey.new("ssh-rsa", "whatupfinger", "robert@local")
|
37
|
+
subject.should have(1).ssh_keys
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "saving" do
|
42
|
+
it "saves changes" do
|
43
|
+
admin.writer.should_receive(:write!)
|
44
|
+
subject.save!
|
45
|
+
end
|
46
|
+
|
47
|
+
it "saves ssh keys" do
|
48
|
+
ssh_key = Rubolite::SSHKey.new("ssh-rsa", "whatupfinger", "robert@local")
|
49
|
+
key_path = "#{admin.path}/keydir"
|
50
|
+
|
51
|
+
ssh_key.should_receive(:write_for).with("robert", key_path)
|
52
|
+
|
53
|
+
subject.add_ssh_key("robert", ssh_key)
|
54
|
+
subject.save_ssh_keys!
|
55
|
+
end
|
56
|
+
|
57
|
+
it "commits the changes to the repo" do
|
58
|
+
admin.git.should_receive(:commit_all)
|
59
|
+
subject.commit!
|
60
|
+
end
|
61
|
+
|
62
|
+
it "pushes changes" do
|
63
|
+
origin = admin.repo_origin
|
64
|
+
admin.git.should_receive(:push).with(origin)
|
65
|
+
subject.push!
|
66
|
+
end
|
67
|
+
|
68
|
+
it "saves, commits, and pushes" do
|
69
|
+
subject.should_receive(:save!)
|
70
|
+
subject.should_receive(:save_ssh_keys!)
|
71
|
+
subject.should_receive(:commit!)
|
72
|
+
subject.should_receive(:push!)
|
73
|
+
subject.save_and_push!
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rubolite::Parser do
|
4
|
+
subject { Rubolite::Parser.new("./spec/fixtures/gitolite-conf.conf") }
|
5
|
+
|
6
|
+
it "initializes with a conf file" do
|
7
|
+
conf_file = "./spec/fixtures/gitolite-conf.conf"
|
8
|
+
parser = Rubolite::Parser.new(conf_file)
|
9
|
+
expect(parser.conf_file).to eq(conf_file)
|
10
|
+
end
|
11
|
+
|
12
|
+
specify "#writer returns a writer object" do
|
13
|
+
expect(subject.writer).to be_kind_of Rubolite::Writer
|
14
|
+
end
|
15
|
+
|
16
|
+
context "parses" do
|
17
|
+
|
18
|
+
specify "repo lines" do
|
19
|
+
expect(subject.parse_repo_line("repo somerepo")).to eq("somerepo")
|
20
|
+
end
|
21
|
+
|
22
|
+
context "permissions" do
|
23
|
+
specify "read permissions" do
|
24
|
+
line = "R = robert"
|
25
|
+
expect(subject.parse_permissions_line(line)).to eq(["R", "robert"])
|
26
|
+
end
|
27
|
+
|
28
|
+
specify "write permissions" do
|
29
|
+
line = "W = robert"
|
30
|
+
expect(subject.parse_permissions_line(line)).to eq(["W", "robert"])
|
31
|
+
end
|
32
|
+
|
33
|
+
specify "read / write permissions" do
|
34
|
+
line = "RW = robert"
|
35
|
+
expect(subject.parse_permissions_line(line)).to eq(["RW", "robert"])
|
36
|
+
end
|
37
|
+
|
38
|
+
specify "read / write / force-push permissions" do
|
39
|
+
line = "RW+ = robert"
|
40
|
+
expect(subject.parse_permissions_line(line)).to eq(["RW+", "robert"])
|
41
|
+
end
|
42
|
+
|
43
|
+
specify "any push permissions" do
|
44
|
+
line = "- = robert"
|
45
|
+
expect(subject.parse_permissions_line(line)).to eq(["-", "robert"])
|
46
|
+
end
|
47
|
+
|
48
|
+
specify "space agnostic" do
|
49
|
+
line = "RW+ = robert"
|
50
|
+
expect(subject.parse_permissions_line(line)).to eq(["RW+", "robert"])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "parses repos" do
|
55
|
+
repo_names = subject.repos.map(&:name)
|
56
|
+
expect(repo_names).to include "gitolite-admin"
|
57
|
+
expect(repo_names).to include "gitolite-awesome"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "parses users" do
|
61
|
+
repo = subject.repos.select {|r| r.name == "gitolite-admin" }.first
|
62
|
+
expect(repo).to have(1).users
|
63
|
+
end
|
64
|
+
|
65
|
+
it "parses users with permissions" do
|
66
|
+
repo = subject.repos.select {|r| r.name == "gitolite-admin" }.first
|
67
|
+
user = repo.users.first
|
68
|
+
|
69
|
+
expect(user.permissions).to eq "RW+"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "parses multiple users" do
|
73
|
+
repo = subject.repos.select {|r| r.name == "gitolite-awesome" }.first
|
74
|
+
expect(repo).to have(3).users
|
75
|
+
end
|
76
|
+
|
77
|
+
context "groups" do
|
78
|
+
let(:group_line) { "@somegroup = robert bobby lauren" }
|
79
|
+
|
80
|
+
it "returns group name and users" do
|
81
|
+
expect(subject.parse_group_line(group_line)).to eq ["somegroup", %w(robert bobby lauren)]
|
82
|
+
end
|
83
|
+
|
84
|
+
it "parses groups" do
|
85
|
+
subject.should have(1).groups
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rubolite::Repo do
|
4
|
+
subject { Rubolite::Repo.new }
|
5
|
+
let(:admin) { Rubolite::Admin.new }
|
6
|
+
|
7
|
+
context "names" do
|
8
|
+
specify { expect(subject).to respond_to :name= }
|
9
|
+
specify { expect(subject).to respond_to :name }
|
10
|
+
|
11
|
+
it "initializes with a name" do
|
12
|
+
repo = Rubolite::Repo.new("newname")
|
13
|
+
expect(repo.name).to eq("newname")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "users" do
|
18
|
+
let(:user) { Rubolite::User.new "robert", "RW+" }
|
19
|
+
let(:repo) { Rubolite::Repo.new("newname") }
|
20
|
+
|
21
|
+
it "adds a user" do
|
22
|
+
repo.add_user(user)
|
23
|
+
expect(repo.users).to include user
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rubolite::SSHKey do
|
4
|
+
context "from a file" do
|
5
|
+
it "generates an ssh key from a file" do
|
6
|
+
ssh_key = Rubolite::SSHKey.from_file("./spec/fixtures/example.pub")
|
7
|
+
|
8
|
+
# Yes this should be 3 separate tests but it's ok, we'll live.
|
9
|
+
expect(ssh_key.type).to eq("ssh-rsa")
|
10
|
+
expect(ssh_key.key).to eq("AAAAB3NzaC1yc2EAAAADAQABAAABAQC/Zkiw2QoYtekwZUYULwQsrPJubWafiuewoP03DRn3xjwoNo0q7FE0nIw2ENODiaM8KD0+L+ax0UCdNcCiJYuzouHENBvXYxsWSk5sZicRWINJ91Jd6KZnMvCr06oObNnJKdE+7UxeC06512nBREW7xHc4urHSiBoejx8fJOUraI6Y0t+Y7l4EiugTUcZLdN3b4YNksQvv16GDnreS+0SkZKcU5zj8pIE3DRBvs8MeuK5N1oQQNkbLXLbTtBqTPfiQz7Ikj8YFaBBX8rXd66yu0sMjGImxWZjBNGPscvch/G5MGSabpRSZALWi+uN67CxJcj3vZPg6mJSxnpsXxOdZ")
|
11
|
+
expect(ssh_key.comment).to eq("robertross@paperwalls.local")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "from a string" do
|
16
|
+
it "generates an ssh key from a string" do
|
17
|
+
ssh_key = Rubolite::SSHKey.from_string("ssh-rsa somekeyfingerprint comment")
|
18
|
+
expect(ssh_key.type).to eq("ssh-rsa")
|
19
|
+
expect(ssh_key.key).to eq("somekeyfingerprint")
|
20
|
+
expect(ssh_key.comment).to eq("comment")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "saving", fake_fs: true do
|
25
|
+
subject { Rubolite::SSHKey.from_string("ssh-rsa awesomekeyprint robertross@local") }
|
26
|
+
|
27
|
+
before(:each) { FileUtils.mkdir_p("./spec/fixtures") }
|
28
|
+
|
29
|
+
it "saves a public key for a username to a path" do
|
30
|
+
subject.write_for "kermit", "./spec/fixtures"
|
31
|
+
expect(File.exists?("./spec/fixtures/kermit.pub")).to be_true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Rubolite::User do
|
4
|
+
subject { Rubolite::User.new }
|
5
|
+
|
6
|
+
context "names" do
|
7
|
+
specify { expect(subject).to respond_to :name= }
|
8
|
+
specify { expect(subject).to respond_to :name }
|
9
|
+
end
|
10
|
+
|
11
|
+
context "permissions" do
|
12
|
+
specify { expect(subject).to respond_to :permissions= }
|
13
|
+
specify { expect(subject).to respond_to :permissions }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "initializes with a name and permissions" do
|
17
|
+
user = Rubolite::User.new("robert", "RW+")
|
18
|
+
expect(user.name).to eq("robert")
|
19
|
+
expect(user.permissions).to eq("RW+")
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "tempfile"
|
3
|
+
|
4
|
+
describe Rubolite::Writer do
|
5
|
+
subject { Rubolite::Writer.new(writer_parser) }
|
6
|
+
let(:temp_file) { Tempfile.new("writespec") }
|
7
|
+
|
8
|
+
let(:writer_parser) { Rubolite::Parser.new("./spec/fixtures/gitolite-conf.conf") }
|
9
|
+
let(:parser) { Rubolite::Parser.new(temp_file.path) }
|
10
|
+
|
11
|
+
before(:each) { subject.write_path = temp_file.path }
|
12
|
+
|
13
|
+
it "sets write path to parser config path on initialize" do
|
14
|
+
writer = Rubolite::Writer.new(parser)
|
15
|
+
expect(writer.write_path).to eq parser.conf_file
|
16
|
+
end
|
17
|
+
|
18
|
+
it "accepts a write path" do
|
19
|
+
expect(subject).to respond_to :write_path
|
20
|
+
expect(subject).to respond_to :write_path=
|
21
|
+
end
|
22
|
+
|
23
|
+
context "groups" do
|
24
|
+
it "creates groups correctly" do
|
25
|
+
expect(subject.groups).to include "@staff = gitolite robert"
|
26
|
+
end
|
27
|
+
|
28
|
+
it "writes groups correctly" do
|
29
|
+
subject.write!
|
30
|
+
expect(parser).to have(1).groups
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "repos" do
|
35
|
+
it "creates repos correctly" do
|
36
|
+
expect(subject.repos).to include "repo gitolite-admin"
|
37
|
+
expect(subject.repos).to include "repo gitolite-awesome"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "writes repos correctly" do
|
41
|
+
subject.write!
|
42
|
+
expect(parser).to have(2).repos
|
43
|
+
end
|
44
|
+
|
45
|
+
context "users" do
|
46
|
+
let(:repo) { Rubolite::Repo.new("somerepo") }
|
47
|
+
before(:each) do
|
48
|
+
repo.add_user Rubolite::User.new "robert", "RW+"
|
49
|
+
end
|
50
|
+
|
51
|
+
it "adds users for a repo block correctly" do
|
52
|
+
expect(subject.repo_block(repo)).to include "RW+ = robert"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "writes users correctly" do
|
56
|
+
subject.write!
|
57
|
+
repo = parser.repos.select {|r| r.name == "gitolite-admin" }.first
|
58
|
+
user = repo.users.select {|u| u.name == "gitolite" }.first
|
59
|
+
|
60
|
+
expect(user.name).to eq("gitolite")
|
61
|
+
expect(user.permissions).to eq("RW+")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require "rubolite"
|
2
|
+
require "ap"
|
3
|
+
require "pry"
|
4
|
+
require 'fakefs/spec_helpers'
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
8
|
+
config.run_all_when_everything_filtered = true
|
9
|
+
config.filter_run :focus
|
10
|
+
|
11
|
+
config.include FakeFS::SpecHelpers, fake_fs: true
|
12
|
+
|
13
|
+
# Run specs in random order to surface order dependencies. If you find an
|
14
|
+
# order dependency and want to debug it, you can fix the order by providing
|
15
|
+
# the seed, which is printed after each run.
|
16
|
+
# --seed 1234
|
17
|
+
config.order = 'random'
|
18
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubolite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,104 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
13
|
-
dependencies:
|
12
|
+
date: 2012-11-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.11.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.11.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: guard-rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: awesome_print
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: pry
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: fakefs
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: git
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 1.2.5
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 1.2.5
|
14
110
|
description: Rubolite is a ruby interface to gitolite.
|
15
111
|
email:
|
16
112
|
- robert@creativequeries.com
|
@@ -19,13 +115,32 @@ extensions: []
|
|
19
115
|
extra_rdoc_files: []
|
20
116
|
files:
|
21
117
|
- .gitignore
|
118
|
+
- .rspec
|
22
119
|
- Gemfile
|
120
|
+
- Guardfile
|
23
121
|
- LICENSE.txt
|
24
122
|
- README.md
|
25
123
|
- Rakefile
|
26
124
|
- lib/rubolite.rb
|
125
|
+
- lib/rubolite/admin.rb
|
126
|
+
- lib/rubolite/client.rb
|
127
|
+
- lib/rubolite/parser.rb
|
128
|
+
- lib/rubolite/repo.rb
|
129
|
+
- lib/rubolite/ssh_key.rb
|
130
|
+
- lib/rubolite/user.rb
|
27
131
|
- lib/rubolite/version.rb
|
132
|
+
- lib/rubolite/writer.rb
|
28
133
|
- rubolite.gemspec
|
134
|
+
- spec/fixtures/example.pub
|
135
|
+
- spec/fixtures/gitolite-conf.conf
|
136
|
+
- spec/lib/rubolite/admin_spec.rb
|
137
|
+
- spec/lib/rubolite/client_spec.rb
|
138
|
+
- spec/lib/rubolite/parser_spec.rb
|
139
|
+
- spec/lib/rubolite/repo_spec.rb
|
140
|
+
- spec/lib/rubolite/ssh_key_spec.rb
|
141
|
+
- spec/lib/rubolite/user_spec.rb
|
142
|
+
- spec/lib/rubolite/writer_spec.rb
|
143
|
+
- spec/spec_helper.rb
|
29
144
|
homepage: http://github.com/bobbytables/rubolite
|
30
145
|
licenses: []
|
31
146
|
post_install_message:
|
@@ -50,4 +165,14 @@ rubygems_version: 1.8.23
|
|
50
165
|
signing_key:
|
51
166
|
specification_version: 3
|
52
167
|
summary: This gem allows you to administer your gitolite instance
|
53
|
-
test_files:
|
168
|
+
test_files:
|
169
|
+
- spec/fixtures/example.pub
|
170
|
+
- spec/fixtures/gitolite-conf.conf
|
171
|
+
- spec/lib/rubolite/admin_spec.rb
|
172
|
+
- spec/lib/rubolite/client_spec.rb
|
173
|
+
- spec/lib/rubolite/parser_spec.rb
|
174
|
+
- spec/lib/rubolite/repo_spec.rb
|
175
|
+
- spec/lib/rubolite/ssh_key_spec.rb
|
176
|
+
- spec/lib/rubolite/user_spec.rb
|
177
|
+
- spec/lib/rubolite/writer_spec.rb
|
178
|
+
- spec/spec_helper.rb
|