diff --git a/.gitignore b/.gitignore index 49907ce..016f7d2 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,5 @@ pkg #*.swp # Gemfile.lock + +.idea/ diff --git a/.travis.yml b/.travis.yml index dd32133..609f756 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: ruby rvm: - 1.8.7 - 1.9.3 + - 2.0.0 - jruby-18mode - jruby-19mode script: bundle exec rake diff --git a/Gemfile b/Gemfile index c55e2d2..bbe8004 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,9 @@ -source "http://rubygems.org" +source "https://rubygems.org" # Specify your gem's dependencies in test.gemspec gemspec gem 'rcov', :platform => :mri_18 -gem 'simplecov', :platform => :mri_19 -gem 'simplecov-rcov', :platform => :mri_19 +gem 'simplecov', :platforms => [:mri_19, :mri_20] +gem 'simplecov-rcov', :platforms => [:mri_19, :mri_20] diff --git a/README.md b/README.md index b56d766..0f80bfd 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,33 @@ -# pairtree +# (r)pairtree -Ruby implementation of the [Pairtree](https://confluence.ucop.edu/display/Curation/PairTree microservice specification from the California Digital Librar) +Ruby implementation of the [Pairtree](https://wiki.ucop.edu/display/Curation/PairTree) specification from the California Digital Library. -# Usage +## Description + +A fork of the seemingly-abandoned [pairtree](https://github.com/microservices/pairtree). + + +## Installation + +Add this line to your application's Gemfile: + +```ruby +gem 'rpairtree' +``` + +And then execute: + + $ bundle + +Or install it yourself as: + + $ gem install rpairtree + +## Usage ```ruby + require 'pairtree' # You'll need to do this in rails, as it won't find it automatically. + # Initiate a tree pairtree = Pairtree.at('./data', :prefix => 'pfx:', :create => true) @@ -29,9 +52,5 @@ Ruby implementation of the [Pairtree](https://confluence.ucop.edu/display/Curati # Delete a ppath and all its contents pairtree.purge!('pfx:abc123def') ``` - -## Copyright -Copyright (c) 2010 Chris Beer. See LICENSE.txt for -further details. diff --git a/lib/pairtree/identifier.rb b/lib/pairtree/identifier.rb index 38f1a33..0ac711e 100644 --- a/lib/pairtree/identifier.rb +++ b/lib/pairtree/identifier.rb @@ -1,3 +1,4 @@ +# encoding: utf-8 module Pairtree class Identifier ENCODE_REGEX = Regexp.compile("[\"*+,<=>?\\\\^|]|[^\x21-\x7e]", nil) @@ -14,7 +15,24 @@ def self.encode id # Decode special characters within an identifier # @param [String] id The identifier def self.decode id - id.tr('=+,', '/:.').gsub(DECODE_REGEX) { |h| hex2char(h) } + input = id.tr('=+,', '/:.').bytes.to_a + intermediate = [] + while input.first + if input.first == 94 + h = [] + input.shift + h << input.shift + h << input.shift + intermediate << h.pack('c*').hex + else + intermediate << input.shift + end + end + result = intermediate.pack('c*') + if result.respond_to? :force_encoding + result.force_encoding('UTF-8') + end + result end ## diff --git a/pairtree.gemspec b/pairtree.gemspec index ed1416c..e7027e3 100644 --- a/pairtree.gemspec +++ b/pairtree.gemspec @@ -1,17 +1,14 @@ Gem::Specification.new do |s| - s.name = %q{pairtree} - s.summary = %q{Ruby Pairtree implementation} - s.version = "0.1.0" - s.homepage = %q{http://github.com/microservices/pairtree} + s.name = %q{rpairtree} + s.summary = %q{Ruby Pairtree implementation, forked from pairtree which is abandoned.} + s.version = "0.2.0" + s.homepage = %q{http://github.com/mlibrary/pairtree} s.licenses = ["Apache2"] - s.rubygems_version = %q{1.3.7} - - s.authors = ["Chris Beer"] - s.date = %q{2010-12-23} - s.email = %q{chris@cbeer.info} + s.authors = ["Chris Beer, Bryan Hockey, Michael Slone"] + s.date = %q{2015-05-05} s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") - s.extra_rdoc_files = ["LICENSE.txt", "README.textile"] + s.extra_rdoc_files = ["LICENSE.txt", "README.md"] s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] diff --git a/spec/pairtree/pairtree_encoding_spec.rb b/spec/pairtree/pairtree_encoding_spec.rb index 4dd8663..bcae279 100644 --- a/spec/pairtree/pairtree_encoding_spec.rb +++ b/spec/pairtree/pairtree_encoding_spec.rb @@ -7,19 +7,19 @@ def roundtrip(id, expected_encoded=nil, expected_path=nil) encoded = Pairtree::Identifier.encode(id) unless expected_encoded.nil? - encoded.should == expected_encoded + expect(encoded).to eql(expected_encoded) end unless expected_path.nil? path = Pairtree::Path.id_to_path(id) - path.should == expected_path + expect(path).to eql(expected_path) end str = Pairtree::Identifier.decode(encoded) if str.respond_to? :force_encoding str.force_encoding("UTF-8") end - - str.should == id + + expect(str).to eql(id) end it "should handle a" do @@ -78,7 +78,7 @@ def roundtrip(id, expected_encoded=nil, expected_path=nil) end it "should roundtrip French" do - roundtrip('Années de Pèlerinage') + roundtrip('Années de Pèlerinage', 'Ann^c3^a9es^20de^20P^c3^a8lerinage', 'An/n^/c3/^a/9e/s^/20/de/^2/0P/^c/3^/a8/le/ri/na/ge/Ann^c3^a9es^20de^20P^c3^a8lerinage') roundtrip(%{ Années de Pèlerinage (Years of Pilgrimage) (S.160, S.161, S.163) is a set of three suites by Franz Liszt for solo piano. Liszt's diff --git a/spec/pairtree/pairtree_obj_spec.rb b/spec/pairtree/pairtree_obj_spec.rb index 3ed41a9..344695e 100644 --- a/spec/pairtree/pairtree_obj_spec.rb +++ b/spec/pairtree/pairtree_obj_spec.rb @@ -17,21 +17,21 @@ end it "should read a file" do - @obj.read('content.xml').should == '' + expect(@obj.read('content.xml')).to eql('') end it "should have entries" do - @obj.entries.should == ['content.xml'] + expect(@obj.entries).to eql(['content.xml']) end it "should glob" do - @obj['*.xml'].should == ['content.xml'] - @obj['*.txt'].should == [] + expect(@obj['*.xml']).to eql(['content.xml']) + expect(@obj['*.txt']).to eql([]) end it "should be enumerable" do - block_body = mock('block_body') - block_body.should_receive(:yielded).with('content.xml') + block_body = double('block_body') + expect(block_body).to receive(:yielded).with('content.xml') @obj.each { |file| block_body.yielded(file) } end @@ -41,27 +41,27 @@ end it "should open a file" do - File.should_receive(:open).with(@target,'r') + expect(File).to receive(:open).with(@target,'r') @obj.open('content.xml','r') end it "should call delete" do - File.should_receive(:delete).with(@target) + expect(File).to receive(:delete).with(@target) @obj.delete('content.xml') end it "should call link" do - File.should_receive(:link).with(@target,@target + '.2') + expect(File).to receive(:link).with(@target,@target + '.2') @obj.link('content.xml','content.xml.2') end it "should call rename" do - File.should_receive(:rename).with(@target,@target + '.new') + expect(File).to receive(:rename).with(@target,@target + '.new') @obj.rename('content.xml','content.xml.new') end it "should call utime" do - File.should_receive(:utime).with(0,1,@target) + expect(File).to receive(:utime).with(0,1,@target) @obj.utime(0,1,'content.xml') end end diff --git a/spec/pairtree/pairtree_path_spec.rb b/spec/pairtree/pairtree_path_spec.rb index f8a9bc1..68778d4 100644 --- a/spec/pairtree/pairtree_path_spec.rb +++ b/spec/pairtree/pairtree_path_spec.rb @@ -8,28 +8,28 @@ end it "should generate an encoded id as the leaf path by default" do - Pairtree::Path.leaf('abc/def').should == "abc=def" + expect(Pairtree::Path.leaf('abc/def')).to eql("abc=def") end it "should accept a nil override" do Pairtree::Path.set_leaf nil - Pairtree::Path.leaf('abc/def').should == "" + expect(Pairtree::Path.leaf('abc/def')).to eql("") end it "should accept a scalar override" do Pairtree::Path.set_leaf 'obj' - Pairtree::Path.leaf('abc/def').should == "obj" + expect(Pairtree::Path.leaf('abc/def')).to eql("obj") end it "should accept a Proc override" do lp = Proc.new { |id| id.reverse } Pairtree::Path.set_leaf(lp) - Pairtree::Path.leaf('abc/def').should == "fed=cba" + expect(Pairtree::Path.leaf('abc/def')).to eql("fed=cba") end it "should accept a block override" do Pairtree::Path.set_leaf { |id| id.reverse } - Pairtree::Path.leaf('abc/def').should == "fed=cba" + expect(Pairtree::Path.leaf('abc/def')).to eql("fed=cba") end end diff --git a/spec/pairtree/pairtree_root_spec.rb b/spec/pairtree/pairtree_root_spec.rb index 38066ee..abe9628 100644 --- a/spec/pairtree/pairtree_root_spec.rb +++ b/spec/pairtree/pairtree_root_spec.rb @@ -16,48 +16,48 @@ end it "should have the correct prefix" do - @root.prefix.should == 'pfx:' + expect(@root.prefix).to eql('pfx:') end it "should be in the correct location" do - File.expand_path(@root.path).should == File.expand_path(@base_path) - File.expand_path(@root.root).should == File.expand_path(File.join(@base_path, "pairtree_root")) + expect(File.expand_path(@root.path)).to eql(File.expand_path(@base_path)) + expect(File.expand_path(@root.root)).to eql(File.expand_path(File.join(@base_path, "pairtree_root"))) end it "should list identifiers" do - @root.list.should == ['pfx:abc123def'] + expect(@root.list).to eql(['pfx:abc123def']) end it "should verify whether an identifier exists" do - @root.exists?('pfx:abc123def').should be_true - @root.exists?('pfx:abc123jkl').should be_false + expect(@root.exists?('pfx:abc123def')).to be true + expect(@root.exists?('pfx:abc123jkl')).to be false end it "should raise an exception if an invalid prefix is used" do - lambda { @root.exists?('xfp:abc123def') }.should raise_error(Pairtree::IdentifierError) + expect { @root.exists?('xfp:abc123def') }.to raise_error(Pairtree::IdentifierError) end it "should get a ppath for a valid ID" do obj = @root.get 'pfx:abc123def' - obj.class.should == Pairtree::Obj - File.expand_path(obj.path).should == File.expand_path(File.join(@base_path, "pairtree_root/ab/c1/23/de/f/abc123def/")) + expect(obj.class).to eql(Pairtree::Obj) + expect(File.expand_path(obj.path)).to eql(File.expand_path(File.join(@base_path, "pairtree_root/ab/c1/23/de/f/abc123def/"))) end it "should raise an exception when attempting to get a ppath for an invalid ID" do - lambda { @root.get 'pfx:abc123jkl' }.should raise_error(Errno::ENOENT) + expect { @root.get 'pfx:abc123jkl' }.to raise_error(Errno::ENOENT) end it "should create a new ppath" do obj = @root.mk 'pfx:abc123jkl' - obj.class.should == Pairtree::Obj - File.expand_path(obj.path).should == File.expand_path(File.join(@base_path, "pairtree_root/ab/c1/23/jk/l/abc123jkl/")) - @root.exists?('pfx:abc123jkl').should be_true + expect(obj.class).to eql(Pairtree::Obj) + expect(File.expand_path(obj.path)).to eql(File.expand_path(File.join(@base_path, "pairtree_root/ab/c1/23/jk/l/abc123jkl/"))) + expect(@root.exists?('pfx:abc123jkl')).to be true end it "should delete a ppath" do - @root.exists?('pfx:abc123jkl').should be_true + expect(@root.exists?('pfx:abc123jkl')).to be true @root.purge!('pfx:abc123jkl') - @root.exists?('pfx:abc123jkl').should be_false + expect(@root.exists?('pfx:abc123jkl')).to be false end end \ No newline at end of file diff --git a/spec/pairtree/pairtree_spec.rb b/spec/pairtree/pairtree_spec.rb index 73e40d6..57b340b 100644 --- a/spec/pairtree/pairtree_spec.rb +++ b/spec/pairtree/pairtree_spec.rb @@ -8,7 +8,7 @@ end it "should raise an error if a non-existent is specified without :create" do - lambda { Pairtree.at(@base_path) }.should raise_error(Pairtree::PathError) + expect { Pairtree.at(@base_path) }.to raise_error(Pairtree::PathError) end describe "new pairtree" do @@ -19,10 +19,10 @@ it "should create a new pairtree" do prefix = 'my_prefix:' pt = Pairtree.at(@base_path, :prefix => prefix, :create => true) - pt.prefix.should == prefix - File.read(File.join(@base_path, 'pairtree_prefix')).should == prefix - pt.root.should == File.join(@base_path, 'pairtree_root') - pt.pairtree_version.should == Pairtree::SPEC_VERSION + expect(pt.prefix).to eql(prefix) + expect(File.read(File.join(@base_path,'pairtree_prefix'))).to eql(prefix) + expect(pt.root).to eql(File.join(@base_path, 'pairtree_root')) + expect(pt.pairtree_version).to eql(Pairtree::SPEC_VERSION) end end @@ -39,29 +39,29 @@ end it "should raise an error if a regular file is specified as a root" do - lambda { Pairtree.at(File.join(@base_path, "pairtree_prefix"), :create => true) }.should raise_error(Pairtree::PathError) + expect { Pairtree.at(File.join(@base_path, "pairtree_prefix"), :create => true) }.to raise_error(Pairtree::PathError) end it "should read the prefix if none is specified" do - Pairtree.at(@base_path).prefix.should == File.read(File.join(@base_path, 'pairtree_prefix')) + expect(Pairtree.at(@base_path).prefix).to eql(File.read(File.join(@base_path, 'pairtree_prefix'))) end it "should not complain if the given prefix matches the saved prefix" do - Pairtree.at(@base_path, :prefix => 'pfx:').prefix.should == File.read(File.join(@base_path, 'pairtree_prefix')) + expect(Pairtree.at(@base_path, :prefix => 'pfx:').prefix).to eql(File.read(File.join(@base_path, 'pairtree_prefix'))) end it "should raise an error if the given prefix does not match the saved prefix" do - lambda { Pairtree.at(@base_path, :prefix => 'wrong-prefix:') }.should raise_error(Pairtree::IdentifierError) + expect { Pairtree.at(@base_path, :prefix => 'wrong-prefix:') }.to raise_error(Pairtree::IdentifierError) end it "should not complain if the given version matches the saved version" do - Pairtree.at(@base_path, :version => Pairtree::SPEC_VERSION).pairtree_version.should == Pairtree::SPEC_VERSION - Pairtree.at(@base_path, :version => Pairtree::SPEC_VERSION, :create => true).pairtree_version.should == Pairtree::SPEC_VERSION + expect(Pairtree.at(@base_path, :version => Pairtree::SPEC_VERSION).pairtree_version).to eql(Pairtree::SPEC_VERSION) + expect(Pairtree.at(@base_path, :version => Pairtree::SPEC_VERSION, :create => true).pairtree_version).to eql(Pairtree::SPEC_VERSION) end it "should raise an error if the given version does not match the saved version" do - lambda { Pairtree.at(@base_path, :version => 0.2) }.should raise_error(Pairtree::VersionMismatch) - lambda { Pairtree.at(@base_path, :version => 0.2, :create => true) }.should raise_error(Pairtree::VersionMismatch) + expect { Pairtree.at(@base_path, :version => 0.2) }.to raise_error(Pairtree::VersionMismatch) + expect { Pairtree.at(@base_path, :version => 0.2, :create => true) }.to raise_error(Pairtree::VersionMismatch) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 6b5da6c..60ca750 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,7 +3,6 @@ require 'bundler/setup' require 'rspec' -require 'rspec/autorun' if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.9/ require 'simplecov'