svn 0.1.0 → 0.2.0
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/lib/svn.rb +8 -0
- data/lib/svn/errors.rb +103 -16
- data/lib/svn/repos.rb +12 -4
- data/lib/svn/roots.rb +1 -1
- data/lib/svn/transactions.rb +6 -0
- data/lib/svn/utils.rb +12 -7
- data/spec/repo_spec.rb +142 -0
- data/spec/spec_helper.rb +81 -0
- metadata +42 -16
data/lib/svn.rb
CHANGED
data/lib/svn/errors.rb
CHANGED
@@ -7,10 +7,51 @@ module Svn
|
|
7
7
|
|
8
8
|
class << self
|
9
9
|
|
10
|
+
ERROR_CLASSES = {}
|
11
|
+
|
12
|
+
# used to turn generic messages for unknown errors into class names
|
13
|
+
# e.g., "Repository creation failed" => 'RepositoryCreationFailedError'
|
14
|
+
def class_name_for( message )
|
15
|
+
message.split(/\s+/).each(&:capitalize!).join + 'Error'
|
16
|
+
end
|
17
|
+
|
18
|
+
def specific_error_class( c_error )
|
19
|
+
# if an error class is already set, return it. otherwise, create a new
|
20
|
+
# one from the error's generic message
|
21
|
+
(
|
22
|
+
get( c_error.code ) ||
|
23
|
+
add( c_error.code, class_name_for( c_error.generic_message ) )
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def get( code )
|
28
|
+
ERROR_CLASSES[code]
|
29
|
+
end
|
30
|
+
|
31
|
+
def add( code, class_or_name )
|
32
|
+
klass = nil # keep in scope
|
33
|
+
|
34
|
+
if class_or_name.is_a? Class
|
35
|
+
klass = class_or_name
|
36
|
+
else
|
37
|
+
name = class_or_name
|
38
|
+
begin
|
39
|
+
# fetch an existing error class and save it for the error code
|
40
|
+
klass = Svn.const_get( name )
|
41
|
+
rescue NameError => err
|
42
|
+
# create the error class and return it
|
43
|
+
$stderr.puts "Creating #{name} for #{code}" if $debug_svn_errors
|
44
|
+
klass = Svn.const_set( name, Class.new( Svn::Error ) )
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
ERROR_CLASSES[code] = klass
|
49
|
+
end
|
50
|
+
|
10
51
|
# checks error and raises an exception for error if necessary
|
11
|
-
def check_and_raise(
|
12
|
-
return if
|
13
|
-
raise
|
52
|
+
def check_and_raise( err_ptr )
|
53
|
+
return if err_ptr.null?
|
54
|
+
raise specific_error_class( err_ptr ).new( err_ptr.message )
|
14
55
|
end
|
15
56
|
|
16
57
|
# returns a proc that calls check_and_raise
|
@@ -24,7 +65,7 @@ module Svn
|
|
24
65
|
|
25
66
|
def initialize( message_or_c_error )
|
26
67
|
if message_or_c_error.is_a? CError
|
27
|
-
super( message_or_c_error.
|
68
|
+
super( message_or_c_error.cause_message )
|
28
69
|
@c_error = message_or_c_error
|
29
70
|
else
|
30
71
|
super( message_or_c_error )
|
@@ -33,9 +74,16 @@ module Svn
|
|
33
74
|
|
34
75
|
end
|
35
76
|
|
77
|
+
# create sensible names for known error classes
|
78
|
+
Error.add( 2, :PathNotFoundError )
|
79
|
+
Error.add( 20, :NotADirectoryError )
|
80
|
+
Error.add( 160006, :InvalidRevisionError )
|
81
|
+
Error.add( 165002, ArgumentError )
|
82
|
+
Error.add( 200011, :DirectoryNotEmptyError )
|
83
|
+
|
36
84
|
class CError < FFI::ManagedStruct
|
37
85
|
layout(
|
38
|
-
:
|
86
|
+
:error_code, :int,
|
39
87
|
:message, :string,
|
40
88
|
:child, :pointer,
|
41
89
|
:pool, :pointer,
|
@@ -49,35 +97,74 @@ module Svn
|
|
49
97
|
end
|
50
98
|
end
|
51
99
|
|
52
|
-
# returns the most accurate message for an error
|
53
|
-
def best_message
|
54
|
-
# create a buffer, which may be used to hold the best message
|
55
|
-
buf = FFI::MemoryPointer.new( 1024 )
|
56
|
-
msg = C.best_message( self, buf, 1024 )
|
57
|
-
|
58
|
-
# return a duplicate of msg, since it may be stored in the buffer
|
59
|
-
# allocated above
|
60
|
-
msg.dup
|
61
|
-
end
|
62
|
-
|
63
100
|
module C
|
64
101
|
extend FFI::Library
|
65
102
|
ffi_lib 'libsvn_subr-1.so.1'
|
66
103
|
|
67
104
|
typedef CError.by_ref, :error
|
68
105
|
typedef :int, :size
|
106
|
+
typedef :int, :error_code
|
69
107
|
|
70
108
|
attach_function :best_message,
|
71
109
|
:svn_err_best_message,
|
72
110
|
[ :error, :buffer_inout, :size ],
|
73
111
|
:string
|
74
112
|
|
113
|
+
attach_function :root_cause,
|
114
|
+
:svn_error_root_cause,
|
115
|
+
[ :error ],
|
116
|
+
:error
|
117
|
+
|
118
|
+
attach_function :generic_message,
|
119
|
+
:svn_strerror,
|
120
|
+
[ :error_code, :buffer_inout, :size ],
|
121
|
+
:string
|
122
|
+
|
75
123
|
attach_function :clear,
|
76
124
|
:svn_error_clear,
|
77
125
|
[ :error ],
|
78
126
|
:void
|
79
127
|
end
|
80
128
|
|
129
|
+
copy_msg = Proc.new { |msg| msg.dup if msg }
|
130
|
+
|
131
|
+
bind_to C
|
132
|
+
|
133
|
+
MSG_BUFFER = FFI::MemoryPointer.new(1024)
|
134
|
+
# returns the error's specific message, if present, and the code's generic
|
135
|
+
# message otherwise
|
136
|
+
bind(
|
137
|
+
:best_message,
|
138
|
+
:before_return => copy_msg
|
139
|
+
) { |this| [this, MSG_BUFFER, 1024] }
|
140
|
+
|
141
|
+
# returns the most specific error struct from this error chain
|
142
|
+
bind :root_cause
|
143
|
+
|
144
|
+
# returns the "generic" message for the error code
|
145
|
+
bind(
|
146
|
+
:generic_message,
|
147
|
+
:before_return => copy_msg
|
148
|
+
) { |this| [ this[:error_code], MSG_BUFFER, 1024 ] }
|
149
|
+
|
150
|
+
# returns the most specific error message from this error chain
|
151
|
+
def cause_message
|
152
|
+
root_cause.best_message
|
153
|
+
end
|
154
|
+
|
155
|
+
# returns a combined message if there are children, or the best otherwise
|
156
|
+
def message
|
157
|
+
if self[:child].null?
|
158
|
+
best_message
|
159
|
+
else
|
160
|
+
"#{best_message}: #{cause_message}"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def code
|
165
|
+
self[:error_code]
|
166
|
+
end
|
167
|
+
|
81
168
|
end
|
82
169
|
|
83
170
|
end
|
data/lib/svn/repos.rb
CHANGED
@@ -23,26 +23,34 @@ module Svn #:nodoc:
|
|
23
23
|
# assertions in SVN libs
|
24
24
|
#++
|
25
25
|
def open( path, parent=RootPool )
|
26
|
+
raise ArgumentError, 'Path cannot be nil' if path.nil?
|
27
|
+
|
26
28
|
# get a new pool for all interactions with this repository
|
27
29
|
pool = Pool.create( parent )
|
28
30
|
|
29
|
-
# TODO: we may need to call find_root_path for this, if C.open expects
|
30
|
-
# an exact repository root path
|
31
31
|
out = FFI::MemoryPointer.new( :pointer )
|
32
32
|
|
33
|
+
# make sure the path is canonical: full path from / and no trailing /
|
34
|
+
final_path = File.expand_path( path.chomp(File::SEPARATOR) )
|
35
|
+
|
33
36
|
Error.check_and_raise(
|
34
|
-
C.open( out,
|
37
|
+
C.open( out, final_path, pool )
|
35
38
|
)
|
36
39
|
|
37
40
|
new( out.read_pointer, pool )
|
38
41
|
end
|
39
42
|
|
40
43
|
def create( path, parent=RootPool )
|
44
|
+
raise ArgumentError, 'Path cannot be nil' if path.nil?
|
45
|
+
|
41
46
|
# get a new pool for all interactions with this repository
|
42
47
|
pool = Pool.create( parent )
|
43
48
|
|
44
49
|
out = FFI::MemoryPointer.new( :pointer )
|
45
50
|
|
51
|
+
# make sure the path is canonical: full path from / and no trailing /
|
52
|
+
final_path = File.expand_path( path.chomp(File::SEPARATOR) )
|
53
|
+
|
46
54
|
Error.check_and_raise(
|
47
55
|
C.create(
|
48
56
|
out, # an out pointer to the newly created repository
|
@@ -227,7 +235,7 @@ module Svn #:nodoc:
|
|
227
235
|
end
|
228
236
|
|
229
237
|
use_fs_and_add_pool = Proc.new { |out, this, *args|
|
230
|
-
[ out, fs
|
238
|
+
([ out, fs ] + args) << pool
|
231
239
|
}
|
232
240
|
|
233
241
|
# use the above C module for the source of bound functions
|
data/lib/svn/roots.rb
CHANGED
@@ -85,7 +85,7 @@ module Svn #:nodoc:
|
|
85
85
|
|
86
86
|
# helper procs for method binding
|
87
87
|
test_c_true = Proc.new { |i| i == 1 }
|
88
|
-
add_pool = Proc.new { |out, this, *args| [ out, this
|
88
|
+
add_pool = Proc.new { |out, this, *args| ([ out, this ] + args) << pool }
|
89
89
|
|
90
90
|
# use the above C module for the source of bound functions
|
91
91
|
bind_to C
|
data/lib/svn/transactions.rb
CHANGED
data/lib/svn/utils.rb
CHANGED
@@ -36,7 +36,7 @@ module Svn #:nodoc:
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def new( *args )
|
39
|
-
@klass.new( *args
|
39
|
+
@klass.new( *(args + @added_args) )
|
40
40
|
end
|
41
41
|
|
42
42
|
def from_native( ptr, ctx )
|
@@ -206,17 +206,22 @@ module Svn #:nodoc:
|
|
206
206
|
# create a new method; blocks are used to re-arrange arguments
|
207
207
|
define_method( name ) do |*args|
|
208
208
|
# create new pointers for the specified out arguments
|
209
|
-
return_ptrs = return_types.map { |type|
|
209
|
+
return_ptrs = return_types.map { |type|
|
210
|
+
FFI::MemoryPointer.new( type )
|
211
|
+
}
|
212
|
+
|
213
|
+
# create the argument list for the function
|
214
|
+
call_args = return_ptrs.dup
|
215
|
+
call_args << self
|
216
|
+
call_args += args
|
210
217
|
|
211
218
|
return_val = nil # keep it in scope
|
212
219
|
if block
|
213
220
|
# call the method with the arguments after re-arranging via block
|
214
|
-
return_val = meth.call( *instance_exec(
|
215
|
-
*return_ptrs, self, *args, &block
|
216
|
-
) )
|
221
|
+
return_val = meth.call( *instance_exec( *call_args, &block ) )
|
217
222
|
else
|
218
223
|
# call the method with the standard argument order
|
219
|
-
return_val = meth.call( *
|
224
|
+
return_val = meth.call( *call_args )
|
220
225
|
end
|
221
226
|
|
222
227
|
# call the return check, if present
|
@@ -241,7 +246,7 @@ module Svn #:nodoc:
|
|
241
246
|
end
|
242
247
|
|
243
248
|
# extend FFI objects with the new helper methods
|
244
|
-
|
249
|
+
FFI::Struct.extend Extensions
|
245
250
|
FFI::AutoPointer.extend Extensions
|
246
251
|
|
247
252
|
end
|
data/spec/repo_spec.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Svn::Repo do
|
4
|
+
|
5
|
+
context ".create" do
|
6
|
+
|
7
|
+
it "complains about nil paths" do
|
8
|
+
expect { Svn::Repo.create(nil) }.to raise_error(
|
9
|
+
ArgumentError, /cannot be nil/
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "will complain about already existing repositories" do
|
14
|
+
expect { Svn::Repo.create(test_repo_path) }.to raise_error(
|
15
|
+
ArgumentError, /existing repository/
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "will not overwrite an existing path" do
|
20
|
+
path = temp_path('existing')
|
21
|
+
FileUtils.mkdir_p(temp_path('existing', 'content'))
|
22
|
+
begin
|
23
|
+
expect { Svn::Repo.create(path) }.to raise_error(
|
24
|
+
Svn::DirectoryNotEmptyError, /exists/
|
25
|
+
)
|
26
|
+
ensure
|
27
|
+
FileUtils.rm_rf(path)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "complains about invalid paths" do
|
32
|
+
expect {
|
33
|
+
invalid_path = temp_path( 'blah', 'blah', 'blah' )
|
34
|
+
Svn::Repo.create( invalid_path )
|
35
|
+
}.to( raise_error( Svn::PathNotFoundError) )
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can create a new repository" do
|
39
|
+
path = temp_path('new_repo')
|
40
|
+
repo = Svn::Repo.create( path )
|
41
|
+
begin
|
42
|
+
repo.should be_a(Svn::Repo)
|
43
|
+
repo.null?.should be_false
|
44
|
+
ensure
|
45
|
+
FileUtils.rm_rf(path) if File.exists? path
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
context ".open" do
|
52
|
+
|
53
|
+
it "complains about nil paths" do
|
54
|
+
expect {
|
55
|
+
Svn::Repo.open(nil)
|
56
|
+
}.to raise_error( ArgumentError, /cannot be nil/ )
|
57
|
+
end
|
58
|
+
|
59
|
+
it "complains about invalid paths" do
|
60
|
+
expect {
|
61
|
+
Svn::Repo.open( temp_path( 'blah', 'blah' ) )
|
62
|
+
}.to( raise_error( Svn::PathNotFoundError ) )
|
63
|
+
end
|
64
|
+
|
65
|
+
it "complains about paths inside the repository" do
|
66
|
+
path = link_test_repo
|
67
|
+
begin
|
68
|
+
expect {
|
69
|
+
Svn::Repo.open( File.join( test_repo_path, 'trunk', 'blah' ) )
|
70
|
+
}.to( raise_error( Svn::PathNotFoundError ) )
|
71
|
+
ensure
|
72
|
+
unlink_test_repo(path)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it "can open an existing repository" do
|
77
|
+
path = link_test_repo
|
78
|
+
begin
|
79
|
+
repo = Svn::Repo.open(path)
|
80
|
+
repo.should be_a(Svn::Repo)
|
81
|
+
repo.null?.should be_false
|
82
|
+
ensure
|
83
|
+
unlink_test_repo( path )
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
context "#revision" do
|
90
|
+
|
91
|
+
before do
|
92
|
+
@path = link_test_repo
|
93
|
+
@repo = open_test( @path )
|
94
|
+
end
|
95
|
+
|
96
|
+
after do
|
97
|
+
unlink_test_repo( @path )
|
98
|
+
end
|
99
|
+
|
100
|
+
it "complains about invalid revision numbers" do
|
101
|
+
expect {
|
102
|
+
@repo.revision(10_000_000)
|
103
|
+
}.to raise_error( Svn::InvalidRevisionError )
|
104
|
+
end
|
105
|
+
|
106
|
+
it "opens valid revisions" do
|
107
|
+
rev = @repo.revision(0)
|
108
|
+
rev.should be_a( Svn::Revision )
|
109
|
+
rev.null?.should be_false
|
110
|
+
rev = @repo.revision(1)
|
111
|
+
rev.should be_a( Svn::Revision )
|
112
|
+
rev.null?.should be_false
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
context "#youngest" do
|
118
|
+
|
119
|
+
before do
|
120
|
+
@path = link_test_repo
|
121
|
+
@repo = open_test( @path )
|
122
|
+
end
|
123
|
+
|
124
|
+
after do
|
125
|
+
unlink_test_repo( @path )
|
126
|
+
end
|
127
|
+
|
128
|
+
it "returns a revision" do
|
129
|
+
rev = @repo.youngest
|
130
|
+
rev.should be_a( Svn::Revision )
|
131
|
+
rev.null?.should be_false
|
132
|
+
end
|
133
|
+
|
134
|
+
it "is aliased as latest" do
|
135
|
+
rev = @repo.latest
|
136
|
+
rev.should be_a( Svn::Revision )
|
137
|
+
rev.null?.should be_false
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper.rb"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
end
|
12
|
+
|
13
|
+
# add the library path
|
14
|
+
$LOAD_PATH.unshift File.join(__FILE__, '..', 'lib')
|
15
|
+
require 'svn'
|
16
|
+
|
17
|
+
# print error codes/classes that are dynamically generated to stderr.
|
18
|
+
$debug_svn_errors = true
|
19
|
+
|
20
|
+
# manage the test repo
|
21
|
+
require 'tempfile'
|
22
|
+
require 'fileutils'
|
23
|
+
require 'zlib'
|
24
|
+
require 'archive/tar/minitar'
|
25
|
+
|
26
|
+
class Counter
|
27
|
+
def initialize
|
28
|
+
@num = 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def next
|
32
|
+
@num += 1
|
33
|
+
@num
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
TEMP_PATH_BASE = File.join( Dir.tmpdir, "svn-#{Process.pid}" )
|
38
|
+
TEST_REPO_TARBALL = File.join( File.dirname(__FILE__), '..', 'test', 'test_repo.tar.gz' )
|
39
|
+
TEST_COUNTER = Counter.new
|
40
|
+
|
41
|
+
ObjectSpace.define_finalizer(TEMP_PATH_BASE) do
|
42
|
+
FileUtils.rm_rf( File.join( Dir.tmpdir, "svn-#{Process.pid}" ) )
|
43
|
+
end
|
44
|
+
|
45
|
+
def temp_path( *parts )
|
46
|
+
File.join( TEMP_PATH_BASE, *parts )
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_repo_path
|
50
|
+
temp_path( 'test_repo' )
|
51
|
+
end
|
52
|
+
|
53
|
+
# unpacks a fresh copy of the test repo tarball
|
54
|
+
def unpack_test_repo
|
55
|
+
FileUtils.mkdir_p(TEMP_PATH_BASE)
|
56
|
+
gzip_stream = Zlib::GzipReader.new(File.open(TEST_REPO_TARBALL))
|
57
|
+
Archive::Tar::Minitar.unpack(gzip_stream, temp_path)
|
58
|
+
end
|
59
|
+
|
60
|
+
def link_test_repo
|
61
|
+
name = "test-#{TEST_COUNTER.next}"
|
62
|
+
link_path = temp_path(name)
|
63
|
+
FileUtils.ln_s(test_repo_path, link_path)
|
64
|
+
link_path
|
65
|
+
end
|
66
|
+
|
67
|
+
def unlink_test_repo( path )
|
68
|
+
FileUtils.rm( path )
|
69
|
+
end
|
70
|
+
|
71
|
+
def open_test( name )
|
72
|
+
Svn::Repo.open( test_repo_path )
|
73
|
+
end
|
74
|
+
|
75
|
+
def remove_test_repo
|
76
|
+
# clean up the temporary repository, if it is present
|
77
|
+
FileUtils.rm_rf test_repo_path if File.exists? test_repo_path
|
78
|
+
end
|
79
|
+
|
80
|
+
# make sure the test repo exists for all specs
|
81
|
+
unpack_test_repo
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: svn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-04-30 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
16
|
-
requirement: &
|
16
|
+
requirement: &20726960 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,7 +21,29 @@ dependencies:
|
|
21
21
|
version: '1.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *20726960
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &20726480 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.8'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *20726480
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: archive-tar-minitar
|
38
|
+
requirement: &20726020 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0.5'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *20726020
|
25
47
|
description:
|
26
48
|
email: rdblue@gmail.com
|
27
49
|
executables: []
|
@@ -29,21 +51,23 @@ extensions: []
|
|
29
51
|
extra_rdoc_files:
|
30
52
|
- README
|
31
53
|
files:
|
32
|
-
- lib/svn
|
33
|
-
- lib/svn/
|
34
|
-
- lib/svn/
|
35
|
-
- lib/svn/diffs.rb
|
54
|
+
- lib/svn.rb
|
55
|
+
- lib/svn/roots.rb
|
56
|
+
- lib/svn/repos.rb
|
36
57
|
- lib/svn/utils.rb
|
58
|
+
- lib/svn/revisions.rb
|
59
|
+
- lib/svn/diffs.rb
|
37
60
|
- lib/svn/transactions.rb
|
38
61
|
- lib/svn/logs.rb
|
39
|
-
- lib/svn/roots.rb
|
40
|
-
- lib/svn/repos.rb
|
41
62
|
- lib/svn/streams.rb
|
42
|
-
- lib/svn/errors.rb
|
43
|
-
- lib/svn/revisions.rb
|
44
63
|
- lib/svn/counted_strings.rb
|
45
|
-
- lib/svn.rb
|
64
|
+
- lib/svn/misc.rb
|
65
|
+
- lib/svn/errors.rb
|
66
|
+
- lib/svn/apr_utils.rb
|
67
|
+
- lib/svn/pools.rb
|
46
68
|
- README
|
69
|
+
- spec/repo_spec.rb
|
70
|
+
- spec/spec_helper.rb
|
47
71
|
homepage: http://github.com/codefoundry/svn
|
48
72
|
licenses: []
|
49
73
|
post_install_message:
|
@@ -64,8 +88,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
88
|
version: '0'
|
65
89
|
requirements: []
|
66
90
|
rubyforge_project:
|
67
|
-
rubygems_version: 1.8.
|
91
|
+
rubygems_version: 1.8.15
|
68
92
|
signing_key:
|
69
93
|
specification_version: 3
|
70
|
-
summary: Ruby bindings for SVN based on FFI
|
71
|
-
test_files:
|
94
|
+
summary: Ruby bindings for subversion (SVN) based on FFI
|
95
|
+
test_files:
|
96
|
+
- spec/repo_spec.rb
|
97
|
+
- spec/spec_helper.rb
|