svn-transform 0.1.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/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +101 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/examples/example_helper.rb +31 -0
- data/examples/fixtures/dir_props.rb +29 -0
- data/examples/fixtures/original.rb +86 -0
- data/examples/fixtures/result.rb +105 -0
- data/examples/svn-transform/dir_example.rb +56 -0
- data/examples/svn-transform/file_example.rb +71 -0
- data/examples/svn-transform/transform/extension_example.rb +48 -0
- data/examples/svn-transform/transform/newline_example.rb +51 -0
- data/examples/svn-transform/transform/noop_example.rb +15 -0
- data/examples/svn-transform/transform/props_to_yaml_example.rb +137 -0
- data/examples/svn-transform_example.rb +148 -0
- data/lib/svn-transform.rb +264 -0
- data/lib/svn-transform/dir.rb +65 -0
- data/lib/svn-transform/file.rb +79 -0
- data/lib/svn-transform/session.rb +62 -0
- data/lib/svn-transform/transform/extension.rb +41 -0
- data/lib/svn-transform/transform/newline.rb +50 -0
- data/lib/svn-transform/transform/noop.rb +28 -0
- data/lib/svn-transform/transform/props_to_yaml.rb +134 -0
- metadata +115 -0
@@ -0,0 +1,264 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'svn-fixture'
|
3
|
+
|
4
|
+
class SvnTransform
|
5
|
+
VERSION = '0.1.0'
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# Use diff to compare two repositories (on local file system)
|
9
|
+
# Where reasonable, this (or something like it) should be run to verify
|
10
|
+
# expected results. I recommend trying a direct copy first to ensure your
|
11
|
+
# original repo doesn't have any featurs that SvnPropsToYaml won't
|
12
|
+
# understand.
|
13
|
+
#
|
14
|
+
# http://www.coderetard.com/2009/02/17/compare-directories-and-file-content-in-linux-without-dircmp/
|
15
|
+
#
|
16
|
+
# ==== Gotchas
|
17
|
+
# svn:entry fields aren't directly copied, but seem to match.
|
18
|
+
# repo uuid is different, but not relevant, so that file is ignored.
|
19
|
+
# other differences may also exist if the in_repo is an older format.
|
20
|
+
#
|
21
|
+
# ==== Parameters
|
22
|
+
# old_dir<String>:: FS Path to original (in) repository.
|
23
|
+
# new_dir<String>:: FS Path to generated (out) repository.
|
24
|
+
#
|
25
|
+
# Note that these are filesystem paths, not Subversion URI's
|
26
|
+
#
|
27
|
+
# ==== Returns
|
28
|
+
# True, False::
|
29
|
+
# Whether the directories are the same (except db/uuid file)
|
30
|
+
# If False, puts the result of running the diff command.
|
31
|
+
def compare(old_dir, new_dir)
|
32
|
+
ret = `diff --brief --exclude=uuid -r "#{old_dir}" "#{new_dir}"`
|
33
|
+
if ret.empty?
|
34
|
+
return true
|
35
|
+
else
|
36
|
+
puts ret
|
37
|
+
return false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Setup and SvnTransform with in (existing) repository URI, a name for the
|
43
|
+
# out (transformed) repository, and options.
|
44
|
+
#
|
45
|
+
# ==== Parameters
|
46
|
+
# in_repo_uri<String>::
|
47
|
+
# URI of existing repository(e.g. file:///home/jm81/repo,
|
48
|
+
# svn://localhost/repo)
|
49
|
+
# out_repo_name<String>::
|
50
|
+
# Name only of out repository (e.g. "out"). See options[:out_repos_path]
|
51
|
+
# for specifying full path (on local filesystem only)
|
52
|
+
#
|
53
|
+
# ==== Options
|
54
|
+
# :username<String>:: Username for in (existing) repository
|
55
|
+
# :password<String>:: Password for in (existing) repository
|
56
|
+
# :out_repos_path<String>::
|
57
|
+
# Full path for out repository (defaults to
|
58
|
+
# "#{SvnFixture.config[:base_path]}/repo_#{out_repo_name}")
|
59
|
+
# :out_wc_path<String>::
|
60
|
+
# Full path for out working copy (used by SvnFixture; defaults to
|
61
|
+
# "#{SvnFixture.config[:base_path]}/wc_#{out_repo_name}")
|
62
|
+
def initialize(in_repo_uri, out_repo_name = nil, options = {})
|
63
|
+
@in_username = options[:username]
|
64
|
+
@in_password = options[:password]
|
65
|
+
@in_repo_uri = in_repo_uri
|
66
|
+
@out_repo_name = out_repo_name
|
67
|
+
@out_repos_path = options[:out_repos_path]
|
68
|
+
@out_wc_path = options[:out_wc_path]
|
69
|
+
@file_transforms = []
|
70
|
+
@dir_transforms = []
|
71
|
+
end
|
72
|
+
|
73
|
+
# Add a transform to be run on files. This can either be a class or a block
|
74
|
+
# (see Parameters). Each file at revision is given as an SvnTransform::File
|
75
|
+
# to each transform, which can alter the basename, body and/or properties
|
76
|
+
# of the file prior to its being committed to the new Repository.
|
77
|
+
#
|
78
|
+
# ==== Parameters
|
79
|
+
# klass<Class>::
|
80
|
+
# A class whose #initialize method accepts a SvnTransform::File as the first
|
81
|
+
# argument and which responds to #run.
|
82
|
+
# args<Array>::
|
83
|
+
# Additional arguments to pass to klass#initialize
|
84
|
+
# block<Proc>::
|
85
|
+
# A block that accepts one argument (a SvnTransform::File). If a klass is
|
86
|
+
# also given, the block is ignored
|
87
|
+
#
|
88
|
+
# ==== Returns
|
89
|
+
# Array:: The current @file_transforms Array
|
90
|
+
#
|
91
|
+
# ==== Raises
|
92
|
+
# ArgumentError:: Neither a Class nor a block was given.
|
93
|
+
def file_transform(klass = nil, *args, &block)
|
94
|
+
if klass
|
95
|
+
@file_transforms << [klass, args]
|
96
|
+
elsif block_given?
|
97
|
+
@file_transforms << block
|
98
|
+
else
|
99
|
+
raise(ArgumentError, "Class or Block required")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Add a transform to be run on directories. See +file_transform+
|
104
|
+
def dir_transform(klass = nil, *args, &block)
|
105
|
+
if klass
|
106
|
+
@dir_transforms << [klass, args]
|
107
|
+
elsif block_given?
|
108
|
+
@dir_transforms << block
|
109
|
+
else
|
110
|
+
raise(ArgumentError, "Class or Block required")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Run the conversion. This method sets up the connection to the existing
|
115
|
+
# repo and the SvnFixture that will generate the final transformed repo, then
|
116
|
+
# calls +changesets+ to do the actual work. Finally, commit the SvnFixture
|
117
|
+
# (out repo) and update its rev 0 date to match the in repo
|
118
|
+
def convert
|
119
|
+
in_repo_session = Session.new(@in_repo_uri, @in_username, @out_username)
|
120
|
+
@in_repo = in_repo_session.session
|
121
|
+
@ctx = in_repo_session.context
|
122
|
+
@out_repo = SvnFixture.repo(@out_repo_name, @out_repos_path, @out_wc_path)
|
123
|
+
|
124
|
+
# Process changesets and commit
|
125
|
+
changesets
|
126
|
+
@out_repo.commit
|
127
|
+
|
128
|
+
# Update rev 0 date
|
129
|
+
r0_date = @ctx.revprop_list(@in_repo_uri, 0)[0]['svn:date']
|
130
|
+
@out_repo.repos.fs.set_prop('svn:date', SvnFixture.svn_time(r0_date), 0)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Process the existing changesets and generate a SvnFixture::Revision for
|
134
|
+
# each.
|
135
|
+
#
|
136
|
+
# TODO This is a massive mess. It works, at least for my purposes. But it is
|
137
|
+
# a mess. Ideally, it should be multiple methods. Part of this is due to how
|
138
|
+
# I set up the SvnFixture::Revision class, which accepts a block at initialize
|
139
|
+
# that is process only when its #commit method is called.
|
140
|
+
def changesets
|
141
|
+
args = ['', 1, @in_repo.latest_revnum, 0, true, nil]
|
142
|
+
path_renames = {}
|
143
|
+
|
144
|
+
@in_repo.log(*args) do |changes, rev_num, author, date, msg|
|
145
|
+
# Sort so that files are processed first (for benefit of PropsToYaml),
|
146
|
+
# and deletes are last
|
147
|
+
changes = changes.sort { |a,b| sort_for(a, rev_num) <=> sort_for(b, rev_num) }
|
148
|
+
# Get revision properties
|
149
|
+
rev_props = @ctx.revprop_list(@in_repo_uri, rev_num)[0]
|
150
|
+
# Create Revision, including all revprops. Note that svn:author and
|
151
|
+
# svn:date are revprops. SvnFixture::Revision allows these without the
|
152
|
+
# svn: prefix (as Symbol), but revprops are written last, and so this
|
153
|
+
# should be completely accurate.
|
154
|
+
in_repo = @in_repo
|
155
|
+
out_wc_path = @out_repo.wc_path
|
156
|
+
svn_transform = self
|
157
|
+
@out_repo.revision(rev_num, msg, rev_props) do
|
158
|
+
# Now go through all the changes. Setup directorie structure for each
|
159
|
+
# node. This is easier to understand, in my opinion.
|
160
|
+
|
161
|
+
changes.each do |full_path, change|
|
162
|
+
full_path = Pathname.new(full_path.sub(/\A\//, ''))
|
163
|
+
# Descend to parent directory
|
164
|
+
parent_dir = self
|
165
|
+
full_path.dirname.descend do |path|
|
166
|
+
unless path.basename == '.'
|
167
|
+
parent_dir = parent_dir.dir(path.basename.to_s)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
# TODO Replaces
|
172
|
+
|
173
|
+
if change.action == 'D'
|
174
|
+
del_path = path_renames['/' + full_path.to_s] || full_path.to_s
|
175
|
+
@ctx.delete(::File.join(out_wc_path, del_path))
|
176
|
+
elsif in_repo.stat(full_path.to_s, rev_num).file?
|
177
|
+
data = in_repo.file(full_path.to_s, rev_num)
|
178
|
+
transform_file = ::SvnTransform::File.new(full_path, data, rev_num, rev_props)
|
179
|
+
original_path = transform_file.path
|
180
|
+
svn_transform.__send__(:process_file_transforms, transform_file)
|
181
|
+
|
182
|
+
if change.copyfrom_path
|
183
|
+
from_path = path_renames[change.copyfrom_path] || change.copyfrom_path
|
184
|
+
@ctx.cp(
|
185
|
+
::File.join(out_wc_path, from_path),
|
186
|
+
::File.join(out_wc_path, transform_file.path.to_s)
|
187
|
+
)
|
188
|
+
end
|
189
|
+
|
190
|
+
unless transform_file.skip?
|
191
|
+
parent_dir.file(transform_file.basename) do
|
192
|
+
body(transform_file.body)
|
193
|
+
transform_file.properties.each_pair do |prop_k, prop_v|
|
194
|
+
prop(prop_k, prop_v) unless prop_k =~ /\Asvn:entry/
|
195
|
+
end
|
196
|
+
end
|
197
|
+
# For benefit of copies
|
198
|
+
if original_path != transform_file.path
|
199
|
+
path_renames['/' + original_path] = '/' + transform_file.path.to_s
|
200
|
+
end
|
201
|
+
end
|
202
|
+
else # directory
|
203
|
+
parent_dir.dir(full_path.basename.to_s) do
|
204
|
+
data = in_repo.dir(full_path.to_s, rev_num)
|
205
|
+
transform_dir = ::SvnTransform::Dir.new(full_path, data, rev_num, rev_props, in_repo, self)
|
206
|
+
svn_transform.__send__(:process_dir_transforms, transform_dir)
|
207
|
+
transform_dir.properties.each_pair do |prop_k, prop_v|
|
208
|
+
prop(prop_k, prop_v) unless prop_k =~ /\Asvn:entry/
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
private
|
218
|
+
|
219
|
+
# Process @file_transforms against the given File
|
220
|
+
#
|
221
|
+
# ==== Parameters
|
222
|
+
# file<SvnTransform::File>:: A file in the original repo at a given revision
|
223
|
+
def process_file_transforms(file)
|
224
|
+
@file_transforms.each do |transform|
|
225
|
+
if transform.is_a?(Proc)
|
226
|
+
transform.call(file)
|
227
|
+
else
|
228
|
+
transform[0].new(file, *transform[1]).run
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
# Process @dir_transforms against the given Dir
|
234
|
+
#
|
235
|
+
# ==== Parameters
|
236
|
+
# dir<SvnTransform::Dir>:: A directory in the original repo at a given revision
|
237
|
+
def process_dir_transforms(dir)
|
238
|
+
@dir_transforms.each do |transform|
|
239
|
+
if transform.is_a?(Proc)
|
240
|
+
transform.call(dir)
|
241
|
+
else
|
242
|
+
transform[0].new(dir, *transform[1]).run
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# Return an Integer such that file changes are first, directories second
|
248
|
+
# and deleted nodes last (to minimize the chance of a Transformation being
|
249
|
+
# overridden.
|
250
|
+
def sort_for(change, rev_num)
|
251
|
+
return 2 if change[1].action == 'D'
|
252
|
+
return 0 if @in_repo.stat(change[0].sub(/\A\//, ''), rev_num).file?
|
253
|
+
return 1
|
254
|
+
end
|
255
|
+
end # SvnTransform
|
256
|
+
|
257
|
+
require 'svn-transform/session'
|
258
|
+
require 'svn-transform/file'
|
259
|
+
require 'svn-transform/dir'
|
260
|
+
|
261
|
+
# Require predefined transforms
|
262
|
+
%w{extension newline noop props_to_yaml}.each do |filename|
|
263
|
+
require 'svn-transform/transform/' + filename
|
264
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
class SvnTransform
|
2
|
+
# A directory in original Subversion Repository, at a given changeset.
|
3
|
+
# Instances are initialized by SvnTransform#changesets.
|
4
|
+
#
|
5
|
+
# An instance for each file in the original repo at each revision will be
|
6
|
+
# passed to any directory transform blocks (TODO more info)
|
7
|
+
#
|
8
|
+
# Although more could theoretically be done (see #initialize fixture_dir
|
9
|
+
# param), the main thing intended to be alterable are the properties.
|
10
|
+
class Dir
|
11
|
+
# Initialize Dir instance using data passed by SvnTransform#changesets.
|
12
|
+
# This is data that will be available to Transformation blocks. It's
|
13
|
+
# relevant to remember that all this happens within a block given to an
|
14
|
+
# SvnFixture::Revision.
|
15
|
+
#
|
16
|
+
# ==== Parameters
|
17
|
+
# path<Pathname>::
|
18
|
+
# Full path within original Repository
|
19
|
+
# node_data<Array[String, Hash]>::
|
20
|
+
# Array returned by SWIG::TYPE_p_svn_ra_session_t#dir. First element is
|
21
|
+
# a Hash of directory entries, second is Hash of properties.
|
22
|
+
# rev_num<Integer>::
|
23
|
+
# Number of current revision
|
24
|
+
# rev_props<Hash>::
|
25
|
+
# Properties for current revision
|
26
|
+
# repos<Svn::Ra::Session>::
|
27
|
+
# Repo session (made available for PropsToYaml)
|
28
|
+
# fixture_dir<SvnFixture::Directory>::
|
29
|
+
# The SvnFixture::Directory representing this directory. This could be
|
30
|
+
# used to add, delete files, subdirs, etc, but doing much of that is
|
31
|
+
# likely to lead to weird results. I certainly don't intend to test this
|
32
|
+
# outside of one use case (PropsToYaml)
|
33
|
+
def initialize(path, node_data, rev_num, rev_props, repos, fixture_dir)
|
34
|
+
@path = path.kind_of?(Pathname) ? path : Pathname.new(path)
|
35
|
+
@entries = node_data[0]
|
36
|
+
@properties = node_data[1]
|
37
|
+
@rev_num = rev_num
|
38
|
+
@rev_props = rev_props
|
39
|
+
@repos = repos
|
40
|
+
@fixture_dir = fixture_dir
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :path, :entries, :properties, :rev_num, :rev_props, :repos, :fixture_dir
|
44
|
+
|
45
|
+
# Assign a new properties Hash to the node
|
46
|
+
#
|
47
|
+
# ==== Parameters
|
48
|
+
# hsh<~each_pair>::
|
49
|
+
# A Hash (or other object) responding to #each_pair, where keys are
|
50
|
+
# svn property keys, and values are the corresponding property values.
|
51
|
+
# This method does not verify that keys are "human-readable"
|
52
|
+
# (See http://svnbook.red-bean.com/en/1.0/ch07s02.html)
|
53
|
+
def properties=(hsh)
|
54
|
+
unless hsh.respond_to?(:each_pair)
|
55
|
+
raise ArgumentError, "Argument must respond to #each_pair, such as a Hash"
|
56
|
+
end
|
57
|
+
@properties = hsh
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get the base of the File
|
61
|
+
def basename
|
62
|
+
@path.basename.to_s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class SvnTransform
|
2
|
+
# A file in original Subversion Repository, at a given changeset. Instances
|
3
|
+
# are initialized by SvnTransform#changesets.
|
4
|
+
#
|
5
|
+
# An instance for each file in the original repo at each revision will be
|
6
|
+
# passed to any file transform blocks (TODO more info)
|
7
|
+
class File
|
8
|
+
# Initialize File instance using data passed by SvnTransform#changesets.
|
9
|
+
# This is data that will be available to Transformation blocks. It's
|
10
|
+
# relevant to remember that all this happens within a block given to an
|
11
|
+
# SvnFixture::Revision
|
12
|
+
#
|
13
|
+
# ==== Parameters
|
14
|
+
# path<Pathname>::
|
15
|
+
# Full path within original Repository
|
16
|
+
# node_data<Array[String, Hash]>::
|
17
|
+
# Array returned by SWIG::TYPE_p_svn_ra_session_t#file. First element is
|
18
|
+
# node body, second is hash of properties.
|
19
|
+
# rev_num<Integer>::
|
20
|
+
# Number of current revision
|
21
|
+
# rev_props<Hash>::
|
22
|
+
# Properties for current revision
|
23
|
+
def initialize(path, node_data, rev_num, rev_props)
|
24
|
+
@path = path.kind_of?(Pathname) ? path : Pathname.new(path)
|
25
|
+
@body = node_data[0]
|
26
|
+
@properties = node_data[1]
|
27
|
+
@rev_num = rev_num
|
28
|
+
@rev_props = rev_props
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :path, :body, :properties, :rev_num, :rev_props
|
32
|
+
|
33
|
+
# Change the body of the node. The new body will be placed in the new
|
34
|
+
# repository.
|
35
|
+
#
|
36
|
+
# ==== Parameters
|
37
|
+
# value<String>:: New body
|
38
|
+
attr_writer :body
|
39
|
+
|
40
|
+
# Assign a new properties Hash to the node
|
41
|
+
#
|
42
|
+
# ==== Parameters
|
43
|
+
# hsh<~each_pair>::
|
44
|
+
# A Hash (or other object) responding to #each_pair, where keys are
|
45
|
+
# svn property keys, and values are the corresponding property values.
|
46
|
+
# This method does not verify that keys are "human-readable"
|
47
|
+
# (See http://svnbook.red-bean.com/en/1.0/ch07s02.html)
|
48
|
+
def properties=(hsh)
|
49
|
+
unless hsh.respond_to?(:each_pair)
|
50
|
+
raise ArgumentError, "Argument must respond to #each_pair, such as a Hash"
|
51
|
+
end
|
52
|
+
@properties = hsh
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the base of the File
|
56
|
+
def basename
|
57
|
+
@path.basename.to_s
|
58
|
+
end
|
59
|
+
|
60
|
+
# Change the basename of the File. Alters the #path
|
61
|
+
#
|
62
|
+
# ==== Parameters
|
63
|
+
# val<String>:: New basename
|
64
|
+
def basename=(val)
|
65
|
+
@path = @path.dirname + val
|
66
|
+
end
|
67
|
+
|
68
|
+
# Skip this file at this revision (that is, don't commit it to new repo).
|
69
|
+
def skip!
|
70
|
+
@skip = true
|
71
|
+
end
|
72
|
+
|
73
|
+
# Whether this file should be skipped (not committed to new repo at this
|
74
|
+
# revision)
|
75
|
+
def skip?
|
76
|
+
@skip == true
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class SvnTransform
|
2
|
+
# A simplistic wrapper for Svn::Ra::Session. This takes care of setting up
|
3
|
+
# the context and callbacks as well as making the actual connection.
|
4
|
+
class Session
|
5
|
+
# Setup repository information
|
6
|
+
#
|
7
|
+
# ==== Parameters
|
8
|
+
# uri<String>:: URI of the repository (e.g. svn://example.com/repo)
|
9
|
+
# username<String>:: Username, if needed
|
10
|
+
# password<String>:: Password, if needed
|
11
|
+
def initialize(uri, username = nil, password = nil)
|
12
|
+
@uri = uri
|
13
|
+
@username = username
|
14
|
+
@password = password
|
15
|
+
end
|
16
|
+
|
17
|
+
# Open and return the actual Svn::Ra::Session
|
18
|
+
#
|
19
|
+
# ==== Returns
|
20
|
+
# Svn::Ra::Session:: A remote access session to a repository.
|
21
|
+
def session
|
22
|
+
# This will raise some error if connection fails for whatever reason.
|
23
|
+
# I don't currently see a reason to handle connection errors here, as I
|
24
|
+
# assume the best handling would be to raise another error.
|
25
|
+
@session ||= ::Svn::Ra::Session.open(@uri, {}, self.callbacks)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Setup, if needed, and return the working context (I don't really
|
29
|
+
# understand all this, but it's required to work with the working copy).
|
30
|
+
#
|
31
|
+
# ==== Returns
|
32
|
+
# Svn::Client::Context:: Context for working with working copy
|
33
|
+
def context
|
34
|
+
@context || begin
|
35
|
+
# Client::Context, which paticularly holds an auth_baton.
|
36
|
+
@context = ::Svn::Client::Context.new
|
37
|
+
if @username && @password
|
38
|
+
# TODO: What if another provider type is needed? Is this plausible?
|
39
|
+
@context.add_simple_prompt_provider(0) do |cred, realm, username, may_save|
|
40
|
+
cred.username = @username
|
41
|
+
cred.password = @password
|
42
|
+
end
|
43
|
+
elsif URI.parse(@uri).scheme == "file"
|
44
|
+
@context.add_username_prompt_provider(0) do |cred, realm, username, may_save|
|
45
|
+
cred.username = @username || "ANON"
|
46
|
+
end
|
47
|
+
else
|
48
|
+
@context.auth_baton = ::Svn::Core::AuthBaton.new()
|
49
|
+
end
|
50
|
+
@context
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Setup callbacks for Svn::Ra::Session.open.
|
55
|
+
#
|
56
|
+
# ==== Returns
|
57
|
+
# Svn::Ra::Callbacks
|
58
|
+
def callbacks
|
59
|
+
::Svn::Ra::Callbacks.new(context.auth_baton)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|