hubbard 0.0.16 → 0.0.18
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/VERSION +1 -1
- data/bin/hub-daemon +11 -0
- data/bin/hubbard +101 -59
- data/commands/add-key.rb +2 -4
- data/commands/add-permission.rb +2 -13
- data/commands/create-project.rb +5 -17
- data/commands/create-repository.rb +2 -2
- data/commands/fork-repository.rb +2 -3
- data/commands/list-forks.rb +4 -1
- data/commands/list-keys.rb +1 -1
- data/commands/list-permissions.rb +7 -20
- data/commands/list-projects.rb +3 -1
- data/commands/list-repositories.rb +1 -1
- data/commands/list-users.rb +4 -3
- data/commands/move-repository.rb +2 -4
- data/commands/remove-key.rb +3 -6
- data/commands/remove-permission.rb +3 -12
- data/commands/rename-project.rb +1 -2
- data/commands/set-description.rb +4 -4
- data/commands/set-visibility.rb +2 -4
- data/hubbard.gemspec +8 -6
- data/lib/project.rb +71 -0
- data/spec/hubbard_spec.rb +36 -29
- data/spec/spec_helper.rb +6 -0
- data/spec/yaml_spec.rb +5 -5
- metadata +23 -10
data/.gitignore
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.18
|
data/bin/hub-daemon
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
|
4
|
+
require 'hubbard'
|
5
|
+
|
6
|
+
puts "git daemon --base-path #{Hubbard::PROJECTS_PATH} #{Hubbard::PROJECTS_PATH}"
|
7
|
+
|
8
|
+
exec "git daemon --base-path=#{Hubbard::PROJECTS_PATH} #{Hubbard::PROJECTS_PATH}"
|
9
|
+
|
10
|
+
|
11
|
+
|
data/bin/hubbard
CHANGED
@@ -2,17 +2,19 @@
|
|
2
2
|
require 'fileutils'
|
3
3
|
require 'optparse'
|
4
4
|
require 'yaml'
|
5
|
+
require 'shellwords'
|
5
6
|
|
6
7
|
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
|
7
8
|
require 'hubbard'
|
9
|
+
require 'project'
|
8
10
|
|
9
11
|
FileUtils.mkdir_p(Hubbard::PROJECTS_PATH)
|
10
12
|
FileUtils.mkdir_p(Hubbard::ACCOUNTS_PATH)
|
11
13
|
|
12
14
|
formats = [:text, :yaml]
|
13
|
-
|
14
|
-
|
15
|
-
|
15
|
+
DEFAULTS = { :format => formats.first }
|
16
|
+
OPTIONS = {}
|
17
|
+
OPTS = OptionParser.new do |opts|
|
16
18
|
opts.banner = <<BANNER
|
17
19
|
Usage: hubbard [options] <command>
|
18
20
|
|
@@ -37,88 +39,69 @@ Options:
|
|
37
39
|
BANNER
|
38
40
|
|
39
41
|
opts.on("--private", "Create project with visibility set to private") do |o|
|
40
|
-
|
42
|
+
OPTIONS[:private] = o
|
41
43
|
end
|
42
44
|
opts.on("-f", "--format [FORMAT]", formats,
|
43
45
|
"Output format (#{formats.join(', ')})") do |o|
|
44
|
-
|
46
|
+
OPTIONS[:format] = o
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
50
|
+
class HubbardException < Exception
|
51
|
+
attr_reader :exitstatus
|
52
|
+
def initialize(exitstatus)
|
53
|
+
@exitstatus = exitstatus
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def error(exitstatus,message)
|
58
|
+
raise HubbardException.new(exitstatus), message
|
59
|
+
end
|
60
|
+
|
48
61
|
def next_arg(msg)
|
49
62
|
if ARGV.length < 1
|
50
|
-
|
51
|
-
exit 1
|
63
|
+
error 1, msg
|
52
64
|
end
|
53
65
|
ARGV.shift
|
54
66
|
end
|
55
67
|
|
68
|
+
def rest_args(msg)
|
69
|
+
if ARGV.length < 1
|
70
|
+
error 1, msg
|
71
|
+
end
|
72
|
+
ARGV
|
73
|
+
end
|
74
|
+
|
56
75
|
def check_status(msg)
|
57
76
|
if $!.exitstatus != 0
|
58
|
-
|
59
|
-
exit 1
|
77
|
+
error $!.exitstatus, msg
|
60
78
|
end
|
61
79
|
end
|
62
80
|
|
63
81
|
def validate_project_name(name)
|
64
82
|
if name !~ /#{Hubbard::PROJECT_REGEX}/
|
65
|
-
|
66
|
-
exit 1
|
83
|
+
error 1, "Project names can only contain letter, numbers, and hyphens"
|
67
84
|
end
|
68
85
|
end
|
69
86
|
|
70
87
|
def validate_repository_name(name)
|
71
88
|
if name !~ /#{Hubbard::REPOSITORY_REGEX}/
|
72
|
-
|
73
|
-
exit 1
|
89
|
+
error 1, "Repository names can only contain letter, numbers, and hyphens"
|
74
90
|
end
|
75
91
|
end
|
76
92
|
|
77
93
|
def validate_user_name(name)
|
78
94
|
if name !~ /#{Hubbard::USERNAME_REGEX}/
|
79
|
-
|
80
|
-
exit 1
|
95
|
+
error 1, "User names can only contain letter, numbers, and hyphens"
|
81
96
|
end
|
82
97
|
end
|
83
98
|
|
84
99
|
def validate_action_name(action)
|
85
100
|
unless Hubbard::ACTIONS.member?(action)
|
86
|
-
|
87
|
-
exit 1
|
101
|
+
error 1, "Not a valid action (must be one of: read, write, admin)"
|
88
102
|
end
|
89
103
|
end
|
90
104
|
|
91
|
-
username = next_arg "Please specify the username to run as"
|
92
|
-
|
93
|
-
if ENV['SSH_ORIGINAL_COMMAND']
|
94
|
-
ARGV.clear
|
95
|
-
ENV['SSH_ORIGINAL_COMMAND'].split.each do |arg|
|
96
|
-
ARGV << arg
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
opts.parse!
|
101
|
-
OPTIONS = defaults.merge(options)
|
102
|
-
OPTIONS.freeze
|
103
|
-
|
104
|
-
if ARGV.empty? || ARGV[0] == 'help'
|
105
|
-
puts opts
|
106
|
-
exit 0
|
107
|
-
end
|
108
|
-
|
109
|
-
command = next_arg "Please specify a command to run"
|
110
|
-
|
111
|
-
if command == "run-as"
|
112
|
-
if username != "admin"
|
113
|
-
$stderr.puts "You don't have permission to do that"
|
114
|
-
exit 1
|
115
|
-
end
|
116
|
-
username = next_arg "Please specify the username to run as"
|
117
|
-
command = next_arg "Please specify a command to run"
|
118
|
-
end
|
119
|
-
|
120
|
-
@username = username
|
121
|
-
|
122
105
|
def implies(a1, a2)
|
123
106
|
case a1
|
124
107
|
when 'admin'
|
@@ -134,8 +117,7 @@ end
|
|
134
117
|
|
135
118
|
def authorize(project_name, action)
|
136
119
|
unless is_authorized(project_name, action)
|
137
|
-
|
138
|
-
exit 3
|
120
|
+
error 3, "You don't have permission to do that"
|
139
121
|
end
|
140
122
|
end
|
141
123
|
|
@@ -204,16 +186,76 @@ def sync_keys
|
|
204
186
|
end
|
205
187
|
end
|
206
188
|
|
207
|
-
|
189
|
+
USERNAME = next_arg "Please specify the username to run as"
|
208
190
|
|
209
|
-
if
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
191
|
+
if ENV['SSH_ORIGINAL_COMMAND']
|
192
|
+
ARGV.clear
|
193
|
+
ENV['SSH_ORIGINAL_COMMAND'].split.each do |arg|
|
194
|
+
ARGV << arg
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def run_command
|
199
|
+
OPTS.parse!
|
200
|
+
@options = DEFAULTS.merge(OPTIONS)
|
201
|
+
@options.freeze
|
202
|
+
|
203
|
+
command = next_arg "Please specify a command to run"
|
204
|
+
|
205
|
+
if command == 'help'
|
206
|
+
puts OPTS
|
207
|
+
puts
|
208
|
+
return 0
|
215
209
|
end
|
210
|
+
|
211
|
+
@username = USERNAME
|
212
|
+
|
213
|
+
if command == "run-as"
|
214
|
+
if USERNAME != "admin"
|
215
|
+
$stderr.puts "You don't have permission to do that"
|
216
|
+
return 1
|
217
|
+
end
|
218
|
+
@username = next_arg "Please specify the username to run as"
|
219
|
+
command = next_arg "Please specify a command to run"
|
220
|
+
end
|
221
|
+
|
222
|
+
command_file = File.expand_path(File.join(File.dirname(__FILE__), "..", "commands", "#{command}.rb"))
|
223
|
+
|
224
|
+
if File.exist?(command_file)
|
225
|
+
begin
|
226
|
+
load command_file
|
227
|
+
rescue SystemCallError => e
|
228
|
+
$stderr.puts "SystemCallError [#{e.errno}]: #{e.message}"
|
229
|
+
return e.errno
|
230
|
+
end
|
231
|
+
else
|
232
|
+
$stderr.puts "Unknown command: #{command}"
|
233
|
+
return 1
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
if ARGV.empty?
|
238
|
+
while true
|
239
|
+
print "hubbard> "
|
240
|
+
line = readline.strip
|
241
|
+
if line == "exit"
|
242
|
+
exit 0
|
243
|
+
else
|
244
|
+
ARGV.clear
|
245
|
+
Shellwords.shellwords(line).each { |arg| ARGV << arg }
|
246
|
+
next if ARGV.empty?
|
247
|
+
begin
|
248
|
+
run_command
|
249
|
+
rescue HubbardException => e
|
250
|
+
$stderr.puts e.message
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
216
254
|
else
|
217
|
-
|
218
|
-
|
255
|
+
begin
|
256
|
+
exit(run_command)
|
257
|
+
rescue HubbardException => e
|
258
|
+
$stderr.puts e.message
|
259
|
+
exit e.exitstatus
|
260
|
+
end
|
219
261
|
end
|
data/commands/add-key.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
name = next_arg("Please specify the key name")
|
2
2
|
if name !~ Hubbard::KEY_NAME_REGEX
|
3
|
-
|
4
|
-
exit 1
|
3
|
+
error 1, "Not a valid key name (letters and numbers only)"
|
5
4
|
end
|
6
5
|
|
7
6
|
key = $stdin.read.strip
|
8
7
|
if key !~ Hubbard::KEY_REGEX
|
9
|
-
|
10
|
-
exit 1
|
8
|
+
error 1, "Not a valid key"
|
11
9
|
end
|
12
10
|
|
13
11
|
type = $1
|
data/commands/add-permission.rb
CHANGED
@@ -5,16 +5,5 @@ username = ARGV.shift
|
|
5
5
|
action = ARGV.shift
|
6
6
|
validate_action_name(action)
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
begin
|
11
|
-
filename = File.join(dir, ".permissions")
|
12
|
-
permissions = File.read(filename).split("\n").map { |line| line.strip }.select { |line| line.split('=')[0] != username }
|
13
|
-
permissions << "#{username}=#{action}"
|
14
|
-
File.open(filename, "w") do |file|
|
15
|
-
permissions.each { |permission| file << permission << "\n" }
|
16
|
-
end
|
17
|
-
ensure
|
18
|
-
lock.flock(File::LOCK_UN)
|
19
|
-
end
|
20
|
-
end
|
8
|
+
project = Project.new(project_name)
|
9
|
+
project.lock { project.add_permission(username,action) }
|
data/commands/create-project.rb
CHANGED
@@ -1,18 +1,6 @@
|
|
1
|
-
require 'fileutils'
|
2
|
-
|
3
1
|
project_name = read_project_name
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
10
|
-
unless Dir.mkdir(dir)
|
11
|
-
$stderr.puts "Unable to create directory: #{dir}"
|
12
|
-
end
|
13
|
-
visibility = OPTIONS[:private] ? "private" : "public"
|
14
|
-
if @username != 'admin'
|
15
|
-
File.open(File.join(dir, ".permissions"), "w") { |f| f << "#{@username}=admin\n" }
|
16
|
-
end
|
17
|
-
File.open(File.join(dir, ".visibility"), "w") { |f| f << "#{visibility}\n" }
|
18
|
-
File.open(File.join(dir, ".description"), "w") { |f| f << "#{description}\n" }
|
2
|
+
|
3
|
+
project = Project.new(project_name)
|
4
|
+
project.create
|
5
|
+
project.add_permission(@username,'admin')
|
6
|
+
project.visibility=@options[:private] ? "private" : "public"
|
@@ -4,6 +4,6 @@ authorize(project_name, 'admin')
|
|
4
4
|
dir = find_repository_dir(project_name, repository_name)
|
5
5
|
FileUtils.mkdir_p(dir)
|
6
6
|
Dir.chdir(dir) do
|
7
|
-
|
8
|
-
|
7
|
+
error $?, "Unable to create repository" unless system "git --bare init --shared"
|
8
|
+
error $?, "Unable to create repository" unless system "git config hubbard.forkid #{project_name}/#{repository_name}/#{Time.now.to_i}"
|
9
9
|
end
|
data/commands/fork-repository.rb
CHANGED
@@ -7,9 +7,8 @@ authorize(to_project_name, 'admin')
|
|
7
7
|
from_dir = find_repository_dir(from_project_name, from_repository_name)
|
8
8
|
to_dir = find_repository_dir(to_project_name, to_repository_name)
|
9
9
|
forkid = Dir.chdir(from_dir) { `git config --get hubbard.forkid` }
|
10
|
-
|
11
|
-
exit $? unless system "git clone --bare --shared #{from_dir} #{to_dir}"
|
10
|
+
error $?, "Unable to create repository" unless system "git clone --bare --shared #{from_dir} #{to_dir}"
|
12
11
|
Dir.chdir(to_dir) do
|
13
|
-
|
12
|
+
error $?, "Unable to create repository" unless system "git config hubbard.forkid #{forkid}"
|
14
13
|
end
|
15
14
|
|
data/commands/list-forks.rb
CHANGED
@@ -3,6 +3,7 @@ repository_name = read_repository_name
|
|
3
3
|
authorize(project_name, 'read')
|
4
4
|
forkid = Dir.chdir(find_repository_dir(project_name, repository_name)) { `git config --get hubbard.forkid` }
|
5
5
|
project_dir = find_project_dir(project_name)
|
6
|
+
forks = []
|
6
7
|
Dir.foreach(File.join(Hubbard::PROJECTS_PATH)) do |dir|
|
7
8
|
next if dir == "." || dir == ".."
|
8
9
|
next unless is_authorized(dir, 'read')
|
@@ -11,8 +12,10 @@ Dir.foreach(File.join(Hubbard::PROJECTS_PATH)) do |dir|
|
|
11
12
|
repository_name = repository_dir.chomp('.git')
|
12
13
|
Dir.chdir(find_repository_dir(project_name, repository_name)) do
|
13
14
|
if forkid == `git config --get hubbard.forkid`
|
14
|
-
|
15
|
+
forks << "#{project_name}/#{repository_name}"
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
18
19
|
end
|
20
|
+
|
21
|
+
puts forks.sort
|
data/commands/list-keys.rb
CHANGED
@@ -1,26 +1,13 @@
|
|
1
1
|
project_name = read_project_name
|
2
2
|
authorize(project_name, 'admin')
|
3
|
-
|
4
|
-
username = ARGV.shift
|
3
|
+
project = Project.new(project_name)
|
5
4
|
|
6
|
-
|
7
|
-
permissions_file = File.join(dir, ".permissions")
|
8
|
-
if File.exists?(permissions_file)
|
9
|
-
File.open(permissions_file, "r+") do |f|
|
10
|
-
f.flock(File::LOCK_EX)
|
11
|
-
contents = f.read
|
12
|
-
f.flock(File::LOCK_UN)
|
13
|
-
end
|
14
|
-
end
|
5
|
+
permissions = project.lock { project.permissions }
|
15
6
|
|
16
|
-
if
|
17
|
-
permissions = []
|
18
|
-
contents.split("\n").map do |l|
|
19
|
-
l.strip!
|
20
|
-
p = l.split('=')
|
21
|
-
permissions << { :user => p.first, :access => p.last }
|
22
|
-
end
|
7
|
+
if @options[:format] == :yaml
|
23
8
|
puts YAML::dump(permissions)
|
24
|
-
elsif
|
25
|
-
|
9
|
+
elsif @options[:format] == :text
|
10
|
+
permissions.each do |permission|
|
11
|
+
puts "#{permission[:user]}=#{permission[:access]}"
|
12
|
+
end
|
26
13
|
end
|
data/commands/list-projects.rb
CHANGED
@@ -7,7 +7,7 @@ Dir.foreach(find_project_dir(project_name)) do |repository_dir|
|
|
7
7
|
repositories << { :name => repository_dir.chomp('.git'), :url => git_url }
|
8
8
|
end
|
9
9
|
|
10
|
-
if
|
10
|
+
if @options[:format] == :yaml
|
11
11
|
puts YAML::dump(repositories)
|
12
12
|
else
|
13
13
|
repositories.each { |r| puts "#{r[:name]}\t#{r[:url]}" }
|
data/commands/list-users.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
if @username != 'admin'
|
2
|
-
|
3
|
-
exit 3
|
2
|
+
error 3, "You don't have permission to do that"
|
4
3
|
end
|
5
4
|
|
6
5
|
accounts = []
|
@@ -9,7 +8,9 @@ Dir.entries(Hubbard::ACCOUNTS_PATH).each do |account|
|
|
9
8
|
accounts << account
|
10
9
|
end
|
11
10
|
|
12
|
-
|
11
|
+
accounts.sort!
|
12
|
+
|
13
|
+
if @options[:format] == :yaml
|
13
14
|
puts YAML::dump(accounts)
|
14
15
|
else
|
15
16
|
accounts.each { |a| puts a }
|
data/commands/move-repository.rb
CHANGED
@@ -11,13 +11,11 @@ authorize(from_project_name, 'admin')
|
|
11
11
|
authorize(to_project_name, 'admin')
|
12
12
|
|
13
13
|
if not File.exist?(from_dir)
|
14
|
-
|
15
|
-
exit 4
|
14
|
+
error 4, "Repository not found"
|
16
15
|
end
|
17
16
|
|
18
17
|
if File.exist?(to_dir)
|
19
|
-
|
20
|
-
exit 4
|
18
|
+
error 4, "Repository already exists with that name"
|
21
19
|
end
|
22
20
|
|
23
21
|
FileUtils.mv(from_dir, to_dir)
|
data/commands/remove-key.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
name = next_arg("Please specify the key name")
|
2
2
|
if name !~ Hubbard::KEY_NAME_REGEX
|
3
|
-
|
4
|
-
exit 1
|
3
|
+
error 1, "Not a valid key name (letters and numbers only)"
|
5
4
|
end
|
6
5
|
|
7
6
|
dirname = File.join(find_account_dir(@username), "keys")
|
@@ -9,13 +8,11 @@ FileUtils.mkdir_p(dirname)
|
|
9
8
|
|
10
9
|
filename = File.join(dirname, name)
|
11
10
|
if !File.exist?(filename)
|
12
|
-
|
13
|
-
exit 1
|
11
|
+
error 1, "Key not found"
|
14
12
|
end
|
15
13
|
|
16
14
|
unless FileUtils.rm(filename)
|
17
|
-
|
18
|
-
exit 1
|
15
|
+
error 1, "Unable to delete key"
|
19
16
|
end
|
20
17
|
|
21
18
|
sync_keys
|
@@ -2,15 +2,6 @@ project_name = read_project_name
|
|
2
2
|
authorize(project_name, 'admin')
|
3
3
|
dir = find_project_dir(project_name)
|
4
4
|
username = ARGV.shift
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
filename = File.join(dir, ".permissions")
|
9
|
-
permissions = File.read(filename).split("\n").map { |line| line.strip }.select { |line| line.split('=')[0] != username }
|
10
|
-
File.open(filename, "w") do |file|
|
11
|
-
permissions.each { |permission| file << permission << "\n" }
|
12
|
-
end
|
13
|
-
ensure
|
14
|
-
lock.flock(File::LOCK_UN)
|
15
|
-
end
|
16
|
-
end
|
5
|
+
|
6
|
+
project = Project.new(project_name)
|
7
|
+
project.lock { project.remove_permission(username) }
|
data/commands/rename-project.rb
CHANGED
@@ -3,8 +3,7 @@ to_project_name = next_arg "Please specify the new project name"
|
|
3
3
|
from_dir = find_project_dir(from_project_name)
|
4
4
|
to_dir = find_project_dir(to_project_name)
|
5
5
|
if File.exist?(to_dir)
|
6
|
-
|
7
|
-
exit 3
|
6
|
+
error 3, "A project already exists with that name"
|
8
7
|
end
|
9
8
|
|
10
9
|
authorize(from_project_name, 'admin')
|
data/commands/set-description.rb
CHANGED
@@ -3,13 +3,13 @@ require 'fileutils'
|
|
3
3
|
project_name = read_project_name
|
4
4
|
authorize(project_name, 'admin')
|
5
5
|
|
6
|
-
description =
|
6
|
+
description = rest_args "Please specify the description"
|
7
|
+
desc = description.join(' ')
|
7
8
|
|
8
9
|
dir = find_project_dir(project_name)
|
9
10
|
if !File.exist?(dir)
|
10
|
-
|
11
|
-
exit 4
|
11
|
+
error 4, "Project not found"
|
12
12
|
end
|
13
13
|
|
14
|
-
File.open(File.join(dir, ".description"), "w") { |f| f <<
|
14
|
+
File.open(File.join(dir, ".description"), "w") { |f| f << desc << "\n" }
|
15
15
|
|
data/commands/set-visibility.rb
CHANGED
@@ -3,14 +3,12 @@ require 'fileutils'
|
|
3
3
|
project_name = read_project_name
|
4
4
|
visibility = next_arg "Please specify one of: public, private"
|
5
5
|
if visibility != 'public' and visibility != 'private'
|
6
|
-
|
7
|
-
exit 3
|
6
|
+
error 3, "Please specify one of: public, private"
|
8
7
|
end
|
9
8
|
|
10
9
|
dir = find_project_dir(project_name)
|
11
10
|
if !File.exist?(dir)
|
12
|
-
|
13
|
-
exit 4
|
11
|
+
error 4, "Project not found"
|
14
12
|
end
|
15
13
|
|
16
14
|
File.open(File.join(dir, ".visibility"), "w") { |f| f << visibility << "\n" }
|
data/hubbard.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{hubbard}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.18"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Matthew Foemmel"]
|
12
|
-
s.date = %q{2010-03-
|
12
|
+
s.date = %q{2010-03-25}
|
13
13
|
s.default_executable = %q{hubbard}
|
14
14
|
s.description = %q{Hubbard is a command line tool for managing git repositories.}
|
15
15
|
s.email = %q{git@foemmel.com}
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
"README.md",
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
|
+
"bin/hub-daemon",
|
28
29
|
"bin/hubbard",
|
29
30
|
"commands/add-key.rb",
|
30
31
|
"commands/add-permission.rb",
|
@@ -49,6 +50,7 @@ Gem::Specification.new do |s|
|
|
49
50
|
"commands/whoami.rb",
|
50
51
|
"hubbard.gemspec",
|
51
52
|
"lib/hubbard.rb",
|
53
|
+
"lib/project.rb",
|
52
54
|
"spec/gitssh",
|
53
55
|
"spec/hubbard_spec.rb",
|
54
56
|
"spec/spec.opts",
|
@@ -58,12 +60,12 @@ Gem::Specification.new do |s|
|
|
58
60
|
s.homepage = %q{http://github.com/mfoemmel/hubbard}
|
59
61
|
s.rdoc_options = ["--charset=UTF-8"]
|
60
62
|
s.require_paths = ["lib"]
|
61
|
-
s.rubygems_version = %q{1.3.
|
63
|
+
s.rubygems_version = %q{1.3.6}
|
62
64
|
s.summary = %q{Hubbard is a command line tool for managing git repositories.}
|
63
65
|
s.test_files = [
|
64
|
-
"spec/
|
65
|
-
"spec/
|
66
|
-
"spec/
|
66
|
+
"spec/hubbard_spec.rb",
|
67
|
+
"spec/spec_helper.rb",
|
68
|
+
"spec/yaml_spec.rb"
|
67
69
|
]
|
68
70
|
|
69
71
|
if s.respond_to? :specification_version then
|
data/lib/project.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
class Project
|
2
|
+
attr_reader :project_name
|
3
|
+
|
4
|
+
def initialize(project_name)
|
5
|
+
@project_name = project_name
|
6
|
+
@dir = find_project_dir project_name
|
7
|
+
end
|
8
|
+
|
9
|
+
def create
|
10
|
+
if File.exist?(@dir)
|
11
|
+
error 4, "Project already exists with that name"
|
12
|
+
end
|
13
|
+
|
14
|
+
unless Dir.mkdir(@dir)
|
15
|
+
error 1, "Unable to create directory: #{dir}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def lock
|
20
|
+
File.open(File.join(@dir, ".lock"), "w+") do |lock|
|
21
|
+
lock.flock(File::LOCK_EX)
|
22
|
+
begin
|
23
|
+
yield
|
24
|
+
ensure
|
25
|
+
lock.flock(File::LOCK_UN)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def visibility=(visibility)
|
31
|
+
File.open(File.join(@dir, ".visibility"), "w") { |f| f << "#{visibility}\n" }
|
32
|
+
end
|
33
|
+
|
34
|
+
def description=(description)
|
35
|
+
File.open(File.join(@dir, ".description"), "w") { |f| f << "#{description}\n" }
|
36
|
+
end
|
37
|
+
|
38
|
+
def permissions
|
39
|
+
if File.exists?(permissions_file)
|
40
|
+
File.read(permissions_file).split("\n").map do |line|
|
41
|
+
permission = line.strip.split('=')
|
42
|
+
{ :user => permission.first, :access => permission.last }
|
43
|
+
end
|
44
|
+
else
|
45
|
+
[]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_permission(username,action)
|
50
|
+
new_permissions = permissions.select { |permission| permission[:user] != username }
|
51
|
+
if username != 'admin'
|
52
|
+
new_permissions << { :user => username, :access => action }
|
53
|
+
end
|
54
|
+
File.open(permissions_file, "w") do |file|
|
55
|
+
new_permissions.each { |permission| file << permission[:user] << '=' << permission[:access] << "\n" }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def remove_permission(username)
|
60
|
+
new_permissions = permissions.select { |permission| permission[:user] != username }
|
61
|
+
File.open(permissions_file, "w") do |file|
|
62
|
+
new_permissions.each { |permission| file << permission[:user] << '=' << permission[:access] << "\n" }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def permissions_file
|
69
|
+
File.join(@dir, ".permissions")
|
70
|
+
end
|
71
|
+
end
|
data/spec/hubbard_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
|
-
describe "
|
4
|
+
describe "Hubbard" do
|
5
5
|
before(:each) do
|
6
6
|
reset_file_system
|
7
7
|
end
|
@@ -14,40 +14,44 @@ describe "Hubble" do
|
|
14
14
|
pending "Not sure how to make sure that hubbard is passing back the proper exit codes from SystemCallErrors. Doing so would introduce complexity or add something that shouldn't be callable."
|
15
15
|
end
|
16
16
|
|
17
|
-
it "should create project" do
|
18
|
-
hub("kipper", "create-project foo
|
17
|
+
it "should create project and set project description" do
|
18
|
+
hub("kipper", "create-project foo")
|
19
|
+
hub("kipper", "set-description foo foo-desc")
|
19
20
|
projects = list_projects('kipper')
|
20
21
|
projects.should == ["foo"]
|
21
22
|
end
|
22
23
|
|
23
24
|
it "should set project description" do
|
24
|
-
hub("kipper", "create-project foo
|
25
|
-
hub("kipper", "set-description foo
|
25
|
+
hub("kipper", "create-project foo")
|
26
|
+
hub("kipper", "set-description foo 'Test description contains a space.'")
|
26
27
|
project = hub("kipper", "list-projects").split("\n")[0].split
|
27
|
-
project
|
28
|
+
project_name = project.shift # throw away unused arg.
|
29
|
+
visibility = project.shift # throw away unused arg.
|
30
|
+
description = project.join(' ')
|
31
|
+
description.should == "Test description contains a space."
|
28
32
|
end
|
29
33
|
|
30
34
|
it "should set project visibility" do
|
31
|
-
|
35
|
+
create_project("kipper", "foo", "foo-desc")
|
32
36
|
hub("kipper", "set-visibility foo private")
|
33
37
|
project = hub("kipper", "list-projects").split("\n")[0].split
|
34
38
|
project[1].should == "private"
|
35
39
|
end
|
36
40
|
|
37
41
|
it "should rename project" do
|
38
|
-
|
42
|
+
create_project("kipper", "foo", "foo-desc")
|
39
43
|
hub("kipper", "rename-project foo bar")
|
40
44
|
project = hub("kipper", "list-projects").split("\n")[0].split
|
41
45
|
project[0].should == "bar"
|
42
46
|
end
|
43
47
|
|
44
48
|
it "should not allow multiple projects with same name" do
|
45
|
-
|
49
|
+
create_project("kipper", "foo", "foo-desc")
|
46
50
|
lambda { hub("kipper", "create-project foo") }.should raise_error
|
47
51
|
end
|
48
52
|
|
49
53
|
it "should delete project" do
|
50
|
-
|
54
|
+
create_project("kipper", "foo", "foo-desc")
|
51
55
|
hub("kipper", "delete-project foo")
|
52
56
|
|
53
57
|
projects = hub("kipper", "list-projects").split("\n")
|
@@ -55,7 +59,7 @@ describe "Hubble" do
|
|
55
59
|
end
|
56
60
|
|
57
61
|
it "should default to public project" do
|
58
|
-
|
62
|
+
create_project("kipper", "foo", "foo-desc")
|
59
63
|
|
60
64
|
# Other users can see...
|
61
65
|
projects = list_projects("tiger")
|
@@ -66,7 +70,8 @@ describe "Hubble" do
|
|
66
70
|
end
|
67
71
|
|
68
72
|
it "should support private project" do
|
69
|
-
hub("kipper", "create-project foo
|
73
|
+
hub("kipper", "create-project foo --private")
|
74
|
+
hub("kipper", "set-description foo new-desc")
|
70
75
|
|
71
76
|
# Other users can't see
|
72
77
|
projects = hub("tiger", "list-projects").split("\n")
|
@@ -74,7 +79,7 @@ describe "Hubble" do
|
|
74
79
|
end
|
75
80
|
|
76
81
|
it "should create repositories" do
|
77
|
-
|
82
|
+
create_project("kipper", "foo", "foo-desc")
|
78
83
|
hub("kipper", "create-repository foo bar")
|
79
84
|
|
80
85
|
repositories = hub("kipper", "list-repositories foo").split("\n")
|
@@ -86,7 +91,7 @@ describe "Hubble" do
|
|
86
91
|
|
87
92
|
describe "when admin creates a project" do
|
88
93
|
before(:each) do
|
89
|
-
|
94
|
+
create_project("admin", "foo", "foo-desc")
|
90
95
|
end
|
91
96
|
|
92
97
|
it "should not raise error on missing permissions file for non-admin listing permissions" do
|
@@ -111,7 +116,7 @@ describe "Hubble" do
|
|
111
116
|
end
|
112
117
|
|
113
118
|
it "should allow git push" do
|
114
|
-
|
119
|
+
create_project("kipper", "foo", "foo-desc")
|
115
120
|
hub("kipper", "create-repository foo bar")
|
116
121
|
|
117
122
|
with_test_project do
|
@@ -120,8 +125,8 @@ describe "Hubble" do
|
|
120
125
|
end
|
121
126
|
|
122
127
|
it "should move repository" do
|
123
|
-
|
124
|
-
|
128
|
+
create_project("kipper", "foo", "foo-desc")
|
129
|
+
create_project("kipper", "new-foo", "foo-desc")
|
125
130
|
hub("kipper", "create-repository foo bar")
|
126
131
|
|
127
132
|
with_test_project do
|
@@ -132,7 +137,7 @@ describe "Hubble" do
|
|
132
137
|
end
|
133
138
|
|
134
139
|
it "should allow git push with write permissions" do
|
135
|
-
|
140
|
+
create_project("kipper", "foo", "foo-desc")
|
136
141
|
hub("kipper", "add-permission foo tiger write")
|
137
142
|
hub("kipper", "create-repository foo bar")
|
138
143
|
|
@@ -142,7 +147,7 @@ describe "Hubble" do
|
|
142
147
|
end
|
143
148
|
|
144
149
|
it "should not allow git push with read permissions" do
|
145
|
-
|
150
|
+
create_project("kipper", "foo", "foo-desc")
|
146
151
|
hub("kipper", "add-permission foo tiger read")
|
147
152
|
hub("kipper", "create-repository foo bar")
|
148
153
|
|
@@ -152,7 +157,7 @@ describe "Hubble" do
|
|
152
157
|
end
|
153
158
|
|
154
159
|
it "should allow git pull" do
|
155
|
-
|
160
|
+
create_project("kipper", "foo", "foo-desc")
|
156
161
|
hub("kipper", "create-repository foo bar")
|
157
162
|
|
158
163
|
with_test_project do
|
@@ -162,7 +167,8 @@ describe "Hubble" do
|
|
162
167
|
end
|
163
168
|
|
164
169
|
it "should not allow git pull with no permissions" do
|
165
|
-
hub("kipper", "create-project foo
|
170
|
+
hub("kipper", "create-project foo --private")
|
171
|
+
hub("kipper", "set-description foo foo-desc")
|
166
172
|
hub("kipper", "create-repository foo bar")
|
167
173
|
|
168
174
|
with_test_project do
|
@@ -182,7 +188,7 @@ describe "Hubble" do
|
|
182
188
|
end
|
183
189
|
|
184
190
|
it "should fork repository in same project" do
|
185
|
-
|
191
|
+
create_project("kipper", "foo", "foo-desc")
|
186
192
|
hub("kipper", "create-repository foo bar")
|
187
193
|
|
188
194
|
with_test_project do
|
@@ -193,8 +199,8 @@ describe "Hubble" do
|
|
193
199
|
end
|
194
200
|
|
195
201
|
it "should fork repository in different project" do
|
196
|
-
|
197
|
-
|
202
|
+
create_project("kipper", "foo", "foo-desc")
|
203
|
+
create_project("kipper", "foo2", "foo2-desc")
|
198
204
|
hub("kipper", "create-repository foo bar")
|
199
205
|
|
200
206
|
with_test_project do
|
@@ -205,7 +211,7 @@ describe "Hubble" do
|
|
205
211
|
end
|
206
212
|
|
207
213
|
it "should track projects related by forking" do
|
208
|
-
|
214
|
+
create_project("kipper", "foo", "foo-desc")
|
209
215
|
hub("kipper", "create-repository foo bar")
|
210
216
|
|
211
217
|
with_test_project do
|
@@ -216,8 +222,8 @@ describe "Hubble" do
|
|
216
222
|
end
|
217
223
|
|
218
224
|
it "should require read access to fork repository" do
|
219
|
-
|
220
|
-
|
225
|
+
create_project("kipper", "foo", "foo-desc")
|
226
|
+
create_project("kipper", "foo2", "foo2-desc")
|
221
227
|
hub("kipper", "create-repository foo bar")
|
222
228
|
|
223
229
|
with_test_project do
|
@@ -234,7 +240,7 @@ describe "Hubble" do
|
|
234
240
|
end
|
235
241
|
|
236
242
|
it "should remove permission" do
|
237
|
-
|
243
|
+
create_project("kipper", "foo", "foo-desc")
|
238
244
|
hub("kipper", "create-repository foo bar")
|
239
245
|
hub("kipper", "add-permission foo tiger read")
|
240
246
|
hub("kipper", "remove-permission foo tiger")
|
@@ -261,7 +267,8 @@ describe "Hubble" do
|
|
261
267
|
end
|
262
268
|
|
263
269
|
it "should allow admin to run-as another user" do
|
264
|
-
hub("admin", "run-as kipper create-project foo
|
270
|
+
hub("admin", "run-as kipper create-project foo")
|
271
|
+
hub("admin", "run-as kipper set-description foo foo-desc")
|
265
272
|
projects = list_projects("kipper")
|
266
273
|
projects.should == ["foo"]
|
267
274
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -42,6 +42,12 @@ def reset_file_system
|
|
42
42
|
FileUtils.rm_rf "tmp"
|
43
43
|
end
|
44
44
|
|
45
|
+
# Simple helper to create a public project with a description.
|
46
|
+
def create_project(user, project_name, project_desc)
|
47
|
+
hub(user, "create-project #{project_name}")
|
48
|
+
hub(user, "set-description #{project_name} #{project_desc}")
|
49
|
+
end
|
50
|
+
|
45
51
|
def list_projects(user)
|
46
52
|
hub(user, "list-projects").split("\n").map { |line| line.split[0] }
|
47
53
|
end
|
data/spec/yaml_spec.rb
CHANGED
@@ -12,16 +12,16 @@ describe "Hubble with yaml output" do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should list-projects" do
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
create_project("yammer", "a", "a-desc")
|
16
|
+
create_project("yammer", "b", "b-desc")
|
17
|
+
create_project("yammer", "c", "c-desc")
|
18
18
|
|
19
19
|
projects = YAML::load(hub("yammer", "#{YAML_OPTION} list-projects")).map{|project|project[:name]}
|
20
20
|
projects.should == ["a", "b", "c"]
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should list repositories" do
|
24
|
-
|
24
|
+
create_project("yammer", "a", "a-desc")
|
25
25
|
hub("yammer", "create-repository a b")
|
26
26
|
|
27
27
|
repositories = YAML::load(hub("yammer", "#{YAML_OPTION} list-repositories a"))
|
@@ -31,7 +31,7 @@ describe "Hubble with yaml output" do
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it "should list permissions" do
|
34
|
-
|
34
|
+
create_project("yammer", "a", "a-desc")
|
35
35
|
permissions = YAML::load(hub("yammer", "#{YAML_OPTION} list-permissions a"))
|
36
36
|
permissions.length.should == 1
|
37
37
|
permissions.first[:user].should == "yammer"
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hubbard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 18
|
9
|
+
version: 0.0.18
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Matthew Foemmel
|
@@ -9,19 +14,23 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-25 00:00:00 -05:00
|
13
18
|
default_executable: hubbard
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: rspec
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
23
31
|
version: 1.2.9
|
24
|
-
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
25
34
|
description: Hubbard is a command line tool for managing git repositories.
|
26
35
|
email: git@foemmel.com
|
27
36
|
executables:
|
@@ -38,6 +47,7 @@ files:
|
|
38
47
|
- README.md
|
39
48
|
- Rakefile
|
40
49
|
- VERSION
|
50
|
+
- bin/hub-daemon
|
41
51
|
- bin/hubbard
|
42
52
|
- commands/add-key.rb
|
43
53
|
- commands/add-permission.rb
|
@@ -62,6 +72,7 @@ files:
|
|
62
72
|
- commands/whoami.rb
|
63
73
|
- hubbard.gemspec
|
64
74
|
- lib/hubbard.rb
|
75
|
+
- lib/project.rb
|
65
76
|
- spec/gitssh
|
66
77
|
- spec/hubbard_spec.rb
|
67
78
|
- spec/spec.opts
|
@@ -80,22 +91,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
80
91
|
requirements:
|
81
92
|
- - ">="
|
82
93
|
- !ruby/object:Gem::Version
|
94
|
+
segments:
|
95
|
+
- 0
|
83
96
|
version: "0"
|
84
|
-
version:
|
85
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
98
|
requirements:
|
87
99
|
- - ">="
|
88
100
|
- !ruby/object:Gem::Version
|
101
|
+
segments:
|
102
|
+
- 0
|
89
103
|
version: "0"
|
90
|
-
version:
|
91
104
|
requirements: []
|
92
105
|
|
93
106
|
rubyforge_project:
|
94
|
-
rubygems_version: 1.3.
|
107
|
+
rubygems_version: 1.3.6
|
95
108
|
signing_key:
|
96
109
|
specification_version: 3
|
97
110
|
summary: Hubbard is a command line tool for managing git repositories.
|
98
111
|
test_files:
|
99
|
-
- spec/yaml_spec.rb
|
100
112
|
- spec/hubbard_spec.rb
|
101
113
|
- spec/spec_helper.rb
|
114
|
+
- spec/yaml_spec.rb
|