regrit 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +3 -0
- data/README.md +3 -0
- data/Rakefile +10 -0
- data/lib/regrit.rb +20 -0
- data/lib/regrit/errors.rb +58 -0
- data/lib/regrit/provider.rb +14 -0
- data/lib/regrit/provider/mock.rb +78 -0
- data/lib/regrit/provider/system.rb +70 -0
- data/lib/regrit/ref.rb +15 -0
- data/lib/regrit/remote_repo.rb +76 -0
- data/lib/regrit/version.rb +3 -0
- data/regrit.gemspec +27 -0
- data/spec/id_rsa +27 -0
- data/spec/id_rsa.pub +1 -0
- data/spec/mocks_enabled_spec.rb +100 -0
- data/spec/remote_repo_spec.rb +109 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/wrong_key +27 -0
- metadata +195 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
data/lib/regrit.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Regrit
|
2
|
+
def self.enable_mock!
|
3
|
+
Provider::Mock.default!
|
4
|
+
@mocking = true
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.disable_mock!
|
8
|
+
@mocking = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.mocking?
|
12
|
+
@mocking
|
13
|
+
end
|
14
|
+
|
15
|
+
disable_mock!
|
16
|
+
end
|
17
|
+
|
18
|
+
require 'regrit/errors'
|
19
|
+
require 'regrit/remote_repo'
|
20
|
+
require 'regrit/provider'
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Regrit
|
2
|
+
# Error base class
|
3
|
+
class Error < RuntimeError
|
4
|
+
end
|
5
|
+
|
6
|
+
# Raised when the URI received is not a valid or able to be parsed.
|
7
|
+
class InvalidURIError < Error
|
8
|
+
def initialize
|
9
|
+
super "Invalid repository URI"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Raised when a repository is not accessible in some form.
|
14
|
+
class Inaccessible < Error
|
15
|
+
def initialize(message)
|
16
|
+
super "Repository Inaccessible: #{message}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Raised when a secure repository is accessed without a key
|
21
|
+
class PrivateKeyRequired < Inaccessible
|
22
|
+
def initialize(uri)
|
23
|
+
super "SSH private key required for secure git repository: #{uri}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Raised when accessing a repository times out
|
28
|
+
class TimeoutError < Inaccessible
|
29
|
+
def initialize(command, uri)
|
30
|
+
super "Timeout when attempting to access git repository: #{uri} with command: #{command.inspect}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Raised when there is an error calling git ls-remote (i.e. inaccessible repo)
|
35
|
+
class CommandError < Inaccessible
|
36
|
+
def initialize(command, status, stdout, stderr)
|
37
|
+
super <<-ERROR
|
38
|
+
Command `#{command}` exited with a non-zero exit status [#{status}]:
|
39
|
+
stdout:
|
40
|
+
#{stdout}
|
41
|
+
|
42
|
+
stderr:
|
43
|
+
#{stderr}
|
44
|
+
ERROR
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Raised when the Refs format is unrecognized
|
49
|
+
class InvalidRefsFormat < Inaccessible
|
50
|
+
def initialize(raw_refs)
|
51
|
+
super <<-ERROR
|
52
|
+
Invalid git refs format:
|
53
|
+
#{raw_refs}
|
54
|
+
ERROR
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module Regrit
|
2
|
+
module Provider
|
3
|
+
class Mock
|
4
|
+
class NotImplemented < Regrit::Error
|
5
|
+
def initialize
|
6
|
+
super "Command not implemented."
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :accessible
|
12
|
+
attr_accessor :refs
|
13
|
+
attr_accessor :timeout
|
14
|
+
|
15
|
+
def default!
|
16
|
+
self.accessible = true
|
17
|
+
self.timeout = false
|
18
|
+
self.refs = <<-REFS
|
19
|
+
123456789abcdef0123456789abcdef012345678\tHEAD
|
20
|
+
123456789abcdef0123456789abcdef012345678\trefs/heads/master
|
21
|
+
REFS
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
default!
|
26
|
+
|
27
|
+
def initialize(uri, options)
|
28
|
+
@uri = uri
|
29
|
+
end
|
30
|
+
|
31
|
+
def ls_remote(named=nil)
|
32
|
+
raise_errors
|
33
|
+
if named
|
34
|
+
one_ref(named) || ''
|
35
|
+
else
|
36
|
+
self.class.refs
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def clone(*argv)
|
41
|
+
raise NotImplemented
|
42
|
+
end
|
43
|
+
|
44
|
+
def fetch(*argv)
|
45
|
+
raise NotImplemented
|
46
|
+
end
|
47
|
+
|
48
|
+
def push(*argv)
|
49
|
+
raise NotImplemented
|
50
|
+
end
|
51
|
+
|
52
|
+
def pull(*argv)
|
53
|
+
raise NotImplemented
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
|
59
|
+
def one_ref(named)
|
60
|
+
self.class.refs.split(/\n/).detect do |ref|
|
61
|
+
ref_name = ref.split(/\t/).last
|
62
|
+
ref_name.split('/').last == named || ref_name.split('/',2).last == named || ref_name == named # git style matching
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def raise_errors
|
67
|
+
unless self.class.accessible
|
68
|
+
raise CommandError.new('mock command', 1, '', 'stderr')
|
69
|
+
end
|
70
|
+
|
71
|
+
if self.class.timeout
|
72
|
+
raise TimeoutError.new('mock command', @uri)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'open4'
|
2
|
+
require 'escape'
|
3
|
+
require 'git-ssh-wrapper'
|
4
|
+
require 'system_timer'
|
5
|
+
|
6
|
+
module Regrit
|
7
|
+
module Provider
|
8
|
+
class System
|
9
|
+
DEFAULT_TIMEOUT = 5
|
10
|
+
|
11
|
+
def initialize(uri, options)
|
12
|
+
@uri = uri
|
13
|
+
@timeout = options[:timeout] || DEFAULT_TIMEOUT
|
14
|
+
load_git_ssh_wrapper(options) if @uri.ssh?
|
15
|
+
end
|
16
|
+
|
17
|
+
def ls_remote(named=nil)
|
18
|
+
git "ls-remote", @uri.to_s, named
|
19
|
+
end
|
20
|
+
|
21
|
+
def clone(*argv)
|
22
|
+
git "clone", *argv
|
23
|
+
end
|
24
|
+
|
25
|
+
def fetch(*argv)
|
26
|
+
git "fetch", *argv
|
27
|
+
end
|
28
|
+
|
29
|
+
def push(*argv)
|
30
|
+
git "push", *argv
|
31
|
+
end
|
32
|
+
|
33
|
+
def pull(*argv)
|
34
|
+
git "pull", *argv
|
35
|
+
end
|
36
|
+
|
37
|
+
def git(*argv)
|
38
|
+
spawn "#{git_command} #{Escape.shell_command(argv.flatten.compact)}"
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
# Only require open4 here so as not to set a hard dependency.
|
44
|
+
#
|
45
|
+
# Might raise CommandError or TimeoutError
|
46
|
+
def spawn(command)
|
47
|
+
stdout, stderr = '', ''
|
48
|
+
SystemTimer.timeout(@timeout) do
|
49
|
+
Open4.spawn(command, :stdout => stdout, :stderr => stderr, :timeout => @timeout)
|
50
|
+
end
|
51
|
+
stdout
|
52
|
+
rescue Open4::SpawnError => e
|
53
|
+
raise CommandError.new(e.cmd, e.exitstatus, stdout, stderr)
|
54
|
+
rescue Timeout::Error
|
55
|
+
raise TimeoutError.new(command, @uri)
|
56
|
+
end
|
57
|
+
|
58
|
+
def git_command
|
59
|
+
# GIT_ASKPASS='echo' keeps password prompts from stalling the proccess (they still fail)
|
60
|
+
"env GIT_ASKPASS='echo' #{@uri.ssh? ? @git_ssh_wrapper.git_ssh : ''} git"
|
61
|
+
end
|
62
|
+
|
63
|
+
def load_git_ssh_wrapper(options)
|
64
|
+
@git_ssh_wrapper = GitSSHWrapper.new(options)
|
65
|
+
rescue GitSSHWrapper::PrivateKeyRequired
|
66
|
+
raise Regrit::PrivateKeyRequired.new(@uri)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/regrit/ref.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Regrit
|
2
|
+
class Ref
|
3
|
+
def initialize(repo, ref)
|
4
|
+
@repo = repo
|
5
|
+
@commit, @name = ref.split(/\t/)
|
6
|
+
raise InvalidRefsFormat.new(ref) if @name.nil?
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :commit, :name
|
10
|
+
|
11
|
+
def abbrev_commit
|
12
|
+
commit[0...7]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'gitable'
|
2
|
+
require 'regrit/ref'
|
3
|
+
|
4
|
+
module Regrit
|
5
|
+
class RemoteRepo
|
6
|
+
|
7
|
+
REFS_REGEXP = /^[0-9a-f]{40}\t\w/i
|
8
|
+
|
9
|
+
attr_reader :uri
|
10
|
+
|
11
|
+
def initialize(uri, options={})
|
12
|
+
if uri.nil? || uri.empty?
|
13
|
+
raise InvalidURIError
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
@uri = Gitable::URI.parse(uri)
|
18
|
+
rescue TypeError, Gitable::URI::InvalidURIError
|
19
|
+
raise InvalidURIError
|
20
|
+
end
|
21
|
+
|
22
|
+
# no user without ssh and no ssh without user - ^ is the XOR operator
|
23
|
+
if @uri.ssh? ^ @uri.user
|
24
|
+
raise InvalidURIError
|
25
|
+
end
|
26
|
+
|
27
|
+
@provider = Provider.new(@uri, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Decide if the URI is likely to require authentication
|
31
|
+
# @return [Boolean] Does the repo require auth?
|
32
|
+
def private_key_required?
|
33
|
+
@uri.ssh?
|
34
|
+
end
|
35
|
+
|
36
|
+
# Attempt to grab refs. If the repository is auth required and a private key
|
37
|
+
# is passed, use ssh to attempt access to the repository.
|
38
|
+
#
|
39
|
+
# @return [Boolean] can the repository be accessed?
|
40
|
+
def accessible?
|
41
|
+
!!refs
|
42
|
+
rescue Inaccessible
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
# Use a git ls-remote to load all repository refs
|
47
|
+
#
|
48
|
+
# @return [Array] An Array of Ref objects
|
49
|
+
def refs
|
50
|
+
@refs ||= load_refs
|
51
|
+
end
|
52
|
+
|
53
|
+
# Use a git ls-remote to find a single ref
|
54
|
+
#
|
55
|
+
# @return [Ref, nil] A Ref object or nil
|
56
|
+
def ref(named)
|
57
|
+
load_refs(named).first
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
attr_reader :provider
|
63
|
+
|
64
|
+
def load_refs(named=nil)
|
65
|
+
raw_refs = provider.ls_remote(named)
|
66
|
+
|
67
|
+
return [] if raw_refs.empty?
|
68
|
+
|
69
|
+
unless raw_refs =~ REFS_REGEXP
|
70
|
+
raise InvalidRefsFormat.new(raw_refs)
|
71
|
+
end
|
72
|
+
|
73
|
+
raw_refs.split(/\n/).map { |ref| Ref.new(self, ref) }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/regrit.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "regrit/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "regrit"
|
7
|
+
s.version = Regrit::VERSION
|
8
|
+
s.authors = ["Martin Emde"]
|
9
|
+
s.email = ["martin.emde@gmail.com"]
|
10
|
+
s.homepage = "http://github.org/martinemde/regrit"
|
11
|
+
s.summary = %q{Never regrit how you talk with remote git repositories}
|
12
|
+
s.description = %q{Deal with remote git repositories, yo.}
|
13
|
+
|
14
|
+
s.add_dependency "gitable", "~> 0.1.2"
|
15
|
+
s.add_dependency "open4"
|
16
|
+
s.add_dependency "escape"
|
17
|
+
s.add_dependency "git-ssh-wrapper", "~> 0.0.1"
|
18
|
+
s.add_dependency "SystemTimer"
|
19
|
+
|
20
|
+
s.add_development_dependency "rspec", "~> 1.3"
|
21
|
+
s.add_development_dependency "rake"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
data/spec/id_rsa
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIIEowIBAAKCAQEAw/yPM/JVRBMB31fNQE5rI38EhGsUGY5yYRlNkojqCTddBdPs
|
3
|
+
DKjq56q4iPn2YCl01h2wYdOYRwgHkWRSCiYuveFKojqlY7/IcXbWqNShAuV6bAMy
|
4
|
+
eCC1c5pNzGJYylv7WuP1MWT+0/mnJp3pykN5u7FDZ3MfYwMbl1SKqKnw6oKa5RCS
|
5
|
+
m7zPuj62o+KdEHTvce4ozoWkGzSAReh1hDTivJFYOMFgrn1y4GMWBskjcYK9iMQB
|
6
|
+
ZI3gzM+QRKk7bMyEh+kwZxhJ4sYJlpJjMzEsMgpER2lzuQDRDktGieaUYBLdo/3R
|
7
|
+
9op3B1Zkb/xJgtS1aOfZQAC720hMjEkNsrZIwwIBIwKCAQEAgMqJ/ZCebpAlzUhT
|
8
|
+
repjqZyckYgxx6bAMS3ihN2hG//PajrOUXZROScLjTaL9gydPD9lR5mtNf32WDqc
|
9
|
+
T8/y1Iy8BDUq2yZB5CmFv2cn+pbMyqMD6IqF3kDUCfd8LTUhhN7xlXzh+QMksvoO
|
10
|
+
qXzMVsTxx6NsZaL038nXdiaIX5aBDyow9XuAGjli6gDjN4+MLtw4VaOdo6GZJmDe
|
11
|
+
pDAf8WIM+y1RtnFcQrZOO6lU+aOAPdi8cboj8mNrgAt0hyOndDqWrWFzBtWviXtV
|
12
|
+
Ok2IcUNvGnO20ax0EaC3oTRTtwEvbywTx9aCSJ6eyGyL64MX749Mr4Tk4mmwXlyx
|
13
|
+
Wf268wKBgQDnrNrSkT856yOCUu2tC95MiC0NyKQF64o+YILIkdzsDJnB7Y7I80wt
|
14
|
+
WkaTLx09RgW6pEbC341fSUIYCaTb/jGynEje74qgjC8bWDtQmXUKbgcznS4qYVgl
|
15
|
+
rcGoAt9ZSXdeDVk2qRqSagahDSEvz8tbXn0NPGXeo8db3XUIIf2hPQKBgQDYkG/7
|
16
|
+
Gn7eAD5P4bvvS92V8Fu6KoR2pfchMI97iTAfH0D8+X5TCbxrNtqRW32yxd0/vgbo
|
17
|
+
Gri6HdTJg0v8BSHH9/k/p12K/kagVt4su3KrLepcdtkc4PAnRbZw1H/zWSpj7XfL
|
18
|
+
HVX89ya7f8ad0ja7LpC7fhNqp09p3HN9P24x/wKBgHclsl2pyL6zcVj3cutH7qsE
|
19
|
+
NG19ISedtM+fWTPzPmrEptjDUL8eCetwQY2F8ce9nIvfdNk/xQxu0Yi0gKunTMJB
|
20
|
+
vxORIrj3ozKiZ6XLQ4G07cLF3Tpd8tGMj3r6Kbjj9D7/jPeKKuw2hxD/cCc3qmmB
|
21
|
+
DRy/+eA2+NAov9hL/sfzAoGBAJSATMlxQQ1B/tewu2JCppKzchlBuer1dkKk9Kx7
|
22
|
+
VDKZFp7W94llwwewleAEOO+dnwcjN++dS3hO+E+qfT8Zdj/6fwcTrdunC9upR+Qo
|
23
|
+
w6iUg3Kao4GETOe6xj69mZDsr1p28w7vi2uiKTAdGnrZShn0C3lAglfDLyQE4Xp0
|
24
|
+
o1V7AoGBAJW1veLTbtmKMQ0WdaN594R75D+ORhSrbj7Dr+ITb9Iz81HBT1lN2hjx
|
25
|
+
T4qWNo4yhny8MH1+NCK8SfQBpgdFo+SYL0fPBEr1DEH2PsnbDAyxvdn4QvfqCEAH
|
26
|
+
duj2CyGRhITAc98l3r6a1j0gDeyLaeXRPGu+CKg3pngW+/IuNTUA
|
27
|
+
-----END RSA PRIVATE KEY-----
|
data/spec/id_rsa.pub
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAw/yPM/JVRBMB31fNQE5rI38EhGsUGY5yYRlNkojqCTddBdPsDKjq56q4iPn2YCl01h2wYdOYRwgHkWRSCiYuveFKojqlY7/IcXbWqNShAuV6bAMyeCC1c5pNzGJYylv7WuP1MWT+0/mnJp3pykN5u7FDZ3MfYwMbl1SKqKnw6oKa5RCSm7zPuj62o+KdEHTvce4ozoWkGzSAReh1hDTivJFYOMFgrn1y4GMWBskjcYK9iMQBZI3gzM+QRKk7bMyEh+kwZxhJ4sYJlpJjMzEsMgpER2lzuQDRDktGieaUYBLdo/3R9op3B1Zkb/xJgtS1aOfZQAC720hMjEkNsrZIww== memde@kaffir.local
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Regrit::RemoteRepo do
|
4
|
+
before { Regrit.enable_mock! }
|
5
|
+
after { Regrit.disable_mock! }
|
6
|
+
|
7
|
+
before { @uri = 'git://example.com/does/not/work.git' }
|
8
|
+
|
9
|
+
context "(public)" do
|
10
|
+
# This uri would not work if we weren't mocked
|
11
|
+
subject { described_class.new(@uri) }
|
12
|
+
|
13
|
+
it { should_not be_private_key_required }
|
14
|
+
|
15
|
+
context "(mocked accessible)" do
|
16
|
+
before { Regrit::Provider::Mock.accessible = true }
|
17
|
+
it { should be_accessible }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "(mocked inaccessible)" do
|
21
|
+
before { Regrit::Provider::Mock.accessible = false }
|
22
|
+
it { should_not be_accessible }
|
23
|
+
end
|
24
|
+
|
25
|
+
context "(mocked timeout)" do
|
26
|
+
before { Regrit::Provider::Mock.timeout = true }
|
27
|
+
it { should_not be_accessible }
|
28
|
+
|
29
|
+
it "should raise TimeoutError" do
|
30
|
+
subject { described_class.new(@uri) }
|
31
|
+
|
32
|
+
lambda { subject.refs }.should raise_error(Regrit::TimeoutError)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
context "(private)" do
|
39
|
+
# This uri would not work if we weren't mocked
|
40
|
+
|
41
|
+
context "(mocked accessible)" do
|
42
|
+
before { Regrit::Provider::Mock.accessible = true }
|
43
|
+
|
44
|
+
it "still raises on bad key" do
|
45
|
+
pending("should we care if the key is blank in mock mode?") do
|
46
|
+
lambda { described_class.new(@uri, :private_key => '') }.should raise_error
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with a key" do
|
51
|
+
subject { described_class.new(@uri, :private_key => 'any key') }
|
52
|
+
it { subject.should be_accessible }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "(mocked inaccessible)" do
|
57
|
+
before { Regrit::Provider::Mock.accessible = false }
|
58
|
+
|
59
|
+
it "still raises on bad key" do
|
60
|
+
pending("should we care if the key is blank in mock mode?") do
|
61
|
+
lambda { described_class.new(@uri, :private_key => '') }.should raise_error
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with a key" do
|
66
|
+
subject { described_class.new(@uri, :private_key => private_key) }
|
67
|
+
it { subject.should_not be_accessible }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "(refs)" do
|
73
|
+
subject { described_class.new(@uri) }
|
74
|
+
|
75
|
+
it "returns default refs" do
|
76
|
+
subject.should have(2).refs
|
77
|
+
subject.ref('master').abbrev_commit.should == "1234567"
|
78
|
+
subject.refs.first.name.should == "HEAD"
|
79
|
+
end
|
80
|
+
|
81
|
+
it "returns nil if no ref matches" do
|
82
|
+
subject.ref('thisdoesntexist').should be_nil
|
83
|
+
end
|
84
|
+
|
85
|
+
context "(setting the response)" do
|
86
|
+
before do
|
87
|
+
Regrit::Provider::Mock.refs = <<-REFS
|
88
|
+
1234567890123456789012345678901234567890\tHEAD
|
89
|
+
1234567890123456789012345678901234567890\trefs/heads/master
|
90
|
+
REFS
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns the refs as set" do
|
94
|
+
subject.should have(2).refs
|
95
|
+
subject.ref('master').abbrev_commit.should == "1234567"
|
96
|
+
subject.refs.first.name.should == "HEAD"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Regrit::RemoteRepo do
|
4
|
+
|
5
|
+
context "(invalid uri)" do
|
6
|
+
[
|
7
|
+
'http://',
|
8
|
+
'git://user@host.com/repo/here.git', # not valid according to docs
|
9
|
+
nil, ""
|
10
|
+
].each do |uri|
|
11
|
+
it "raises on initialization with #{uri.inspect}" do
|
12
|
+
lambda { described_class.new(uri) }.should raise_error(Regrit::InvalidURIError)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "(valid uri)" do
|
18
|
+
[
|
19
|
+
# valid host names as described by git documentation
|
20
|
+
'rsync://host.xz/path/to/repo.git/',
|
21
|
+
'ftps://host.xz/path/to/repo.git/',
|
22
|
+
'ftp://host.xz/path/to/repo.git/',
|
23
|
+
'http://host.xz/path/to/repo.git/',
|
24
|
+
'https://host.xz/path/to/repo.git/',
|
25
|
+
'git://host.xz/path/to/repo.git',
|
26
|
+
'git://host.xz:8888/path/to/repo.git/',
|
27
|
+
'git://host.xz/~user/path/to/repo.git',
|
28
|
+
'git://host.xz:8888/~user/path/to/repo.git/',
|
29
|
+
'git://11.22.33.44/~user/path/to/repo.git',
|
30
|
+
'git://12.34.56.78:8888/~user/path/to/repo.git/',
|
31
|
+
'ssh://user@11.22.33.44/path/to/repo.git/',
|
32
|
+
'ssh://user@111.222.333.444:8888/path/to/repo.git',
|
33
|
+
'ssh://user@host.xz:8888/path/to/repo.git',
|
34
|
+
'ssh://user@host.xz/path/to/repo.git/',
|
35
|
+
'ssh://user@host.xz/~user/path/to/repo.git/',
|
36
|
+
'ssh://user@host.xz/~/path/to/repo.git',
|
37
|
+
'user@host.xz:/path/to/repo.git',
|
38
|
+
'user@123.123.123.123:/path/to/repo.git',
|
39
|
+
'user@host.xz:~user/path/to/repo.git/',
|
40
|
+
'user@1.0.0.0:~user/path/to/repo.git/',
|
41
|
+
'user@host.xz:path/to/repo.git',
|
42
|
+
].each do |uri|
|
43
|
+
it "creates a Regrit::RemoteRepo with #{uri.inspect}" do
|
44
|
+
described_class.new(uri, :private_key => private_key).should be_a_kind_of(described_class)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# These specs could be a bit more brittle because they access public repositories
|
50
|
+
describe "accessing" do
|
51
|
+
context "(non-resolving)" do
|
52
|
+
subject { described_class.new("git://example.com/non-resolve.git") }
|
53
|
+
|
54
|
+
it "doesn't hang when trying to access a bad server name" do
|
55
|
+
should_not be_accessible
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "(non-existant)" do
|
60
|
+
subject { described_class.new("git://github.com/engineyard/this_project_will_never_exist_and_if_it_does_then_this_will_break.git") }
|
61
|
+
|
62
|
+
it { should_not be_private_key_required }
|
63
|
+
it { should_not be_accessible }
|
64
|
+
end
|
65
|
+
|
66
|
+
context "(public)" do
|
67
|
+
subject { described_class.new("git://github.com/rails/rails.git") }
|
68
|
+
|
69
|
+
it { should_not be_private_key_required }
|
70
|
+
it { should be_accessible }
|
71
|
+
end
|
72
|
+
|
73
|
+
context "(private)" do
|
74
|
+
before { @uri = "git@github.com:martinemde/regrit.git" }
|
75
|
+
subject { described_class.new(@uri, :private_key => private_key) }
|
76
|
+
|
77
|
+
it { should be_private_key_required }
|
78
|
+
it { should be_accessible }
|
79
|
+
|
80
|
+
describe "loading refs" do
|
81
|
+
it { should have_at_least(2).refs }
|
82
|
+
|
83
|
+
it "has a master ref" do
|
84
|
+
subject.ref('master').name.should == 'refs/heads/master'
|
85
|
+
end
|
86
|
+
|
87
|
+
it "has a refs/heads/master ref" do
|
88
|
+
subject.ref('refs/heads/master').name.should == 'refs/heads/master'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it "raises on initialization without a key" do
|
93
|
+
lambda { described_class.new(@uri) }.should raise_error(Regrit::PrivateKeyRequired)
|
94
|
+
end
|
95
|
+
|
96
|
+
it "raises on initialization with an empty key" do
|
97
|
+
lambda { described_class.new(@uri, :private_key => '') }.should raise_error(Regrit::PrivateKeyRequired)
|
98
|
+
end
|
99
|
+
|
100
|
+
context "with wrong key" do
|
101
|
+
subject { described_class.new(@uri, :private_key => wrong_private_key) }
|
102
|
+
it { should_not be_accessible }
|
103
|
+
it "raises a CommandError on trying to access refs" do
|
104
|
+
lambda { subject.refs }.should raise_error(Regrit::CommandError)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
unless defined? Bundler
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler'
|
4
|
+
Bundler.setup
|
5
|
+
end
|
6
|
+
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
9
|
+
require 'regrit'
|
10
|
+
require 'spec'
|
11
|
+
|
12
|
+
module TestPrivateKey
|
13
|
+
def private_key
|
14
|
+
Pathname.new('spec/id_rsa').read
|
15
|
+
end
|
16
|
+
|
17
|
+
def wrong_private_key
|
18
|
+
Pathname.new('spec/wrong_key').read
|
19
|
+
end
|
20
|
+
|
21
|
+
def private_key_path
|
22
|
+
Pathname.new('spec/id_rsa').to_s
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
Spec::Runner.configure do |config|
|
27
|
+
config.include TestPrivateKey
|
28
|
+
end
|
data/spec/wrong_key
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIIEogIBAAKCAQEAwxjNTMWto8Q0l6TLQoWb5cT81f02+lapbhmGEqrEcF/cM1Un
|
3
|
+
QaQmJfvz+ZC32pyYqmav5x4RT4RRaxm4xjlRo22hMroXlnzKLgm+a6hA0R5a2gk+
|
4
|
+
quxs25XtvRxIig/H4OoLcfxmbUIqpT3ma7rgWE1+cxWsryCLKjv4Pp1bLeIAjyWk
|
5
|
+
eANUXbr7xn+uDSuL69b08A5AlvS1AfE1Mtwj2X1djoeivByJ4MAj5oOwIuoijHvW
|
6
|
+
bL+VDeXm1FPUMtRDN7t8NLOjbKU/UXZXSQJDqhJ9agb6DTSCrsZcarSbP3fr5I19
|
7
|
+
W6IeH1vDjCydHOdno4pQdZbpuI9c5c+x+WHv5wIBIwKCAQAQuPunfqh7wFxHgydd
|
8
|
+
eSqeqnwSV4hembbAS1Sig6pwCDdyHT3hDhHl/6cypgEhXeEzLV+I1rEG0NPHWfnl
|
9
|
+
Gtscov8wO9Yi138LQqnr+HqVlOM3Qp74tS3m75gI5SrKAVpGenYCdLhSggOnw3om
|
10
|
+
fbt1SHiNhYPUfyHfDHRdI243IdmxX2UIwhmUkHSUwWFTJqvwXZx6MnlPGV/s/hew
|
11
|
+
1lwIJKkdbNavphv0Sw6ycYs0KpRx5FHJStT25r6R59JRsmnTbDEZWEso5B4doHzp
|
12
|
+
JQbYbKxIPOx7bRyKo/vAZ6tozqjLRabs7QQaK7zjS+5KZBlbz1NfCMueZF+iS/AS
|
13
|
+
b2FLAoGBAOpoVIK43ry44ETA2vJAKh47VYQ61k7fnyfES+Mg9k4b+va68ddOPL2G
|
14
|
+
SZ6bxwFx5YG+KCCkVcIaO39/BaHhimD1UnZAmBV/lMmxBeoneWT6N3tqdSHQbXha
|
15
|
+
zLeko0QgzwIcAXSC1l1Q/XEs9k+apoVMYmbs1rJj27RvKUSYHCGhAoGBANUReDGu
|
16
|
+
TBffmrw+KfcC6O0RkqR46xUcgtjGEOhYIPlegVx8Sq1sozDjCtnTkAFQaTJIQVDx
|
17
|
+
Vh5d0Q1ZvZyYKGT1JXPMasu6qxZGyrvW2OQoPH1fdbvyI2gCgIEBV9ytPeMvtMK3
|
18
|
+
U+ZHtWFYwHFzsQ/StRzeru/HdfdmhdHfh7SHAoGBAKC8kbi5SEblLBHjVE5X4l3f
|
19
|
+
ixjX42lI4inlsGE7LI1VA9xi7voJw0AhkZFU4DuBTOtAkItpX2CHBDorNw/rHQ9J
|
20
|
+
Ipo66/F8DkEo7hzn3jac8thI/9ysLc7fLUq6CY3NWr+eLOIt1NJGKiG4bmJ4rLMt
|
21
|
+
EEaTxmuyMEE2SC8JN9yLAoGATyO+7eGnPBE5eR5nW79AkpF/nCzpmiCIXyT+9zat
|
22
|
+
KWw+rVK8ptCUYp15DxQQ6ouUyYiNSfM9PnqeGubRZgyhShHpVuWGwLMMWLs1W7Yz
|
23
|
+
TW4H1suvYxDLUoSWIUmkSqa/NyBZFR+FkAwBio6t4P8V4U5DRTzEojQkgHaJedau
|
24
|
+
v2UCgYEA2nCMG3AQLEy1QRz1ZaNiZ+kzdWByWj235YozBBtWgygt14/LBlM9+Tc4
|
25
|
+
lwdu/+eJFa4b+PV22MJNyfHUAq7PuYAxyc3PpAfrv9XC7PuIVue5u+GyIjqVrUYU
|
26
|
+
fDZo8xXylLsAceKIu8gftDx3yRFRqc7VQuqHu2OKnz606CviYU4=
|
27
|
+
-----END RSA PRIVATE KEY-----
|
metadata
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: regrit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Martin Emde
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-01-14 00:00:00 -08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ~>
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
hash: 31
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
- 1
|
31
|
+
- 2
|
32
|
+
version: 0.1.2
|
33
|
+
requirement: *id001
|
34
|
+
name: gitable
|
35
|
+
prerelease: false
|
36
|
+
type: :runtime
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
requirement: *id002
|
48
|
+
name: open4
|
49
|
+
prerelease: false
|
50
|
+
type: :runtime
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
requirement: *id003
|
62
|
+
name: escape
|
63
|
+
prerelease: false
|
64
|
+
type: :runtime
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - ~>
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 29
|
72
|
+
segments:
|
73
|
+
- 0
|
74
|
+
- 0
|
75
|
+
- 1
|
76
|
+
version: 0.0.1
|
77
|
+
requirement: *id004
|
78
|
+
name: git-ssh-wrapper
|
79
|
+
prerelease: false
|
80
|
+
type: :runtime
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
requirement: *id005
|
92
|
+
name: SystemTimer
|
93
|
+
prerelease: false
|
94
|
+
type: :runtime
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
hash: 9
|
102
|
+
segments:
|
103
|
+
- 1
|
104
|
+
- 3
|
105
|
+
version: "1.3"
|
106
|
+
requirement: *id006
|
107
|
+
name: rspec
|
108
|
+
prerelease: false
|
109
|
+
type: :development
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
112
|
+
none: false
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
hash: 3
|
117
|
+
segments:
|
118
|
+
- 0
|
119
|
+
version: "0"
|
120
|
+
requirement: *id007
|
121
|
+
name: rake
|
122
|
+
prerelease: false
|
123
|
+
type: :development
|
124
|
+
description: Deal with remote git repositories, yo.
|
125
|
+
email:
|
126
|
+
- martin.emde@gmail.com
|
127
|
+
executables: []
|
128
|
+
|
129
|
+
extensions: []
|
130
|
+
|
131
|
+
extra_rdoc_files: []
|
132
|
+
|
133
|
+
files:
|
134
|
+
- .gitignore
|
135
|
+
- Gemfile
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- lib/regrit.rb
|
139
|
+
- lib/regrit/errors.rb
|
140
|
+
- lib/regrit/provider.rb
|
141
|
+
- lib/regrit/provider/mock.rb
|
142
|
+
- lib/regrit/provider/system.rb
|
143
|
+
- lib/regrit/ref.rb
|
144
|
+
- lib/regrit/remote_repo.rb
|
145
|
+
- lib/regrit/version.rb
|
146
|
+
- regrit.gemspec
|
147
|
+
- spec/id_rsa
|
148
|
+
- spec/id_rsa.pub
|
149
|
+
- spec/mocks_enabled_spec.rb
|
150
|
+
- spec/remote_repo_spec.rb
|
151
|
+
- spec/spec.opts
|
152
|
+
- spec/spec_helper.rb
|
153
|
+
- spec/wrong_key
|
154
|
+
has_rdoc: true
|
155
|
+
homepage: http://github.org/martinemde/regrit
|
156
|
+
licenses: []
|
157
|
+
|
158
|
+
post_install_message:
|
159
|
+
rdoc_options: []
|
160
|
+
|
161
|
+
require_paths:
|
162
|
+
- lib
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
164
|
+
none: false
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
hash: 3
|
169
|
+
segments:
|
170
|
+
- 0
|
171
|
+
version: "0"
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
none: false
|
174
|
+
requirements:
|
175
|
+
- - ">="
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
hash: 3
|
178
|
+
segments:
|
179
|
+
- 0
|
180
|
+
version: "0"
|
181
|
+
requirements: []
|
182
|
+
|
183
|
+
rubyforge_project:
|
184
|
+
rubygems_version: 1.3.7
|
185
|
+
signing_key:
|
186
|
+
specification_version: 3
|
187
|
+
summary: Never regrit how you talk with remote git repositories
|
188
|
+
test_files:
|
189
|
+
- spec/id_rsa
|
190
|
+
- spec/id_rsa.pub
|
191
|
+
- spec/mocks_enabled_spec.rb
|
192
|
+
- spec/remote_repo_spec.rb
|
193
|
+
- spec/spec.opts
|
194
|
+
- spec/spec_helper.rb
|
195
|
+
- spec/wrong_key
|