diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..9cdb6af --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,26 @@ +name: Run Tests + +on: push + +jobs: + test: + runs-on: ubuntu-latest + name: Ruby ${{ matrix.ruby }} + strategy: + matrix: + ruby: [2.7, 3.0, 3.1, 3.2] + steps: + - uses: actions/checkout@v3 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + bundler-cache: true + - name: Run linter for Ruby + run: bundle exec standardrb + - name: Run tests + run: bundle exec rspec + - name: Report to Coveralls + uses: coverallsapp/github-action@1.1.3 + with: + github-token: ${{ secrets.github_token }} diff --git a/.gitignore b/.gitignore index 016f7d2..b5c5896 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ doc # bundler .bundle +vendor/ # jeweler generated pkg diff --git a/Gemfile b/Gemfile index bbe8004..562266a 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,8 @@ source "https://rubygems.org" # Specify your gem's dependencies in test.gemspec gemspec - -gem 'rcov', :platform => :mri_18 -gem 'simplecov', :platforms => [:mri_19, :mri_20] -gem 'simplecov-rcov', :platforms => [:mri_19, :mri_20] +group :development, :test do + gem "simplecov" + gem "standardrb" + gem "simplecov-lcov" +end diff --git a/README.md b/README.md index 0f80bfd..1f4821d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +[![Tests](https://github.com/mlibrary/pairtree/actions/workflows/tests.yaml/badge.svg)](https://github.com/mlibrary/pairtree/actions/workflows/tests.yaml) +[![Coverage Status](https://coveralls.io/repos/github/mlibrary/pairtree/badge.svg?branch=main)](https://coveralls.io/github/mlibrary/pairtree?branch=main) +[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard) + # (r)pairtree Ruby implementation of the [Pairtree](https://wiki.ucop.edu/display/Curation/PairTree) specification from the California Digital Library. diff --git a/Rakefile b/Rakefile index 4120efb..8ab446e 100644 --- a/Rakefile +++ b/Rakefile @@ -1,40 +1,40 @@ -require 'rubygems' -require 'bundler' +require "rubygems" +require "bundler" begin Bundler.setup(:default, :development) rescue Bundler::BundlerError => e - $stderr.puts e.message - $stderr.puts "Run `bundle install` to install missing gems" + warn e.message + warn "Run `bundle install` to install missing gems" exit e.status_code end Bundler::GemHelper.install_tasks -require 'rake' -require 'rspec' -require 'rspec/core/rake_task' +require "rake" +require "rspec" +require "rspec/core/rake_task" -desc 'Default: run specs.' -task :default => :spec +desc "Default: run specs." +task default: :spec RSpec::Core::RakeTask.new do |t| - if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.8/ + if ENV["COVERAGE"] && RUBY_VERSION =~ (/^1.8/) t.rcov = true - t.rcov_opts = ['--exclude', 'spec', '--exclude', 'gems'] + t.rcov_opts = ["--exclude", "spec", "--exclude", "gems"] end end # Use yard to build docs begin - require 'yard' - require 'yard/rake/yardoc_task' - project_root = File.expand_path(File.dirname(__FILE__)) - doc_destination = File.join(project_root, 'doc') + require "yard" + require "yard/rake/yardoc_task" + project_root = __dir__ + doc_destination = File.join(project_root, "doc") YARD::Rake::YardocTask.new(:doc) do |yt| - yt.files = Dir.glob(File.join(project_root, 'lib', '**', '*.rb')) + - [ File.join(project_root, 'README.md') ] - yt.options = ['--output-dir', doc_destination, '--readme', 'README.md'] + yt.files = Dir.glob(File.join(project_root, "lib", "**", "*.rb")) + + [File.join(project_root, "README.md")] + yt.options = ["--output-dir", doc_destination, "--readme", "README.md"] end rescue LoadError desc "Generate YARD Documentation" @@ -42,4 +42,3 @@ rescue LoadError abort "Please install the YARD gem to generate rdoc." end end - diff --git a/lib/pairtree.rb b/lib/pairtree.rb index 514f1cd..d175301 100644 --- a/lib/pairtree.rb +++ b/lib/pairtree.rb @@ -1,17 +1,19 @@ -require 'pairtree/identifier' -require 'pairtree/path' -require 'pairtree/obj' -require 'pairtree/root' +require "pairtree/identifier" +require "pairtree/path" +require "pairtree/obj" +require "pairtree/root" -require 'fileutils' +require "fileutils" module Pairtree - class IdentifierError < Exception; end - class PathError < Exception; end - class VersionMismatch < Exception; end + class IdentifierError < RuntimeError; end + + class PathError < RuntimeError; end + + class VersionMismatch < RuntimeError; end SPEC_VERSION = 0.1 - + ## # Instantiate a pairtree at a given path location # @param [String] path The path in which the pairtree resides @@ -20,34 +22,34 @@ class VersionMismatch < Exception; end # @option args [String] :version (Pairtree::SPEC_VERSION) the version of the pairtree spec that this tree conforms to # @option args [Boolean] :create (false) if true, create the pairtree and its directory structure if it doesn't already exist def self.at path, args = {} - args = { :prefix => nil, :version => nil, :create => false }.merge(args) + args = {prefix: nil, version: nil, create: false}.merge(args) args[:version] ||= SPEC_VERSION args[:version] = args[:version].to_f - - root_path = File.join(path, 'pairtree_root') - prefix_file = File.join(path, 'pairtree_prefix') + + root_path = File.join(path, "pairtree_root") + prefix_file = File.join(path, "pairtree_prefix") version_file = File.join(path, pairtree_version_filename(args[:version])) - existing_version_file = Dir[File.join(path, "pairtree_version*")].sort.last - + existing_version_file = Dir[File.join(path, "pairtree_version*")].max + if args.delete(:create) - if File.exists?(path) and not File.directory?(path) + if File.exist?(path) && !File.directory?(path) raise PathError, "#{path} exists, but is not a valid pairtree root" end FileUtils.mkdir_p(root_path) - unless File.exists? prefix_file - File.open(prefix_file, 'w') { |f| f.write(args[:prefix].to_s) } + unless File.exist? prefix_file + File.write(prefix_file, args[:prefix].to_s) end - + if existing_version_file if existing_version_file != version_file - stored_version = existing_version_file.scan(/([0-9]+)_([0-9]+)/).flatten.join('.').to_f + stored_version = existing_version_file.scan(/([0-9]+)_([0-9]+)/).flatten.join(".").to_f raise VersionMismatch, "Version #{args[:version]} specified, but #{stored_version} found." end else args[:version] ||= SPEC_VERSION version_file = File.join(path, pairtree_version_filename(args[:version])) - File.open(version_file, 'w') { |f| f.write %{This directory conforms to Pairtree Version #{args[:version]}. Updated spec: http://www.cdlib.org/inside/diglib/pairtree/pairtreespec.html} } + File.write(version_file, %(This directory conforms to Pairtree Version #{args[:version]}. Updated spec: http://www.cdlib.org/inside/diglib/pairtree/pairtreespec.html)) existing_version_file = version_file end else @@ -57,22 +59,25 @@ def self.at path, args = {} end stored_prefix = File.read(prefix_file) - unless args[:prefix].nil? or args[:prefix].to_s == stored_prefix + unless args[:prefix].nil? || (args[:prefix].to_s == stored_prefix) raise IdentifierError, "Specified prefix #{args[:prefix].inspect} does not match stored prefix #{stored_prefix.inspect}" end args[:prefix] = stored_prefix - stored_version = existing_version_file.scan(/([0-9]+)_([0-9]+)/).flatten.join('.').to_f + stored_version = existing_version_file.scan(/([0-9]+)_([0-9]+)/).flatten.join(".").to_f args[:version] ||= stored_version unless args[:version] == stored_version raise VersionMismatch, "Version #{args[:version]} specified, but #{stored_version} found." end - - Pairtree::Root.new(File.join(path, 'pairtree_root'), args) + + Pairtree::Root.new(File.join(path, "pairtree_root"), args) end - private - def self.pairtree_version_filename(version) - "pairtree_version#{version.to_s.gsub(/\./,'_')}" + class << self + private + + def pairtree_version_filename(version) + "pairtree_version#{version.to_s.tr(".", "_")}" + end end end diff --git a/lib/pairtree/identifier.rb b/lib/pairtree/identifier.rb index 0ac711e..00a3d61 100644 --- a/lib/pairtree/identifier.rb +++ b/lib/pairtree/identifier.rb @@ -1,4 +1,3 @@ -# encoding: utf-8 module Pairtree class Identifier ENCODE_REGEX = Regexp.compile("[\"*+,<=>?\\\\^|]|[^\x21-\x7e]", nil) @@ -8,14 +7,14 @@ class Identifier # Encode special characters within an identifier # @param [String] id The identifier def self.encode id - id.gsub(ENCODE_REGEX) { |c| char2hex(c) }.tr('/:.', '=+,') + id.gsub(ENCODE_REGEX) { |c| char2hex(c) }.tr("/:.", "=+,") end ## # Decode special characters within an identifier # @param [String] id The identifier def self.decode id - input = id.tr('=+,', '/:.').bytes.to_a + input = id.tr("=+,", "/:.").bytes.to_a intermediate = [] while input.first if input.first == 94 @@ -23,14 +22,14 @@ def self.decode id input.shift h << input.shift h << input.shift - intermediate << h.pack('c*').hex + intermediate << h.pack("c*").hex else intermediate << input.shift end end - result = intermediate.pack('c*') + result = intermediate.pack("c*") if result.respond_to? :force_encoding - result.force_encoding('UTF-8') + result.force_encoding("UTF-8") end result end @@ -39,14 +38,14 @@ def self.decode id # Convert a character to its pairtree hexidecimal representation # @param [Char] c The character to convert def self.char2hex c - c.unpack('H*')[0].scan(/../).map { |x| "^#{x}"}.join('') + c.unpack1("H*").scan(/../).map { |x| "^#{x}" }.join("") end ## # Convert a pairtree hexidecimal string to its character representation # @param [String] h The hexidecimal string to convert def self.hex2char h - '' << h.delete('^').hex + "" << h.delete("^").hex end end end diff --git a/lib/pairtree/obj.rb b/lib/pairtree/obj.rb index d447e96..d884c88 100644 --- a/lib/pairtree/obj.rb +++ b/lib/pairtree/obj.rb @@ -1,52 +1,51 @@ -module Pairtree +module Pairtree class Obj < ::Dir - - FILE_METHODS = [:atime, :open, :read, :file?, :directory?, :exist?, :exists?, :file?, :ftype, :lstat, + FILE_METHODS = [:atime, :open, :read, :file?, :directory?, :exist?, :exists?, :file?, :ftype, :lstat, :mtime, :readable?, :size, :stat, :truncate, :writable?, :zero?] FILE_METHODS.each do |file_method| - define_method file_method do |fname,*args,&block| - File.send(file_method, File.join(self.path, fname), *args, &block) + define_method file_method do |fname, *args, &block| + File.send(file_method, File.join(path, fname), *args, &block) end end def delete *args - File.delete(*(prepend_filenames(args))) + File.delete(*prepend_filenames(args)) end alias_method :unlink, :delete def link *args - File.link(*(prepend_filenames(args))) + File.link(*prepend_filenames(args)) end def rename *args - File.rename(*(prepend_filenames(args))) + File.rename(*prepend_filenames(args)) end - + def utime atime, mtime, *args - File.utime(atime, mtime, *(prepend_filenames(args))) + File.utime(atime, mtime, *prepend_filenames(args)) end - + def entries - super - ['.','..'] + super - [".", ".."] end - + def each &block - super { |entry| yield(entry) unless entry =~ /^\.{1,2}$/ } + super { |entry| yield(entry) unless /^\.{1,2}$/.match?(entry) } end - + def glob(string, flags = 0) - result = Dir.glob(File.join(self.path, string), flags) - ['.','..'] - result.collect { |f| f.sub(%r{^#{self.path}/},'') } + result = Dir.glob(File.join(path, string), flags) - [".", ".."] + result.collect { |f| f.sub(%r{^#{path}/}, "") } end - + def [](string) glob(string, 0) end - + private + def prepend_filenames(files) - files.collect { |fname| File.join(self.path, fname) } + files.collect { |fname| File.join(path, fname) } end - end end diff --git a/lib/pairtree/path.rb b/lib/pairtree/path.rb index abfe92f..7f8dd31 100644 --- a/lib/pairtree/path.rb +++ b/lib/pairtree/path.rb @@ -1,43 +1,41 @@ module Pairtree class Path @@leaf_proc = lambda { |id| id } - + def self.set_leaf value = nil, &block - if value.nil? - @@leaf_proc = block + @@leaf_proc = if value.nil? + block + elsif value.is_a?(Proc) + value else - if value.is_a?(Proc) - @@leaf_proc = value - else - @@leaf_proc = lambda { |id| value } - end + lambda { |id| value } end end - + def self.leaf id if @@leaf_proc Pairtree::Identifier.encode(@@leaf_proc.call(id)) else - '' + "" end end - + def self.id_to_path id - path = File.join(Pairtree::Identifier.encode(id).scan(/..?/),self.leaf(id)) - path.sub(%r{#{File::SEPARATOR}+$},'') + path = File.join(Pairtree::Identifier.encode(id).scan(/..?/), leaf(id)) + path.sub(%r{#{File::SEPARATOR}+$}o, "") end def self.path_to_id ppath parts = ppath.split(File::SEPARATOR) - parts.pop if @@leaf_proc and parts.last.length > Root::SHORTY_LENGTH + parts.pop if @@leaf_proc && (parts.last.length > Root::SHORTY_LENGTH) Pairtree::Identifier.decode(parts.join) end - + def self.remove! path FileUtils.remove_dir(path, true) parts = path.split(File::SEPARATOR) parts.pop - while parts.length > 0 and parts.last != 'pairtree_root' + while (parts.length > 0) && (parts.last != "pairtree_root") begin FileUtils.rmdir(parts.join(File::SEPARATOR)) parts.pop diff --git a/lib/pairtree/root.rb b/lib/pairtree/root.rb index 77b0c14..d294bf5 100644 --- a/lib/pairtree/root.rb +++ b/lib/pairtree/root.rb @@ -1,10 +1,10 @@ -require 'fileutils' +require "fileutils" module Pairtree class Root SHORTY_LENGTH = 2 attr_reader :root, :prefix - + ## # @param [String] root The pairtree_root directory within the pairtree home # @param [Hash] args Pairtree options @@ -12,9 +12,9 @@ class Root # @option args [String] :version (Pairtree::SPEC_VERSION) the version of the pairtree spec that this tree conforms to def initialize root, args = {} @root = root - + @shorty_length = args.delete(:shorty_length) || SHORTY_LENGTH - @prefix = args.delete(:prefix) || '' + @prefix = args.delete(:prefix) || "" @options = args end @@ -22,15 +22,15 @@ def initialize root, args = {} ## # Get a list of valid existing identifiers within the pairtree # @return [Array] - def list + def list objects = [] return [] unless File.directory? @root Dir.chdir(@root) do - possibles = Dir['**/?'] + Dir['**/??'] + possibles = Dir["**/?"] + Dir["**/??"] possibles.each { |path| contents = Dir.entries(path).reject { |x| x =~ /^\./ } - objects << path unless contents.all? { |f| f.length <= @shorty_length and File.directory?(File.join(path, f)) } + objects << path unless contents.all? { |f| (f.length <= @shorty_length) && File.directory?(File.join(path, f)) } } end objects.map { |x| @prefix + Pairtree::Path.path_to_id(x) } @@ -42,7 +42,7 @@ def list def path File.dirname(root) end - + ## # Get the full path for a given identifier (whether it exists or not) # @param [String] id The full, prefixed identifier @@ -51,7 +51,7 @@ def path_for id unless id.start_with? @prefix raise IdentifierError, "Identifier must start with #{@prefix}" end - path_id = id[@prefix.length..-1] + path_id = id[@prefix.length..] File.join(@root, Pairtree::Path.id_to_path(path_id)) end @@ -62,7 +62,7 @@ def path_for id def exists? id File.directory?(path_for(id)) end - + ## # Get an existing ppath # @param [String] id The full, prefixed identifier @@ -71,7 +71,7 @@ def get id Pairtree::Obj.new path_for(id) end alias_method :[], :get - + ## # Create a new ppath # @param [String] id The full, prefixed identifier @@ -80,7 +80,7 @@ def mk id FileUtils.mkdir_p path_for(id) get(id) end - + ## # Delete a ppath # @param [String] id The full, prefixed identifier @@ -89,7 +89,7 @@ def purge! id if exists?(id) Pairtree::Path.remove!(path_for(id)) end - not exists?(id) + !exists?(id) end ## @@ -98,6 +98,5 @@ def purge! id def pairtree_version @options[:version] end - end end diff --git a/lib/tasks/rdoc.rake b/lib/tasks/rdoc.rake index 57e663b..869d8df 100644 --- a/lib/tasks/rdoc.rake +++ b/lib/tasks/rdoc.rake @@ -1,21 +1,21 @@ desc "Generate RDoc" -task :doc => ['doc:generate'] +task doc: ["doc:generate"] namespace :doc do - project_root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')) - doc_destination = File.join(project_root, 'rdoc') + project_root = File.expand_path(File.join(File.dirname(__FILE__), "..", "..")) + doc_destination = File.join(project_root, "rdoc") begin - require 'yard' - require 'yard/rake/yardoc_task' + require "yard" + require "yard/rake/yardoc_task" YARD::Rake::YardocTask.new(:generate) do |yt| - yt.files = Dir.glob(File.join(project_root, 'lib', '*.rb')) + - Dir.glob(File.join(project_root, 'lib', '**', '*.rb')) + - [ File.join(project_root, 'README.rdoc') ] + - [ File.join(project_root, 'LICENSE') ] - - yt.options = ['--output-dir', doc_destination, '--readme', 'README.rdoc'] + yt.files = Dir.glob(File.join(project_root, "lib", "*.rb")) + + Dir.glob(File.join(project_root, "lib", "**", "*.rb")) + + [File.join(project_root, "README.rdoc")] + + [File.join(project_root, "LICENSE")] + + yt.options = ["--output-dir", doc_destination, "--readme", "README.rdoc"] end rescue LoadError desc "Generate YARD Documentation" @@ -26,7 +26,6 @@ namespace :doc do desc "Remove generated documenation" task :clean do - rm_r doc_destination if File.exists?(doc_destination) + rm_r doc_destination if File.exist?(doc_destination) end - -end \ No newline at end of file +end diff --git a/pairtree.gemspec b/pairtree.gemspec index e7027e3..cfc62ce 100644 --- a/pairtree.gemspec +++ b/pairtree.gemspec @@ -1,21 +1,17 @@ Gem::Specification.new do |s| - 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.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.name = "rpairtree" + s.summary = "Ruby Pairtree implementation, forked from pairtree which is abandoned." + s.version = "0.2.0" + s.homepage = "http://github.com/mlibrary/pairtree" + s.licenses = ["Apache2"] + s.authors = ["Chris Beer, Bryan Hockey, Michael Slone"] + s.files = `git ls-files`.split("\n") 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"] - + s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) } + s.require_paths = ["lib"] s.add_development_dependency "bundler" s.add_development_dependency "rspec", ">= 2.0" s.add_development_dependency "yard" s.add_development_dependency "rake" end - diff --git a/spec/pairtree/pairtree_encoding_spec.rb b/spec/pairtree/pairtree_encoding_spec.rb index bcae279..11e2efc 100644 --- a/spec/pairtree/pairtree_encoding_spec.rb +++ b/spec/pairtree/pairtree_encoding_spec.rb @@ -1,10 +1,8 @@ -# encoding: utf-8 -require 'spec_helper' -require 'pairtree' +require "spec_helper" +require "pairtree" describe "Pairtree encoding" do - - def roundtrip(id, expected_encoded=nil, expected_path=nil) + def roundtrip(id, expected_encoded = nil, expected_path = nil) encoded = Pairtree::Identifier.encode(id) unless expected_encoded.nil? expect(encoded).to eql(expected_encoded) @@ -14,50 +12,50 @@ def roundtrip(id, expected_encoded=nil, expected_path=nil) expect(path).to eql(expected_path) end str = Pairtree::Identifier.decode(encoded) - + if str.respond_to? :force_encoding str.force_encoding("UTF-8") end expect(str).to eql(id) end - + it "should handle a" do - roundtrip('a', 'a', 'a/a') + roundtrip("a", "a", "a/a") end it "should handle ab" do - roundtrip('ab', 'ab', 'ab/ab') + roundtrip("ab", "ab", "ab/ab") end it "should handle abc" do - roundtrip('abc', 'abc', 'ab/c/abc') + roundtrip("abc", "abc", "ab/c/abc") end it "should handle abcd" do - roundtrip('abcd', 'abcd', 'ab/cd/abcd') + roundtrip("abcd", "abcd", "ab/cd/abcd") end it "should handle space" do - roundtrip('hello world', 'hello^20world', 'he/ll/o^/20/wo/rl/d/hello^20world') + roundtrip("hello world", "hello^20world", "he/ll/o^/20/wo/rl/d/hello^20world") end it "should handle slash" do - roundtrip("/","=",'=/=') + roundtrip("/", "=", "=/=") end it "should handle urn" do - roundtrip('http://n2t.info/urn:nbn:se:kb:repos-1','http+==n2t,info=urn+nbn+se+kb+repos-1','ht/tp/+=/=n/2t/,i/nf/o=/ur/n+/nb/n+/se/+k/b+/re/po/s-/1/http+==n2t,info=urn+nbn+se+kb+repos-1') + roundtrip("http://n2t.info/urn:nbn:se:kb:repos-1", "http+==n2t,info=urn+nbn+se+kb+repos-1", "ht/tp/+=/=n/2t/,i/nf/o=/ur/n+/nb/n+/se/+k/b+/re/po/s-/1/http+==n2t,info=urn+nbn+se+kb+repos-1") end - + it "should handle wtf" do - roundtrip('what-the-*@?#!^!?', "what-the-^2a@^3f#!^5e!^3f", "wh/at/-t/he/-^/2a/@^/3f/#!/^5/e!/^3/f/what-the-^2a@^3f#!^5e!^3f") + roundtrip("what-the-*@?#!^!?", "what-the-^2a@^3f#!^5e!^3f", "wh/at/-t/he/-^/2a/@^/3f/#!/^5/e!/^3/f/what-the-^2a@^3f#!^5e!^3f") end it "should handle special characters" do roundtrip('\\"*+,<=>?^|', "^5c^22^2a^2b^2c^3c^3d^3e^3f^5e^7c") end - + it "should roundtrip hardcore Unicode" do roundtrip(%{ 1. Euro Symbol: €. @@ -76,9 +74,9 @@ def roundtrip(id, expected_encoded=nil, expected_path=nil) 14. Thai: ฉันกินกระจกได้ แต่มันไม่ทำให้ฉันเจ็บ " }) end - + it "should roundtrip French" do - 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", "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 @@ -89,6 +87,5 @@ def roundtrip(id, expected_encoded=nil, expected_path=nil) was composed well after the first two volumes and often displays less showy virtuosity and more harmonic experimentation. }) - end - + end end diff --git a/spec/pairtree/pairtree_obj_spec.rb b/spec/pairtree/pairtree_obj_spec.rb index 344695e..1855d19 100644 --- a/spec/pairtree/pairtree_obj_spec.rb +++ b/spec/pairtree/pairtree_obj_spec.rb @@ -1,69 +1,67 @@ -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -require 'pairtree' +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") +require "pairtree" describe "Pairtree::Obj" do - before(:all) do @base_path = File.join(File.dirname(__FILE__), "../test_data/working") Dir.chdir(File.join(File.dirname(__FILE__), "../test_data")) do - FileUtils.cp_r('fixtures/pairtree_root_spec', './working') + FileUtils.cp_r("fixtures/pairtree_root_spec", "./working") end @root = Pairtree.at(@base_path) - @obj = @root.get('pfx:abc123def') + @obj = @root.get("pfx:abc123def") end - + after(:all) do FileUtils.rm_rf(@base_path) end - + it "should read a file" do - expect(@obj.read('content.xml')).to eql('') + expect(@obj.read("content.xml")).to eql("") end it "should have entries" do - expect(@obj.entries).to eql(['content.xml']) + expect(@obj.entries).to eql(["content.xml"]) end - + it "should glob" do - expect(@obj['*.xml']).to eql(['content.xml']) - expect(@obj['*.txt']).to eql([]) + expect(@obj["*.xml"]).to eql(["content.xml"]) + expect(@obj["*.txt"]).to eql([]) end - + it "should be enumerable" do - block_body = double('block_body') - expect(block_body).to 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 - + describe "Call a bunch of File methods" do before(:each) do - @target = File.join(@base_path, 'pairtree_root/ab/c1/23/de/f/abc123def/content.xml') + @target = File.join(@base_path, "pairtree_root/ab/c1/23/de/f/abc123def/content.xml") end - + it "should open a file" do - expect(File).to receive(:open).with(@target,'r') - @obj.open('content.xml','r') + expect(File).to receive(:open).with(@target, "r") + @obj.open("content.xml", "r") end it "should call delete" do expect(File).to receive(:delete).with(@target) - @obj.delete('content.xml') + @obj.delete("content.xml") end it "should call link" do - expect(File).to receive(:link).with(@target,@target + '.2') - @obj.link('content.xml','content.xml.2') + expect(File).to receive(:link).with(@target, @target + ".2") + @obj.link("content.xml", "content.xml.2") end it "should call rename" do - expect(File).to receive(:rename).with(@target,@target + '.new') - @obj.rename('content.xml','content.xml.new') + expect(File).to receive(:rename).with(@target, @target + ".new") + @obj.rename("content.xml", "content.xml.new") end it "should call utime" do - expect(File).to receive(:utime).with(0,1,@target) - @obj.utime(0,1,'content.xml') + expect(File).to receive(:utime).with(0, 1, @target) + @obj.utime(0, 1, "content.xml") end end - -end \ No newline at end of file +end diff --git a/spec/pairtree/pairtree_path_spec.rb b/spec/pairtree/pairtree_path_spec.rb index 68778d4..f44627c 100644 --- a/spec/pairtree/pairtree_path_spec.rb +++ b/spec/pairtree/pairtree_path_spec.rb @@ -1,35 +1,33 @@ -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -require 'pairtree' +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") +require "pairtree" describe "Pairtree::Path" do - after(:each) do Pairtree::Path.set_leaf { |id| id } end - + it "should generate an encoded id as the leaf path by default" do - expect(Pairtree::Path.leaf('abc/def')).to eql("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 - expect(Pairtree::Path.leaf('abc/def')).to eql("") + expect(Pairtree::Path.leaf("abc/def")).to eql("") end - + it "should accept a scalar override" do - Pairtree::Path.set_leaf 'obj' - expect(Pairtree::Path.leaf('abc/def')).to eql("obj") + Pairtree::Path.set_leaf "obj" + expect(Pairtree::Path.leaf("abc/def")).to eql("obj") end - + it "should accept a Proc override" do - lp = Proc.new { |id| id.reverse } + lp = proc { |id| id.reverse } Pairtree::Path.set_leaf(lp) - expect(Pairtree::Path.leaf('abc/def')).to eql("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 } - expect(Pairtree::Path.leaf('abc/def')).to eql("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 abe9628..08c412d 100644 --- a/spec/pairtree/pairtree_root_spec.rb +++ b/spec/pairtree/pairtree_root_spec.rb @@ -1,63 +1,61 @@ -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -require 'pairtree' +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") +require "pairtree" describe "Pairtree::Root" do - before(:all) do @base_path = File.join(File.dirname(__FILE__), "../test_data/working") Dir.chdir(File.join(File.dirname(__FILE__), "../test_data")) do - FileUtils.cp_r('fixtures/pairtree_root_spec', './working') + FileUtils.cp_r("fixtures/pairtree_root_spec", "./working") end @root = Pairtree.at(@base_path) end - + after(:all) do FileUtils.rm_rf(@base_path) end - + it "should have the correct prefix" do - expect(@root.prefix).to eql('pfx:') + expect(@root.prefix).to eql("pfx:") end - + it "should be in the correct location" do 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 - expect(@root.list).to eql(['pfx:abc123def']) + expect(@root.list).to eql(["pfx:abc123def"]) end - + it "should verify whether an identifier exists" do - expect(@root.exists?('pfx:abc123def')).to be true - expect(@root.exists?('pfx:abc123jkl')).to 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 - expect { @root.exists?('xfp:abc123def') }.to 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 = @root.get "pfx: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 - expect { @root.get 'pfx:abc123jkl' }.to 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 = @root.mk "pfx:abc123jkl" 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 + expect(@root.exists?("pfx:abc123jkl")).to be true end - + it "should delete a ppath" do - expect(@root.exists?('pfx:abc123jkl')).to be true - @root.purge!('pfx:abc123jkl') - expect(@root.exists?('pfx:abc123jkl')).to be false + expect(@root.exists?("pfx:abc123jkl")).to be true + @root.purge!("pfx:abc123jkl") + expect(@root.exists?("pfx:abc123jkl")).to be false end - -end \ No newline at end of file +end diff --git a/spec/pairtree/pairtree_spec.rb b/spec/pairtree/pairtree_spec.rb index 57b340b..25910db 100644 --- a/spec/pairtree/pairtree_spec.rb +++ b/spec/pairtree/pairtree_spec.rb @@ -1,12 +1,11 @@ -require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') -require 'pairtree' +require File.expand_path(File.dirname(__FILE__) + "/../spec_helper") +require "pairtree" describe "Pairtree" do - before(:all) do @base_path = File.join(File.dirname(__FILE__), "../test_data/working") end - + it "should raise an error if a non-existent is specified without :create" do expect { Pairtree.at(@base_path) }.to raise_error(Pairtree::PathError) end @@ -17,53 +16,50 @@ end it "should create a new pairtree" do - prefix = 'my_prefix:' - pt = Pairtree.at(@base_path, :prefix => prefix, :create => true) + prefix = "my_prefix:" + pt = Pairtree.at(@base_path, prefix: prefix, create: true) 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(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 - + describe "existing pairtree" do before(:all) do Dir.chdir(File.join(File.dirname(__FILE__), "../test_data")) do - FileUtils.cp_r('fixtures/pairtree_root_spec', './working') + FileUtils.cp_r("fixtures/pairtree_root_spec", "./working") end end - + after(:all) do FileUtils.rm_rf(@base_path) end it "should raise an error if a regular file is specified as a root" do - expect { Pairtree.at(File.join(@base_path, "pairtree_prefix"), :create => true) }.to 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 - expect(Pairtree.at(@base_path).prefix).to eql(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 - expect(Pairtree.at(@base_path, :prefix => 'pfx:').prefix).to eql(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 - expect { Pairtree.at(@base_path, :prefix => 'wrong-prefix:') }.to 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 - 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) + 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 - 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) + 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 - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 60ca750..d3ddefa 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,16 +1,22 @@ $LOAD_PATH.unshift(File.dirname(__FILE__)) -$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) +$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) -require 'bundler/setup' -require 'rspec' +require "bundler/setup" +require "rspec" -if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.9/ - require 'simplecov' - SimpleCov.start +require "simplecov" +require "simplecov-lcov" +SimpleCov::Formatter::LcovFormatter.config do |c| + c.report_with_single_file = true + c.single_report_path = "coverage/lcov.info" end +SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([ + SimpleCov::Formatter::HTMLFormatter, + SimpleCov::Formatter::LcovFormatter +]) +SimpleCov.start -require 'pairtree' +require "pairtree" RSpec.configure do |config| - end