ipfs-api 0.1.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: f5f308798c9180262f9aa758b6010b910142a0d9
4
- data.tar.gz: 13fde3fde504683f14df8e5d891d5291ac3624ba
2
+ SHA256:
3
+ metadata.gz: 9bd8f7653d00434d0ee809fa1c0225c5ea983ccc53c61157932cf10953f00679
4
+ data.tar.gz: 93e65ff69174cb7a06f8cd63c3a4277055c8d8e5d9759a1715ac6d083f5c750a
5
5
  SHA512:
6
- metadata.gz: 9932b1d74862af972ded69d873a42b719b3be8dbbd8cc2977106e746b87282d0eb84efa97f9e288b60e13ef04290b1d42eead4cdaf4f88b072b88420e7a264c6
7
- data.tar.gz: e0ddc8dd3188cdce71cb4f64f738f71fc33f78d92521b03c154d6b861d427bffc77230cfa77f42111bf5154d21a803635321e496a0dbaad12b66f186851bedc9
6
+ metadata.gz: 99d6311039ea27fbb777af8211b34a17e6b1458c9c45336bdaa3f634d2aab21afc4cee6ada77068eab51ad93a8c2a347925ee419bead1f3a2c8fa3d7327146d3
7
+ data.tar.gz: fbfaadb695eb7fab708573778e794652c13cae4432418ecade50b78fd70feb68b399375fc9af8da67c770060581203c6005037e9daa092a6f8a49c6168294e74
data/README.md CHANGED
@@ -1,58 +1,66 @@
1
1
  # Overview
2
2
 
3
- IPFS4R is a client library to access the [Interplanetary Filesystem (IPFS)](https://ipfs.io) from Ruby.
3
+ IPFS-API for Ruby is a client library to access the [Interplanetary Filesystem (IPFS)](https://ipfs.io) from Ruby.
4
4
 
5
5
  You can find more examples in the
6
6
  [examples directory](https://github.com/hjoest/ruby-ipfs-api/tree/master/examples).
7
7
 
8
8
  ## Installation
9
9
 
10
- Use ``gem`` to install it
10
+ You need an [IPFS daemon](https://ipfs.io/docs/install/) running
11
11
 
12
- ```bash
13
- gem install ipfs-api
14
- ```
12
+ ipfs daemon
13
+
14
+ To install this gem, run
15
+
16
+ gem install ipfs-api
15
17
 
16
18
  or simply add this line to your ``Gemfile``
17
19
 
18
- ```ruby
19
- gem 'ipfs-api', '~> 0.1.0'
20
- ```
20
+ gem 'ipfs-api', '~> 0.4.0'
21
21
 
22
22
  ## Basic examples
23
23
 
24
24
  This example will add a directory to *IPFS*. The directory ``data``
25
25
  must exist or otherwise an ``Errno::ENOENT`` error will be raised.
26
26
 
27
- ```ruby
28
- require 'ipfs-api'
27
+ require 'ipfs-api'
28
+
29
+ ipfs = IPFS::Connection.new
30
+ ipfs.add Dir.new('data')
31
+
32
+ Afterwards, we can retrieve what we put in.
33
+
34
+ require 'ipfs-api'
35
+
36
+ ipfs = IPFS::Connection.new
37
+
38
+ # retrieve contents of a file
39
+ print ipfs.cat('QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG')
29
40
 
30
- ipfs = IPFS::Connection.new
31
- ipfs.add Dir.new('data')
32
- ```
41
+ # retrieve the whole directory and make a copy of it in ``copy-of-data``
42
+ ipfs.get('QmSh4Xjoy16v6XmnREE1yCrPM1dnizZc2h6LfrqXsnbBV7', 'copy-of-data')
33
43
 
34
44
  ## Advanced
35
45
 
36
46
  Dynamically add folders and files to *IPFS*, without creating them
37
47
  on the local file system:
38
48
 
39
- ```ruby
40
- require 'ipfs-api'
41
-
42
- ipfs = IPFS::Connection.new
43
- folder = IPFS::Upload.folder('test') do |test|
44
- test.add_file('hello.txt') do |fd|
45
- fd.write 'Hello'
46
- end
47
- test.add_file('world.txt') do |fd|
48
- fd.write 'World'
49
- end
50
- end
51
- ipfs.add folder do |node|
52
- # display each uploaded node:
53
- print "#{node.name}: #{node.hash}\n" if node.finished?
54
- end
55
- ```
49
+ require 'ipfs-api'
50
+
51
+ ipfs = IPFS::Connection.new
52
+ folder = IPFS::Upload.folder('test') do |test|
53
+ test.add_file('hello.txt') do |fd|
54
+ fd.write 'Hello'
55
+ end
56
+ test.add_file('world.txt') do |fd|
57
+ fd.write 'World'
58
+ end
59
+ end
60
+ ipfs.add folder do |node|
61
+ # display each uploaded node:
62
+ print "#{node.name}: #{node.hash}\n" if node.finished?
63
+ end
56
64
 
57
65
  ## License
58
66
 
data/Rakefile CHANGED
@@ -11,7 +11,7 @@ PKG_NAME = 'ipfs-api'
11
11
  PKG_VERSION = IPFS::VERSION
12
12
  AUTHORS = ['Holger Joest']
13
13
  EMAIL = 'holger@joest.org'
14
- HOMEPAGE = 'http://ruby-ipfs-api.github.io'
14
+ HOMEPAGE = 'http://hjoest.github.io/ruby-ipfs-api'
15
15
  SUMMARY = 'Interplanetary File System for Ruby'
16
16
  DESCRIPTION = 'This is a client library to access the IPFS from Ruby'
17
17
  RDOC_OPTIONS = [ '--title', SUMMARY, '--quiet', '--main', 'lib/ipfs-api.rb' ]
@@ -32,7 +32,7 @@ RDoc::Task.new do |rd|
32
32
  rd.options = RDOC_OPTIONS
33
33
  end
34
34
 
35
- CLEAN.include [ "*.gem*", "pkg", "rdoc" ]
35
+ CLEAN.include [ "*.gem*", "pkg", "rdoc", "test/tmp" ]
36
36
 
37
37
  spec = Gem::Specification.new do |s|
38
38
  s.name = PKG_NAME
@@ -40,7 +40,6 @@ spec = Gem::Specification.new do |s|
40
40
  s.authors = AUTHORS
41
41
  s.email = EMAIL
42
42
  s.homepage = HOMEPAGE
43
- s.rubyforge_project = PKG_NAME
44
43
  s.summary = SUMMARY
45
44
  s.description = DESCRIPTION
46
45
  s.platform = Gem::Platform::RUBY
@@ -49,10 +48,9 @@ spec = Gem::Specification.new do |s|
49
48
  s.executables = []
50
49
  s.files = PKG_FILES
51
50
  s.test_files = []
52
- s.has_rdoc = true
53
51
  s.extra_rdoc_files = RDOC_FILES
54
52
  s.rdoc_options = RDOC_OPTIONS
55
- s.required_ruby_version = ">= 1.9.3"
53
+ s.required_ruby_version = ">= 2.0.0"
56
54
  end
57
55
 
58
56
  # also keep the gemspec up to date each time we package a tarball or gem
@@ -78,7 +76,7 @@ namespace :gem do
78
76
  spec.instance_variables.sort.each do |ivar|
79
77
  value = spec.instance_variable_get(ivar)
80
78
  name = ivar.to_s.split("@").last
81
- next if skip_fields.include?(name) || value.nil? || value == "" || (value.respond_to?(:empty?) && value.empty?)
79
+ next if skip_fields.include?(name) || value.nil? || (value.respond_to?(:empty?) && value.empty?)
82
80
  if name == "dependencies"
83
81
  value.each do |d|
84
82
  dep, *ver = d.to_s.split(" ")
data/examples/basic.rb CHANGED
@@ -1,4 +1,12 @@
1
1
  require 'ipfs-api'
2
2
 
3
3
  ipfs = IPFS::Connection.new
4
+
5
+ # add a directory
4
6
  ipfs.add Dir.new('data')
7
+
8
+ # retrieve contents of a file
9
+ print ipfs.cat('QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG')
10
+
11
+ # retrieve the whole directory
12
+ ipfs.get('QmSh4Xjoy16v6XmnREE1yCrPM1dnizZc2h6LfrqXsnbBV7', 'copy-of-data')
data/ipfs-api.gemspec CHANGED
@@ -20,29 +20,25 @@ Gem::Specification.new do |s|
20
20
  "lib/ipfs-api/io.rb",
21
21
  "lib/ipfs-api/upload.rb",
22
22
  "lib/ipfs-api/version.rb",
23
- "test/common.rb",
24
23
  "test/samples.rb",
25
24
  "test/test_cmd_add.rb",
26
25
  "test/test_cmd_cat.rb",
27
26
  "test/test_cmd_get.rb",
28
27
  "test/test_cmd_id.rb",
29
28
  "test/test_cmd_ls.rb",
30
- "test/test_cmd_name.rb",
31
29
  "test/test_io.rb",
32
30
  "test/test_upload.rb"]
33
- s.full_name = "ipfs-api-0.1.0"
34
- s.has_rdoc = true
35
- s.homepage = "http://ruby-ipfs-api.github.io"
31
+ s.full_name = "ipfs-api-0.4.0"
32
+ s.homepage = "http://hjoest.github.io/ruby-ipfs-api"
36
33
  s.licenses = ["MIT"]
37
34
  s.name = "ipfs-api"
38
35
  s.platform = "ruby"
39
36
  s.rdoc_options = ["--title", "Interplanetary File System for Ruby", "--quiet", "--main", "lib/ipfs-api.rb"]
40
37
  s.require_paths = ["lib"]
41
- s.required_ruby_version = ">= 1.9.3"
38
+ s.required_ruby_version = ">= 2.0.0"
42
39
  s.required_rubygems_version = ">= 0"
43
- s.rubyforge_project = "ipfs-api"
44
- s.rubygems_version = "2.4.8"
40
+ s.rubygems_version = "3.1.4"
45
41
  s.specification_version = 4
46
42
  s.summary = "Interplanetary File System for Ruby"
47
- s.version = "0.1.0"
43
+ s.version = "0.4.0"
48
44
  end
@@ -11,66 +11,70 @@ module IPFS
11
11
  end
12
12
 
13
13
  def add nodes, &block
14
- boundaries = [ generate_boundary ]
15
- headers = {
16
- 'Content-Disposition' => 'form-data: name="files"',
17
- 'Content-Type' => "multipart/form-data; boundary=#{boundaries[0]}"
18
- }
19
- walker = Upload::TreeWalker.depth_first(nodes)
14
+ boundary = generate_boundary
15
+ tree_walker = Upload::TreeWalker.depth_first(nodes)
20
16
  node_map = {}
21
- stream = IO::ReadFromWriterIO.new do |buf|
22
- next if walker.nil?
23
- begin
24
- node, depth = walker.next
25
- node_map[node.path] = node
26
- rescue StopIteration
27
- depth = -1
28
- walker = nil
29
- end
30
- while boundaries.size > depth+1 && boundary = boundaries.shift
31
- buf << %Q{\
32
- --#{boundary}--\r\n\
17
+ producer = IO::StreamProducer.new do |buf|
18
+ buf << %Q{\
19
+ --#{boundary}\r\n\
20
+ Content-Disposition: file; filename="root"\r\n\
21
+ Content-Type: application/x-directory\r\n\
33
22
  \r\n\
34
23
  \r\n\
35
24
  }
36
- end
37
- next if walker.nil?
38
- if node.folder?
39
- boundaries.unshift generate_boundary
40
- buf << %Q{\
41
- --#{boundaries[1]}\r\n\
42
- Content-Disposition: form-data; name="file"; filename="#{node.path}"\r\n\
43
- Content-Type: multipart/mixed; boundary=#{boundaries[0]}\r\n\
25
+ tree_walker.each do |node, depth|
26
+ node_map[node.path] = node
27
+ if node.folder?
28
+ buf << %Q{\
29
+ --#{boundary}\r\n\
30
+ Content-Disposition: file; filename="root#{node.path.gsub('/', '%2F')}"\r\n\
31
+ Content-Type: application/x-directory\r\n\
44
32
  \r\n\
45
33
  \r\n\
46
34
  }
47
- elsif node.file?
48
- buf << %Q{\
49
- --#{boundaries[0]}\r\n\
50
- Content-Disposition: file; filename="#{node.path}"\r\n\
35
+ elsif node.file?
36
+ buf << %Q{\
37
+ --#{boundary}\r\n\
38
+ Content-Disposition: file; filename="root#{node.path.gsub('/', '%2F')}"\r\n\
51
39
  Content-Type: application/octet-stream\r\n\
52
40
  \r\n\
53
41
  #{node.content}\r\n\
54
42
  }
55
- else
56
- raise "Unknown node type: #{node}"
43
+ else
44
+ raise "Unknown node type: #{node}"
45
+ end
57
46
  end
47
+ buf << %Q{\
48
+ --#{boundary}\r\n\
49
+ }
58
50
  end
59
- nodes = []
51
+ headers = {
52
+ 'Content-Type' => "multipart/form-data; boundary=#{boundary}"
53
+ }
54
+ stream = producer.stream
55
+ uploaded_nodes = []
60
56
  post("add?encoding=json&r=true&progress=true", stream, headers) do |chunk|
61
57
  next if chunk.empty?
62
- upload = JSON.parse(chunk)
58
+ upload = nil
59
+ begin
60
+ upload = JSON.parse(chunk)
61
+ rescue JSON::ParserError
62
+ end
63
+ next if upload.nil?
63
64
  path, bytes, hash = ['Name', 'Bytes', 'Hash'].map { |p| upload[p] }
65
+ next if not path.start_with?('root/')
66
+ path = path[4..-1]
64
67
  node = node_map[path]
68
+ next if not node
65
69
  node.bytes = bytes if bytes
66
70
  node.hash = hash if hash
67
71
  if block_given?
68
72
  block.call(node)
69
73
  elsif hash
70
- nodes << node
74
+ uploaded_nodes << node
71
75
  end
72
76
  end
73
- block_given? ? nil : nodes
77
+ block_given? ? nil : uploaded_nodes
74
78
  end
75
79
 
76
80
  def cat path
@@ -81,13 +85,18 @@ Content-Type: application/octet-stream\r\n\
81
85
  result
82
86
  end
83
87
 
84
- # FIXME: provides only raw response yet
85
- def get path
86
- result = ''
87
- post("get?arg=#{CGI.escape(path)}") do |chunk|
88
- result << chunk
88
+ def get path, destination = nil
89
+ producer = IO::StreamProducer.new do |buf|
90
+ post("get?arg=#{CGI.escape(path)}") do |chunk|
91
+ buf << chunk
92
+ end
93
+ buf.close
94
+ end
95
+ if destination.nil?
96
+ return producer.stream
97
+ else
98
+ return IO::Tar.extract(producer.stream, destination)
89
99
  end
90
- result
91
100
  end
92
101
 
93
102
  def id
@@ -137,9 +146,21 @@ Content-Type: application/octet-stream\r\n\
137
146
  @connection = connection
138
147
  end
139
148
 
140
- def resolve
149
+ def resolve id = nil
150
+ @connection.instance_exec(self) do
151
+ if id
152
+ JSON.parse(post("name/resolve?arg=#{CGI.escape(id)}").body)['Path']
153
+ else
154
+ JSON.parse(post('name/resolve').body)['Path']
155
+ end
156
+ end
157
+ end
158
+
159
+ def publish node, key = nil
160
+ params = "arg=#{CGI.escape(node.hash)}"
161
+ params << "&key=#{CGI.escape(key)}" if key
141
162
  @connection.instance_exec(self) do
142
- JSON.parse(post('name/resolve').body)['Path']
163
+ JSON.parse(post("name/publish?#{params}").body)['Name']
143
164
  end
144
165
  end
145
166
 
data/lib/ipfs-api/io.rb CHANGED
@@ -1,38 +1,61 @@
1
- require 'stringio'
1
+ require 'tempfile'
2
+ require 'rubygems/package'
2
3
 
3
4
  module IPFS; end
4
5
  module IPFS::IO # :nodoc:
5
6
 
6
- class ReadFromWriterIO # :nodoc:
7
+ class StreamProducer # :nodoc:
7
8
 
8
9
  def initialize &block
9
10
  @block = block
10
- @stream = StringIO.new
11
- fetch_data
12
11
  end
13
12
 
14
- def read length = nil, outbuf = ''
15
- return nil if @stream.size == 0
16
- outbuf.slice!(length..-1) if !length.nil?
17
- q = 0
18
- while @stream.size > 0
19
- s = @stream.size - @p
20
- s = [length - q, s].min if !length.nil?
21
- outbuf[q, s] = @stream.string[@p, s]
22
- @p += s
23
- q += s
24
- break if q == length
25
- fetch_data if @stream.size == @p
13
+ def stream
14
+ io = Tempfile.new('ruby-ipfs')
15
+ begin
16
+ @block.call io
17
+ ensure
18
+ io.close
26
19
  end
27
- outbuf
20
+ File.open(io.path, 'r')
28
21
  end
29
22
 
30
- private
31
- def fetch_data
32
- @p = 0
33
- @stream.string = ""
34
- @block.call @stream if not @stream.closed?
23
+ end
24
+
25
+ module Tar # :nodoc:
26
+
27
+ def extract stream, destination
28
+ Gem::Package::TarReader.new(stream) do |tar|
29
+ path = nil
30
+ tar.each do |entry|
31
+ if entry.full_name == '././@LongLink'
32
+ path = File.join(destination, entry.read.strip)
33
+ next
34
+ end
35
+ path ||= File.join(destination, entry.full_name)
36
+ if entry.directory?
37
+ if File.exist?(path) and not File.directory?(path)
38
+ raise IOError.new("Not a directory: #{path}")
39
+ end
40
+ FileUtils.mkdir_p path, :mode => entry.header.mode, :verbose => false
41
+ elsif entry.file?
42
+ if File.exist?(path) and not File.file?(path)
43
+ raise IOError.new("Not a file: #{path}")
44
+ end
45
+ File.open path, "wb" do |fd|
46
+ while (chunk = entry.read(1024))
47
+ fd.write chunk
48
+ end
49
+ end
50
+ FileUtils.chmod entry.header.mode, path, :verbose => false
51
+ end
52
+ path = nil
53
+ end
35
54
  end
55
+ true
56
+ end
57
+
58
+ module_function :extract
36
59
 
37
60
  end
38
61
 
@@ -63,8 +63,8 @@ module IPFS::Upload
63
63
 
64
64
  def inspect
65
65
  s = "<#{@name}"
66
- s << ":#{@bytes}" if @bytes
67
- s << ":#{@hash}" if @hash
66
+ s << ":#{@bytes}" if defined?(@bytes)
67
+ s << ":#{@hash}" if defined?(@hash)
68
68
  s << '>'
69
69
  end
70
70
 
@@ -1,4 +1,4 @@
1
1
  module IPFS
2
- VERSION = '0.1.0'
2
+ VERSION = '0.4.0'
3
3
  end
4
4
 
data/lib/ipfs-api.rb CHANGED
@@ -1,10 +1,10 @@
1
- # =IPFS4R - Interplanetary Filesystem Library for Ruby
1
+ # =IPFS API for Ruby
2
2
  # License:: MIT (see the LICENSE file)
3
- # Website:: https://ruby-ipfs-api.github.io
3
+ # Website:: https://hjoest.github.io/ruby-ipfs-api
4
4
  #
5
5
  # ==Introduction
6
6
  #
7
- # IPFS4R is an IPFS[https://ipfs.io] library for Ruby.
7
+ # IPFS API for Ruby is an IPFS[https://ipfs.io] library for Ruby.
8
8
  #
9
9
  require 'ipfs-api/version'
10
10
  require 'ipfs-api/io'
data/test/samples.rb CHANGED
@@ -1,9 +1,25 @@
1
1
  require 'tmpdir'
2
- require 'test/common'
2
+ require 'minitest/autorun'
3
+ begin
4
+ Minitest.const_get('Test')
5
+ rescue
6
+ module Minitest
7
+ Test = Unit::TestCase
8
+ end
9
+ end
10
+ if ENV['DEBUG']
11
+ require 'byebug'
12
+ else
13
+ def byebug; end
14
+ end
15
+
16
+ $:.unshift File.expand_path('../../lib', __FILE__)
3
17
  require 'ipfs-api/upload'
4
18
 
5
19
  module Samples
6
20
 
21
+ TEMP_DIR_PREFIX = 'ruby-ipfs-api-unit-test-'
22
+
7
23
  include IPFS
8
24
 
9
25
  def some_virtual_folders
@@ -61,7 +77,7 @@ module Samples
61
77
  module_function :some_virtual_folders
62
78
 
63
79
  def some_filesystem_folders
64
- Dir.mktmpdir('ruby-ipfs-api-unit-test-') do |root|
80
+ Dir.mktmpdir(TEMP_DIR_PREFIX) do |root|
65
81
  a1 = File.join(root, 'a1')
66
82
  Dir.mkdir(a1, 0755)
67
83
  b1 = File.join(a1, 'b1')
@@ -81,4 +97,10 @@ module Samples
81
97
  end
82
98
  module_function :some_filesystem_folders
83
99
 
100
+ def some_byte_sequences
101
+ s = ('a'..'z').to_a.join
102
+ [ s ] * 17
103
+ end
104
+ module_function :some_byte_sequences
105
+
84
106
  end
data/test/test_cmd_add.rb CHANGED
@@ -1,6 +1,6 @@
1
- $:.unshift File.expand_path('../..', __FILE__)
1
+ $:.unshift File.expand_path('..', __FILE__)
2
2
 
3
- require 'test/samples'
3
+ require 'samples'
4
4
  require 'ipfs-api'
5
5
 
6
6
  include IPFS
data/test/test_cmd_cat.rb CHANGED
@@ -1,6 +1,6 @@
1
- $:.unshift File.expand_path('../..', __FILE__)
1
+ $:.unshift File.expand_path('..', __FILE__)
2
2
 
3
- require 'test/samples'
3
+ require 'samples'
4
4
  require 'ipfs-api'
5
5
 
6
6
  include IPFS
data/test/test_cmd_get.rb CHANGED
@@ -1,18 +1,40 @@
1
- $:.unshift File.expand_path('../..', __FILE__)
1
+ $:.unshift File.expand_path('..', __FILE__)
2
2
 
3
- require 'test/samples'
3
+ require 'samples'
4
4
  require 'ipfs-api'
5
5
 
6
6
  include IPFS
7
7
 
8
8
  class CommandGetTest < Minitest::Test
9
9
 
10
- def test_get
10
+ def test_get_as_tar_stream
11
11
  ipfs = Connection.new
12
12
  Samples.some_virtual_folders do |fixture, expectation|
13
13
  ipfs.add fixture
14
- # FIXME: provides only raw response yet
15
- actual = ipfs.get('QmedYJNEKn656faSHaMv5UFVkgfSzwYf9u4zsYoXqgvnch')
14
+ hash = 'QmedYJNEKn656faSHaMv5UFVkgfSzwYf9u4zsYoXqgvnch'
15
+ stream = ipfs.get(hash)
16
+ tar = stream.read
17
+ # take some samples of the TAR archive
18
+ assert_equal 3072, tar.length
19
+ [ 0x101, 0x301, 0x501 ].each do |seek|
20
+ assert_equal 'ustar', tar[seek..seek+4]
21
+ end
22
+ [ 0x0, 0x200, 0x400 ].each do |seek|
23
+ assert_equal hash, tar[seek..seek+45]
24
+ end
25
+ end
26
+ end
27
+
28
+ def test_get_and_extract
29
+ ipfs = Connection.new
30
+ Samples.some_virtual_folders do |fixture, expectation|
31
+ ipfs.add fixture
32
+ hash = 'QmedYJNEKn656faSHaMv5UFVkgfSzwYf9u4zsYoXqgvnch'
33
+ Dir.mktmpdir(Samples::TEMP_DIR_PREFIX) do |target|
34
+ ipfs.get hash, target
35
+ actual = File.read(File.join(target, hash, 'b1/hello.txt'))
36
+ assert_equal "Hello World!\n", actual
37
+ end
16
38
  end
17
39
  end
18
40
 
data/test/test_cmd_id.rb CHANGED
@@ -1,6 +1,6 @@
1
- $:.unshift File.expand_path('../..', __FILE__)
1
+ $:.unshift File.expand_path('..', __FILE__)
2
2
 
3
- require 'test/common'
3
+ require 'samples'
4
4
  require 'ipfs-api'
5
5
 
6
6
  include IPFS
@@ -10,8 +10,11 @@ class CommandIdTest < Minitest::Test
10
10
  def test_id
11
11
  ipfs = Connection.new
12
12
  id = ipfs.id
13
- assert_equal 46, id.size
14
- assert id.start_with?('Qm')
13
+ if id.start_with?('Qm')
14
+ assert_equal 46, id.size
15
+ else
16
+ assert_equal 52, id.size
17
+ end
15
18
  end
16
19
 
17
20
  end
data/test/test_cmd_ls.rb CHANGED
@@ -1,6 +1,6 @@
1
- $:.unshift File.expand_path('../..', __FILE__)
1
+ $:.unshift File.expand_path('..', __FILE__)
2
2
 
3
- require 'test/samples'
3
+ require 'samples'
4
4
  require 'ipfs-api'
5
5
 
6
6
  include IPFS
@@ -12,6 +12,7 @@ class CommandLsTest < Minitest::Test
12
12
  Samples.some_virtual_folders do |fixture, expectation|
13
13
  ipfs.add fixture
14
14
  actual = ipfs.ls('QmcsmfcY8SQzNxJQYGZMHLXCkeTgxDBhASDPJyVEGi8Wrv')
15
+ actual = streamline_result(actual)
15
16
  expectation = {
16
17
  'Objects' => [
17
18
  {
@@ -20,13 +21,13 @@ class CommandLsTest < Minitest::Test
20
21
  {
21
22
  'Name' => 'foo.txt',
22
23
  'Hash' => 'QmTz3oc4gdpRMKP2sdGUPZTAGRngqjsi99BPoztyP53JMM',
23
- 'Size' => 12,
24
+ 'Size' => 4,
24
25
  'Type' => 2
25
26
  },
26
27
  {
27
28
  'Name' => 'hello.txt',
28
29
  'Hash' => 'QmfM2r8seH2GiRaC4esTjeraXEachRt8ZsSeGaWTPLyMoG',
29
- 'Size' => 21,
30
+ 'Size' => 13,
30
31
  'Type' => 2
31
32
  }
32
33
  ]
@@ -37,4 +38,19 @@ class CommandLsTest < Minitest::Test
37
38
  end
38
39
  end
39
40
 
41
+ # At some point, around version 0.4.2, a new property "Target" was introduced
42
+ # to the "Links" objects. In order to match the test expectation, and still not
43
+ # fail for older versions, we just remove these here whenever they're empty.
44
+ private
45
+ def streamline_result result
46
+ result['Objects'].each do |object|
47
+ object['Links'].each do |link|
48
+ if link['Target'] == ''
49
+ link.delete('Target')
50
+ end
51
+ end
52
+ end
53
+ result
54
+ end
55
+
40
56
  end
data/test/test_io.rb CHANGED
@@ -1,20 +1,70 @@
1
- $:.unshift File.expand_path('../..', __FILE__)
1
+ $:.unshift File.expand_path('..', __FILE__)
2
2
 
3
- require 'test/samples'
3
+ require 'samples'
4
4
  require 'ipfs-api/io'
5
5
 
6
6
  include IPFS::IO
7
7
 
8
- class ReadFromWriterIOTest < Minitest::Test
8
+ class StreamProducerTest < Minitest::Test
9
9
 
10
- def test_read_write_io
11
- msg = ('a'..'z').to_a.join
12
- reader = ReadFromWriterIO.new do |writer|
13
- writer << msg
14
- writer.close
10
+ def setup
11
+ @parts = Samples.some_byte_sequences
12
+ enum = @parts.each
13
+ producer = StreamProducer.new do |writer|
14
+ enum.each do |part|
15
+ writer << part
16
+ end
15
17
  end
16
- result = reader.read
17
- assert_equal msg, result
18
+ @reader = producer.stream
19
+ end
20
+
21
+ def test_read_byte_wise
22
+ result = ''
23
+ while (byte = @reader.read(1))
24
+ result << byte
25
+ assert_equal result.size, @reader.pos
26
+ end
27
+ assert_eof @reader
28
+ assert_equal @parts.join, result
29
+ end
30
+
31
+ def test_read_larger_chunks
32
+ result = ''
33
+ while (chunk = @reader.read(199))
34
+ result << chunk
35
+ assert_equal result.size, @reader.pos
36
+ if chunk.size < 199
37
+ assert_eof @reader
38
+ else
39
+ assert_not_eof @reader
40
+ end
41
+ end
42
+ assert_eof @reader
43
+ assert_equal @parts.join, result
44
+ end
45
+
46
+ def test_different_variants_of_read
47
+ chunk = @reader.read(199)
48
+ assert_equal 199, chunk.size
49
+ assert_not_eof @reader
50
+ chunk = @reader.read(0)
51
+ assert_equal 0, chunk.size
52
+ assert_not_eof @reader
53
+ chunk = @reader.read
54
+ assert_equal 243, chunk.size
55
+ assert_eof @reader
56
+ chunk = @reader.read
57
+ assert_equal 0, chunk.size
58
+ assert_eof @reader
59
+ end
60
+
61
+ private
62
+ def assert_eof stream
63
+ assert stream.eof?, "Stream should have reached end-of-file"
64
+ end
65
+
66
+ def assert_not_eof stream
67
+ assert !stream.eof?, "Stream should not yet have reached end-of-file"
18
68
  end
19
69
 
20
70
  end
data/test/test_upload.rb CHANGED
@@ -1,6 +1,6 @@
1
- $:.unshift File.expand_path('../..', __FILE__)
1
+ $:.unshift File.expand_path('..', __FILE__)
2
2
 
3
- require 'test/samples'
3
+ require 'samples'
4
4
  require 'ipfs-api/upload'
5
5
 
6
6
  class NodeTest < Minitest::Test
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ipfs-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Holger Joest
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-10 00:00:00.000000000 Z
11
+ date: 2022-07-16 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: This is a client library to access the IPFS from Ruby
14
14
  email: holger@joest.org
@@ -30,21 +30,19 @@ files:
30
30
  - lib/ipfs-api/io.rb
31
31
  - lib/ipfs-api/upload.rb
32
32
  - lib/ipfs-api/version.rb
33
- - test/common.rb
34
33
  - test/samples.rb
35
34
  - test/test_cmd_add.rb
36
35
  - test/test_cmd_cat.rb
37
36
  - test/test_cmd_get.rb
38
37
  - test/test_cmd_id.rb
39
38
  - test/test_cmd_ls.rb
40
- - test/test_cmd_name.rb
41
39
  - test/test_io.rb
42
40
  - test/test_upload.rb
43
- homepage: http://ruby-ipfs-api.github.io
41
+ homepage: http://hjoest.github.io/ruby-ipfs-api
44
42
  licenses:
45
43
  - MIT
46
44
  metadata: {}
47
- post_install_message:
45
+ post_install_message:
48
46
  rdoc_options:
49
47
  - "--title"
50
48
  - Interplanetary File System for Ruby
@@ -57,16 +55,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
55
  requirements:
58
56
  - - ">="
59
57
  - !ruby/object:Gem::Version
60
- version: 1.9.3
58
+ version: 2.0.0
61
59
  required_rubygems_version: !ruby/object:Gem::Requirement
62
60
  requirements:
63
61
  - - ">="
64
62
  - !ruby/object:Gem::Version
65
63
  version: '0'
66
64
  requirements: []
67
- rubyforge_project: ipfs-api
68
- rubygems_version: 2.4.8
69
- signing_key:
65
+ rubygems_version: 3.1.4
66
+ signing_key:
70
67
  specification_version: 4
71
68
  summary: Interplanetary File System for Ruby
72
69
  test_files: []
data/test/common.rb DELETED
@@ -1,4 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'byebug'
3
-
4
- $:.unshift File.expand_path('../../lib', __FILE__)
@@ -1,16 +0,0 @@
1
- $:.unshift File.expand_path('../..', __FILE__)
2
-
3
- require 'test/common'
4
- require 'ipfs-api'
5
-
6
- include IPFS
7
-
8
- class CommandNameTest < Minitest::Test
9
-
10
- def test_name_resolve
11
- ipfs = Connection.new
12
- resolved = ipfs.name.resolve
13
- assert resolved.start_with?('/ipfs/Qm')
14
- end
15
-
16
- end