ruby-libstorj 0.0.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.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/Gemfile +23 -0
  6. data/Gemfile.lock +111 -0
  7. data/Guardfile +21 -0
  8. data/LICENSE +502 -0
  9. data/README.md +262 -0
  10. data/Rakefile +76 -0
  11. data/ext/libstorj/.gitignore +47 -0
  12. data/ext/libstorj/.travis.yml +27 -0
  13. data/ext/libstorj/Doxyfile +2427 -0
  14. data/ext/libstorj/LICENSE +502 -0
  15. data/ext/libstorj/Makefile.am +6 -0
  16. data/ext/libstorj/README.md +198 -0
  17. data/ext/libstorj/autogen.sh +3 -0
  18. data/ext/libstorj/configure.ac +64 -0
  19. data/ext/libstorj/depends/Makefile +153 -0
  20. data/ext/libstorj/depends/config.guess +1462 -0
  21. data/ext/libstorj/depends/config.sub +1823 -0
  22. data/ext/libstorj/depends/extract-osx-sdk.sh +33 -0
  23. data/ext/libstorj/depends/packages/cctools.mk +7 -0
  24. data/ext/libstorj/depends/packages/clang.mk +7 -0
  25. data/ext/libstorj/depends/packages/gmp.mk +23 -0
  26. data/ext/libstorj/depends/packages/gnutls.mk +25 -0
  27. data/ext/libstorj/depends/packages/json-c.mk +7 -0
  28. data/ext/libstorj/depends/packages/libcurl.mk +39 -0
  29. data/ext/libstorj/depends/packages/libmicrohttpd.mk +7 -0
  30. data/ext/libstorj/depends/packages/libuv.mk +7 -0
  31. data/ext/libstorj/depends/packages/nettle.mk +30 -0
  32. data/ext/libstorj/libstorj.pc.in +11 -0
  33. data/ext/libstorj/src/Makefile.am +23 -0
  34. data/ext/libstorj/src/bip39.c +233 -0
  35. data/ext/libstorj/src/bip39.h +64 -0
  36. data/ext/libstorj/src/bip39_english.h +2074 -0
  37. data/ext/libstorj/src/cli.c +1494 -0
  38. data/ext/libstorj/src/crypto.c +525 -0
  39. data/ext/libstorj/src/crypto.h +178 -0
  40. data/ext/libstorj/src/downloader.c +1923 -0
  41. data/ext/libstorj/src/downloader.h +163 -0
  42. data/ext/libstorj/src/http.c +688 -0
  43. data/ext/libstorj/src/http.h +175 -0
  44. data/ext/libstorj/src/rs.c +962 -0
  45. data/ext/libstorj/src/rs.h +99 -0
  46. data/ext/libstorj/src/storj.c +1523 -0
  47. data/ext/libstorj/src/storj.h +1014 -0
  48. data/ext/libstorj/src/uploader.c +2736 -0
  49. data/ext/libstorj/src/uploader.h +181 -0
  50. data/ext/libstorj/src/utils.c +336 -0
  51. data/ext/libstorj/src/utils.h +65 -0
  52. data/ext/libstorj/test/Makefile.am +27 -0
  53. data/ext/libstorj/test/mockbridge.c +260 -0
  54. data/ext/libstorj/test/mockbridge.json +687 -0
  55. data/ext/libstorj/test/mockbridgeinfo.json +1836 -0
  56. data/ext/libstorj/test/mockfarmer.c +358 -0
  57. data/ext/libstorj/test/storjtests.h +41 -0
  58. data/ext/libstorj/test/tests.c +1617 -0
  59. data/ext/libstorj/test/tests_rs.c +869 -0
  60. data/ext/ruby-libstorj/extconf.rb +8 -0
  61. data/ext/ruby-libstorj/ruby-libstorj.cc +17 -0
  62. data/lib/ruby-libstorj.rb +1 -0
  63. data/lib/ruby-libstorj/arg_forwarding_task.rb +58 -0
  64. data/lib/ruby-libstorj/env.rb +178 -0
  65. data/lib/ruby-libstorj/ext/bucket.rb +71 -0
  66. data/lib/ruby-libstorj/ext/create_bucket_request.rb +53 -0
  67. data/lib/ruby-libstorj/ext/curl_code.rb +139 -0
  68. data/lib/ruby-libstorj/ext/ext.rb +71 -0
  69. data/lib/ruby-libstorj/ext/file.rb +84 -0
  70. data/lib/ruby-libstorj/ext/get_bucket_request.rb +45 -0
  71. data/lib/ruby-libstorj/ext/json_request.rb +51 -0
  72. data/lib/ruby-libstorj/ext/list_files_request.rb +63 -0
  73. data/lib/ruby-libstorj/ext/types.rb +226 -0
  74. data/lib/ruby-libstorj/ext/upload_options.rb +38 -0
  75. data/lib/ruby-libstorj/libstorj.rb +22 -0
  76. data/lib/ruby-libstorj/mixins/storj.rb +27 -0
  77. data/lib/ruby-libstorj/struct.rb +42 -0
  78. data/ruby-libstorj.gemspec +57 -0
  79. data/spec/helpers/options.yml.example +22 -0
  80. data/spec/helpers/shared_rake_examples.rb +132 -0
  81. data/spec/helpers/storj_options.rb +96 -0
  82. data/spec/helpers/upload.data +3 -0
  83. data/spec/helpers/upload.data.sha256 +1 -0
  84. data/spec/libstorj_spec.rb +0 -0
  85. data/spec/ruby-libstorj/arg_forwarding_task_spec.rb +311 -0
  86. data/spec/ruby-libstorj/env_spec.rb +353 -0
  87. data/spec/ruby-libstorj/ext_spec.rb +75 -0
  88. data/spec/ruby-libstorj/json_request_spec.rb +13 -0
  89. data/spec/ruby-libstorj/libstorj_spec.rb +81 -0
  90. data/spec/ruby-libstorj/struct_spec.rb +64 -0
  91. data/spec/spec_helper.rb +113 -0
  92. metadata +136 -0
@@ -0,0 +1,38 @@
1
+ module LibStorj
2
+ module Ext
3
+ module Storj
4
+ class UploadOptions < FFI::Struct
5
+ layout :prepare_frame_limit, :int,
6
+ :push_frame_limit, :int,
7
+ :push_shard_limit, :int,
8
+ :rs, :bool,
9
+ :index, :pointer, # char*
10
+ :bucket_id, :pointer, # char*
11
+ :file_name, :pointer, # char*
12
+ :fd, :pointer # FILE*
13
+
14
+ def initialize(bucket_id:,
15
+ file_path:,
16
+ file_name: nil,
17
+ index: nil)
18
+ if file_path.nil? || !::File.exists?(file_path)
19
+ raise Errno::ENOENT.new(file_path || 'nil')
20
+ end
21
+
22
+ file_name = ::File.basename(file_path) if !file_name
23
+ super()
24
+
25
+ self[:prepare_frame_limit] = 1
26
+ self[:push_frame_limit] = 64
27
+ self[:push_shard_limit] = 64
28
+ self[:rs] = true
29
+ self[:index] = (index.is_a?(String) && index.length == 64) ?
30
+ index : FFI::MemoryPointer::NULL
31
+ self[:bucket_id] = FFI::MemoryPointer.from_string bucket_id
32
+ self[:file_name] = FFI::MemoryPointer.from_string file_name
33
+ self[:fd] = ::LibStorj::Ext::LibC.fopen file_path, 'r'
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'ffi'
3
+ require 'date'
4
+
5
+ module LibStorj
6
+ # NB: not currently used but useful for debugging
7
+ require 'ruby-libstorj/struct'
8
+ require 'ruby-libstorj/ext/types'
9
+ require 'ruby-libstorj/ext/json_request'
10
+ require 'ruby-libstorj/ext/get_bucket_request'
11
+ require 'ruby-libstorj/ext/create_bucket_request'
12
+ require 'ruby-libstorj/ext/list_files_request'
13
+ require 'ruby-libstorj/ext/bucket'
14
+ require 'ruby-libstorj/ext/ext'
15
+ require 'ruby-libstorj/ext/upload_options'
16
+ require 'ruby-libstorj/ext/file'
17
+
18
+ require 'ruby-libstorj/env'
19
+ require 'ruby-libstorj/mixins/storj'
20
+
21
+ extend ::LibStorj::Ext::Storj::Mixins
22
+ end
@@ -0,0 +1,27 @@
1
+ module LibStorj
2
+ module Ext
3
+ module Storj
4
+ module Mixins
5
+ def util_timestamp
6
+ ::LibStorj::Ext::Storj.util_timestamp
7
+ end
8
+
9
+ def util_datetime
10
+ # '%Q' - Number of milliseconds since 1970-01-01 00:00:00 UTC.
11
+ DateTime.strptime(::LibStorj::Ext::Storj.util_timestamp.to_s, '%Q')
12
+ end
13
+
14
+ def mnemonic_check(mnemonic)
15
+ ::LibStorj::Ext::Storj.mnemonic_check(mnemonic)
16
+ end
17
+
18
+ # default to highest strength; strength range: (128..256)
19
+ def mnemonic_generate(strength = 256)
20
+ pointer = FFI::MemoryPointer.new :pointer, 1
21
+ ::LibStorj::Ext::Storj.mnemonic_generate(strength, pointer)
22
+ pointer.read_pointer.read_string
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ module LibStorj
2
+ class FFI::Struct
3
+ # allows for destructuring. NB: `values_at` members array order
4
+ # must match assignment order!
5
+ #
6
+ # example: ```
7
+ # bucket = ::LibStorj::Ext::Bucket.new
8
+ # name, id, decrypted = bucket.values_at(:name, :id, :decrypted)
9
+ # # OR name, id, decrypted = bucket.values_at([:name, :id, :decrypted])
10
+ # # OR name, id, decrypted = bucket.values_at(%i[name id decrypted])
11
+ # ```
12
+
13
+ def values_at(*members)
14
+ members.flatten.map {|member_name| self[member_name]}
15
+ end
16
+
17
+ # convenience method for inspecting struct hierarchies
18
+ def map_layout
19
+ # NB: Hash[ [ [key, value], ... ] ] → new_hash
20
+ Hash[members.map do |member_name|
21
+ member = self[member_name]
22
+ value = member.is_a?(FFI::Struct) ? member.map_layout : member
23
+ if value.is_a? FFI::Pointer
24
+ next [member_name, nil] if value.null?
25
+
26
+ # attempt to read as string
27
+ begin
28
+ string_value = value.read_string
29
+ # update value to string_value if it contains only printable characters
30
+ if string_value =~ /^[[:print:]]*$/
31
+ value = string_value
32
+ end
33
+ rescue
34
+ # do nothing...
35
+ # let value remain a pointer if an exception was raised
36
+ end
37
+ end
38
+ [member_name, value]
39
+ end]
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # require File.expand_path("../lib/ruby-libstorj/version", __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'ruby-libstorj'
7
+ gem.version = '0.0.0' #LibStorj::VERSION
8
+ gem.license = 'AGPL-3.0'
9
+ gem.authors = ['Bryan White']
10
+ gem.email = ['bryanchriswhite@gmail.com', 'bryan@storj.io']
11
+ gem.homepage = 'https://github.com/storj/ruby-libstorj'
12
+ gem.summary = 'libstorj bindings for Ruby'
13
+ gem.description = 'Ruby bindings to the libstorj C Storj API library' # TODO: elaborate
14
+
15
+ # gem.extensions << 'ext/Rakefile'
16
+ # TODO: uncomment if this gem needs to build native extensions
17
+ gem.extensions = %w[ext/ruby-libstorj/extconf.rb]
18
+
19
+ gem.required_ruby_version = '>= 2.0.0'
20
+ gem.require_paths = ['lib']
21
+
22
+ # TODO: is this necessary?
23
+ # gem.add_runtime_dependency '<gem name>', '~> <version>'
24
+ #
25
+ # gem.add_development_dependency '<gem name', '~> <version>'
26
+
27
+ gem.files = `git ls-files`.split("\n").reject {|f| f =~ /^test/}
28
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
29
+
30
+ # Add the submodule to the gem
31
+ relative_path = File.expand_path("../", __FILE__) + '/'
32
+ `git submodule --quiet foreach pwd`.split($\).each do |submodule_path|
33
+
34
+ if (ENV['OS'] == 'Windows_NT') && submodule_path[0] == '/'
35
+ # Detect if cygwin path is being used by git
36
+ submodule_path = submodule_path[1..-1]
37
+ submodule_path.insert(1, ':')
38
+ end
39
+
40
+ # for each submodule, change working directory to that submodule
41
+ Dir.chdir(submodule_path) do
42
+ # Make the submodule path relative
43
+ submodule_path = submodule_path.gsub(/#{relative_path}/i, '')
44
+
45
+ # issue git ls-files in submodule's directory
46
+ submodule_files = `git ls-files`.split($\)
47
+
48
+ # prepend the submodule path to create relative file paths
49
+ submodule_files_paths = submodule_files.map do |filename|
50
+ File.join(submodule_path, filename)
51
+ end
52
+
53
+ # add relative paths to gem.files
54
+ gem.files += submodule_files_paths
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,22 @@
1
+ bridge:
2
+ proto: https
3
+ port: 443
4
+ host: api.storj.io
5
+ user: yourusername
6
+ pass: yourpassword
7
+
8
+ encrypt:
9
+ mnemonic: 'this is not really a mnemonic and i hope it does not break anything'
10
+
11
+ http:
12
+ user_agent: 'curl/7.52.1'
13
+ proxy_url:
14
+ #cainfo_path: #-- leave blank to use curl default CA bundle, see:
15
+ # (https://curl.haxx.se/libcurl/c/CURLOPT_CAINFO.html)
16
+ low_speed_limit: 30720
17
+ low_speed_time: 20
18
+ timeout: 60
19
+
20
+ log:
21
+ logger: JSON_LOGGER
22
+ level: 0
@@ -0,0 +1,132 @@
1
+ def lookup_task(task_name)
2
+ begin
3
+ ::Rake::Task[task_name]
4
+ rescue RuntimeError
5
+ raise "exception raised when looking up rake task: #{task_name}"
6
+ end
7
+ end
8
+
9
+
10
+ shared_examples 'defines the target task' do
11
+ it 'defines the target task' do
12
+ task = instantiate
13
+ begin
14
+ registered_task = ::Rake::Task[task_name]
15
+ expect(registered_task).to be_equal(task.target_task)
16
+ rescue RuntimeError => err
17
+ fail("exception raised trying to lookup task: #{task_name}")
18
+ end
19
+ end
20
+ end
21
+
22
+ shared_context 'invokes all dependencies when invoked' do
23
+ it 'invokes all depencencies when invoked' do
24
+ task = instantiate
25
+ deps.each do |dep_name|
26
+ begin
27
+ dep_task = ::Rake::Task[dep_name]
28
+ rescue RuntimeError
29
+ raise "exception raised when looking up rake task: #{dep_name}"
30
+ end
31
+
32
+ task.invoke(*expected_args.values)
33
+ expect(dep_task.already_invoked).to be(true)
34
+
35
+ #-- reset
36
+ task.reenable
37
+ end
38
+ end
39
+ end
40
+
41
+ shared_context 'invokes all dependencies when invoked via any alias' do
42
+ it 'invokes all depencencies when invoked via any alias' do
43
+ task = instantiate
44
+ alias_names.map(&method(:lookup_task)).each do |alias_task|
45
+ alias_task.invoke(*expected_args.values)
46
+
47
+ deps.map(&method(:lookup_task)).each do |dep_task|
48
+ expect(dep_task.already_invoked).to be(true)
49
+
50
+ #-- reset
51
+ dep_task.reenable
52
+ end
53
+
54
+ #-- reset
55
+ alias_task.reenable
56
+ end
57
+ end
58
+ end
59
+
60
+ shared_examples 'gets invoked with args via any alias' do
61
+ it 'gets invoked with args via any alias' do
62
+ yield_counter = 0
63
+ task = described_class.new task_name,
64
+ alias_names: alias_names,
65
+ args_deps_hash: {args => deps} do
66
+ |actual_task, actual_args, actual_deps|
67
+ yield_counter += 1
68
+ expect(task.target_task).to be(actual_task)
69
+ expect(expected_args).to eq(actual_args.to_hash)
70
+ expect(deps).to eq(actual_deps)
71
+ end
72
+
73
+
74
+ alias_names.map(&method(:lookup_task)).each do |alias_task|
75
+ alias_task.invoke(*expected_args.values)
76
+
77
+ #-- reset
78
+ task.reenable
79
+ alias_task.reenable
80
+ end
81
+
82
+ expect(yield_counter > 0).to be(true)
83
+ expect(yield_counter).to be(alias_names.count)
84
+ end
85
+ end
86
+
87
+ shared_examples 'gets invoked via any alias' do
88
+ it 'gets invoked via any alias' do
89
+ task = instantiate
90
+ alias_names.each do |alias_name|
91
+ begin
92
+ alias_task = ::Rake::Task[alias_name]
93
+ rescue RuntimeError
94
+ raise "exception raised when looking up rake task: #{alias_name}"
95
+ end
96
+
97
+ alias_task.invoke(*expected_args.values)
98
+ expect(task.already_invoked).to be(true)
99
+
100
+ #-- reset
101
+ task.reenable
102
+ alias_task.reenable
103
+ end
104
+ end
105
+ end
106
+
107
+ shared_examples 'yields to the block' do
108
+ it 'yields the rake task, args, and dependencies to the block' do
109
+ task = described_class.new task_name,
110
+ alias_names: alias_names,
111
+ args_deps_hash: {args => deps} do
112
+ |actual_task, actual_args, actual_deps|
113
+ expect(task.target_task).to be(actual_task)
114
+ expect(expected_args).to eq(actual_args.to_hash)
115
+ expect(deps).to eq(actual_deps)
116
+ end
117
+
118
+
119
+ task.invoke(*expected_args.values)
120
+
121
+ #-- reset
122
+ task.reenable
123
+ end
124
+ end
125
+
126
+ shared_context 'raises `ArgumentError`' do
127
+ it 'raises an `ArgumentError`' do
128
+ expect do
129
+ instantiate
130
+ end.to raise_error(ArgumentError)
131
+ end
132
+ end
@@ -0,0 +1,96 @@
1
+ module LibStorjTest
2
+ require 'yaml'
3
+ require 'ruby-libstorj'
4
+
5
+ def build_options(type_map)
6
+ options_yml = YAML.load_file "#{__dir__}/options.yml"
7
+ options_yml.to_a.map do |option_group|
8
+ group_name, options = option_group
9
+
10
+ option_type = type_map[group_name.to_sym]
11
+ member_field_hash = Hash[option_type.members.zip option_type.layout.fields]
12
+ option_instance = option_type.new
13
+
14
+ options.each do |option|
15
+ name, value = [option[0].to_sym, option[1]]
16
+
17
+ if name == :logger
18
+ option_instance[:logger] = ::LibStorj::Ext::Storj.const_get value
19
+
20
+ next
21
+ end
22
+
23
+ option_field = member_field_hash[name]
24
+
25
+ # TODO: check types and/or error handle
26
+ if option_field.nil?
27
+ option_instance = FFI::MemoryPointer::NULL
28
+ elsif option_field.is_a?(FFI::StructLayout::Pointer)
29
+ # Assuming pointers are strings
30
+ #
31
+ pointer = FFI::MemoryPointer.from_string(value.nil? ? '' : value)
32
+ option_instance[name] = pointer
33
+ else
34
+ option_instance[name] = value
35
+ end
36
+
37
+ end
38
+
39
+ option_instance
40
+ end
41
+ end
42
+
43
+ def default_options
44
+ build_options bridge: ::LibStorj::Ext::Storj::BridgeOptions,
45
+ encrypt: ::LibStorj::Ext::Storj::EncryptOptions,
46
+ http: ::LibStorj::Ext::Storj::HttpOptions,
47
+ log: ::LibStorj::Ext::Storj::LogOptions
48
+ end
49
+
50
+ def get_test_bucket_id(&block)
51
+ instance.get_buckets do |error, buckets|
52
+ throw(:no_bucket) if buckets.nil?
53
+
54
+ test_bucket = buckets.find {|bucket| bucket.name == test_bucket_name}
55
+ throw(:no_bucket) unless test_bucket
56
+ block.call test_bucket.id
57
+ end
58
+ end
59
+
60
+ def get_test_file_id(&block)
61
+ get_test_bucket_id do |test_bucket_id|
62
+ instance.list_files test_bucket_id do |error, files|
63
+ throw(:no_file) if files.nil?
64
+
65
+ test_file = files.find {|file| file.name == test_file_name}
66
+ throw(:no_file) unless test_file
67
+ block.call test_file.id, test_bucket_id
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+ def clean_buckets(&block)
74
+ catch(:no_bucket) do
75
+ return get_test_bucket_id do |id|
76
+ instance.delete_bucket(id, &block)
77
+ end
78
+ end
79
+
80
+ yield if block_given?
81
+ end
82
+
83
+ def clean_files(&block)
84
+ catch(:no_bucket) do
85
+ return get_test_bucket_id do |test_bucket_id|
86
+ catch(:no_file) do
87
+ get_test_file_id do |test_file_id|
88
+ instance.delete_file(test_bucket_id, test_file_id, &block)
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ yield if block_given?
95
+ end
96
+ end