Skip to content

Commit 8667d00

Browse files
authored
Merge pull request #5 from mlibrary/update-upstream
Updates for current ruby
2 parents cd133a9 + 62de3ff commit 8667d00

19 files changed

+330
-298
lines changed

.github/workflows/tests.yml

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Run Tests
2+
3+
on: push
4+
5+
jobs:
6+
test:
7+
runs-on: ubuntu-latest
8+
name: Ruby ${{ matrix.ruby }}
9+
strategy:
10+
matrix:
11+
ruby: [2.7, 3.0, 3.1, 3.2]
12+
steps:
13+
- uses: actions/checkout@v3
14+
- name: Set up Ruby
15+
uses: ruby/setup-ruby@v1
16+
with:
17+
ruby-version: ${{ matrix.ruby }}
18+
bundler-cache: true
19+
- name: Run linter for Ruby
20+
run: bundle exec standardrb
21+
- name: Run tests
22+
run: bundle exec rspec

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ doc
1010

1111
# bundler
1212
.bundle
13+
vendor/
1314

1415
# jeweler generated
1516
pkg
@@ -42,3 +43,5 @@ pkg
4243
#*.swp
4344
#
4445
Gemfile.lock
46+
47+
.idea/

.travis.yml

-7
This file was deleted.

Gemfile

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
source "http://rubygems.org"
1+
source "https://rubygems.org"
22

33
# Specify your gem's dependencies in test.gemspec
44
gemspec
55

6-
7-
gem 'rcov', :platform => :mri_18
8-
gem 'simplecov', :platform => :mri_19
9-
gem 'simplecov-rcov', :platform => :mri_19
6+
group :development, :test do
7+
gem "simplecov"
8+
gem "standardrb"
9+
gem "simplecov-lcov"
10+
end

README.md

+25-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,31 @@
1+
[![Tests](https://github.com/ruby-microservices/pairtree/actions/workflows/tests.yml/badge.svg)](https://github.com/ruby-microservices/pairtree/actions/workflows/tests.yml)
2+
[![Ruby Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://github.com/testdouble/standard)
3+
14
# pairtree
25

3-
Ruby implementation of the [Pairtree](https://confluence.ucop.edu/display/Curation/PairTree microservice specification from the California Digital Librar)
6+
Ruby implementation of the [Pairtree](https://www.ietf.org/archive/id/draft-kunze-pairtree-01.txt) specification from the California Digital Library.
7+
8+
## Installation
9+
10+
Add this line to your application's Gemfile:
11+
12+
```ruby
13+
gem 'pairtree'
14+
```
15+
16+
And then execute:
417

5-
# Usage
18+
$ bundle
19+
20+
Or install it yourself as:
21+
22+
$ gem install pairtree
23+
24+
## Usage
625

726
```ruby
27+
require 'pairtree'
28+
829
# Initiate a tree
930
pairtree = Pairtree.at('./data', :prefix => 'pfx:', :create => true)
1031

@@ -29,9 +50,7 @@ Ruby implementation of the [Pairtree](https://confluence.ucop.edu/display/Curati
2950
# Delete a ppath and all its contents
3051
pairtree.purge!('pfx:abc123def')
3152
```
32-
33-
## Copyright
3453

35-
Copyright (c) 2010 Chris Beer. See LICENSE.txt for
36-
further details.
54+
## Copyright
3755

56+
Copyright (c) 2010 Chris Beer. See LICENSE.txt for further details.

Rakefile

+16-24
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,37 @@
1-
require 'rubygems'
2-
require 'bundler'
1+
require "rubygems"
2+
require "bundler"
33
begin
44
Bundler.setup(:default, :development)
55
rescue Bundler::BundlerError => e
6-
$stderr.puts e.message
7-
$stderr.puts "Run `bundle install` to install missing gems"
6+
warn e.message
7+
warn "Run `bundle install` to install missing gems"
88
exit e.status_code
99
end
1010

1111
Bundler::GemHelper.install_tasks
1212

13-
require 'rake'
14-
require 'rspec'
15-
require 'rspec/core/rake_task'
13+
require "rake"
14+
require "rspec"
15+
require "rspec/core/rake_task"
1616

17-
desc 'Default: run specs.'
18-
task :default => :spec
19-
20-
RSpec::Core::RakeTask.new do |t|
21-
if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.8/
22-
t.rcov = true
23-
t.rcov_opts = ['--exclude', 'spec', '--exclude', 'gems']
24-
end
25-
end
17+
desc "Default: run specs."
18+
task default: :spec
2619

2720
# Use yard to build docs
2821
begin
29-
require 'yard'
30-
require 'yard/rake/yardoc_task'
31-
project_root = File.expand_path(File.dirname(__FILE__))
32-
doc_destination = File.join(project_root, 'doc')
22+
require "yard"
23+
require "yard/rake/yardoc_task"
24+
project_root = __dir__
25+
doc_destination = File.join(project_root, "doc")
3326

3427
YARD::Rake::YardocTask.new(:doc) do |yt|
35-
yt.files = Dir.glob(File.join(project_root, 'lib', '**', '*.rb')) +
36-
[ File.join(project_root, 'README.md') ]
37-
yt.options = ['--output-dir', doc_destination, '--readme', 'README.md']
28+
yt.files = Dir.glob(File.join(project_root, "lib", "**", "*.rb")) +
29+
[File.join(project_root, "README.md")]
30+
yt.options = ["--output-dir", doc_destination, "--readme", "README.md"]
3831
end
3932
rescue LoadError
4033
desc "Generate YARD Documentation"
4134
task :doc do
4235
abort "Please install the YARD gem to generate rdoc."
4336
end
4437
end
45-

lib/pairtree.rb

+33-28
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
require 'pairtree/identifier'
2-
require 'pairtree/path'
3-
require 'pairtree/obj'
4-
require 'pairtree/root'
1+
require "pairtree/identifier"
2+
require "pairtree/path"
3+
require "pairtree/obj"
4+
require "pairtree/root"
55

6-
require 'fileutils'
6+
require "fileutils"
77

88
module Pairtree
9-
class IdentifierError < Exception; end
10-
class PathError < Exception; end
11-
class VersionMismatch < Exception; end
9+
class IdentifierError < RuntimeError; end
10+
11+
class PathError < RuntimeError; end
12+
13+
class VersionMismatch < RuntimeError; end
1214

1315
SPEC_VERSION = 0.1
14-
16+
1517
##
1618
# Instantiate a pairtree at a given path location
1719
# @param [String] path The path in which the pairtree resides
@@ -20,34 +22,34 @@ class VersionMismatch < Exception; end
2022
# @option args [String] :version (Pairtree::SPEC_VERSION) the version of the pairtree spec that this tree conforms to
2123
# @option args [Boolean] :create (false) if true, create the pairtree and its directory structure if it doesn't already exist
2224
def self.at path, args = {}
23-
args = { :prefix => nil, :version => nil, :create => false }.merge(args)
25+
args = {prefix: nil, version: nil, create: false}.merge(args)
2426
args[:version] ||= SPEC_VERSION
2527
args[:version] = args[:version].to_f
26-
27-
root_path = File.join(path, 'pairtree_root')
28-
prefix_file = File.join(path, 'pairtree_prefix')
28+
29+
root_path = File.join(path, "pairtree_root")
30+
prefix_file = File.join(path, "pairtree_prefix")
2931
version_file = File.join(path, pairtree_version_filename(args[:version]))
30-
existing_version_file = Dir[File.join(path, "pairtree_version*")].sort.last
31-
32+
existing_version_file = Dir[File.join(path, "pairtree_version*")].max
33+
3234
if args.delete(:create)
33-
if File.exists?(path) and not File.directory?(path)
35+
if File.exist?(path) && !File.directory?(path)
3436
raise PathError, "#{path} exists, but is not a valid pairtree root"
3537
end
3638
FileUtils.mkdir_p(root_path)
3739

38-
unless File.exists? prefix_file
39-
File.open(prefix_file, 'w') { |f| f.write(args[:prefix].to_s) }
40+
unless File.exist? prefix_file
41+
File.write(prefix_file, args[:prefix].to_s)
4042
end
41-
43+
4244
if existing_version_file
4345
if existing_version_file != version_file
44-
stored_version = existing_version_file.scan(/([0-9]+)_([0-9]+)/).flatten.join('.').to_f
46+
stored_version = existing_version_file.scan(/([0-9]+)_([0-9]+)/).flatten.join(".").to_f
4547
raise VersionMismatch, "Version #{args[:version]} specified, but #{stored_version} found."
4648
end
4749
else
4850
args[:version] ||= SPEC_VERSION
4951
version_file = File.join(path, pairtree_version_filename(args[:version]))
50-
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} }
52+
File.write(version_file, %(This directory conforms to Pairtree Version #{args[:version]}. Updated spec: http://www.cdlib.org/inside/diglib/pairtree/pairtreespec.html))
5153
existing_version_file = version_file
5254
end
5355
else
@@ -57,22 +59,25 @@ def self.at path, args = {}
5759
end
5860

5961
stored_prefix = File.read(prefix_file)
60-
unless args[:prefix].nil? or args[:prefix].to_s == stored_prefix
62+
unless args[:prefix].nil? || (args[:prefix].to_s == stored_prefix)
6163
raise IdentifierError, "Specified prefix #{args[:prefix].inspect} does not match stored prefix #{stored_prefix.inspect}"
6264
end
6365
args[:prefix] = stored_prefix
6466

65-
stored_version = existing_version_file.scan(/([0-9]+)_([0-9]+)/).flatten.join('.').to_f
67+
stored_version = existing_version_file.scan(/([0-9]+)_([0-9]+)/).flatten.join(".").to_f
6668
args[:version] ||= stored_version
6769
unless args[:version] == stored_version
6870
raise VersionMismatch, "Version #{args[:version]} specified, but #{stored_version} found."
6971
end
70-
71-
Pairtree::Root.new(File.join(path, 'pairtree_root'), args)
72+
73+
Pairtree::Root.new(File.join(path, "pairtree_root"), args)
7274
end
7375

74-
private
75-
def self.pairtree_version_filename(version)
76-
"pairtree_version#{version.to_s.gsub(/\./,'_')}"
76+
class << self
77+
private
78+
79+
def pairtree_version_filename(version)
80+
"pairtree_version#{version.to_s.tr(".", "_")}"
81+
end
7782
end
7883
end

lib/pairtree/identifier.rb

+21-4
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,45 @@ class Identifier
77
# Encode special characters within an identifier
88
# @param [String] id The identifier
99
def self.encode id
10-
id.gsub(ENCODE_REGEX) { |c| char2hex(c) }.tr('/:.', '=+,')
10+
id.gsub(ENCODE_REGEX) { |c| char2hex(c) }.tr("/:.", "=+,")
1111
end
1212

1313
##
1414
# Decode special characters within an identifier
1515
# @param [String] id The identifier
1616
def self.decode id
17-
id.tr('=+,', '/:.').gsub(DECODE_REGEX) { |h| hex2char(h) }
17+
input = id.tr("=+,", "/:.").bytes.to_a
18+
intermediate = []
19+
while input.first
20+
if input.first == 94
21+
h = []
22+
input.shift
23+
h << input.shift
24+
h << input.shift
25+
intermediate << h.pack("c*").hex
26+
else
27+
intermediate << input.shift
28+
end
29+
end
30+
result = intermediate.pack("c*")
31+
if result.respond_to? :force_encoding
32+
result.force_encoding("UTF-8")
33+
end
34+
result
1835
end
1936

2037
##
2138
# Convert a character to its pairtree hexidecimal representation
2239
# @param [Char] c The character to convert
2340
def self.char2hex c
24-
c.unpack('H*')[0].scan(/../).map { |x| "^#{x}"}.join('')
41+
c.unpack1("H*").scan(/../).map { |x| "^#{x}" }.join("")
2542
end
2643

2744
##
2845
# Convert a pairtree hexidecimal string to its character representation
2946
# @param [String] h The hexidecimal string to convert
3047
def self.hex2char h
31-
'' << h.delete('^').hex
48+
"" << h.delete("^").hex
3249
end
3350
end
3451
end

0 commit comments

Comments
 (0)