kenai_tools 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/wiki-copy +201 -0
- data/kenai_tools.gemspec +4 -2
- data/lib/kenai_tools/kenai_client.rb +21 -9
- data/lib/kenai_tools/version.rb +1 -1
- metadata +142 -72
data/bin/wiki-copy
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
$LOAD_PATH << File.dirname(__FILE__) + '/../lib'
|
6
|
+
require 'optparse'
|
7
|
+
require 'highline/import'
|
8
|
+
require 'kenai_tools'
|
9
|
+
|
10
|
+
$terminal = HighLine.new($stdin, $stderr)
|
11
|
+
|
12
|
+
def fail(message, exit_code = 2)
|
13
|
+
$stderr.puts(message)
|
14
|
+
exit exit_code
|
15
|
+
end
|
16
|
+
|
17
|
+
def check_project(kc, url, proj_name)
|
18
|
+
fail "Unable to find project '#{proj_name}' at #{url}" unless kc.project(proj_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_url(host_or_url)
|
22
|
+
host_or_url =~ %r{^http(s?)://} ? host_or_url : "https://#{host_or_url}/"
|
23
|
+
end
|
24
|
+
|
25
|
+
def copy_images(src_client, src_proj, dst_client, dst_proj)
|
26
|
+
if on_page = @options[:on_page]
|
27
|
+
images = src_client.wiki_images(src_proj, on_page)
|
28
|
+
puts "Found #{images.size} source wiki images on page #{on_page}"
|
29
|
+
else
|
30
|
+
images = src_client.wiki_images(src_proj)
|
31
|
+
puts "Found #{images.size} source wiki images"
|
32
|
+
end
|
33
|
+
|
34
|
+
images.each do |image|
|
35
|
+
filename = image['filename']
|
36
|
+
print "Copying wiki image #{filename}..."
|
37
|
+
image_data = src_client.wiki_image_data(image)
|
38
|
+
unless @options[:dry_run]
|
39
|
+
tries = 0
|
40
|
+
begin
|
41
|
+
tries += 1
|
42
|
+
dst_client.create_or_update_wiki_image(dst_proj, :image_data => image_data,
|
43
|
+
:content_type => image['image_content_type'], :filename => filename,
|
44
|
+
:comments => image['comments'])
|
45
|
+
rescue IOError => ex
|
46
|
+
if (tries < 4)
|
47
|
+
print " retrying..."
|
48
|
+
sleep(2**tries) # Wait for 2, 4, or 8 secs
|
49
|
+
retry
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
puts "done"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def copy_pages(src_client, src_proj, dst_client, dst_proj)
|
58
|
+
if on_page = @options[:on_page]
|
59
|
+
pages = src_client.wiki_pages(src_proj, on_page)
|
60
|
+
puts "Found #{pages.size} source wiki pages on page #{on_page}"
|
61
|
+
else
|
62
|
+
pages = src_client.wiki_pages(src_proj)
|
63
|
+
puts "Found #{pages.size} source wiki pages"
|
64
|
+
end
|
65
|
+
|
66
|
+
pages.each do |page|
|
67
|
+
page_name = page['name']
|
68
|
+
print "Copying page #{page_name}..."
|
69
|
+
contents = src_client.wiki_page(src_proj, page_name)['text']
|
70
|
+
unless @options[:dry_run]
|
71
|
+
dst_client.edit_wiki_page(dst_proj, page_name) { |s| contents }
|
72
|
+
end
|
73
|
+
puts "done"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def usage
|
78
|
+
puts @opts
|
79
|
+
exit 1
|
80
|
+
end
|
81
|
+
|
82
|
+
def parse_endpoint_spec(spec, type)
|
83
|
+
usage unless spec
|
84
|
+
host, project = spec.split(',')
|
85
|
+
fail "Bad #{type}_ENDPOINT: PROJECT not specified" unless project
|
86
|
+
[host, project]
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_credentials(option, url)
|
90
|
+
user, password = nil
|
91
|
+
if option[:prompt]
|
92
|
+
say "Please enter your login credentials for #{url}"
|
93
|
+
user = ask('Username: ')
|
94
|
+
password = ask('Password: ') { |q| q.echo = '*' }
|
95
|
+
else
|
96
|
+
File.open(option[:file]) do |f|
|
97
|
+
user, password = f.read.split
|
98
|
+
end
|
99
|
+
end
|
100
|
+
[user, password]
|
101
|
+
end
|
102
|
+
|
103
|
+
def main
|
104
|
+
program = File.basename(__FILE__)
|
105
|
+
@options = {}
|
106
|
+
@opts = OptionParser.new do |opts|
|
107
|
+
opts.banner = "Usage: #{program} [options] SRC_ENDPOINT DST_ENDPOINT"
|
108
|
+
opts.separator " where ENDPOINT is HOST,PROJECT"
|
109
|
+
opts.separator "Note: unix-like OS is recommended as this tool may fail on Windows"
|
110
|
+
opts.separator "Examples:"
|
111
|
+
opts.separator " #{program} kenai.com,my-project java.net,my-project"
|
112
|
+
opts.separator " #{program} --text-only kenai.com,my-project java.net,my-project"
|
113
|
+
opts.separator ""
|
114
|
+
opts.separator "Specific options:"
|
115
|
+
|
116
|
+
opts.on("-p", "--password FILE", "Read DST nl-separated username/password from file") do |v|
|
117
|
+
@options[:password] = {:prompt => !v, :file => v}
|
118
|
+
end
|
119
|
+
|
120
|
+
opts.on("-s", "--source-password [FILE]", "Prompt or read SRC username/password from file") do |v|
|
121
|
+
@options[:source_password] = {:prompt => !v, :file => v}
|
122
|
+
end
|
123
|
+
|
124
|
+
opts.on("--images-only", "Copy images only") do |v|
|
125
|
+
@options[:images_only] = v
|
126
|
+
end
|
127
|
+
|
128
|
+
opts.on("--text-only", "Copy text only") do |v|
|
129
|
+
@options[:text_only] = v
|
130
|
+
end
|
131
|
+
|
132
|
+
opts.on("-n", "--dry-run", "No writes, dry run only") do |v|
|
133
|
+
@options[:dry_run] = v
|
134
|
+
end
|
135
|
+
|
136
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
137
|
+
@options[:verbose] = v
|
138
|
+
end
|
139
|
+
|
140
|
+
opts.on_tail("--on-page API_PAGE", "Copy only text or images on API_PAGE") do |v|
|
141
|
+
@options[:on_page] = v
|
142
|
+
end
|
143
|
+
|
144
|
+
opts.on_tail("--version", "Show kenai_tools gem version") do |v|
|
145
|
+
puts KenaiTools::VERSION
|
146
|
+
exit
|
147
|
+
end
|
148
|
+
|
149
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
150
|
+
usage
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
begin
|
155
|
+
@opts.parse!
|
156
|
+
rescue Exception => ex
|
157
|
+
fail ex
|
158
|
+
end
|
159
|
+
|
160
|
+
kc_opts = {}
|
161
|
+
kc_opts[:log] = $stderr if @options[:verbose]
|
162
|
+
|
163
|
+
if @options[:dry_run]
|
164
|
+
puts "Dry run, no actual writes will be performed..."
|
165
|
+
end
|
166
|
+
|
167
|
+
src_host, src_proj = parse_endpoint_spec(ARGV.shift, "SRC")
|
168
|
+
dst_host, dst_proj = parse_endpoint_spec(ARGV.shift, "DST")
|
169
|
+
|
170
|
+
unless src_host && src_proj
|
171
|
+
usage
|
172
|
+
end
|
173
|
+
src_url = to_url(src_host)
|
174
|
+
|
175
|
+
unless dst_host && dst_proj
|
176
|
+
usage
|
177
|
+
end
|
178
|
+
dst_url = to_url(dst_host)
|
179
|
+
|
180
|
+
dst_client = KenaiTools::KenaiClient.new(dst_url, kc_opts)
|
181
|
+
user, password = get_credentials(@options[:password], dst_url)
|
182
|
+
result = dst_client.authenticate(user, password)
|
183
|
+
fail "Invalid DST_ENDPOINT credentials for #{dst_url}" unless result
|
184
|
+
check_project(dst_client, dst_url, dst_proj)
|
185
|
+
|
186
|
+
src_client = KenaiTools::KenaiClient.new(src_url, kc_opts)
|
187
|
+
user, password = get_credentials(@options[:source_password], src_url)
|
188
|
+
result = src_client.authenticate(user, password)
|
189
|
+
fail "Invalid SRC_ENDPOINT credentials #{src_url}" unless result
|
190
|
+
check_project(src_client, src_url, src_proj)
|
191
|
+
|
192
|
+
unless @options[:dry_run]
|
193
|
+
copy_images(src_client, src_proj, dst_client, dst_proj) unless @options[:text_only]
|
194
|
+
copy_pages(src_client, src_proj, dst_client, dst_proj) unless @options[:images_only]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
begin
|
199
|
+
main
|
200
|
+
rescue SystemExit
|
201
|
+
end
|
data/kenai_tools.gemspec
CHANGED
@@ -9,8 +9,9 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Edwin Goei", "Project Kenai Team"]
|
10
10
|
s.email = ["edwin.goei@oracle.com"]
|
11
11
|
s.homepage = "http://kenai.com/projects/kenaiapis"
|
12
|
-
s.summary = %q{Tools for sites hosted on the Kenai platform. Use dlutil to
|
13
|
-
s.description = %q{Tools for sites such as java.net that are hosted on the Kenai platform. Use dlutil to upload and download files.
|
12
|
+
s.summary = %q{Tools for sites hosted on the Kenai platform. Use dlutil to manage downloads and wiki-copy to copy wikis.}
|
13
|
+
s.description = %q{Tools for sites such as java.net that are hosted on the Kenai platform. Use dlutil to upload and download files.
|
14
|
+
Use wiki-copy to copy wiki contents and images from one project to another across sites.}
|
14
15
|
s.post_install_message = %q{
|
15
16
|
==============================================================================
|
16
17
|
|
@@ -40,4 +41,5 @@ OS. For more info, see http://kenai.com/jira/browse/KENAI-2853.
|
|
40
41
|
s.add_dependency("rest-client", "~> 1.6")
|
41
42
|
s.add_dependency("json", "~> 1.5")
|
42
43
|
s.add_dependency("highline", "~> 1.6")
|
44
|
+
s.add_dependency("multipart-post", "~> 1.1")
|
43
45
|
end
|
@@ -2,6 +2,7 @@ require 'rubygems'
|
|
2
2
|
|
3
3
|
require 'rest_client'
|
4
4
|
require 'json'
|
5
|
+
require 'net/http/post/multipart'
|
5
6
|
|
6
7
|
module KenaiTools
|
7
8
|
class KenaiClient
|
@@ -12,6 +13,7 @@ module KenaiTools
|
|
12
13
|
attr_reader :host, :user, :password
|
13
14
|
|
14
15
|
def initialize(host = nil, opts = {})
|
16
|
+
RestClient.log = opts[:log] if opts[:log]
|
15
17
|
@host = host || DEFAULT_HOST
|
16
18
|
@opts = opts
|
17
19
|
end
|
@@ -81,7 +83,9 @@ module KenaiTools
|
|
81
83
|
|
82
84
|
# get wiki images for a project
|
83
85
|
def wiki_images(project, on_page = nil)
|
84
|
-
|
86
|
+
opts = {}
|
87
|
+
opts[:page] = on_page if on_page
|
88
|
+
fetch_all("projects/#{project}/features/wiki/images", 'images', opts)
|
85
89
|
end
|
86
90
|
|
87
91
|
# get the wiki raw image data for an image
|
@@ -89,25 +93,33 @@ module KenaiTools
|
|
89
93
|
RestClient.get(image['image_url'], :accept => image['image_content_type'])
|
90
94
|
end
|
91
95
|
|
92
|
-
#
|
93
|
-
# +:
|
96
|
+
# opts has the following keys
|
97
|
+
# +:image_data+ = raw image data, required only if creating a new image
|
98
|
+
# +:content_type+ = image_data content-type
|
99
|
+
# +:filename+ = filename for multipart
|
100
|
+
#
|
94
101
|
# +:comments+ = optional comments for the image
|
95
102
|
# throws IOError unless create or update was successful
|
96
|
-
def create_or_update_wiki_image(proj_name,
|
103
|
+
def create_or_update_wiki_image(proj_name, opts)
|
97
104
|
req_params = {}
|
98
|
-
if data =
|
99
|
-
|
100
|
-
|
105
|
+
if data = opts[:image_data]
|
106
|
+
content_type = opts[:content_type]
|
107
|
+
filename = opts[:filename]
|
108
|
+
req_params["image[uploaded_data]"] = UploadIO.new(StringIO.new(data), content_type, filename)
|
101
109
|
end
|
102
|
-
if comments =
|
110
|
+
if comments = opts[:comments]
|
103
111
|
req_params["image[comments]"] = comments
|
104
112
|
end
|
105
113
|
return false if req_params.empty?
|
114
|
+
|
115
|
+
self["projects/#{proj_name}/features/wiki/images/#{filename}"].put(req_params)
|
106
116
|
end
|
107
117
|
|
108
118
|
# get wiki pages for a project
|
109
119
|
def wiki_pages(project, on_page = nil)
|
110
|
-
|
120
|
+
opts = {}
|
121
|
+
opts[:page] = on_page if on_page
|
122
|
+
fetch_all("projects/#{project}/features/wiki/pages", 'pages', opts)
|
111
123
|
end
|
112
124
|
|
113
125
|
def wiki_page(proj_name, page_name)
|
data/lib/kenai_tools/version.rb
CHANGED
metadata
CHANGED
@@ -1,97 +1,147 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: kenai_tools
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Edwin Goei
|
9
14
|
- Project Kenai Team
|
10
15
|
autorequire:
|
11
16
|
bindir: bin
|
12
17
|
cert_chain: []
|
13
|
-
|
14
|
-
|
15
|
-
|
18
|
+
|
19
|
+
date: 2012-05-15 00:00:00 -07:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
16
23
|
name: rspec
|
17
|
-
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
18
26
|
none: false
|
19
|
-
requirements:
|
27
|
+
requirements:
|
20
28
|
- - ~>
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 9
|
31
|
+
segments:
|
32
|
+
- 2
|
33
|
+
- 5
|
34
|
+
version: "2.5"
|
23
35
|
type: :development
|
24
|
-
|
25
|
-
|
26
|
-
- !ruby/object:Gem::Dependency
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
27
38
|
name: bundler
|
28
|
-
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
29
41
|
none: false
|
30
|
-
requirements:
|
42
|
+
requirements:
|
31
43
|
- - ~>
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 15
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 0
|
49
|
+
version: "1.0"
|
34
50
|
type: :development
|
35
|
-
|
36
|
-
|
37
|
-
- !ruby/object:Gem::Dependency
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
38
53
|
name: gemcutter
|
39
|
-
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
56
|
none: false
|
41
|
-
requirements:
|
42
|
-
- -
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
45
64
|
type: :development
|
46
|
-
|
47
|
-
|
48
|
-
- !ruby/object:Gem::Dependency
|
65
|
+
version_requirements: *id003
|
66
|
+
- !ruby/object:Gem::Dependency
|
49
67
|
name: rest-client
|
50
|
-
|
68
|
+
prerelease: false
|
69
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
51
70
|
none: false
|
52
|
-
requirements:
|
71
|
+
requirements:
|
53
72
|
- - ~>
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
hash: 3
|
75
|
+
segments:
|
76
|
+
- 1
|
77
|
+
- 6
|
78
|
+
version: "1.6"
|
56
79
|
type: :runtime
|
57
|
-
|
58
|
-
|
59
|
-
- !ruby/object:Gem::Dependency
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
60
82
|
name: json
|
61
|
-
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
62
85
|
none: false
|
63
|
-
requirements:
|
86
|
+
requirements:
|
64
87
|
- - ~>
|
65
|
-
- !ruby/object:Gem::Version
|
66
|
-
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 5
|
90
|
+
segments:
|
91
|
+
- 1
|
92
|
+
- 5
|
93
|
+
version: "1.5"
|
67
94
|
type: :runtime
|
68
|
-
|
69
|
-
|
70
|
-
- !ruby/object:Gem::Dependency
|
95
|
+
version_requirements: *id005
|
96
|
+
- !ruby/object:Gem::Dependency
|
71
97
|
name: highline
|
72
|
-
|
98
|
+
prerelease: false
|
99
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
73
100
|
none: false
|
74
|
-
requirements:
|
101
|
+
requirements:
|
75
102
|
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
hash: 3
|
105
|
+
segments:
|
106
|
+
- 1
|
107
|
+
- 6
|
108
|
+
version: "1.6"
|
78
109
|
type: :runtime
|
110
|
+
version_requirements: *id006
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: multipart-post
|
79
113
|
prerelease: false
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
114
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ~>
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
hash: 13
|
120
|
+
segments:
|
121
|
+
- 1
|
122
|
+
- 1
|
123
|
+
version: "1.1"
|
124
|
+
type: :runtime
|
125
|
+
version_requirements: *id007
|
126
|
+
description: |-
|
127
|
+
Tools for sites such as java.net that are hosted on the Kenai platform. Use dlutil to upload and download files.
|
128
|
+
Use wiki-copy to copy wiki contents and images from one project to another across sites.
|
129
|
+
email:
|
84
130
|
- edwin.goei@oracle.com
|
85
|
-
executables:
|
131
|
+
executables:
|
86
132
|
- dlutil
|
133
|
+
- wiki-copy
|
87
134
|
extensions: []
|
135
|
+
|
88
136
|
extra_rdoc_files: []
|
89
|
-
|
137
|
+
|
138
|
+
files:
|
90
139
|
- .gitignore
|
91
140
|
- Gemfile
|
92
141
|
- README.md
|
93
142
|
- Rakefile
|
94
143
|
- bin/dlutil
|
144
|
+
- bin/wiki-copy
|
95
145
|
- kenai_tools.gemspec
|
96
146
|
- lib/kenai_tools.rb
|
97
147
|
- lib/kenai_tools/downloads_client.rb
|
@@ -115,35 +165,55 @@ files:
|
|
115
165
|
- spec/fixtures/data/sax2r2.jar
|
116
166
|
- spec/fixtures/data/text1.txt
|
117
167
|
- spec/spec_helper.rb
|
168
|
+
has_rdoc: true
|
118
169
|
homepage: http://kenai.com/projects/kenaiapis
|
119
170
|
licenses: []
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
171
|
+
|
172
|
+
post_install_message: |+
|
173
|
+
|
174
|
+
==============================================================================
|
175
|
+
|
176
|
+
Thanks for installing kenai_tools. Run the following command for what to do
|
177
|
+
next:
|
178
|
+
|
179
|
+
dlutil --help
|
180
|
+
|
181
|
+
Warning: this tool is not yet supported on Windows. Please use a unix-based
|
182
|
+
OS. For more info, see http://kenai.com/jira/browse/KENAI-2853.
|
183
|
+
|
184
|
+
==============================================================================
|
185
|
+
|
186
|
+
|
124
187
|
rdoc_options: []
|
125
|
-
|
188
|
+
|
189
|
+
require_paths:
|
126
190
|
- lib
|
127
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
191
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
192
|
none: false
|
129
|
-
requirements:
|
130
|
-
- -
|
131
|
-
- !ruby/object:Gem::Version
|
132
|
-
|
133
|
-
|
193
|
+
requirements:
|
194
|
+
- - ">="
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
hash: 3
|
197
|
+
segments:
|
198
|
+
- 0
|
199
|
+
version: "0"
|
200
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
201
|
none: false
|
135
|
-
requirements:
|
136
|
-
- -
|
137
|
-
- !ruby/object:Gem::Version
|
138
|
-
|
202
|
+
requirements:
|
203
|
+
- - ">="
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
hash: 3
|
206
|
+
segments:
|
207
|
+
- 0
|
208
|
+
version: "0"
|
139
209
|
requirements: []
|
210
|
+
|
140
211
|
rubyforge_project: kenai_tools
|
141
|
-
rubygems_version: 1.
|
212
|
+
rubygems_version: 1.6.2
|
142
213
|
signing_key:
|
143
214
|
specification_version: 3
|
144
|
-
summary: Tools for sites hosted on the Kenai platform. Use dlutil to
|
145
|
-
|
146
|
-
test_files:
|
215
|
+
summary: Tools for sites hosted on the Kenai platform. Use dlutil to manage downloads and wiki-copy to copy wikis.
|
216
|
+
test_files:
|
147
217
|
- spec/downloads_client_spec.rb
|
148
218
|
- spec/fixtures/data/irs_docs/irs-form-1040.pdf
|
149
219
|
- spec/fixtures/data/irs_docs/irs-p555.pdf
|