roku-packager 0.0.1
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/.gitignore +17 -0
- data/.travis.yml +8 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +70 -0
- data/Rakefile +12 -0
- data/lib/roku-packager.rb +8 -0
- data/lib/roku-packager/client.rb +32 -0
- data/lib/roku-packager/genkey_output.rb +17 -0
- data/lib/roku-packager/key_gen.rb +45 -0
- data/lib/roku-packager/packager.rb +45 -0
- data/lib/roku-packager/uploader.rb +29 -0
- data/lib/roku-packager/version.rb +3 -0
- data/roku-packager.gemspec +24 -0
- data/spec/roku-packager/genkey_output_spec.rb +29 -0
- data/spec/roku-packager/key_gen_spec.rb +36 -0
- data/spec/roku-packager/packager_spec.rb +27 -0
- data/spec/roku-packager/uploader_spec.rb +22 -0
- data/spec/spec_helper.rb +4 -0
- metadata +119 -0
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 brookemckim
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# Roku Packager
|
2
|
+
|
3
|
+
Roku Packager is a ruby library for uploading and packaging Roku
|
4
|
+
applications. Normally this interaction has to be done through the
|
5
|
+
clunky Roku web GUI. Given a Roku with the installer enabled and a compiled zip
|
6
|
+
of your code you can pass it to Roku Packager and it will return the url
|
7
|
+
to dowload the pkg file that is ready for upload to roku.com.
|
8
|
+
|
9
|
+
[](https://travis-ci.org/brookemckim/roku-packager)
|
10
|
+
[](https://codeclimate.com/github/brookemckim/roku-packager)
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
gem 'roku-packager'
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install roku-packager
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
First you need a Roku in development mode on your network and a zip file of
|
31
|
+
your Roku source file.
|
32
|
+
|
33
|
+
Then you can instansiate a client.
|
34
|
+
```
|
35
|
+
ip_of_your_roku = '192.168.0.10'
|
36
|
+
roku = RokuPackager.new(ip_of_your_roku)
|
37
|
+
|
38
|
+
# Pass in a logger for inside information.
|
39
|
+
roku = RokuPackager.new(ip_of_your_roku, Logger.new(STDOUT))
|
40
|
+
|
41
|
+
# This may take a couple minutes. Generating the keys is the slowest part.
|
42
|
+
roku.package('application_name', '/path/to/roku/app.zip')
|
43
|
+
# => http://192.168.0.10/pkg/app.pkg
|
44
|
+
```
|
45
|
+
|
46
|
+
You can then download this package with your tool of choice.
|
47
|
+
```
|
48
|
+
wget http://192.168.0.10/pkg/app.pkg
|
49
|
+
```
|
50
|
+
|
51
|
+
Each part of the process can be used as a standalone piece.
|
52
|
+
```
|
53
|
+
# Generate DevID and Password.
|
54
|
+
dev_id, password = RokuPackager::KeyGen.new(ip_of_your_roku).create
|
55
|
+
|
56
|
+
# Upload application zip.
|
57
|
+
RokuPackager::Uploader.new(ip_of_your_roku).run('/path/to/app.zip')
|
58
|
+
|
59
|
+
# Package an uploaded application.
|
60
|
+
download_uri = RokuPackager::Packager.new(ip_of_your_roku, 'application_name',
|
61
|
+
password).submit
|
62
|
+
```
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
1. Fork it
|
67
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
68
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
69
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
70
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'roku-packager/key_gen'
|
2
|
+
require 'roku-packager/uploader'
|
3
|
+
require 'roku-packager/packager'
|
4
|
+
|
5
|
+
module RokuPackager
|
6
|
+
class Client
|
7
|
+
def initialize(development_roku_ip, logger = NullLogger)
|
8
|
+
@host = development_roku_ip
|
9
|
+
@logger = logger
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :password, :dev_id, :download_url
|
13
|
+
|
14
|
+
def package(name, path_to_application_zip)
|
15
|
+
@logger.info 'Generating keys...'
|
16
|
+
@dev_id, @password = KeyGen.new(@host).create
|
17
|
+
|
18
|
+
@logger.info 'Uploading application file...'
|
19
|
+
Uploader.new(@host).upload(path_to_application_zip)
|
20
|
+
|
21
|
+
@logger.info 'Building package...'
|
22
|
+
uri = Packager.new(@host, name, @password).submit
|
23
|
+
|
24
|
+
uri.to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class NullLogger
|
29
|
+
def info
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RokuPackager
|
2
|
+
module GenkeyOutput
|
3
|
+
def parse(output)
|
4
|
+
dev_id, password = nil, nil
|
5
|
+
|
6
|
+
if (match = /Password: (\S*)/.match(output))
|
7
|
+
password = match[1]
|
8
|
+
end
|
9
|
+
|
10
|
+
if (match = /DevID: (\S*)/.match(output))
|
11
|
+
dev_id = match[1]
|
12
|
+
end
|
13
|
+
|
14
|
+
[dev_id, password]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'net/telnet'
|
2
|
+
require 'roku-packager/genkey_output'
|
3
|
+
|
4
|
+
module RokuPackager
|
5
|
+
class KeyGen
|
6
|
+
class ConnectionError < StandardError; end
|
7
|
+
class GenerationError < StandardError; end
|
8
|
+
|
9
|
+
def initialize(roku_hostname)
|
10
|
+
@hostname = roku_hostname
|
11
|
+
end
|
12
|
+
|
13
|
+
def create
|
14
|
+
dev_id, password = parse(generate)
|
15
|
+
|
16
|
+
if dev_id && password
|
17
|
+
[dev_id, password]
|
18
|
+
else
|
19
|
+
raise GenerationError, 'Error generating credentials'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def generate
|
24
|
+
output_from_connection = ''
|
25
|
+
|
26
|
+
connection.cmd('genkey') do |output|
|
27
|
+
output_from_connection << output
|
28
|
+
end
|
29
|
+
rescue Timeout::Error
|
30
|
+
output_from_connection
|
31
|
+
end
|
32
|
+
|
33
|
+
def connection
|
34
|
+
@connection ||= Net::Telnet::new("Host" => @hostname, "Port" => '8080')
|
35
|
+
rescue Errno::ECONNREFUSED
|
36
|
+
raise ConnectionError, 'Connection to device was refused. Possibly wrong host.'
|
37
|
+
rescue Timeout::Error
|
38
|
+
raise ConnectionError, 'Connection to device failed. Host is possibly down.'
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
include GenkeyOutput
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'uri'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module RokuPackager
|
6
|
+
class Packager
|
7
|
+
class PackagingError < StandardError; end
|
8
|
+
|
9
|
+
def initialize(host, name_and_version, password)
|
10
|
+
@host = host
|
11
|
+
@name_and_version = name_and_version
|
12
|
+
@password = password
|
13
|
+
end
|
14
|
+
|
15
|
+
def submit
|
16
|
+
if relative_path_match = pull_out_relative_package_path(submission_response)
|
17
|
+
relative_path = relative_path_match[1]
|
18
|
+
else
|
19
|
+
raise PackagingError, submission_response
|
20
|
+
end
|
21
|
+
|
22
|
+
URI::HTTP.build(host: @host, path: '/' + relative_path)
|
23
|
+
end
|
24
|
+
|
25
|
+
def submission_response
|
26
|
+
parameters = { passwd: @password,
|
27
|
+
pkg_time: Time.now.to_i,
|
28
|
+
app_name: @name_and_version,
|
29
|
+
mysubmit: 'Package',
|
30
|
+
multipart: true }
|
31
|
+
|
32
|
+
RestClient.post url.to_s, parameters
|
33
|
+
end
|
34
|
+
|
35
|
+
def url
|
36
|
+
@url ||= URI::HTTP.build(host: @host, path: '/plugin_package')
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def pull_out_relative_package_path(html_body)
|
42
|
+
/a href="(pkgs\S*)">/.match(html_body)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'rest_client'
|
3
|
+
|
4
|
+
module RokuPackager
|
5
|
+
class Uploader
|
6
|
+
def initialize(host)
|
7
|
+
@host = host
|
8
|
+
end
|
9
|
+
|
10
|
+
def run(file)
|
11
|
+
delete
|
12
|
+
upload(file)
|
13
|
+
end
|
14
|
+
|
15
|
+
def upload(file)
|
16
|
+
parameters = { archive: File.new(file), mysubmit: 'Replace' }
|
17
|
+
RestClient.post url.to_s, parameters
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete
|
21
|
+
parameters = { mysubmit: 'Delete', archive: nil, multipart: true }
|
22
|
+
RestClient.post url.to_s, parameters
|
23
|
+
end
|
24
|
+
|
25
|
+
def url
|
26
|
+
@url ||= URI::HTTP.build(host: @host, path: '/plugin_install')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'roku-packager/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "roku-packager"
|
8
|
+
gem.version = RokuPackager::VERSION
|
9
|
+
gem.authors = ["brookemckim"]
|
10
|
+
gem.email = ["brooke.mckim@gmail.com"]
|
11
|
+
gem.description = %q{Ruby library for packaging Roku applications. Requires a Roku in development mode and a zipped up application.}
|
12
|
+
gem.summary = %q{Package roku applications from within Ruby.}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency 'rest-client', '~> 1.6.6'
|
21
|
+
|
22
|
+
gem.add_development_dependency 'mocha'
|
23
|
+
gem.add_development_dependency 'minitest'
|
24
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RokuPackager::GenkeyOutput do
|
4
|
+
before do
|
5
|
+
class Genkey
|
6
|
+
extend RokuPackager::GenkeyOutput
|
7
|
+
end
|
8
|
+
|
9
|
+
@output =<<EOF
|
10
|
+
.
|
11
|
+
.
|
12
|
+
.
|
13
|
+
.
|
14
|
+
+
|
15
|
+
+
|
16
|
+
+
|
17
|
+
Password: jO3nThMQZxaAMSH2a1mIiw==
|
18
|
+
DevID: 65b331d470432d609fec8c5f78e09683559e56b9
|
19
|
+
>
|
20
|
+
EOF
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'parses out devid and password' do
|
24
|
+
Genkey.parse(@output).must_equal [
|
25
|
+
'65b331d470432d609fec8c5f78e09683559e56b9',
|
26
|
+
'jO3nThMQZxaAMSH2a1mIiw=='
|
27
|
+
]
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RokuPackager::KeyGen do
|
4
|
+
describe '#create' do
|
5
|
+
before do
|
6
|
+
@key_gen = RokuPackager::KeyGen.new('192.168.1.10')
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'returns parsed_output' do
|
10
|
+
@key_gen.expects(:generate).returns('output_from_device')
|
11
|
+
@key_gen.expects(:parse)
|
12
|
+
.with('output_from_device').returns(['devid', 'password'])
|
13
|
+
|
14
|
+
@key_gen.create.must_equal ['devid', 'password']
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'raises exception if dev_id is nil' do
|
18
|
+
@key_gen.stubs(:generate).returns(nil)
|
19
|
+
@key_gen.stubs(:parse).returns([nil, 'password'])
|
20
|
+
|
21
|
+
lambda {
|
22
|
+
@key_gen.create
|
23
|
+
}.must_raise RokuPackager::KeyGen::GenerationError
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'raises exception if password is nil' do
|
27
|
+
@key_gen.stubs(:generate).returns(nil)
|
28
|
+
@key_gen.stubs(:parse).returns(['devid', nil])
|
29
|
+
|
30
|
+
lambda {
|
31
|
+
@key_gen.create
|
32
|
+
}.must_raise RokuPackager::KeyGen::GenerationError
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RokuPackager::Packager do
|
4
|
+
before do
|
5
|
+
host = '192.168.0.10'
|
6
|
+
name_and_version = 'Lol 1.0'
|
7
|
+
password = 'sporks'
|
8
|
+
|
9
|
+
@packager = RokuPackager::Packager.new(host, name_and_version, password)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#url' do
|
13
|
+
it 'builds a the proper url' do
|
14
|
+
@packager.url.must_equal URI('http://192.168.0.10/plugin_package')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#submit' do
|
19
|
+
it 'builds a download url for the submitted package' do
|
20
|
+
@packager.expects(:submission_response).returns(nil)
|
21
|
+
@packager.expects(:pull_out_relative_package_path).returns([nil,'pkg/blah.zip'])
|
22
|
+
|
23
|
+
@packager.submit.must_equal URI('http://192.168.0.10/pkg/blah.zip')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RokuPackager::Uploader do
|
4
|
+
before do
|
5
|
+
@uploader = RokuPackager::Uploader.new("192.168.0.10")
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#run' do
|
9
|
+
it 'deletes and then uploads the file' do
|
10
|
+
@uploader.expects(:delete)
|
11
|
+
@uploader.expects(:upload).with('afile')
|
12
|
+
|
13
|
+
@uploader.run('afile')
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '#url' do
|
18
|
+
it 'builds a proper url' do
|
19
|
+
@uploader.url.must_equal URI("http://192.168.0.10/plugin_install")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: roku-packager
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- brookemckim
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-11-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rest-client
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.6.6
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.6.6
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: mocha
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: minitest
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Ruby library for packaging Roku applications. Requires a Roku in development
|
63
|
+
mode and a zipped up application.
|
64
|
+
email:
|
65
|
+
- brooke.mckim@gmail.com
|
66
|
+
executables: []
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- .gitignore
|
71
|
+
- .travis.yml
|
72
|
+
- Gemfile
|
73
|
+
- LICENSE.txt
|
74
|
+
- README.md
|
75
|
+
- Rakefile
|
76
|
+
- lib/roku-packager.rb
|
77
|
+
- lib/roku-packager/client.rb
|
78
|
+
- lib/roku-packager/genkey_output.rb
|
79
|
+
- lib/roku-packager/key_gen.rb
|
80
|
+
- lib/roku-packager/packager.rb
|
81
|
+
- lib/roku-packager/uploader.rb
|
82
|
+
- lib/roku-packager/version.rb
|
83
|
+
- roku-packager.gemspec
|
84
|
+
- spec/roku-packager/genkey_output_spec.rb
|
85
|
+
- spec/roku-packager/key_gen_spec.rb
|
86
|
+
- spec/roku-packager/packager_spec.rb
|
87
|
+
- spec/roku-packager/uploader_spec.rb
|
88
|
+
- spec/spec_helper.rb
|
89
|
+
homepage: ''
|
90
|
+
licenses: []
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ! '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 1.8.24
|
110
|
+
signing_key:
|
111
|
+
specification_version: 3
|
112
|
+
summary: Package roku applications from within Ruby.
|
113
|
+
test_files:
|
114
|
+
- spec/roku-packager/genkey_output_spec.rb
|
115
|
+
- spec/roku-packager/key_gen_spec.rb
|
116
|
+
- spec/roku-packager/packager_spec.rb
|
117
|
+
- spec/roku-packager/uploader_spec.rb
|
118
|
+
- spec/spec_helper.rb
|
119
|
+
has_rdoc:
|