rom-files 0.2.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 (122) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +9 -0
  3. data/.gitignore +11 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +112 -0
  6. data/.rubocop_todo.yml +7 -0
  7. data/.ruby-version +1 -0
  8. data/.simplecov +6 -0
  9. data/.travis.yml +24 -0
  10. data/.yardopts +6 -0
  11. data/CHANGELOG.md +10 -0
  12. data/Gemfile +25 -0
  13. data/Guardfile +48 -0
  14. data/LICENSE.md +21 -0
  15. data/README.md +44 -0
  16. data/Rakefile +37 -0
  17. data/Roadmap.taskpaper +44 -0
  18. data/bin/_guard-core +21 -0
  19. data/bin/console +7 -0
  20. data/bin/guard +21 -0
  21. data/bin/rake +21 -0
  22. data/bin/rspec +21 -0
  23. data/bin/yard +21 -0
  24. data/bin/yardoc +21 -0
  25. data/bin/yri +21 -0
  26. data/lib/dry/types/pathname.rb +25 -0
  27. data/lib/pathname/extensions.rb +32 -0
  28. data/lib/pathname/extensions/constants.rb +12 -0
  29. data/lib/pathname/extensions/explode.rb +27 -0
  30. data/lib/pathname/extensions/ext.rb +28 -0
  31. data/lib/pathname/extensions/partial.rb +30 -0
  32. data/lib/pathname/extensions/pathmap.rb +128 -0
  33. data/lib/rom-files.rb +3 -0
  34. data/lib/rom/files.rb +28 -0
  35. data/lib/rom/files/associations.rb +6 -0
  36. data/lib/rom/files/associations/many_to_many.rb +12 -0
  37. data/lib/rom/files/associations/many_to_one.rb +12 -0
  38. data/lib/rom/files/associations/one_to_many.rb +12 -0
  39. data/lib/rom/files/associations/one_to_one.rb +12 -0
  40. data/lib/rom/files/attribute.rb +21 -0
  41. data/lib/rom/files/commands/create.rb +18 -0
  42. data/lib/rom/files/commands/delete.rb +17 -0
  43. data/lib/rom/files/commands/update.rb +17 -0
  44. data/lib/rom/files/connection.rb +120 -0
  45. data/lib/rom/files/constants.rb +16 -0
  46. data/lib/rom/files/dataset.rb +89 -0
  47. data/lib/rom/files/dataset/filtering.rb +96 -0
  48. data/lib/rom/files/dataset/mime_type.rb +44 -0
  49. data/lib/rom/files/dataset/paths.rb +79 -0
  50. data/lib/rom/files/dataset/sorting.rb +27 -0
  51. data/lib/rom/files/extensions.rb +30 -0
  52. data/lib/rom/files/extensions/gem.rb +29 -0
  53. data/lib/rom/files/extensions/gem/relations/documentations.rb +18 -0
  54. data/lib/rom/files/extensions/gem/relations/executables.rb +20 -0
  55. data/lib/rom/files/extensions/gem/relations/implementations.rb +29 -0
  56. data/lib/rom/files/extensions/gem/relations/specifications.rb +29 -0
  57. data/lib/rom/files/extensions/markdown/attributes_inferrer.rb +20 -0
  58. data/lib/rom/files/extensions/markdown/types.rb +18 -0
  59. data/lib/rom/files/extensions/markup/attributes_inferrer.rb +32 -0
  60. data/lib/rom/files/extensions/ruby/attributes_inferrer.rb +21 -0
  61. data/lib/rom/files/extensions/ruby/types.rb +45 -0
  62. data/lib/rom/files/extensions/text/attributes_inferrer.rb +20 -0
  63. data/lib/rom/files/gateway.rb +63 -0
  64. data/lib/rom/files/plugins/configuration/gem.rb +30 -0
  65. data/lib/rom/files/plugins/relation/instrumentation.rb +28 -0
  66. data/lib/rom/files/plugins/schema/contents.rb +72 -0
  67. data/lib/rom/files/plugins/schema/mime.rb +59 -0
  68. data/lib/rom/files/plugins/schema/shebang.rb +79 -0
  69. data/lib/rom/files/plugins/schema/stat.rb +108 -0
  70. data/lib/rom/files/relation.rb +143 -0
  71. data/lib/rom/files/schema.rb +77 -0
  72. data/lib/rom/files/schema/attributes_inferrer.rb +79 -0
  73. data/lib/rom/files/schema/inferrer.rb +36 -0
  74. data/lib/rom/files/types.rb +37 -0
  75. data/lib/rom/files/version.rb +7 -0
  76. data/rom-files.gemspec +48 -0
  77. data/spec/integration/rom/files/gateway_spec.rb +28 -0
  78. data/spec/integration/rom/files/gem_spec.rb +98 -0
  79. data/spec/integration/rom/files/relations_spec.rb +63 -0
  80. data/spec/integration/rom/files/schema/inferrer_spec.rb +77 -0
  81. data/spec/lib/dry/types/pathname_spec.rb +50 -0
  82. data/spec/lib/pathname/extensions/explode_spec.rb +25 -0
  83. data/spec/lib/pathname/extensions/ext_spec.rb +33 -0
  84. data/spec/lib/pathname/extensions/partial_spec.rb +17 -0
  85. data/spec/lib/pathname/extensions/pathmap_spec.rb +147 -0
  86. data/spec/lib/rom/files/attribute_spec.rb +43 -0
  87. data/spec/lib/rom/files/connection_spec.rb +76 -0
  88. data/spec/lib/rom/files/dataset/inside_spec.rb +22 -0
  89. data/spec/lib/rom/files/dataset/mime_type_spec.rb +23 -0
  90. data/spec/lib/rom/files/dataset/recursive_question_mark_spec.rb +42 -0
  91. data/spec/lib/rom/files/dataset/recursive_spec.rb +29 -0
  92. data/spec/lib/rom/files/dataset/reject_append_spec.rb +68 -0
  93. data/spec/lib/rom/files/dataset/reject_spec.rb +26 -0
  94. data/spec/lib/rom/files/dataset/select_append_spec.rb +69 -0
  95. data/spec/lib/rom/files/dataset/select_spec.rb +38 -0
  96. data/spec/lib/rom/files/dataset/sort_spec.rb +22 -0
  97. data/spec/lib/rom/files/dataset_spec.rb +52 -0
  98. data/spec/lib/rom/files/extensions/text/attributes_inferrer_spec.rb +54 -0
  99. data/spec/lib/rom/files/gateway_spec.rb +39 -0
  100. data/spec/lib/rom/files/plugins/schema/contents_spec.rb +66 -0
  101. data/spec/lib/rom/files/plugins/schema/mime_spec.rb +66 -0
  102. data/spec/lib/rom/files/plugins/schema/stat_spec.rb +109 -0
  103. data/spec/lib/rom/files/relation/pluck_spec.rb +20 -0
  104. data/spec/lib/rom/files/relation/reject_spec.rb +22 -0
  105. data/spec/lib/rom/files/relation/select_spec.rb +35 -0
  106. data/spec/lib/rom/files/relation/sort_spec.rb +21 -0
  107. data/spec/lib/rom/files/relation/to_a_spec.rb +39 -0
  108. data/spec/lib/rom/files/relation_spec.rb +10 -0
  109. data/spec/lib/rom/files/schema/attributes_inferrer_spec.rb +45 -0
  110. data/spec/lib/rom/files/schema/inferrer_spec.rb +29 -0
  111. data/spec/lib/rom/files/schema_spec.rb +109 -0
  112. data/spec/lib/rom/files/types/mime_type_spec.rb +9 -0
  113. data/spec/lib/rom/files/types/path_spec.rb +10 -0
  114. data/spec/lib/rom/files/types_spec.rb +6 -0
  115. data/spec/shared/rom/files/files_setup.rb +19 -0
  116. data/spec/shared/rom/files/filesystem_setup.rb +10 -0
  117. data/spec/shared/rom/files/gateway_setup.rb +17 -0
  118. data/spec/shared/rom/files/media_dataset.rb +10 -0
  119. data/spec/shared/rom/files/media_files.rb +17 -0
  120. data/spec/shared/rom/files/media_relation.rb +30 -0
  121. data/spec/spec_helper.rb +10 -0
  122. metadata +421 -0
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'rom-files'
5
+ require 'rspec'
6
+
7
+ RSpec.example_group ROM::Files, 'usage with gem' do
8
+ # @param [ROM::ConfigurationDSL] config
9
+ def def_tools(config)
10
+ config.relation :tools do
11
+ dataset do
12
+ select('*') # .stat(executable: true)
13
+ end
14
+
15
+ schema 'bin' do
16
+ # use :shebang
17
+ end
18
+ end
19
+ end
20
+
21
+ # @param [ROM::ConfigurationDSL] config
22
+ def def_examples(config)
23
+ config.relation :examples do
24
+ dataset { select '**/*.rb' }
25
+
26
+ schema 'examples' do
27
+ # use :ruby
28
+ end
29
+ end
30
+ end
31
+
32
+ def def_docs(config)
33
+ config.relation :docs do
34
+ dataset { select '**/*.md' }
35
+
36
+ schema 'text/markdown' do
37
+ # use :contents, type: Types::Markdown
38
+ end
39
+ end
40
+ end
41
+
42
+ def def_library(config)
43
+ config.relation :implementations do
44
+ dataset { inside('lib').recursive }
45
+
46
+ schema 'lib' do
47
+ # associations do
48
+ # has_one :specification
49
+ # end
50
+ end
51
+ end
52
+ end
53
+
54
+ def def_specification(config)
55
+ config.relation :specifications do
56
+ dataset { select '**/*_spec.rb' }
57
+
58
+ schema 'spec' do
59
+ # associations do
60
+ # belongs_to :implementation
61
+ # end
62
+ end
63
+ end
64
+ end
65
+
66
+ # @return [ROM::Container]
67
+ subject(:container) do
68
+ ROM.container(:files, uri) do |config|
69
+ def_docs(config)
70
+ def_tools(config)
71
+ def_examples(config)
72
+ def_library(config)
73
+ def_specification(config)
74
+ config.relation :gem do
75
+ schema :gem do
76
+ # associations do
77
+ # has_many :implementations
78
+ # has_many :specifications
79
+ # has_many :rake_files
80
+ # end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ let(:uri) { SPEC_ROOT.dirname }
86
+ let(:library_files) { container.relations[:implementations] }
87
+
88
+ xexample 'Container usage' do
89
+ require 'pry'
90
+ binding.pry # rubocop:disable Lint/Debugger
91
+ end
92
+
93
+ example 'List library files' do
94
+ expect(library_files.to_a).to be_a Array
95
+ end
96
+ end
97
+
98
+ require 'rspec/autorun' if $PROGRAM_NAME == __FILE__
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'rom-files'
5
+ require 'rspec'
6
+
7
+ RSpec.example_group ROM::Files::Relation do
8
+ Files = ROM::Files
9
+ Types = Files::Types
10
+
11
+ class Implementations < ROM::Files::Relation
12
+ dataset { select('*.rb').recursive }
13
+ schema :lib, as: :implementations do
14
+ attribute Files::ID, Types::Coercible::Pathname
15
+
16
+ primary_key Files::ID
17
+ end
18
+ end
19
+
20
+ class Specifications < ROM::Files::Relation
21
+ dataset { select('*_spec.rb').recursive }
22
+ schema :spec, as: :specifications do
23
+ attribute Files::ID, Types::Path
24
+ end
25
+ end
26
+
27
+ class TempFiles < ROM::Files::Relation
28
+ dataset { recursive }
29
+ schema :tmp, as: :temporary_files do
30
+ attribute Files::ID, Types::Pathname.meta(primary_key: true)
31
+ end
32
+ end
33
+
34
+ let(:configuration) do
35
+ ROM::Configuration.new(:files, Pathname(__dir__).dirname) do |config|
36
+ config.register_relation(Implementations)
37
+ config.register_relation(Specifications)
38
+ config.register_relation(TempFiles)
39
+ end
40
+ end
41
+ let(:container) { ROM.container(configuration) }
42
+
43
+ example 'Retrieving relations' do
44
+ p container
45
+
46
+ lib = container.relations[:implementations]
47
+ spec = container.relations[:specifications]
48
+ tmp = container.relations[:temporary_files]
49
+
50
+ expect(lib).to be_a Implementations
51
+ expect(spec).to be_a Specifications
52
+ expect(tmp).to be_a TempFiles
53
+
54
+ puts "lib #=> #{lib.inspect}"
55
+ puts 'pluck(:to_s) #=>', lib.pluck(:to_s)
56
+ # p :to_a, lib.to_a
57
+ puts 'spec #=>', spec.pluck(:basename)
58
+
59
+ puts "tmp #=> #{tmp.to_a}"
60
+ end
61
+ end
62
+
63
+ require 'rspec/autorun' if $PROGRAM_NAME == __FILE__
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rom/files/schema/inferrer'
4
+ require 'shared/rom/files/media_files'
5
+
6
+ RSpec.describe 'Schema inference for common file types' do
7
+ include_context 'media files'
8
+
9
+ let(:relation) { container.relations[relation_name] }
10
+ let(:schema) { relation.schema }
11
+ let(:source) { schema.name }
12
+ let(:relation_name) { dataset }
13
+
14
+ describe 'inferring attributes' do
15
+ before do
16
+ name = dataset
17
+ configuration.relation(relation_name) { schema(name, infer: true) }
18
+ end
19
+
20
+ context 'for any file set' do
21
+ let(:dataset) { :media }
22
+
23
+ describe '__FILE__' do
24
+ subject(:attribute) { schema[:__FILE__] }
25
+
26
+ its(:source) { is_expected.to eql source }
27
+ its('type.primitive') { is_expected.to be Pathname }
28
+ end
29
+ end
30
+
31
+ context 'for `text/plain` file set' do
32
+ let(:relation_name) { :texts }
33
+ let(:dataset) { 'text/plain' }
34
+
35
+ describe '__FILE__' do
36
+ subject(:attribute) { schema[:__FILE__] }
37
+
38
+ its(:source) { is_expected.to eql source }
39
+ its('type.primitive') { is_expected.to be Pathname }
40
+ end
41
+
42
+ describe 'DATA' do
43
+ subject(:attribute) { schema[:DATA] }
44
+
45
+ its(:source) { is_expected.to eql source }
46
+ its('type.primitive') { is_expected.to be String }
47
+
48
+ it 'autoloads contents' do
49
+ expect(attribute.meta[:DATA]).to be(true)
50
+ end
51
+ end
52
+ end
53
+
54
+ context 'for `text/markdown` file set' do
55
+ let(:relation_name) { :texts }
56
+ let(:dataset) { 'text/markdown' }
57
+
58
+ describe '__FILE__' do
59
+ subject(:attribute) { schema[:__FILE__] }
60
+
61
+ its(:source) { is_expected.to eql source }
62
+ its('type.primitive') { is_expected.to be Pathname }
63
+ end
64
+
65
+ describe 'DATA' do
66
+ subject(:attribute) { schema[:DATA] }
67
+
68
+ its(:source) { is_expected.to eql source }
69
+ its('type.primitive') { is_expected.to be Kramdown::Document }
70
+
71
+ it 'autoloads contents' do
72
+ expect(attribute.meta[:DATA]).to be(true)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'dry/types/pathname'
4
+
5
+ RSpec.describe Dry::Types do
6
+ subject(:types) { described_class }
7
+ specify { expect(types['optional.pathname']).to be_a Dry::Types::Sum }
8
+
9
+ describe 'pathname' do
10
+ subject(:type) { types['pathname'] }
11
+
12
+ it { is_expected.to be_a Dry::Types::Definition }
13
+
14
+ specify { expect(type[nil]).to eq nil }
15
+ specify { expect(type['sample.rb']).to eq 'sample.rb' }
16
+ specify { expect(type[Pathname('sample.rb')]).to eq Pathname('sample.rb') }
17
+ end
18
+
19
+ describe 'optional.pathname' do
20
+ subject(:type) { types['optional.pathname'] }
21
+
22
+ it { is_expected.to be_a Dry::Types::Sum }
23
+
24
+ specify { expect(type[nil]).to eq nil }
25
+ specify { expect(type['sample.rb']).to eq 'sample.rb' }
26
+ specify { expect(type[Pathname('sample.rb')]).to eq Pathname('sample.rb') }
27
+ end
28
+
29
+ describe 'coercible.pathname' do
30
+ subject(:type) { types['coercible.pathname'] }
31
+
32
+ it { is_expected.to be_a Dry::Types::Definition }
33
+
34
+ specify { expect(type[nil]).to eq Pathname('') }
35
+ specify { expect(type[:media]).to eq Pathname('media') }
36
+ specify { expect(type['sample.rb']).to eq Pathname('sample.rb') }
37
+ specify { expect(type[Pathname('sample.rb')]).to eq Pathname('sample.rb') }
38
+ end
39
+
40
+ describe 'strict.pathname' do
41
+ subject(:type) { types['strict.pathname'] }
42
+
43
+ it { is_expected.to be_a Dry::Types::Constrained }
44
+
45
+ specify { expect { type[nil] }.to raise_error Dry::Types::ConstraintError }
46
+ specify { expect { type['sample.rb'] }.to raise_error Dry::Types::ConstraintError }
47
+ specify { expect { type[Pathname('sample.rb')] }.not_to raise_error }
48
+ specify { expect(type[Pathname('sample.rb')]).to eq Pathname('sample.rb') }
49
+ end
50
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname/extensions'
4
+
5
+ RSpec.describe Pathname do
6
+ before { described_class.load_extensions :explode }
7
+
8
+ describe '#explode' do
9
+ specify { expect(Pathname('a').explode).to eq [Pathname('a')] }
10
+ specify { expect(Pathname('a/b').explode).to eq [Pathname('a'), Pathname('b')] }
11
+ specify { expect(Pathname('a/b/c').explode).to eq [Pathname('a'), Pathname('b'), Pathname('c')] }
12
+ specify { expect(Pathname('/a').explode).to eq [Pathname('/'), Pathname('a')] }
13
+ specify { expect(Pathname('/a/b').explode).to eq [Pathname('/'), Pathname('a'), Pathname('b')] }
14
+ specify { expect(Pathname('/a/b/c').explode).to eq [Pathname('/'), Pathname('a'), Pathname('b'), Pathname('c')] }
15
+
16
+ if File::ALT_SEPARATOR
17
+ specify { expect(Pathname('c:a').explode).to eq [Pathname('c:.'), Pathname('a')] }
18
+ specify { expect(Pathname('c:a/b').explode).to eq [Pathname('c:.'), Pathname('a'), Pathname('b')] }
19
+ specify { expect(Pathname('c:a/b/c').explode).to eq [Pathname('c:.'), Pathname('a'), Pathname('b'), Pathname('c')] }
20
+ specify { expect(Pathname('c:/a').explode).to eq [Pathname('c:/'), Pathname('a')] }
21
+ specify { expect(Pathname('c:/a/b').explode).to eq [Pathname('c:/'), Pathname('a'), Pathname('b')] }
22
+ specify { expect(Pathname('c:/a/b/c').explode).to eq [Pathname('c:/'), Pathname('a'), Pathname('b'), Pathname('c')] }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname/extensions'
4
+
5
+ RSpec.describe Pathname do
6
+ before { described_class.load_extensions :ext }
7
+
8
+ describe '#ext' do
9
+ specify { expect(Pathname('one.two').ext('net')).to eq Pathname('one.net') }
10
+ specify { expect(Pathname('one.two').ext('.net')).to eq Pathname('one.net') }
11
+ specify { expect(Pathname('one').ext('net')).to eq Pathname('one.net') }
12
+ specify { expect(Pathname('one').ext('.net')).to eq Pathname('one.net') }
13
+ specify { expect(Pathname('one.two.c').ext('.net')).to eq Pathname('one.two.net') }
14
+ specify { expect(Pathname('one/two.c').ext('.net')).to eq Pathname('one/two.net') }
15
+ specify { expect(Pathname('one.x/two.c').ext('.net')).to eq Pathname('one.x/two.net') }
16
+ specify { expect(Pathname('one.x/two').ext('.net')).to eq Pathname('one.x/two.net') }
17
+ specify { expect(Pathname('.onerc.dot').ext('net')).to eq Pathname('.onerc.net') }
18
+ specify { expect(Pathname('.onerc').ext('net')).to eq Pathname('.onerc.net') }
19
+ specify { expect(Pathname('.a/.onerc').ext('net')).to eq Pathname('.a/.onerc.net') }
20
+ specify { expect(Pathname('one.two').ext('')).to eq Pathname('one') }
21
+ specify { expect(Pathname('one.two').ext).to eq Pathname('one') }
22
+ specify { expect(Pathname('.one.two').ext).to eq Pathname('.one') }
23
+ specify { expect(Pathname('.one').ext).to eq Pathname('.one') }
24
+ specify { expect(Pathname('.').ext('c')).to eq Pathname('.') }
25
+ specify { expect(Pathname('..').ext('c')).to eq Pathname('..') }
26
+
27
+ # These only need to work in windows
28
+ if RbConfig::CONFIG['host_os'].match?(/(msdos|mswin|djgpp|mingw|[Ww]indows)/)
29
+ specify { expect(Pathname('one.x\\two.c').ext('.net')).to eq Pathname('one.x\\two.net') }
30
+ specify { expect(Pathname('one.x\\two').ext('.net')).to eq Pathname('one.x\\two.net') }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname/extensions'
4
+
5
+ RSpec.describe Pathname do
6
+ before { described_class.load_extensions :partial }
7
+
8
+ describe '#partial' do
9
+ specify { expect(Pathname('1/2/file').partial(1)).to eq Pathname('1') }
10
+ specify { expect(Pathname('1/2/file').partial(2)).to eq Pathname('1/2') }
11
+ specify { expect(Pathname('1/2/file').partial(3)).to eq Pathname('1/2') }
12
+ specify { expect(Pathname('1/2/file').partial(0)).to eq Pathname('.') }
13
+ specify { expect(Pathname('1/2/file').partial(-1)).to eq Pathname('2') }
14
+ specify { expect(Pathname('1/2/file').partial(-2)).to eq Pathname('1/2') }
15
+ specify { expect(Pathname('1/2/file').partial(-3)).to eq Pathname('1/2') }
16
+ end
17
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname/extensions'
4
+
5
+ RSpec.describe Pathname do
6
+ before { described_class.load_extensions :pathmap }
7
+
8
+ it 'returns_self_with_no_args', :aggregate_failures do
9
+ expect(Pathname('abc.rb').pathmap).to eq Pathname('abc.rb')
10
+ end
11
+
12
+ it 's_returns_file_separator', :aggregate_failures do
13
+ sep = File::ALT_SEPARATOR || File::SEPARATOR
14
+ expect(Pathname('abc.rb').pathmap('%s')).to eq Pathname(sep)
15
+ expect(Pathname('').pathmap('%s')).to eq Pathname(sep)
16
+ expect(Pathname('a/b').pathmap('%d%s%f')).to eq Pathname("a#{sep}b")
17
+ end
18
+
19
+ it 'f_returns_basename', :aggregate_failures do
20
+ expect(Pathname('abc.rb').pathmap('%f')).to eq Pathname('abc.rb')
21
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%f')).to eq Pathname('abc.rb')
22
+ expect(Pathname('/this/is/a/dir/abc.rb').pathmap('%f')).to eq Pathname('abc.rb')
23
+ end
24
+
25
+ it 'n_returns_basename_without_extension', :aggregate_failures do
26
+ expect(Pathname('abc.rb').pathmap('%n')).to eq Pathname('abc')
27
+ expect(Pathname('abc').pathmap('%n')).to eq Pathname('abc')
28
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%n')).to eq Pathname('abc')
29
+ expect(Pathname('/this/is/a/dir/abc.rb').pathmap('%n')).to eq Pathname('abc')
30
+ expect(Pathname('/this/is/a/dir/abc').pathmap('%n')).to eq Pathname('abc')
31
+ end
32
+
33
+ it 'd_returns_dirname', :aggregate_failures do
34
+ expect(Pathname('abc.rb').pathmap('%d')).to eq Pathname('.')
35
+ expect(Pathname('/abc').pathmap('%d')).to eq Pathname('/')
36
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%d')).to eq Pathname('this/is/a/dir')
37
+ expect(Pathname('/this/is/a/dir/abc.rb').pathmap('%d')).to eq Pathname('/this/is/a/dir')
38
+ end
39
+
40
+ it '9d_returns_partial_dirname', :aggregate_failures do
41
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%2d')).to eq Pathname('this/is')
42
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%1d')).to eq Pathname('this')
43
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%0d')).to eq Pathname('.')
44
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%-1d')).to eq Pathname('dir')
45
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%-2d')).to eq Pathname('a/dir')
46
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%100d')).to eq Pathname('this/is/a/dir')
47
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%-100d')).to eq Pathname('this/is/a/dir')
48
+ end
49
+
50
+ it 'x_returns_extension', :aggregate_failures do
51
+ expect(Pathname('abc').pathmap('%x')).to eq Pathname('')
52
+ expect(Pathname('abc.rb').pathmap('%x')).to eq Pathname('.rb')
53
+ expect(Pathname('abc.xyz.rb').pathmap('%x')).to eq Pathname('.rb')
54
+ expect(Pathname('.depends').pathmap('%x')).to eq Pathname('')
55
+ expect(Pathname('dir/.depends').pathmap('%x')).to eq Pathname('')
56
+ end
57
+
58
+ it 'x_returns_everything_but_extension', :aggregate_failures do
59
+ expect(Pathname('abc').pathmap('%X')).to eq Pathname('abc')
60
+ expect(Pathname('abc.rb').pathmap('%X')).to eq Pathname('abc')
61
+ expect(Pathname('abc.xyz.rb').pathmap('%X')).to eq Pathname('abc.xyz')
62
+ expect(Pathname('ab.xyz.rb').pathmap('%X')).to eq Pathname('ab.xyz')
63
+ expect(Pathname('a.xyz.rb').pathmap('%X')).to eq Pathname('a.xyz')
64
+ expect(Pathname('abc.rb').pathmap('%X')).to eq Pathname('abc')
65
+ expect(Pathname('ab.rb').pathmap('%X')).to eq Pathname('ab')
66
+ expect(Pathname('a.rb').pathmap('%X')).to eq Pathname('a')
67
+ expect(Pathname('.depends').pathmap('%X')).to eq Pathname('.depends')
68
+ expect(Pathname('a/dir/.depends').pathmap('%X')).to eq Pathname('a/dir/.depends')
69
+ expect(Pathname('/.depends').pathmap('%X')).to eq Pathname('/.depends')
70
+ end
71
+
72
+ it 'p_returns_entire_pathname', :aggregate_failures do
73
+ expect(Pathname('abc.rb').pathmap('%p')).to eq Pathname('abc.rb')
74
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%p')).to eq Pathname('this/is/a/dir/abc.rb')
75
+ expect(Pathname('/this/is/a/dir/abc.rb').pathmap('%p')).to eq Pathname('/this/is/a/dir/abc.rb')
76
+ end
77
+
78
+ it 'dash_returns_empty_string', :aggregate_failures do
79
+ expect(Pathname('abc.rb').pathmap('%-')).to eq Pathname('')
80
+ expect(Pathname('abc.rb').pathmap('%X%-%x')).to eq Pathname('abc.rb')
81
+ end
82
+
83
+ it 'percent_percent_returns_percent', :aggregate_failures do
84
+ expect(Pathname('').pathmap('a%%b')).to eq Pathname('a%b')
85
+ end
86
+
87
+ it 'undefined_percent_causes_error', :aggregate_failures do
88
+ expect { Pathname('dir/abc.rb').pathmap('%z') }.to raise_error ArgumentError
89
+ end
90
+
91
+ it 'pattern_returns_substitutions', :aggregate_failures do
92
+ expect(Pathname('src/org/osb/Xyz.java').pathmap('%{src,bin}d')).to eq Pathname('bin/org/osb')
93
+ end
94
+
95
+ it 'pattern_can_use_backreferences', :aggregate_failures do
96
+ expect(Pathname('dir/this/is').pathmap('%{t(hi)s,\\1}p')).to eq Pathname('dir/hi/is')
97
+ end
98
+
99
+ it 'pattern_with_star_replacement_string_uses_block', :aggregate_failures do
100
+ expect(Pathname('src/org/osb/Xyz.java').pathmap('%{/org,*}d', &:upcase)).to eq Pathname('src/ORG/osb')
101
+ expect(Pathname('src/org/osb/Xyz.java').pathmap('%{.*,*}f', &:capitalize)).to eq Pathname('Xyz.java')
102
+ end
103
+
104
+ it 'pattern_with_no_replacement_nor_block_substitutes_empty_string', :aggregate_failures do
105
+ expect(Pathname('abc.rb').pathmap('%{a}f')).to eq Pathname('bc.rb')
106
+ end
107
+
108
+ it 'pattern_works_with_certain_valid_operators', :aggregate_failures do
109
+ expect(Pathname('dir/abc.rb').pathmap('%{a,x}p')).to eq Pathname('dir/xbc.rb')
110
+ expect(Pathname('dir/abc.rb').pathmap('%{i,1}d')).to eq Pathname('d1r')
111
+ expect(Pathname('dir/abc.rb').pathmap('%{a,x}f')).to eq Pathname('xbc.rb')
112
+ expect(Pathname('dir/abc.rb').pathmap('%{r,R}x')).to eq Pathname('.Rb')
113
+ expect(Pathname('dir/abc.rb').pathmap('%{a,x}n')).to eq Pathname('xbc')
114
+ end
115
+
116
+ it 'multiple_patterns', :aggregate_failures do
117
+ expect(Pathname('this/is/a/dir/abc.rb').pathmap('%{a,b;dir,\\0ectory}p')).to eq Pathname('this/is/b/directory/abc.rb')
118
+ end
119
+
120
+ it 'partial_directory_selection_works_with_patterns', :aggregate_failures do
121
+ expect(Pathname('this/is/a/really/long/path/ok.rb').pathmap('%{/really/,/}5d')).to eq Pathname('this/is/a/long')
122
+ end
123
+
124
+ it 'pattern_with_invalid_operator', :aggregate_failures do
125
+ expect do
126
+ Pathname('abc.xyz').pathmap('%{src,bin}z')
127
+ end.to raise_error ArgumentError, /unknown.*pathmap.*spec.*z/i
128
+ end
129
+
130
+ it 'works_with_windows_separators', :aggregate_failures do
131
+ if File::ALT_SEPARATOR
132
+ expect(Pathname('dir\abc.rb').pathmap('%n')).to eq Pathname('abc')
133
+ expect(Pathname('this\is\a\dir\abc.rb').pathmap('%d')).to eq Pathname('this\is\a\dir')
134
+ end
135
+ end
136
+
137
+ it 'complex_patterns', :aggregate_failures do
138
+ sep = Pathname('').pathmap('%s')
139
+ expect(Pathname('dir/abc.rb').pathmap('%d/%n%x')).to eq Pathname('dir/abc.rb')
140
+ expect(Pathname('abc.rb').pathmap('%d/%n%x')).to eq Pathname('./abc.rb')
141
+ expect(Pathname('dir/abc.rb').pathmap("Your file extension is '%x'")).to eq Pathname("Your file extension is '.rb'")
142
+ expect(Pathname('src/org/onestepback/proj/A.java').pathmap('%{src,bin}d/%n.class')).to eq Pathname('bin/org/onestepback/proj/A.class')
143
+ expect(Pathname('src_work/src/org/onestepback/proj/A.java').pathmap('%{\bsrc\b,bin}X.class')).to eq Pathname('src_work/bin/org/onestepback/proj/A.class')
144
+ expect(Pathname('.depends').pathmap('%X.bak')).to eq Pathname('.depends.bak')
145
+ expect(Pathname('a/b/c/d/file.txt').pathmap('%-1d%s%3d%s%f')).to eq Pathname("d#{sep}a/b/c#{sep}file.txt")
146
+ end
147
+ end