oplop 0.0.7 → 2.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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/Gemfile +1 -1
- data/README.md +35 -4
- data/bin/loplop +68 -0
- data/bin/oplop +7 -4
- data/lib/oplop/cli.rb +22 -8
- data/lib/oplop/v1.rb +47 -0
- data/lib/oplop/version.rb +1 -1
- data/lib/oplop.rb +2 -41
- data/oplop.gemspec +7 -5
- data/shippable.yml +16 -0
- data/spec/oplop_spec.rb +7 -23
- data/spec/{testdata.json → testdata/v1.json} +0 -0
- metadata +83 -76
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: da687d83f164bc06c61d8013127d72fd41ae7bc3974c5f6976fba4b1dbf1cce3
|
4
|
+
data.tar.gz: ae5d3252688c2f38766ef9d31d078723c394a8c28021c7b1ce85aa717484f0c3
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d55f5ecc8bcc8d2132b647893c86300b1bfc49221183e4e4164fd463cd2f66a16d5fba7880f3aba7c23d0c21a50a4ede2ac4d6fed2d1281e95a382edcd0bb57d
|
7
|
+
data.tar.gz: 9be6c692c906b38ec9dfc584a4aab1f68cdeec303b18df6d09f586eed6ed4732dea9288d7c4af0defac44e2e27717ca9cf9b83f76280ef6f9de364679683d069
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.5.0
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,19 +1,50 @@
|
|
1
1
|
Oplop
|
2
2
|
=====
|
3
3
|
|
4
|
-
This is a ruby implementation of Oplop http://code.google.com/p/oplop/
|
4
|
+
This is a ruby implementation of Oplop http://code.google.com/p/oplop/, supporting the long oplop variation (see: https://github.com/thedod/loplop).
|
5
5
|
|
6
6
|
Install
|
7
7
|
=======
|
8
8
|
|
9
|
-
|
9
|
+
```
|
10
|
+
gem install oplop
|
11
|
+
```
|
10
12
|
|
11
13
|
Usage
|
12
14
|
=====
|
13
15
|
|
14
|
-
|
16
|
+
Oplop and Loplop. Long Oplop defaults to 16 characters and support `<n>*` label
|
17
|
+
prefix for specifying length.
|
18
|
+
|
19
|
+
These will all produce the same password with the new default 16 character length:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
Oplop::V1.password(:master => "master-password", :label => "nickname")
|
23
|
+
Oplop::V1.password(:master => "master-password", :label => "16*nickname")
|
24
|
+
Oplop::V1.password(:master => "master-password", :label => "nickname", :length => 16)
|
25
|
+
```
|
26
|
+
|
27
|
+
These will all produce the same password with the legacy 8 character length:
|
28
|
+
```
|
29
|
+
Oplop::V1.password(:master => "master-password", :label => "*nickname")
|
30
|
+
Oplop::V1.password(:master => "master-password", :label => "8*nickname")
|
31
|
+
Oplop::V1.password(:master => "master-password", :label => "nickname", :length => 8)
|
32
|
+
```
|
33
|
+
|
34
|
+
This is a 20-character password
|
35
|
+
```
|
36
|
+
Oplop::V1.password(:master => "master-password", :label => "20*nickname")
|
37
|
+
```
|
15
38
|
|
16
39
|
CLI
|
17
40
|
===
|
18
41
|
|
19
|
-
This includes an `oplop` program
|
42
|
+
This includes an `oplop` program that defaults to 8 character passwords. And a
|
43
|
+
new `loplop` program that defaults to 16 character passwords.
|
44
|
+
|
45
|
+
Run `oplop --help` for more information.
|
46
|
+
|
47
|
+
License
|
48
|
+
=======
|
49
|
+
|
50
|
+
MIT
|
data/bin/loplop
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
oplop_dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
$LOAD_PATH.unshift(oplop_dir) unless $LOAD_PATH.include?(oplop_dir)
|
4
|
+
|
5
|
+
require 'oplop'
|
6
|
+
require 'oplop/cli'
|
7
|
+
require 'highline/import'
|
8
|
+
require 'optparse'
|
9
|
+
|
10
|
+
# -- exit nicely if control-c
|
11
|
+
Signal.trap("SIGINT") { exit 2 }
|
12
|
+
|
13
|
+
# -- options
|
14
|
+
options = {}
|
15
|
+
optparse = OptionParser.new do |opts|
|
16
|
+
opts.banner = Oplop::Cli.banner
|
17
|
+
|
18
|
+
options[:verbose] = false
|
19
|
+
opts.on( '-v', '--verbose', 'Output the password to STDOUT' ) do
|
20
|
+
options[:verbose] = true
|
21
|
+
end
|
22
|
+
|
23
|
+
options[:new] = false
|
24
|
+
opts.on( '-n', '--new', 'New mode (2 prompt for master)') do
|
25
|
+
options[:new] = true
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
29
|
+
puts opts
|
30
|
+
puts "\n"
|
31
|
+
puts Oplop::Cli.help
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
end.parse!
|
36
|
+
|
37
|
+
# -- program
|
38
|
+
label = ARGV.shift
|
39
|
+
|
40
|
+
if label.nil? or label.empty?
|
41
|
+
puts "!! You need to pass in a label!"
|
42
|
+
exit 2
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
master = ask("Enter your master password: ") { |q| q.echo = "*" }
|
47
|
+
|
48
|
+
if options[:new]
|
49
|
+
master_confirm = ask("Enter your master password (again): ") { |q| q.echo = "*" }
|
50
|
+
if (master != master_confirm)
|
51
|
+
puts "!! Your master and confirm don't match!"
|
52
|
+
exit 2
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
password = Oplop.password(:label => label, :master => master)
|
57
|
+
|
58
|
+
if options[:verbose]
|
59
|
+
puts "\n Password for #{label}:\t#{password}\n\n"
|
60
|
+
end
|
61
|
+
|
62
|
+
if Oplop::Cli.copy_to_clipboard(password)
|
63
|
+
print "Your #{label} password has been copied to your clipboard. \n"
|
64
|
+
else
|
65
|
+
print "!! Could not copy to clipboard, try installing xclip. "
|
66
|
+
print "Run with --verbose flag to see password on STDOUT." unless options[:verbose]
|
67
|
+
print "\n"
|
68
|
+
end
|
data/bin/oplop
CHANGED
@@ -7,6 +7,9 @@ require 'oplop/cli'
|
|
7
7
|
require 'highline/import'
|
8
8
|
require 'optparse'
|
9
9
|
|
10
|
+
# -- exit nicely if control-c
|
11
|
+
Signal.trap("SIGINT") { exit 2 }
|
12
|
+
|
10
13
|
# -- options
|
11
14
|
options = {}
|
12
15
|
optparse = OptionParser.new do |opts|
|
@@ -39,18 +42,18 @@ if label.nil? or label.empty?
|
|
39
42
|
exit 2
|
40
43
|
end
|
41
44
|
|
45
|
+
|
46
|
+
master = ask("Enter your master password: ") { |q| q.echo = "*" }
|
47
|
+
|
42
48
|
if options[:new]
|
43
|
-
master = ask("Enter your master password: ") { |q| q.echo = "*" }
|
44
49
|
master_confirm = ask("Enter your master password (again): ") { |q| q.echo = "*" }
|
45
50
|
if (master != master_confirm)
|
46
51
|
puts "!! Your master and confirm don't match!"
|
47
52
|
exit 2
|
48
53
|
end
|
49
|
-
else
|
50
|
-
master = ask("Enter your master password: ") { |q| q.echo = "*" }
|
51
54
|
end
|
52
55
|
|
53
|
-
password = Oplop.password(:label => label, :master => master)
|
56
|
+
password = Oplop::V1.password(:label => label, :master => master, :length => Oplop::V1::LEGACY_LENGTH)
|
54
57
|
|
55
58
|
if options[:verbose]
|
56
59
|
puts "\n Password for #{label}:\t#{password}\n\n"
|
data/lib/oplop/cli.rb
CHANGED
@@ -2,7 +2,7 @@ require 'open3'
|
|
2
2
|
|
3
3
|
module Oplop
|
4
4
|
module Cli
|
5
|
-
|
5
|
+
|
6
6
|
def self.banner
|
7
7
|
"Usage: oplop [OPTIONS] [label]"
|
8
8
|
end
|
@@ -11,14 +11,14 @@ module Oplop
|
|
11
11
|
help = <<-HELP
|
12
12
|
This is a simple cli program to generate oplop passwords.
|
13
13
|
|
14
|
-
You will be prompted for your master password.
|
14
|
+
You will be prompted for your master password.
|
15
15
|
|
16
|
-
The default behavior is to copy the password to your clipboard, and
|
17
|
-
|
18
|
-
|
16
|
+
The default behavior is to copy the password to your clipboard, and not display
|
17
|
+
it. This works if you are on a Mac (and/or have pbcopy installed), or if you
|
18
|
+
have xclip (installed for Linux).
|
19
19
|
|
20
|
-
If you do not have pbcopy or xclip, you will have to run the program
|
21
|
-
|
20
|
+
If you do not have pbcopy or xclip, you will have to run the program in verbose
|
21
|
+
mode (--verbose).
|
22
22
|
|
23
23
|
Here are some examples:
|
24
24
|
|
@@ -31,6 +31,20 @@ Print my gmail password to STDOUT.
|
|
31
31
|
Copy a new password for amazon (prompts for master twice):
|
32
32
|
oplop --new amazon
|
33
33
|
|
34
|
+
NEW: loplop
|
35
|
+
|
36
|
+
There is a new cli program called `loplop`, or long oplop. It will default to
|
37
|
+
passwords of 16 characters. It also has a new UX feature to specify the length:
|
38
|
+
|
39
|
+
loplop <n>*<label>
|
40
|
+
|
41
|
+
Where <n> is how long the password will be. The max is 22 characters. If you
|
42
|
+
start a label with *, it is a short-cut to the legacy length 8 (in other words
|
43
|
+
`8*label` and `*label` will generate the same password).
|
44
|
+
|
45
|
+
See: https://github.com/thedod/loplop
|
46
|
+
|
47
|
+
|
34
48
|
Feedback, patches and bugs: https://github.com/bkaney/oplop
|
35
49
|
HELP
|
36
50
|
end
|
@@ -53,6 +67,6 @@ HELP
|
|
53
67
|
end
|
54
68
|
end
|
55
69
|
end
|
56
|
-
|
70
|
+
|
57
71
|
end
|
58
72
|
end
|
data/lib/oplop/v1.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module Oplop
|
5
|
+
class V1
|
6
|
+
attr_reader :master, :label, :length
|
7
|
+
|
8
|
+
LEGACY_LENGTH = 8
|
9
|
+
DEFAULT_LENGTH = 16
|
10
|
+
|
11
|
+
def self.password(args={})
|
12
|
+
self.new(args).password
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(args={})
|
16
|
+
@master = args[:master]
|
17
|
+
@label = args[:label]
|
18
|
+
@length = args[:length] || DEFAULT_LENGTH
|
19
|
+
|
20
|
+
if @label =~ /^([0-9]*)?\*/
|
21
|
+
(@length, @label) = @label.split('*')
|
22
|
+
@length = length.to_i
|
23
|
+
@length = LEGACY_LENGTH if length <= 0
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def master_label
|
28
|
+
@master_label ||= '%s%s' % [ master, label ]
|
29
|
+
end
|
30
|
+
|
31
|
+
def password
|
32
|
+
password = Base64.urlsafe_encode64(Digest::MD5.digest(master_label))
|
33
|
+
|
34
|
+
if password.respond_to?(:encode)
|
35
|
+
password = password.encode('UTF-8')
|
36
|
+
end
|
37
|
+
|
38
|
+
if m = password.match(/\d+/)
|
39
|
+
password = '%s%s' % [ m[0], password ] if (m.begin(0) >= length)
|
40
|
+
else
|
41
|
+
password = '1%s' % password
|
42
|
+
end
|
43
|
+
|
44
|
+
password[0,length]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/oplop/version.rb
CHANGED
data/lib/oplop.rb
CHANGED
@@ -1,42 +1,3 @@
|
|
1
|
-
|
2
|
-
require 'base64'
|
1
|
+
module Oplop; end
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
LENGTH = 8
|
7
|
-
|
8
|
-
#
|
9
|
-
# Oplop.password(:master => 'p@ssw0rd', :label => 'github')
|
10
|
-
#
|
11
|
-
def self.password(args={})
|
12
|
-
unless (args.keys.include?(:master) && args.keys.include?(:label))
|
13
|
-
raise ArgumentError.new 'Master and label are required arguments.'
|
14
|
-
end
|
15
|
-
|
16
|
-
master_label = '%s%s' % [ args.delete(:master), args.delete(:label) ]
|
17
|
-
|
18
|
-
raise ArgumentError.new "Unknown keys #{args.keys.join(',')}." if args.keys.any?
|
19
|
-
|
20
|
-
|
21
|
-
password = urlsafe_b64encode(Digest::MD5.digest(master_label))
|
22
|
-
|
23
|
-
if password.respond_to?(:encode)
|
24
|
-
password = password.encode('UTF-8')
|
25
|
-
end
|
26
|
-
|
27
|
-
if m = password.match(/\d+/)
|
28
|
-
password = '%s%s' % [ m[0], password ] if (m.begin(0) >= LENGTH)
|
29
|
-
else
|
30
|
-
password = '1%s' % password
|
31
|
-
end
|
32
|
-
|
33
|
-
password[0,LENGTH]
|
34
|
-
end
|
35
|
-
|
36
|
-
# See http://www.ietf.org/rfc/rfc4648.txt
|
37
|
-
# Ruby 1.8.x does not have this as part of the Base64 lib
|
38
|
-
def self.urlsafe_b64encode(string)
|
39
|
-
Base64.encode64(string).tr('+/', '-_')
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
3
|
+
require 'oplop/v1'
|
data/oplop.gemspec
CHANGED
@@ -11,14 +11,16 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = "http://github.com/bkaney/oplop"
|
12
12
|
s.summary = %q{Oplop for Ruby}
|
13
13
|
s.description = %q{Provides a ruby library and command line tool for Oplop}
|
14
|
+
s.license = 'MIT'
|
14
15
|
|
15
16
|
s.rubyforge_project = "oplop"
|
16
17
|
|
17
|
-
s.add_dependency
|
18
|
-
|
19
|
-
s.add_development_dependency
|
20
|
-
s.add_development_dependency
|
21
|
-
|
18
|
+
s.add_dependency 'highline', '~> 2.0'
|
19
|
+
|
20
|
+
s.add_development_dependency 'rake', '~> 13.0'
|
21
|
+
s.add_development_dependency 'rspec', '~> 3.11'
|
22
|
+
s.add_development_dependency 'yajl-ruby', '~> 1.4'
|
23
|
+
|
22
24
|
s.files = `git ls-files`.split("\n")
|
23
25
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
26
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
data/shippable.yml
ADDED
data/spec/oplop_spec.rb
CHANGED
@@ -1,34 +1,18 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Oplop do
|
4
|
-
|
3
|
+
describe Oplop::V1 do
|
5
4
|
describe ".password" do
|
6
|
-
|
7
|
-
specify "valid arguments" do
|
8
|
-
lambda{ Oplop.password(:master => "a", :label => "a") }.should_not raise_error(ArgumentError)
|
9
|
-
end
|
10
|
-
|
11
|
-
specify "invalid arguments" do
|
12
|
-
lambda{ Oplop.password }.should raise_error(ArgumentError, /Master and label are required/)
|
13
|
-
end
|
14
|
-
|
15
|
-
specify "invalid arguments" do
|
16
|
-
lambda{ Oplop.password(:master => "a", :label => "b", :foo => 'c') }.should raise_error(ArgumentError, /Unknown key/)
|
17
|
-
end
|
18
|
-
|
19
5
|
context "tests from testdata.json (see Python implementation at http://code.google.com/p/oplop/)" do
|
20
|
-
|
21
6
|
# loop around each "case" in testdata.yml
|
22
|
-
Yajl::Parser.new.parse(File.new(File.dirname(__FILE__) + "/testdata.json", 'r')).each do |testdata|
|
23
|
-
|
7
|
+
Yajl::Parser.new.parse(File.new(File.dirname(__FILE__) + "/testdata/v1.json", 'r')).each do |testdata|
|
24
8
|
specify testdata["why"] do
|
25
|
-
Oplop.password(:master => testdata["master"], :label =>
|
26
|
-
|
9
|
+
password = Oplop::V1.password(:master => testdata["master"], :label => "*" + testdata["label"])
|
10
|
+
expect(password).to eq testdata["password"]
|
27
11
|
|
12
|
+
password = Oplop::V1.password(:master => testdata["master"], :length => 8, :label => testdata["label"])
|
13
|
+
expect(password).to eq testdata["password"]
|
14
|
+
end
|
28
15
|
end
|
29
|
-
|
30
16
|
end
|
31
|
-
|
32
17
|
end
|
33
|
-
|
34
18
|
end
|
File without changes
|
metadata
CHANGED
@@ -1,113 +1,120 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: oplop
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.0.7
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.1.0
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
6
|
+
authors:
|
8
7
|
- Brian Kaney
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2022-07-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
17
14
|
name: highline
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
- !ruby/object:Gem::Version
|
24
|
-
version: 1.6.1
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
25
20
|
type: :runtime
|
26
|
-
version_requirements: *id001
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: ruby-debug19
|
29
21
|
prerelease: false
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '13.0'
|
36
34
|
type: :development
|
37
|
-
version_requirements: *id002
|
38
|
-
- !ruby/object:Gem::Dependency
|
39
|
-
name: rspec
|
40
35
|
prerelease: false
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '13.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.11'
|
47
48
|
type: :development
|
48
|
-
version_requirements: *id003
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: yajl-ruby
|
51
49
|
prerelease: false
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.11'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yajl-ruby
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.4'
|
58
62
|
type: :development
|
59
|
-
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.4'
|
60
69
|
description: Provides a ruby library and command line tool for Oplop
|
61
|
-
email:
|
70
|
+
email:
|
62
71
|
- brian@vermonster.com
|
63
|
-
executables:
|
72
|
+
executables:
|
73
|
+
- loplop
|
64
74
|
- oplop
|
65
75
|
extensions: []
|
66
|
-
|
67
76
|
extra_rdoc_files: []
|
68
|
-
|
69
|
-
|
70
|
-
- .
|
77
|
+
files:
|
78
|
+
- ".gitignore"
|
79
|
+
- ".ruby-version"
|
71
80
|
- Gemfile
|
72
81
|
- README.md
|
73
82
|
- Rakefile
|
83
|
+
- bin/loplop
|
74
84
|
- bin/oplop
|
75
85
|
- lib/oplop.rb
|
76
86
|
- lib/oplop/cli.rb
|
87
|
+
- lib/oplop/v1.rb
|
77
88
|
- lib/oplop/version.rb
|
78
89
|
- oplop.gemspec
|
90
|
+
- shippable.yml
|
79
91
|
- spec/oplop_spec.rb
|
80
92
|
- spec/spec_helper.rb
|
81
|
-
- spec/testdata.json
|
82
|
-
has_rdoc: true
|
93
|
+
- spec/testdata/v1.json
|
83
94
|
homepage: http://github.com/bkaney/oplop
|
84
|
-
licenses:
|
85
|
-
|
86
|
-
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
87
99
|
rdoc_options: []
|
88
|
-
|
89
|
-
require_paths:
|
100
|
+
require_paths:
|
90
101
|
- lib
|
91
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
-
|
93
|
-
requirements:
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
94
104
|
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version:
|
97
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
-
|
99
|
-
requirements:
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
100
109
|
- - ">="
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
version:
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
103
112
|
requirements: []
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
signing_key:
|
108
|
-
specification_version: 3
|
113
|
+
rubygems_version: 3.3.7
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
109
116
|
summary: Oplop for Ruby
|
110
|
-
test_files:
|
117
|
+
test_files:
|
111
118
|
- spec/oplop_spec.rb
|
112
119
|
- spec/spec_helper.rb
|
113
|
-
- spec/testdata.json
|
120
|
+
- spec/testdata/v1.json
|