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