From 0670128ffe3174fb1fa9c7c5389a753d16b52305 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 15:16:35 -0800 Subject: [PATCH 01/70] Update Gem Versions, Initial Rubocop Migration --- .rubocop_todo.yml | 4 ++-- pathspec.gemspec | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 86655e2..6c8109c 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -16,7 +16,7 @@ Layout/BlockEndNewline: # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. # SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent -Layout/IndentHeredoc: +Layout/HeredocIndentation: Exclude: - 'spec/unit/pathspec_spec.rb' @@ -127,5 +127,5 @@ Style/SymbolProc: # Offense count: 7 # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https -Metrics/LineLength: +Layout/LineLength: Max: 108 diff --git a/pathspec.gemspec b/pathspec.gemspec index dfb857e..657c267 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -8,7 +8,7 @@ Gem::Specification.new do |s| s.summary = 'PathSpec: for matching path patterns' s.description = 'Use to match path patterns such as gitignore' s.authors = ['Brandon High'] - s.email = 'bh@brandon-high.com' + s.email = 'highb@users.noreply.github.com' s.files = Dir.glob('{lib,spec,docs}/**/*') + %w[LICENSE README.md CHANGELOG.md] s.bindir = 'bin' s.executables << 'pathspec-rb' @@ -16,10 +16,10 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.homepage = 'https://github.com/highb/pathspec-ruby' s.license = 'Apache-2.0' - s.add_development_dependency 'bundler', '~> 1.0' - s.add_development_dependency 'fakefs', '~> 0.13' - s.add_development_dependency 'rake', '~> 12.3' - s.add_development_dependency 'rspec', '~> 3.0' - s.add_development_dependency 'rubocop', '~> 0.52' - s.add_development_dependency 'simplecov', '~> 0.15' + s.add_development_dependency 'bundler', '~> 2.2' + s.add_development_dependency 'fakefs', '~> 1.3' + s.add_development_dependency 'rake', '~> 13.0' + s.add_development_dependency 'rspec', '~> 3.10' + s.add_development_dependency 'rubocop', '~> 1.7' + s.add_development_dependency 'simplecov', '~> 0.21' end From 6e0d7a38dd1bcbfbf910e5752ebebf7e3bd36db9 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 15:17:21 -0800 Subject: [PATCH 02/70] Rubocop autocorrections --- Rakefile | 10 ++++------ lib/pathspec.rb | 7 ++++--- lib/pathspec/gitignorespec.rb | 17 +++++++---------- lib/pathspec/spec.rb | 3 +-- 4 files changed, 16 insertions(+), 21 deletions(-) diff --git a/Rakefile b/Rakefile index a9f557c..b372b7a 100644 --- a/Rakefile +++ b/Rakefile @@ -13,12 +13,10 @@ end task default: %i[rubocop spec man_pages] -desc "Generate man page for executable script" +desc 'Generate man page for executable script' task :man_pages do - rst2man = %x{which rst2man}.chomp - unless File.executable?(rst2man) - abort("rst2man could not be found and is needed to build man pages") - end + rst2man = `which rst2man`.chomp + abort('rst2man could not be found and is needed to build man pages') unless File.executable?(rst2man) - %x{rst2man docs/man/pathspec-rb.man.1.rst > docs/man/pathspec-rb.man.1} + `rst2man docs/man/pathspec-rb.man.1.rst > docs/man/pathspec-rb.man.1` end diff --git a/lib/pathspec.rb b/lib/pathspec.rb index b317df2..9cd4b14 100644 --- a/lib/pathspec.rb +++ b/lib/pathspec.rb @@ -63,7 +63,7 @@ def match_paths(paths, root = '/') end def drive_letter_to_path(path) - path.gsub(%r{^([a-zA-Z]):\/}, '/\1/') + path.gsub(%r{^([a-zA-Z]):/}, '/\1/') end # Generate specs from a filename, such as a .gitignore @@ -101,9 +101,10 @@ def empty? end def spec_type(type) - if type == :git + case type + when :git GitIgnoreSpec - elsif type == :regex + when :regex RegexSpec else raise "Unknown spec type #{type}" diff --git a/lib/pathspec/gitignorespec.rb b/lib/pathspec/gitignorespec.rb index 09392be..43d853e 100644 --- a/lib/pathspec/gitignorespec.rb +++ b/lib/pathspec/gitignorespec.rb @@ -3,8 +3,7 @@ class PathSpec # Class for parsing a .gitignore spec class GitIgnoreSpec < RegexSpec - attr_reader :regex - attr_reader :pattern + attr_reader :regex, :pattern def initialize(original_pattern) pattern = original_pattern.strip unless original_pattern.nil? @@ -94,7 +93,8 @@ def initialize(original_pattern) pattern_segs.each_index do |i| seg = pattern_segs[i] - if seg == '**' + case seg + when '**' # A pattern consisting solely of double-asterisks ('**') # will match every path. if i == 0 && i == regex_end @@ -119,7 +119,7 @@ def initialize(original_pattern) end # Match single path segment. - elsif seg == '*' + when '*' regex.concat(path_sep) if need_slash regex.concat("[^#{path_sep}]+") @@ -152,10 +152,6 @@ def initialize(original_pattern) end end - def match(path) - super(path) - end - def translate_segment_glob(pattern) ''" Translates the glob pattern to a regular expression. This is used in @@ -220,7 +216,8 @@ def translate_segment_glob(pattern) expr = '[' # Braket expression needs to be negated. - if pattern[i].chr == '!' + case pattern[i].chr + when '!' expr += '^' i += 1 @@ -229,7 +226,7 @@ def translate_segment_glob(pattern) # `fnmatch.translate()` escapes the caret ('^') as a # literal. To maintain consistency with undefined behavior, # I am escaping the '^' as well. - elsif pattern[i].chr == '^' + when '^' expr += '\\^' i += 1 end diff --git a/lib/pathspec/spec.rb b/lib/pathspec/spec.rb index 69f69c4..812d69d 100644 --- a/lib/pathspec/spec.rb +++ b/lib/pathspec/spec.rb @@ -1,8 +1,7 @@ class PathSpec # Abstract spec class Spec - attr_reader :regex - attr_reader :pattern + attr_reader :regex, :pattern def initialize(*_); end From bd4a66c2ca36bb05ba778d9416e36f089dd9f8b8 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 15:21:29 -0800 Subject: [PATCH 03/70] Specify Ruby 2.6 as min ruby version, more autocorrects --- .rubocop.yml | 3 +++ lib/pathspec/gitignorespec.rb | 4 ++-- pathspec.gemspec | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 28dc231..9a0f0b9 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,5 +1,8 @@ inherit_from: .rubocop_todo.yml +AllCops: + TargetRubyVersion: 2.6 + Style/NumericPredicate: Enabled: false diff --git a/lib/pathspec/gitignorespec.rb b/lib/pathspec/gitignorespec.rb index 43d853e..6fcddc2 100644 --- a/lib/pathspec/gitignorespec.rb +++ b/lib/pathspec/gitignorespec.rb @@ -42,14 +42,14 @@ def initialize(original_pattern) if pattern.start_with?('!') @inclusive = false # Remove leading exclamation mark. - pattern = pattern[1..-1] + pattern = pattern[1..] else @inclusive = true end # Remove leading back-slash escape for escaped hash ('#') or # exclamation mark ('!'). - pattern = pattern[1..-1] if pattern.start_with?('\\') + pattern = pattern[1..] if pattern.start_with?('\\') # Split pattern into segments. -1 to allow trailing slashes. pattern_segs = pattern.split('/', -1) diff --git a/pathspec.gemspec b/pathspec.gemspec index 657c267..55b5bbb 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -16,6 +16,7 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.homepage = 'https://github.com/highb/pathspec-ruby' s.license = 'Apache-2.0' + s.required_ruby_version = '>= 2.6.0' s.add_development_dependency 'bundler', '~> 2.2' s.add_development_dependency 'fakefs', '~> 1.3' s.add_development_dependency 'rake', '~> 13.0' From 5d9400f50b6b9c5f7873855b0004fa1685dc40bb Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 15:24:12 -0800 Subject: [PATCH 04/70] Ignore cyclomatic complexity for now Only exceeds rubocop's rule by 1 so this would likely be an easy refactor later. --- lib/pathspec/gitignorespec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pathspec/gitignorespec.rb b/lib/pathspec/gitignorespec.rb index 6fcddc2..0e969ec 100644 --- a/lib/pathspec/gitignorespec.rb +++ b/lib/pathspec/gitignorespec.rb @@ -5,7 +5,7 @@ class PathSpec class GitIgnoreSpec < RegexSpec attr_reader :regex, :pattern - def initialize(original_pattern) + def initialize(original_pattern) # rubocop:disable Metrics/CyclomaticComplexity pattern = original_pattern.strip unless original_pattern.nil? # A pattern starting with a hash ('#') serves as a comment From 61f33ee8cbd6eedb57213c81c24ccf2b9e8d16b4 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 17:59:47 -0800 Subject: [PATCH 05/70] Add kramdown gem and change docs syntax to use md --- Rakefile | 11 +++-- docs/html/pathspec-rb.html | 82 ++++++++++++++++++++++++++++++++++ docs/man/pathspec-rb.man.1.rst | 62 ------------------------- docs/pathspec-rb.md | 64 ++++++++++++++++++++++++++ pathspec.gemspec | 1 + 5 files changed, 155 insertions(+), 65 deletions(-) create mode 100644 docs/html/pathspec-rb.html delete mode 100644 docs/man/pathspec-rb.man.1.rst create mode 100644 docs/pathspec-rb.md diff --git a/Rakefile b/Rakefile index b372b7a..ad27dd2 100644 --- a/Rakefile +++ b/Rakefile @@ -6,6 +6,7 @@ rescue LoadError end require 'rubocop/rake_task' +require 'kramdown' RuboCop::RakeTask.new(:rubocop) do |t| t.options = ['--display-cop-names'] @@ -15,8 +16,12 @@ task default: %i[rubocop spec man_pages] desc 'Generate man page for executable script' task :man_pages do - rst2man = `which rst2man`.chomp - abort('rst2man could not be found and is needed to build man pages') unless File.executable?(rst2man) + kramdown = Kramdown::Document.new(File.read('docs/pathspec-rb.md')) + File.open('docs/man/pathspec-rb.man.1', 'w') do |f| + f.write(kramdown.to_man) + end - `rst2man docs/man/pathspec-rb.man.1.rst > docs/man/pathspec-rb.man.1` + File.open('docs/html/pathspec-rb.html', 'w') do |f| + f.write(kramdown.to_html) + end end diff --git a/docs/html/pathspec-rb.html b/docs/html/pathspec-rb.html new file mode 100644 index 0000000..be9c694 --- /dev/null +++ b/docs/html/pathspec-rb.html @@ -0,0 +1,82 @@ +

pathspec-rb(1)

+ +

NAME

+ +

pathspec - Test pathspecs against a specific path

+ +

SYNOPSIS

+ +

pathspec-rb [OPTIONS] [SUBCOMMAND] [PATH] NAME PATH

+ +

DESCRIPTION

+ +

pathspc-rb is a tool that accompanies the pathspec-ruby library to help +you test what match results the library would find using path specs. You can +either find all specs matching a path, find all files matching specs, or +verify that a path would match any spec.

+ +

https://github.com/highb/pathspec-ruby

+ +

SUB-COMMANDS

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescription
specs_matchFind all specs matching path
treeFind all files under path matching the spec
matchCheck if the path matches any spec
+ +

OPTIONS

+ +
+
-f <FILENAME>, --file <FILENAME>
+
Load path specs from the file passed in as argument. If this option is not specified, pathspec-rb defaults to loading .gitignore.
+
-t [git|regex], --type [git|regex]
+
Type of spec expected in the loaded specs file (see -f option). Defaults to git.
+
-v, --verbose
+
Only output if there are matches.
+
+ +

EXAMPLE

+ +

Find all files ignored by git under your source directory:

+ +
  $ pathspec-rb tree src/
+
+ +

List all spec rules that would match for the specified path:

+ +
  $ pathspec-rb specs_match build/
+
+ +

Check that a path matches at least one of the specs in a new version of a +gitignore file:

+ +
  $ pathspec-rb match -f .gitignore.new spec/fixtures/
+
+ +

AUTHOR

+ +

Brandon High highb@users.noreply.github.com

+ +

Gabriel Filion

diff --git a/docs/man/pathspec-rb.man.1.rst b/docs/man/pathspec-rb.man.1.rst deleted file mode 100644 index d18bbfc..0000000 --- a/docs/man/pathspec-rb.man.1.rst +++ /dev/null @@ -1,62 +0,0 @@ -=========== -pathspec-rb -=========== - --------------------------------------- -Test pathspecs against a specific path --------------------------------------- - -:Author: Gabriel Filion -:Date: 2019 -:Manual section: 1 - -Synopsis -======== - -| pathspec-rb [options] [subcommand] [path] - -Description -=========== - -``pathspc-rb`` is a tool that accompanies the pathspec-ruby library to help -you test what match results the library would find using path specs. You can -either find all specs matching a path, find all files matching specs, or -verify that a path would match any spec. - -Sub-commands -============ - -| **specs_match** Find all specs matching path -| **tree** Find all files under path matching the spec -| **match** Check if the path matches any spec - -Options -======= - -| **-f** | **--file** -|     Load path specs from the file passed in as argument. If this option is -| not specified, ``pathspec-rb`` defaults to loading ``.gitignore``. - -| **-t** | **--type** [``git``\ \|\ ``regex``] -|     Type of spec expected in the loaded specs file (see **-f** option). -| Defaults to ``git``. - -| **-v** | **--verbose** -|     Only output if there are matches. - -Examples -======== - -Find all files ignored by git under your source directory:: - - $ pathspec-rb tree src/ - -List all spec rules that would match for the specified path:: - - $ pathspec-rb specs_match build/ - -Check that a path matches at least one of the specs in a new version of a -gitignore file:: - - $ pathspec-rb match -f .gitignore.new spec/fixtures/ - diff --git a/docs/pathspec-rb.md b/docs/pathspec-rb.md new file mode 100644 index 0000000..d2106a7 --- /dev/null +++ b/docs/pathspec-rb.md @@ -0,0 +1,64 @@ +# pathspec-rb(1) + +{:data-date="2020/01/04"} + +## NAME + +pathspec - Test pathspecs against a specific path + +## SYNOPSIS + +`pathspec-rb` [`OPTIONS`] [`SUBCOMMAND`] [`PATH`] NAME PATH + +## DESCRIPTION + +`pathspc-rb` is a tool that accompanies the pathspec-ruby library to help +you test what match results the library would find using path specs. You can +either find all specs matching a path, find all files matching specs, or +verify that a path would match any spec. + +https://github.com/highb/pathspec-ruby + +## SUB-COMMANDS + +|- +| Name | Description +|- +| *specs_match* | Find all specs matching path +|- +| *tree* | Find all files under path matching the spec +|- +| *match* | Check if the path matches any spec +|- + +## OPTIONS + +`-f `, `--file ` +: Load path specs from the file passed in as argument. If this option is not specified, `pathspec-rb` defaults to loading `.gitignore`. + +`-t [git|regex]`, `--type [git|regex]` +: Type of spec expected in the loaded specs file (see `-f` option). Defaults to `git`. + +`-v`, `--verbose` +: Only output if there are matches. + +## EXAMPLE + +Find all files ignored by git under your source directory: + + $ pathspec-rb tree src/ + +List all spec rules that would match for the specified path: + + $ pathspec-rb specs_match build/ + +Check that a path matches at least one of the specs in a new version of a +gitignore file: + + $ pathspec-rb match -f .gitignore.new spec/fixtures/ + +## AUTHOR + +Brandon High highb@users.noreply.github.com + +Gabriel Filion diff --git a/pathspec.gemspec b/pathspec.gemspec index 55b5bbb..cbcfd96 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -20,6 +20,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'bundler', '~> 2.2' s.add_development_dependency 'fakefs', '~> 1.3' s.add_development_dependency 'rake', '~> 13.0' + s.add_development_dependency 'kramdown', '~> 2.3' s.add_development_dependency 'rspec', '~> 3.10' s.add_development_dependency 'rubocop', '~> 1.7' s.add_development_dependency 'simplecov', '~> 0.21' From 6189f18ca6dfd476eecfb8c90a486f750543f8d7 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:02:29 -0800 Subject: [PATCH 06/70] Rubocop fix: bundler dep ordering --- pathspec.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathspec.gemspec b/pathspec.gemspec index cbcfd96..2f7c74e 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -19,8 +19,8 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 2.6.0' s.add_development_dependency 'bundler', '~> 2.2' s.add_development_dependency 'fakefs', '~> 1.3' - s.add_development_dependency 'rake', '~> 13.0' s.add_development_dependency 'kramdown', '~> 2.3' + s.add_development_dependency 'rake', '~> 13.0' s.add_development_dependency 'rspec', '~> 3.10' s.add_development_dependency 'rubocop', '~> 1.7' s.add_development_dependency 'simplecov', '~> 0.21' From 020b04e98e727878803f9d561e6acc429dce972a Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:04:08 -0800 Subject: [PATCH 07/70] Add asdf .tool-versions --- .tool-versions | 1 + 1 file changed, 1 insertion(+) create mode 100644 .tool-versions diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..9eb38ed --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +ruby 2.7.2 From 3ebfcff1a9a20fde023dec63cdfc2baa82558374 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:06:59 -0800 Subject: [PATCH 08/70] Change rake man_pages to rake docs --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index ad27dd2..d9a3d8c 100644 --- a/Rakefile +++ b/Rakefile @@ -15,7 +15,7 @@ end task default: %i[rubocop spec man_pages] desc 'Generate man page for executable script' -task :man_pages do +task :docs do kramdown = Kramdown::Document.new(File.read('docs/pathspec-rb.md')) File.open('docs/man/pathspec-rb.man.1', 'w') do |f| f.write(kramdown.to_man) From 27df862c112a3f699cc12676152df2be3952ac7e Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:09:41 -0800 Subject: [PATCH 09/70] Update travis --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 73f17bb..b27fe07 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: ruby -script: 'bundle exec rake spec' +script: 'bundle exec rake' rvm: - - 2.4.6 - - 2.5.6 - - 2.6.4 + - 2.6.5 + - 2.7.2 From 9226c4672336db464f275919e9b3b50525d77574 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:13:30 -0800 Subject: [PATCH 10/70] Use bundler 2 in travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index b27fe07..ae50bb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: ruby +before_install: + - gem install bundler script: 'bundle exec rake' rvm: - 2.6.5 From 03591ef2ed25ef6c8a02245bf7c251566ace7ac8 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:23:32 -0800 Subject: [PATCH 11/70] Switch rakefile default to use docs --- Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rakefile b/Rakefile index d9a3d8c..2b5f01d 100644 --- a/Rakefile +++ b/Rakefile @@ -12,7 +12,7 @@ RuboCop::RakeTask.new(:rubocop) do |t| t.options = ['--display-cop-names'] end -task default: %i[rubocop spec man_pages] +task default: %i[rubocop spec docs] desc 'Generate man page for executable script' task :docs do From 9d9fdedd26ca93e418415fd397e47252d4b21be9 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:26:40 -0800 Subject: [PATCH 12/70] mkdir_p the docs folders just to be sure --- Rakefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Rakefile b/Rakefile index 2b5f01d..9d3e685 100644 --- a/Rakefile +++ b/Rakefile @@ -7,6 +7,7 @@ end require 'rubocop/rake_task' require 'kramdown' +require 'fileutils' RuboCop::RakeTask.new(:rubocop) do |t| t.options = ['--display-cop-names'] @@ -17,10 +18,13 @@ task default: %i[rubocop spec docs] desc 'Generate man page for executable script' task :docs do kramdown = Kramdown::Document.new(File.read('docs/pathspec-rb.md')) + + FileUtils.mkdir_p 'docs/man' File.open('docs/man/pathspec-rb.man.1', 'w') do |f| f.write(kramdown.to_man) end + FileUtils.mkdir_p 'docs/html' File.open('docs/html/pathspec-rb.html', 'w') do |f| f.write(kramdown.to_html) end From a054b4f12f063acfe38cb6027bc8eba0852d8baa Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:27:37 -0800 Subject: [PATCH 13/70] Add Ruby 3.0.0 to test matrix Why not give it a try? --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ae50bb2..784ef67 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,3 +5,4 @@ script: 'bundle exec rake' rvm: - 2.6.5 - 2.7.2 + - 3.0.0 From 9d7bfdcfac6b5447c5c5bed551037464eca5c4f8 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:34:46 -0800 Subject: [PATCH 14/70] Enable Rubocop newCops, ignore Lint/DuplicatBranch I like the Lint/DuplicateBranch cop but in this specific case I would like to preserve the existing comments and flow because it is easier to follow than checking all of the conditions in one statement. --- .rubocop.yml | 1 + bin/pathspec-rb | 2 +- lib/pathspec/gitignorespec.rb | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 9a0f0b9..8b19348 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -2,6 +2,7 @@ inherit_from: .rubocop_todo.yml AllCops: TargetRubyVersion: 2.6 + NewCops: enable Style/NumericPredicate: Enabled: false diff --git a/bin/pathspec-rb b/bin/pathspec-rb index 8c8969e..26096ce 100755 --- a/bin/pathspec-rb +++ b/bin/pathspec-rb @@ -59,7 +59,7 @@ when 'specs_match' end when 'tree' tree_matches = spec.match_tree(path) - if !tree_matches.empty? + if tree_matches.any? puts "Files in #{path} that match #{options[:spec_filename]}" if options[:verbose] puts tree_matches else diff --git a/lib/pathspec/gitignorespec.rb b/lib/pathspec/gitignorespec.rb index 0e969ec..379df3e 100644 --- a/lib/pathspec/gitignorespec.rb +++ b/lib/pathspec/gitignorespec.rb @@ -17,19 +17,19 @@ def initialize(original_pattern) # rubocop:disable Metrics/CyclomaticComplexity # A blank pattern is a null-operation (neither includes nor # excludes files). - elsif pattern.empty? + elsif pattern.empty? # rubocop:disable Lint/DuplicateBranch @regex = nil @inclusive = nil # Patterns containing three or more consecutive stars are invalid and # will be ignored. - elsif /\*\*\*+/.match?(pattern) + elsif /\*\*\*+/.match?(pattern) # rubocop:disable Lint/DuplicateBranch @regex = nil @inclusive = nil # EDGE CASE: According to git check-ignore (v2.4.1)), a single '/' # does not match any file - elsif pattern == '/' + elsif pattern == '/' # rubocop:disable Lint/DuplicateBranch @regex = nil @inclusive = nil From 32f017b976671758224b63ce76e36e0c68a813bf Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 4 Jan 2021 18:44:16 -0800 Subject: [PATCH 15/70] Bump major version Given that I've changed the required ruby version in the gemspec, I think that necessitates a major version bump. Hello version 1.0.0! --- pathspec.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathspec.gemspec b/pathspec.gemspec index 2f7c74e..a9ad1e8 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |s| s.name = 'pathspec' - s.version = '0.2.0' + s.version = '1.0.0' s.date = '2018-01-11' s.summary = 'PathSpec: for matching path patterns' s.description = 'Use to match path patterns such as gitignore' From 8ad61a5ae7e029b0228ef4e3eacd64b5d7292b1d Mon Sep 17 00:00:00 2001 From: James Coleman Date: Fri, 7 Jan 2022 10:44:08 -0500 Subject: [PATCH 16/70] Fix case typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 36b3b06..dc53087 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ require 'pathspec' # Create a .gitignore-style Pathspec by giving it newline separated gitignore # lines, an array of gitignore lines, or any other enumable object that will # give strings matching the .gitignore-style (File, etc.) -gitignore = Pathspec.from_filename('spec/files/gitignore_readme') +gitignore = PathSpec.from_filename('spec/files/gitignore_readme') # Our .gitignore in this example contains: # !**/important.txt From 9b9ec5ad995fd943e7b04f88ee133a370e045b1c Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sat, 29 Jan 2022 10:41:32 -0800 Subject: [PATCH 17/70] Required ruby version to "In security maintenance phase" ruby (2.6.9) --- pathspec.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathspec.gemspec b/pathspec.gemspec index a9ad1e8..5d035f9 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |s| s.name = 'pathspec' - s.version = '1.0.0' + s.version = '1.0.1' s.date = '2018-01-11' s.summary = 'PathSpec: for matching path patterns' s.description = 'Use to match path patterns such as gitignore' @@ -16,7 +16,7 @@ Gem::Specification.new do |s| s.require_paths = ['lib'] s.homepage = 'https://github.com/highb/pathspec-ruby' s.license = 'Apache-2.0' - s.required_ruby_version = '>= 2.6.0' + s.required_ruby_version = '>= 2.6.9' s.add_development_dependency 'bundler', '~> 2.2' s.add_development_dependency 'fakefs', '~> 1.3' s.add_development_dependency 'kramdown', '~> 2.3' From 9dad97caef0633059ac48478de2b3d707b003b30 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sat, 29 Jan 2022 10:45:29 -0800 Subject: [PATCH 18/70] Setup rake GH action --- .github/workflows/ruby.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/ruby.yml diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml new file mode 100644 index 0000000..9f19016 --- /dev/null +++ b/.github/workflows/ruby.yml @@ -0,0 +1,35 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake +# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby + +name: Ruby + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + test: + + runs-on: ubuntu-latest + strategy: + matrix: + ruby-version: ['2.6', '2.7', '3.0', '3.1'] + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, + # change this to (see https://github.com/ruby/setup-ruby#versioning): + # uses: ruby/setup-ruby@v1 + uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - name: Run tests + run: bundle exec rake From 8e6e5c6f638a9d3752911fc197a07d8bdf31c9a8 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sat, 29 Jan 2022 10:49:39 -0800 Subject: [PATCH 19/70] Increase version bump to minor release Required major version changes, even if they are a patch, could be a breaking change. --- pathspec.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathspec.gemspec b/pathspec.gemspec index 5d035f9..954f309 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |s| s.name = 'pathspec' - s.version = '1.0.1' + s.version = '1.1.0' s.date = '2018-01-11' s.summary = 'PathSpec: for matching path patterns' s.description = 'Use to match path patterns such as gitignore' From 2aa17707e4c029da35c6ae974eed265f2a8b4ebf Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sat, 29 Jan 2022 15:26:48 -0800 Subject: [PATCH 20/70] New rubies and GH actions (#38) * Update supported Ruby versions in README * Remove Ruby 3.1 from GH actions Unsupported by GH actions at this time * Update ruby.yml * Update ruby.yml * Update README.md * Fix Style/Filewrite lint * gitignorespec OpPrecedence and TripleQuote lint * Update pathspec.gemspec * quote linting * Update gitignorespec.rb * Remove silly Lint/AmbiguousOperatorPrecedence rule * Undo trying to fix silly lint rule * Rubocop drives me crazy sometimes --- .github/workflows/ruby.yml | 2 +- .rubocop.yml | 5 +++++ README.md | 6 +++--- Rakefile | 8 ++------ lib/pathspec/gitignorespec.rb | 17 ++++++++--------- pathspec.gemspec | 3 ++- 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 9f19016..eea46ec 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['2.6', '2.7', '3.0', '3.1'] + ruby-version: ['2.7', '3.0'] steps: - uses: actions/checkout@v2 diff --git a/.rubocop.yml b/.rubocop.yml index 8b19348..bb0a941 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -9,3 +9,8 @@ Style/NumericPredicate: Layout/ClosingHeredocIndentation: Enabled: false + +# This rule is silly +# https://github.com/rubocop/rubocop/issues/10080 +Lint/AmbiguousOperatorPrecedence: + Enabled: false diff --git a/README.md b/README.md index dc53087..7a1f854 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ [Supported Rubies](https://www.ruby-lang.org/en/downloads/): -- 2.4.6 (Maintenance) -- 2.5.6 (Stable) -- 2.6.4 (Stable) +- 2.6 (Security Maintenance) +- 2.7 (Stable, Tested) +- 3.0 (Stable, Tested) Match Path Specifications, such as .gitignore, in Ruby! diff --git a/Rakefile b/Rakefile index 9d3e685..ad4ee3b 100644 --- a/Rakefile +++ b/Rakefile @@ -20,12 +20,8 @@ task :docs do kramdown = Kramdown::Document.new(File.read('docs/pathspec-rb.md')) FileUtils.mkdir_p 'docs/man' - File.open('docs/man/pathspec-rb.man.1', 'w') do |f| - f.write(kramdown.to_man) - end + File.write('docs/man/pathspec-rb.man.1', kramdown.to_man) FileUtils.mkdir_p 'docs/html' - File.open('docs/html/pathspec-rb.html', 'w') do |f| - f.write(kramdown.to_html) - end + File.write('docs/html/pathspec-rb.html', kramdown.to_html) end diff --git a/lib/pathspec/gitignorespec.rb b/lib/pathspec/gitignorespec.rb index 379df3e..38e2a25 100644 --- a/lib/pathspec/gitignorespec.rb +++ b/lib/pathspec/gitignorespec.rb @@ -153,15 +153,14 @@ def initialize(original_pattern) # rubocop:disable Metrics/CyclomaticComplexity end def translate_segment_glob(pattern) - ''" - Translates the glob pattern to a regular expression. This is used in - the constructor to translate a path segment glob pattern to its - corresponding regular expression. - - *pattern* (``str``) is the glob pattern. - - Returns the regular expression (``str``). - "'' + # Translates the glob pattern to a regular expression. This is used in + # the constructor to translate a path segment glob pattern to its + # corresponding regular expression. + # + # *pattern* (``str``) is the glob pattern. + # + # Returns the regular expression (``str``). + # # NOTE: This is derived from `fnmatch.translate()` and is similar to # the POSIX function `fnmatch()` with the `FNM_PATHNAME` flag set. diff --git a/pathspec.gemspec b/pathspec.gemspec index 954f309..491b3a5 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -4,7 +4,6 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |s| s.name = 'pathspec' s.version = '1.1.0' - s.date = '2018-01-11' s.summary = 'PathSpec: for matching path patterns' s.description = 'Use to match path patterns such as gitignore' s.authors = ['Brandon High'] @@ -14,6 +13,8 @@ Gem::Specification.new do |s| s.executables << 'pathspec-rb' s.test_files = s.files.grep(%r{^spec/}) s.require_paths = ['lib'] + s.metadata['allowed_push_host'] = 'https://rubygems.org' + s.metadata['rubygems_mfa_required'] = 'true' s.homepage = 'https://github.com/highb/pathspec-ruby' s.license = 'Apache-2.0' s.required_ruby_version = '>= 2.6.9' From 10e941c067ded2eaaec9db56ffbf5b7f78d4323b Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sat, 29 Jan 2022 17:09:39 -0800 Subject: [PATCH 21/70] RIP Travis --- .travis.yml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 784ef67..0000000 --- a/.travis.yml +++ /dev/null @@ -1,8 +0,0 @@ -language: ruby -before_install: - - gem install bundler -script: 'bundle exec rake' -rvm: - - 2.6.5 - - 2.7.2 - - 3.0.0 From 63007b235e383a377a0b6b609f4a69956b7a0777 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sat, 29 Jan 2022 17:28:30 -0800 Subject: [PATCH 22/70] Update ruby.yml (#40) --- .github/workflows/ruby.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index eea46ec..b8d1a27 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -20,6 +20,7 @@ jobs: strategy: matrix: ruby-version: ['2.7', '3.0'] + raketasks: ['rubocop', 'spec', 'docs'] steps: - uses: actions/checkout@v2 @@ -31,5 +32,7 @@ jobs: with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically - - name: Run tests - run: bundle exec rake + - name: Rake Tasks + env: + TASK: ${{matrix.raketasks}} + run: bundle exec rake $TASK From 746ee20217900e471ffe1b9e026e9a624698deb4 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 12:25:46 -0800 Subject: [PATCH 23/70] Update readme example to be clearer Removed my shell alias be=bundle exec here and the PWD in the prompt so it's clearer what is going on --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7a1f854..75e2262 100644 --- a/README.md +++ b/README.md @@ -23,19 +23,19 @@ gem install pathspec ## CLI Usage ```bash -➜ test-pathspec cat .gitignore +➜ cat .gitignore *.swp /coverage/ -➜ test-pathspec be pathspec-rb specs_match "coverage/foo" +➜ bundle exec pathspec-rb specs_match "coverage/foo" /coverage/ -➜ test-pathspec be pathspec-rb specs_match "file.swp" +➜ bundle exec pathspec-rb specs_match "file.swp" *.swp -➜ test-pathspec be pathspec-rb match "file.swp" -➜ test-pathspec echo $? +➜ bundle exec pathspec-rb match "file.swp" +➜ echo $? 0 -➜ test-pathspec ls +➜ ls Gemfile Gemfile.lock coverage file.swp source.rb -➜ test-pathspec be pathspec-rb tree . +➜ bundle exec pathspec-rb tree . ./coverage ./coverage/index.html ./file.swp From ac92bb6144e10fe106f66e7c8ca3c2725a12268f Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 12:27:29 -0800 Subject: [PATCH 24/70] Update CHANGELOG for 1.1.0 --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 927f6dd..0a3529d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # pathspec-ruby CHANGELOG +## 1.1.0 (Minor Release) + +- (Maint) Updated Supported Ruby Versions +- (Maint) Linting corrections + +## Undocumented Releases (Sorry!) + ## 0.2.0 (Minor Release) - (Feature) A CLI tool, pathspec-rb, is now provided with the gem. - (API Change) New namespace for gem: `PathSpec`: Everything is now namespaced under `PathSpec`, to prevent naming collisions with other libraries. Thanks @tenderlove! From 665b8c37d407f3a164da40ff098b3c04b15dba19 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 12:38:00 -0800 Subject: [PATCH 25/70] Update docs rake task --- Rakefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Rakefile b/Rakefile index ad4ee3b..b09e579 100644 --- a/Rakefile +++ b/Rakefile @@ -19,9 +19,8 @@ desc 'Generate man page for executable script' task :docs do kramdown = Kramdown::Document.new(File.read('docs/pathspec-rb.md')) + File.write('docs/index.html', kramdown.to_html) + FileUtils.mkdir_p 'docs/man' File.write('docs/man/pathspec-rb.man.1', kramdown.to_man) - - FileUtils.mkdir_p 'docs/html' - File.write('docs/html/pathspec-rb.html', kramdown.to_html) end From e8edea34b607f77831d2db738693707121bb6d0a Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 12:41:11 -0800 Subject: [PATCH 26/70] Move html docs to location that works with GH pages --- docs/{html/pathspec-rb.html => index.html} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/{html/pathspec-rb.html => index.html} (100%) diff --git a/docs/html/pathspec-rb.html b/docs/index.html similarity index 100% rename from docs/html/pathspec-rb.html rename to docs/index.html From 4b918f76652a5d3fedfd683d2d0debd93234e147 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 12:43:32 -0800 Subject: [PATCH 27/70] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 75e2262..5dcfe3d 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ [![Gem Version](https://badge.fury.io/rb/pathspec.svg)](https://badge.fury.io/rb/pathspec) [![Build Status](https://travis-ci.org/highb/pathspec-ruby.svg?branch=master)](https://travis-ci.org/highb/pathspec-ruby) [![Maintainability](https://api.codeclimate.com/v1/badges/4f3b5917e01fb34f790d/maintainability)](https://codeclimate.com/github/highb/pathspec-ruby/maintainability) +[man Page as HTML](http://highb.github.io/pathspec-ruby/) + [Supported Rubies](https://www.ruby-lang.org/en/downloads/): - 2.6 (Security Maintenance) From 6252d2f464f3f75ed1d55891286b9043dc3afd86 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 12:46:00 -0800 Subject: [PATCH 28/70] Add Gemspec example to README.md Closes #28 --- README.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/README.md b/README.md index 5dcfe3d..4eec614 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,36 @@ gitignore.match_paths ['/abc/123', '/abc/important.txt', '/abc/'] # There is no CLI equivalent to this. ``` +## Example Usage in Gemspec + +``` +lib = File.expand_path("lib", __dir__) +$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) +require "gemspec_pathspec_test/version" +require 'pathspec' + +Gem::Specification.new do |spec| + spec.name = "gemspec_pathspec_test" + spec.version = GemspecPathspecTest::VERSION + spec.authors = ["Brandon High"] + spec.email = ["highb@users.noreply.github.com"] + + spec.summary = "whatever" + + spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'" + + ps = PathSpec.from_filename('.gitignore') + spec.files = Dir['lib/*.rb'].reject { |f| ps.match(f) } + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.require_paths = ["lib"] + + spec.add_development_dependency "bundler", "~> 2.0" + spec.add_development_dependency "rake", "~> 10.0" + spec.add_development_dependency "rspec", "~> 3.0" +end +``` + ## Building/Installing from Source ```shell From d67bb5f0bb9af5188c6544f8c5feacee70e6a42d Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 12:57:48 -0800 Subject: [PATCH 29/70] Add build step to CI --- .github/workflows/ruby.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index b8d1a27..4aa24c5 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -14,6 +14,28 @@ on: branches: [ master ] jobs: + build: + + runs-on: ubuntu-latest + strategy: + matrix: + ruby-version: ['2.7', '3.0'] + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby + # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, + # change this to (see https://github.com/ruby/setup-ruby#versioning): + # uses: ruby/setup-ruby@v1 + uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e + with: + ruby-version: ${{ matrix.ruby-version }} + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + - name: Gem Build + run: gem build pathspec.gemspec + - name: Gem Install + run: gem install ./pathspec*.gem + test: runs-on: ubuntu-latest From bae23b721a3080e038bf2897a62de3f8aa9d65d5 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 13:08:50 -0800 Subject: [PATCH 30/70] Create gem-push.yml --- .github/workflows/gem-push.yml | 44 ++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/workflows/gem-push.yml diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml new file mode 100644 index 0000000..6ed8cd3 --- /dev/null +++ b/.github/workflows/gem-push.yml @@ -0,0 +1,44 @@ +name: Ruby Gem + +on: + push: + tags: + - '*' + +jobs: + build: + name: Build + Publish + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - uses: actions/checkout@v2 + - name: Set up Ruby 2.7 + uses: actions/setup-ruby@v1 + with: + ruby-version: 2.7.x + + - name: Publish to GPR + run: | + mkdir -p $HOME/.gem + touch $HOME/.gem/credentials + chmod 0600 $HOME/.gem/credentials + printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials + gem build *.gemspec + gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem + env: + GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}" + OWNER: ${{ github.repository_owner }} + + - name: Publish to RubyGems + run: | + mkdir -p $HOME/.gem + touch $HOME/.gem/credentials + chmod 0600 $HOME/.gem/credentials + printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials + gem build *.gemspec + gem push *.gem + env: + GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}" From e6cb4b66985325ccfe129ff043f21b3226a65877 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 13:13:53 -0800 Subject: [PATCH 31/70] Remove GPR push Don't have any pressing need to push to GitHub's registry at this time --- .github/workflows/gem-push.yml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 6ed8cd3..073ef19 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -19,19 +19,7 @@ jobs: uses: actions/setup-ruby@v1 with: ruby-version: 2.7.x - - - name: Publish to GPR - run: | - mkdir -p $HOME/.gem - touch $HOME/.gem/credentials - chmod 0600 $HOME/.gem/credentials - printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials - gem build *.gemspec - gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem - env: - GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}" - OWNER: ${{ github.repository_owner }} - + - name: Publish to RubyGems run: | mkdir -p $HOME/.gem From 1fa8afd04e236f2b24ddc86f97406eab015e8f8b Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 13:15:21 -0800 Subject: [PATCH 32/70] Bump to 1.1.1 since I'm burning the 1.1.0 tag --- pathspec.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathspec.gemspec b/pathspec.gemspec index 491b3a5..cf75859 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |s| s.name = 'pathspec' - s.version = '1.1.0' + s.version = '1.1.1' s.summary = 'PathSpec: for matching path patterns' s.description = 'Use to match path patterns such as gitignore' s.authors = ['Brandon High'] From 43e9e46fb1cf3cef42a2a1ec774ee8671b44562c Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 13:27:34 -0800 Subject: [PATCH 33/70] Add note to future self on how the release works --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 4eec614..90258d1 100644 --- a/README.md +++ b/README.md @@ -117,3 +117,11 @@ cd pathspec-ruby && bash ./build_from_source.sh ## Contributing Pull requests, bug reports, and feature requests welcome! :smile: I've tried to write exhaustive tests but who knows what cases I've missed. + +## Releasing + +This is mainly a reminder to myself but the release process is: +1. Make sure CI is passing +2. Update the CHANGELOG with relevant changes to Gem consumers +3. Update version in gemspec with correct SemVer bump for scope of changes +4. Tag/release using GitHub UI and the Build & Push workflow should do the rest. From b6f595c73165abb707430fd9416aad9df0bd36d9 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 13:28:43 -0800 Subject: [PATCH 34/70] Remove rspec_all_versions.sh since I now have GH actions running It's redundant and yet another thing to keep up to date --- rspec_all_versions.sh | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100755 rspec_all_versions.sh diff --git a/rspec_all_versions.sh b/rspec_all_versions.sh deleted file mode 100755 index 3992b14..0000000 --- a/rspec_all_versions.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash -function testversion { - echo Testing Ruby $1 - rbenv install -s $1 - rbenv local $1 - gem install bundler --quiet - bundle install --quiet - bundle exec rspec - if [ $? -eq 0 ]; then - echo -e "\033[32mSuccess testing Ruby $1\033[0m" - else - echo -e "\033[31mFailed testing Ruby $1 Exit code was $?\033[0m" - fi - echo - -} - -for VERSION in 2.2.9 2.3.6 2.4.3 2.5.0; do - testversion $VERSION -done From e8b135d69a5f4e9b189551299448b3a8a50a1c32 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 13:29:20 -0800 Subject: [PATCH 35/70] Update install_from_source.sh --- install_from_source.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/install_from_source.sh b/install_from_source.sh index 55c719f..2821eed 100755 --- a/install_from_source.sh +++ b/install_from_source.sh @@ -8,5 +8,8 @@ bundle exec rspec spec # Ensure there is no existing version bundle exec gem uninstall pathspec +# Clear old artifacts +rm pathspec-*.gem + # Build and install! -bundle exec gem build pathspec.gemspec && bundle exec gem install pathspec-0.2.0.gem +bundle exec gem build pathspec.gemspec && bundle exec gem install pathspec-*.gem From 0eac7b4d3e155cc9799b1cd0f10c9d840a0ce27a Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 13:36:28 -0800 Subject: [PATCH 36/70] Switch Travis to GH action status badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 90258d1..de1e716 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pathspec-ruby -[![Gem Version](https://badge.fury.io/rb/pathspec.svg)](https://badge.fury.io/rb/pathspec) [![Build Status](https://travis-ci.org/highb/pathspec-ruby.svg?branch=master)](https://travis-ci.org/highb/pathspec-ruby) [![Maintainability](https://api.codeclimate.com/v1/badges/4f3b5917e01fb34f790d/maintainability)](https://codeclimate.com/github/highb/pathspec-ruby/maintainability) +[![Gem Version](https://badge.fury.io/rb/pathspec.svg)](https://badge.fury.io/rb/pathspec) [![Ruby](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/4f3b5917e01fb34f790d/maintainability)](https://codeclimate.com/github/highb/pathspec-ruby/maintainability) [man Page as HTML](http://highb.github.io/pathspec-ruby/) From b8423448f5719965eea0fe6cb5810c3fca144a43 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 13:41:34 -0800 Subject: [PATCH 37/70] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index de1e716..657660e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pathspec-ruby -[![Gem Version](https://badge.fury.io/rb/pathspec.svg)](https://badge.fury.io/rb/pathspec) [![Ruby](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/4f3b5917e01fb34f790d/maintainability)](https://codeclimate.com/github/highb/pathspec-ruby/maintainability) +[![Gem Version](https://badge.fury.io/rb/pathspec.svg)](https://badge.fury.io/rb/pathspec) [![Ruby](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/4f3b5917e01fb34f790d/maintainability)](https://codeclimate.com/github/highb/pathspec-ruby/maintainability) [![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=highb_pathspec-ruby)](https://sonarcloud.io/summary/new_code?id=highb_pathspec-ruby) [man Page as HTML](http://highb.github.io/pathspec-ruby/) From af6b78a12a92cf61e14772dcfa94afc2b52ee831 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 13:43:38 -0800 Subject: [PATCH 38/70] Use less obnoxious quality gate badge from SonarCloud --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 657660e..f582b03 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pathspec-ruby -[![Gem Version](https://badge.fury.io/rb/pathspec.svg)](https://badge.fury.io/rb/pathspec) [![Ruby](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/4f3b5917e01fb34f790d/maintainability)](https://codeclimate.com/github/highb/pathspec-ruby/maintainability) [![Quality gate](https://sonarcloud.io/api/project_badges/quality_gate?project=highb_pathspec-ruby)](https://sonarcloud.io/summary/new_code?id=highb_pathspec-ruby) +[![Gem Version](https://badge.fury.io/rb/pathspec.svg)](https://badge.fury.io/rb/pathspec) [![Ruby](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/4f3b5917e01fb34f790d/maintainability)](https://codeclimate.com/github/highb/pathspec-ruby/maintainability) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=highb_pathspec-ruby&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=highb_pathspec-ruby) [man Page as HTML](http://highb.github.io/pathspec-ruby/) From e1f3979e36e4f62bbf60928e817cd7274c7cf94c Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 14:15:19 -0800 Subject: [PATCH 39/70] Add docs generation to build + push workflow --- .github/workflows/gem-push.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 073ef19..47bc6f8 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -16,9 +16,13 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Ruby 2.7 - uses: actions/setup-ruby@v1 + uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e with: - ruby-version: 2.7.x + ruby-version: '2.7' + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + + - name: Generate man page + run: bundle exec rake docs - name: Publish to RubyGems run: | From 0417bf34776620363cb3d3c3673bb6a567d0161c Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 14:18:24 -0800 Subject: [PATCH 40/70] Update gem-push.yml Add workflow_dispatch for manual kickoff while testing without having to re-tag --- .github/workflows/gem-push.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 47bc6f8..b03bf6e 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -4,6 +4,7 @@ on: push: tags: - '*' + workflow_dispatch: jobs: build: From 5d3daab4bced0bb45c9cb593b6935dfc510bca38 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Sun, 30 Jan 2022 14:22:37 -0800 Subject: [PATCH 41/70] Bump to 1.1.3 --- pathspec.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathspec.gemspec b/pathspec.gemspec index cf75859..e25e5bf 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |s| s.name = 'pathspec' - s.version = '1.1.1' + s.version = '1.1.3' s.summary = 'PathSpec: for matching path patterns' s.description = 'Use to match path patterns such as gitignore' s.authors = ['Brandon High'] From a037ee6a7335fd6b99c88c8c9aee5aab2d1a3004 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 19:30:43 -0800 Subject: [PATCH 42/70] Add renovate.json (#41) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 renovate.json diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..5db72dd --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ] +} From f831dd4fe724d688b02cc2f50fdcbccdc4c58cfe Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 15 Jan 2024 19:33:48 -0800 Subject: [PATCH 43/70] Update GHA: Disable rubocop --- .github/workflows/ruby.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 4aa24c5..3a3ca7a 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -42,7 +42,10 @@ jobs: strategy: matrix: ruby-version: ['2.7', '3.0'] - raketasks: ['rubocop', 'spec', 'docs'] + # TODO: Fix rubocop issues + # raketasks: ['rubocop', 'spec', 'docs'] + raketasks: ['spec', 'docs'] + steps: - uses: actions/checkout@v2 From ee73ddecef31daff5d6f3f3fc228bea8ab84c2e1 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 15 Jan 2024 19:35:17 -0800 Subject: [PATCH 44/70] Update GHA: Remove Ruby 2.7 (Unsupported) --- .github/workflows/ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 3a3ca7a..a9ceb87 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['2.7', '3.0'] + ruby-version: ['3.0'] # TODO: Fix rubocop issues # raketasks: ['rubocop', 'spec', 'docs'] raketasks: ['spec', 'docs'] From 94f02371840236de8e61d499ac53250a531d2000 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 15 Jan 2024 19:36:33 -0800 Subject: [PATCH 45/70] Update gem-push.yml --- .github/workflows/gem-push.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index b03bf6e..1e9c805 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -16,10 +16,10 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up Ruby 2.7 + - name: Set up Ruby 3.0 uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e with: - ruby-version: '2.7' + ruby-version: '3.0' bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Generate man page From cefb0f62e7d7d7fcb0aef56022cadfdb7d39973d Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 15 Jan 2024 19:40:38 -0800 Subject: [PATCH 46/70] Update ruby.yml --- .github/workflows/ruby.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index a9ceb87..a8c604d 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['2.7', '3.0'] + ruby-version: ['3.0'] steps: - uses: actions/checkout@v2 From 643f645d9f4545f77cf04678460efcee3113757b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 19:42:16 -0800 Subject: [PATCH 47/70] Update ruby/setup-ruby digest to 360dc86 (#42) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/gem-push.yml | 2 +- .github/workflows/ruby.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 1e9c805..dc227c6 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Set up Ruby 3.0 - uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e + uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 with: ruby-version: '3.0' bundler-cache: true # runs 'bundle install' and caches installed gems automatically diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index a8c604d..fd07624 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -27,7 +27,7 @@ jobs: # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, # change this to (see https://github.com/ruby/setup-ruby#versioning): # uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e + uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically @@ -53,7 +53,7 @@ jobs: # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, # change this to (see https://github.com/ruby/setup-ruby#versioning): # uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e + uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically From 0aad662f2608152341c08143419bea62b45b1643 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 15 Jan 2024 19:43:10 -0800 Subject: [PATCH 48/70] Update .tool-versions --- .tool-versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tool-versions b/.tool-versions index 9eb38ed..3294aed 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -ruby 2.7.2 +ruby 3.3.0 From 5e8982c967171c021bd12a2894aef5161bd2a460 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 19:44:23 -0800 Subject: [PATCH 49/70] Update actions/checkout action to v4 (#45) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/gem-push.yml | 2 +- .github/workflows/ruby.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index dc227c6..e0b648d 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -15,7 +15,7 @@ jobs: packages: write steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby 3.0 uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 with: diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index fd07624..076c7f8 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -22,7 +22,7 @@ jobs: ruby-version: ['3.0'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, # change this to (see https://github.com/ruby/setup-ruby#versioning): @@ -48,7 +48,7 @@ jobs: steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Ruby # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, # change this to (see https://github.com/ruby/setup-ruby#versioning): From 7c8b7d0095186fb8cf24f5a4cd0d40671d475e38 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Mon, 15 Jan 2024 19:53:58 -0800 Subject: [PATCH 50/70] Upgrade to modern supported Rubies (3.1, 3.2, 3.3) (#46) * Upgrade to modern supported Rubies * Update pathspec.gemspec * Update gem-push.yml * Update README.md: Remove sonar * Update README.md * Update CHANGELOG.md --- .github/workflows/gem-push.yml | 4 ++-- .github/workflows/ruby.yml | 4 ++-- CHANGELOG.md | 4 ++++ README.md | 8 ++++---- pathspec.gemspec | 4 ++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index e0b648d..051278a 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -16,10 +16,10 @@ jobs: steps: - uses: actions/checkout@v4 - - name: Set up Ruby 3.0 + - name: Set up Ruby 3.1 uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 with: - ruby-version: '3.0' + ruby-version: '3.1' bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Generate man page diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 076c7f8..f25bc63 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['3.0'] + ruby-version: ['3.1', '3.2', '3.3'] steps: - uses: actions/checkout@v4 @@ -41,7 +41,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['3.0'] + ruby-version: ['3.1', '3.2', '3.3'] # TODO: Fix rubocop issues # raketasks: ['rubocop', 'spec', 'docs'] raketasks: ['spec', 'docs'] diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a3529d..9b6fe95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # pathspec-ruby CHANGELOG +## 2.0.0 + +- (Maint) Remove deprecated/security release versions of Ruby. The Gem will now only support and be tested against >= 3.1.0 e.g. 3.1, 3.2, and 3.3. + ## 1.1.0 (Minor Release) - (Maint) Updated Supported Ruby Versions diff --git a/README.md b/README.md index f582b03..76686a8 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # pathspec-ruby -[![Gem Version](https://badge.fury.io/rb/pathspec.svg)](https://badge.fury.io/rb/pathspec) [![Ruby](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/4f3b5917e01fb34f790d/maintainability)](https://codeclimate.com/github/highb/pathspec-ruby/maintainability) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=highb_pathspec-ruby&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=highb_pathspec-ruby) +[![Gem Version](https://badge.fury.io/rb/pathspec.svg)](https://badge.fury.io/rb/pathspec) [![Ruby](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/highb/pathspec-ruby/actions/workflows/ruby.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/4f3b5917e01fb34f790d/maintainability)](https://codeclimate.com/github/highb/pathspec-ruby/maintainability) [man Page as HTML](http://highb.github.io/pathspec-ruby/) [Supported Rubies](https://www.ruby-lang.org/en/downloads/): -- 2.6 (Security Maintenance) -- 2.7 (Stable, Tested) -- 3.0 (Stable, Tested) +- 3.1 (Stable, Tested) +- 3.2 (Stable, Tested) +- 3.3 (Stable, Tested) Match Path Specifications, such as .gitignore, in Ruby! diff --git a/pathspec.gemspec b/pathspec.gemspec index e25e5bf..7d81b12 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |s| s.name = 'pathspec' - s.version = '1.1.3' + s.version = '2.0.0' s.summary = 'PathSpec: for matching path patterns' s.description = 'Use to match path patterns such as gitignore' s.authors = ['Brandon High'] @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.metadata['rubygems_mfa_required'] = 'true' s.homepage = 'https://github.com/highb/pathspec-ruby' s.license = 'Apache-2.0' - s.required_ruby_version = '>= 2.6.9' + s.required_ruby_version = '>= 3.1.0' s.add_development_dependency 'bundler', '~> 2.2' s.add_development_dependency 'fakefs', '~> 1.3' s.add_development_dependency 'kramdown', '~> 2.3' From 4b725fa268f479d7eb26a6d2c18cb57c68bf2009 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 21:03:39 -0800 Subject: [PATCH 51/70] Update ruby/setup-ruby digest to 5daca16 (#47) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/gem-push.yml | 2 +- .github/workflows/ruby.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 051278a..9f033bb 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Ruby 3.1 - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 + uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d with: ruby-version: '3.1' bundler-cache: true # runs 'bundle install' and caches installed gems automatically diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index f25bc63..4993c32 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -27,7 +27,7 @@ jobs: # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, # change this to (see https://github.com/ruby/setup-ruby#versioning): # uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 + uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically @@ -53,7 +53,7 @@ jobs: # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, # change this to (see https://github.com/ruby/setup-ruby#versioning): # uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@360dc864d5da99d54fcb8e9148c14a84b90d3e88 + uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically From 7b67ad997591732a9ddfaab1fb76077d6a8419e3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 26 Feb 2024 16:12:52 -0800 Subject: [PATCH 52/70] Update ruby/setup-ruby digest to d4526a5 (#48) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/gem-push.yml | 2 +- .github/workflows/ruby.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 9f033bb..8a84c28 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Ruby 3.1 - uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d + uses: ruby/setup-ruby@d4526a55538b775af234ba4af27118ed6f8f6677 with: ruby-version: '3.1' bundler-cache: true # runs 'bundle install' and caches installed gems automatically diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 4993c32..d5d2562 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -27,7 +27,7 @@ jobs: # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, # change this to (see https://github.com/ruby/setup-ruby#versioning): # uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d + uses: ruby/setup-ruby@d4526a55538b775af234ba4af27118ed6f8f6677 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically @@ -53,7 +53,7 @@ jobs: # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, # change this to (see https://github.com/ruby/setup-ruby#versioning): # uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@5daca165445f0ae10478593083f72ca2625e241d + uses: ruby/setup-ruby@d4526a55538b775af234ba4af27118ed6f8f6677 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically From 23737d21836238e81598dd2dabd1b95f298b5f23 Mon Sep 17 00:00:00 2001 From: Eric Proulx Date: Wed, 10 Apr 2024 02:21:39 +0200 Subject: [PATCH 53/70] Add frozen string literal + small update (#50) * Update fakefs and rubocop to latest version Remove `spec` from files (spec are included when gem installed) Remove `test_files` (not required anymore) * Regenerate rubocop Fix frozen_string_literal * Update ruby/setup-ruby to v1 --- .github/workflows/gem-push.yml | 2 +- .github/workflows/ruby.yml | 19 +---- .rubocop.yml | 2 +- .rubocop_todo.yml | 100 ++++++++++------------- Gemfile | 2 + Rakefile | 2 + lib/pathspec.rb | 2 + lib/pathspec/gitignorespec.rb | 6 +- lib/pathspec/regexspec.rb | 2 + lib/pathspec/spec.rb | 2 + pathspec.gemspec | 9 +- spec/spec_helper.rb | 2 + spec/unit/pathspec/gitignorespec_spec.rb | 2 + spec/unit/pathspec/spec_spec.rb | 2 + spec/unit/pathspec_spec.rb | 2 + 15 files changed, 73 insertions(+), 83 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 8a84c28..891d491 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Set up Ruby 3.1 - uses: ruby/setup-ruby@d4526a55538b775af234ba4af27118ed6f8f6677 + uses: ruby/setup-ruby@v1 with: ruby-version: '3.1' bundler-cache: true # runs 'bundle install' and caches installed gems automatically diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index d5d2562..bff8253 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -15,19 +15,14 @@ on: jobs: build: - runs-on: ubuntu-latest strategy: matrix: ruby-version: ['3.1', '3.2', '3.3'] - steps: - uses: actions/checkout@v4 - name: Set up Ruby - # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, - # change this to (see https://github.com/ruby/setup-ruby#versioning): - # uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@d4526a55538b775af234ba4af27118ed6f8f6677 + uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically @@ -37,23 +32,15 @@ jobs: run: gem install ./pathspec*.gem test: - runs-on: ubuntu-latest strategy: matrix: ruby-version: ['3.1', '3.2', '3.3'] - # TODO: Fix rubocop issues - # raketasks: ['rubocop', 'spec', 'docs'] - raketasks: ['spec', 'docs'] - - + raketasks: ['rubocop', 'spec', 'docs'] steps: - uses: actions/checkout@v4 - name: Set up Ruby - # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, - # change this to (see https://github.com/ruby/setup-ruby#versioning): - # uses: ruby/setup-ruby@v1 - uses: ruby/setup-ruby@d4526a55538b775af234ba4af27118ed6f8f6677 + uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby-version }} bundler-cache: true # runs 'bundle install' and caches installed gems automatically diff --git a/.rubocop.yml b/.rubocop.yml index bb0a941..63c3ce1 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,7 +1,7 @@ inherit_from: .rubocop_todo.yml AllCops: - TargetRubyVersion: 2.6 + TargetRubyVersion: 3.1 NewCops: enable Style/NumericPredicate: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 6c8109c..40eed2d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,27 +1,33 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2018-01-11 16:42:16 -0800 using RuboCop version 0.52.1. +# on 2024-04-08 19:36:04 UTC using RuboCop version 1.63.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. +# Offense count: 7 +# Configuration parameters: EnforcedStyle, AllowedGems, Include. +# SupportedStyles: Gemfile, gems.rb, gemspec +# Include: **/*.gemspec, **/Gemfile, **/gems.rb +Gemspec/DevelopmentDependencies: + Exclude: + - 'pathspec.gemspec' + # Offense count: 2 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). Layout/BlockEndNewline: Exclude: - 'spec/unit/pathspec_spec.rb' # Offense count: 6 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: auto_detection, squiggly, active_support, powerpack, unindent +# This cop supports safe autocorrection (--autocorrect). Layout/HeredocIndentation: Exclude: - 'spec/unit/pathspec_spec.rb' # Offense count: 8 -# Cop supports --auto-correct. +# This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. # SupportedStyles: space, no_space # SupportedStylesForEmptyBraces: space, no_space @@ -30,39 +36,37 @@ Layout/SpaceInsideBlockBraces: - 'lib/pathspec.rb' - 'spec/unit/pathspec_spec.rb' -# Offense count: 2 -Lint/ImplicitStringConcatenation: - Exclude: - - 'lib/pathspec/gitignorespec.rb' - # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. Lint/UnusedMethodArgument: Exclude: - 'lib/pathspec/spec.rb' # Offense count: 3 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AutoCorrect. Lint/UselessAssignment: Exclude: - 'spec/unit/pathspec_spec.rb' -# Offense count: 2 +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AutoCorrect, CheckForMethodsWithNoSideEffects. Lint/Void: Exclude: - 'lib/pathspec.rb' - - 'lib/pathspec/gitignorespec.rb' # Offense count: 3 +# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: - Enabled: false - Max: 62 + Max: 63 -# Offense count: 7 -# Configuration parameters: CountComments, ExcludedMethods. +# Offense count: 8 +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. +# AllowedMethods: refine Metrics/BlockLength: - Enabled: false - Max: 270 + Max: 300 # Offense count: 2 # Configuration parameters: CountBlocks. @@ -70,62 +74,40 @@ Metrics/BlockNesting: Max: 4 # Offense count: 1 -# Configuration parameters: CountComments. +# Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 146 + Max: 123 -# Offense count: 2 +# Offense count: 1 +# Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/CyclomaticComplexity: - Max: 26 + Max: 18 # Offense count: 3 -# Configuration parameters: CountComments. +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: - Max: 77 + Max: 69 # Offense count: 2 +# Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/PerceivedComplexity: - Max: 32 + Max: 31 # Offense count: 25 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods. -# SupportedStyles: line_count_based, semantic, braces_for_chaining +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. +# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object # FunctionalMethods: let, let!, subject, watch -# IgnoredMethods: lambda, proc, it +# AllowedMethods: lambda, proc, it Style/BlockDelimiters: Exclude: - 'spec/unit/pathspec_spec.rb' -# Offense count: 11 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyle. -# SupportedStyles: when_needed, always, never -Style/FrozenStringLiteralComment: - Exclude: - - 'Gemfile' - - 'Rakefile' - - 'lib/pathspec.rb' - - 'lib/pathspec/gitignorespec.rb' - - 'lib/pathspec/regexspec.rb' - - 'lib/pathspec/spec.rb' - - 'pathspec.gemspec' - - 'spec/spec_helper.rb' - - 'spec/unit/pathspec/gitignorespec_spec.rb' - - 'spec/unit/pathspec/spec_spec.rb' - - 'spec/unit/pathspec_spec.rb' - # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: IgnoredMethods. -# IgnoredMethods: respond_to, define_method +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. +# AllowedMethods: define_method Style/SymbolProc: Exclude: - 'lib/pathspec.rb' - -# Offense count: 7 -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. -# URISchemes: http, https -Layout/LineLength: - Max: 108 diff --git a/Gemfile b/Gemfile index fa75df1..7f4f5e9 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + source 'https://rubygems.org' gemspec diff --git a/Rakefile b/Rakefile index b09e579..ab05425 100644 --- a/Rakefile +++ b/Rakefile @@ -1,3 +1,5 @@ +# frozen_string_literal: true + begin require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) diff --git a/lib/pathspec.rb b/lib/pathspec.rb index 9cd4b14..4f468ab 100644 --- a/lib/pathspec.rb +++ b/lib/pathspec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'pathspec/gitignorespec' require 'pathspec/regexspec' require 'find' diff --git a/lib/pathspec/gitignorespec.rb b/lib/pathspec/gitignorespec.rb index 38e2a25..7eb595c 100644 --- a/lib/pathspec/gitignorespec.rb +++ b/lib/pathspec/gitignorespec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'pathspec/regexspec' class PathSpec @@ -87,7 +89,7 @@ def initialize(original_pattern) # rubocop:disable Metrics/CyclomaticComplexity end # Build regular expression from pattern. - regex = '^' + regex = +'^' need_slash = false regex_end = pattern_segs.size - 1 pattern_segs.each_index do |i| @@ -165,7 +167,7 @@ def translate_segment_glob(pattern) # the POSIX function `fnmatch()` with the `FNM_PATHNAME` flag set. escape = false - regex = '' + regex = +'' i = 0 while i < pattern.size diff --git a/lib/pathspec/regexspec.rb b/lib/pathspec/regexspec.rb index 46b7e44..521c192 100644 --- a/lib/pathspec/regexspec.rb +++ b/lib/pathspec/regexspec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'pathspec/spec' class PathSpec diff --git a/lib/pathspec/spec.rb b/lib/pathspec/spec.rb index 812d69d..1181684 100644 --- a/lib/pathspec/spec.rb +++ b/lib/pathspec/spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class PathSpec # Abstract spec class Spec diff --git a/pathspec.gemspec b/pathspec.gemspec index 7d81b12..f6a8eee 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -1,3 +1,5 @@ +# frozen_string_literal: true + lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) @@ -8,10 +10,9 @@ Gem::Specification.new do |s| s.description = 'Use to match path patterns such as gitignore' s.authors = ['Brandon High'] s.email = 'highb@users.noreply.github.com' - s.files = Dir.glob('{lib,spec,docs}/**/*') + %w[LICENSE README.md CHANGELOG.md] + s.files = Dir.glob('{lib,docs}/**/*') + %w[LICENSE README.md CHANGELOG.md] s.bindir = 'bin' s.executables << 'pathspec-rb' - s.test_files = s.files.grep(%r{^spec/}) s.require_paths = ['lib'] s.metadata['allowed_push_host'] = 'https://rubygems.org' s.metadata['rubygems_mfa_required'] = 'true' @@ -19,10 +20,10 @@ Gem::Specification.new do |s| s.license = 'Apache-2.0' s.required_ruby_version = '>= 3.1.0' s.add_development_dependency 'bundler', '~> 2.2' - s.add_development_dependency 'fakefs', '~> 1.3' + s.add_development_dependency 'fakefs', '~> 2.5' s.add_development_dependency 'kramdown', '~> 2.3' s.add_development_dependency 'rake', '~> 13.0' s.add_development_dependency 'rspec', '~> 3.10' - s.add_development_dependency 'rubocop', '~> 1.7' + s.add_development_dependency 'rubocop', '~> 1.63.0' s.add_development_dependency 'simplecov', '~> 0.21' end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3ae0c3b..4da3bd2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + begin require 'simplecov' SimpleCov.start diff --git a/spec/unit/pathspec/gitignorespec_spec.rb b/spec/unit/pathspec/gitignorespec_spec.rb index edea99c..b2cdeda 100644 --- a/spec/unit/pathspec/gitignorespec_spec.rb +++ b/spec/unit/pathspec/gitignorespec_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'pathspec/gitignorespec' diff --git a/spec/unit/pathspec/spec_spec.rb b/spec/unit/pathspec/spec_spec.rb index 7a9059e..e1cf0ac 100644 --- a/spec/unit/pathspec/spec_spec.rb +++ b/spec/unit/pathspec/spec_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'pathspec/spec' diff --git a/spec/unit/pathspec_spec.rb b/spec/unit/pathspec_spec.rb index 8a27ca0..f079fe1 100644 --- a/spec/unit/pathspec_spec.rb +++ b/spec/unit/pathspec_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' require 'fakefs/safe' require 'pathspec' From ed1437d66b09ea8c7e13443fa109cf4d4e123008 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Tue, 9 Apr 2024 17:44:09 -0700 Subject: [PATCH 54/70] build: Prep 2.1.0 release, fill in CHANGELOG gaps. (#51) Co-authored-by: Brandon High <759848+highb@users.noreply.github.com> --- CHANGELOG.md | 41 ++++++++++++++++++++++++++++++++++++++++- pathspec.gemspec | 2 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b6fe95..6b4ced6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,52 @@ # pathspec-ruby CHANGELOG +## 2.1.0 + +## refactor/perf + +- Add missing frozen_string_literal comments to reduce object allocations + +## build + +- Updated Rubocop to 1.18.3 +- Fixed/re-enabled Rubocop +- Updated fakefs to 1.3 +- Cleaned up unnecessary spec files from the Gem + +Thanks for the above contributions @ericproulx! #50 + ## 2.0.0 - (Maint) Remove deprecated/security release versions of Ruby. The Gem will now only support and be tested against >= 3.1.0 e.g. 3.1, 3.2, and 3.3. +## 1.1.3 (Patch/Bug Fix Release) + +- Fixed Man page generation bug in GH Actions + +## 1.1.1 (Patch/Bug Fix Release) + +- (Maint) Updated Supported Ruby Versions (>= 2.6.9 is the earliest supported now) +- (Maint) Linting corrections +- Setup a CI system with GH Actions to do better validation of the gem before release. + ## 1.1.0 (Minor Release) +:alert: This release was mis-tagged. Use 1.1.1 instead. :alert: + - (Maint) Updated Supported Ruby Versions - (Maint) Linting corrections -## Undocumented Releases (Sorry!) +## 1.0.0 (Major Release) + +- Adds a required ruby version of 2.6 (reason for major version bump) +- Adds man/html docs + +## 0.2.1 (Patch/Bug Fix Release) + +- Fixes incorrectly pushed gem on Rubygems.org ## 0.2.0 (Minor Release) + - (Feature) A CLI tool, pathspec-rb, is now provided with the gem. - (API Change) New namespace for gem: `PathSpec`: Everything is now namespaced under `PathSpec`, to prevent naming collisions with other libraries. Thanks @tenderlove! - (License) License version updated to Apache 2. Thanks @kytrinyx! @@ -20,20 +55,24 @@ - (Maint) Added Rubocop and made some corrections ## 0.1.2 (Patch/Bug Fix Release) + - Fix for regexp matching Thanks @incase! #16 - File handling cleanup Thanks @martinandert! #13 - `from_filename` actually works now! Thanks @martinandert! #12 ## 0.1.0 (Minor Release) + - Port new edgecase handling from [python-path-specification](https://github.com/cpburnz/python-path-specification/pull/8). Many thanks to @jdpace! :) - Removed EOL Ruby support - Added current Ruby stable to Travis testing ## 0.0.2 (Patch/Bug Fix Release) + - Fixed issues with Ruby 1.8.7/2.1.1 - Added more testing scripts - Fixed Windows path related issues - Cleanup unnecessary things in gem ## 0.0.1 + - Initial version. diff --git a/pathspec.gemspec b/pathspec.gemspec index f6a8eee..0c0827d 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |s| s.name = 'pathspec' - s.version = '2.0.0' + s.version = '2.1.0' s.summary = 'PathSpec: for matching path patterns' s.description = 'Use to match path patterns such as gitignore' s.authors = ['Brandon High'] From 2ff376a550c63699873c7dfb13530dad2a7248ab Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 11:10:38 -0800 Subject: [PATCH 55/70] chore(deps): update actions/checkout action to v5 (#54) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/gem-push.yml | 2 +- .github/workflows/ruby.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 891d491..7e14395 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -15,7 +15,7 @@ jobs: packages: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Ruby 3.1 uses: ruby/setup-ruby@v1 with: diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index bff8253..7f59877 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -20,7 +20,7 @@ jobs: matrix: ruby-version: ['3.1', '3.2', '3.3'] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: @@ -38,7 +38,7 @@ jobs: ruby-version: ['3.1', '3.2', '3.3'] raketasks: ['rubocop', 'spec', 'docs'] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: From 897619a2091aa2e63ab423666efbb582f53da824 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 20 Nov 2025 13:34:35 -0800 Subject: [PATCH 56/70] chore(deps): update actions/checkout action to v6 (#55) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/gem-push.yml | 2 +- .github/workflows/ruby.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 7e14395..8043a30 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -15,7 +15,7 @@ jobs: packages: write steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Set up Ruby 3.1 uses: ruby/setup-ruby@v1 with: diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 7f59877..6d43f67 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -20,7 +20,7 @@ jobs: matrix: ruby-version: ['3.1', '3.2', '3.3'] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: @@ -38,7 +38,7 @@ jobs: ruby-version: ['3.1', '3.2', '3.3'] raketasks: ['rubocop', 'spec', 'docs'] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: From effa2b348ebf38ca32e14f06f926b05a508efcff Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:47:37 -0800 Subject: [PATCH 57/70] build: Update to Ruby 3.2+ and prep for 3.0.0 release Remove Ruby 3.1 (EOL March 2025) from testing matrix and update minimum required version to >= 3.2.0. Add Ruby 3.4 to testing matrix and document planned Ruby 4.0 support. Add comprehensive "Deprecated Rubies" section to README documenting historical deprecations. Update CHANGELOG for 3.0.0 release. Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/gem-push.yml | 4 ++-- .github/workflows/ruby.yml | 4 ++-- CHANGELOG.md | 15 +++++++++++++++ README.md | 13 ++++++++++++- pathspec.gemspec | 2 +- 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 8043a30..d7c4d72 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -16,10 +16,10 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Set up Ruby 3.1 + - name: Set up Ruby 3.4 uses: ruby/setup-ruby@v1 with: - ruby-version: '3.1' + ruby-version: '3.4' bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: Generate man page diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 6d43f67..6d9ca25 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['3.1', '3.2', '3.3'] + ruby-version: ['3.2', '3.3', '3.4', '4.0.1'] steps: - uses: actions/checkout@v6 - name: Set up Ruby @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['3.1', '3.2', '3.3'] + ruby-version: ['3.2', '3.3', '3.4', '4.0.1'] raketasks: ['rubocop', 'spec', 'docs'] steps: - uses: actions/checkout@v6 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b4ced6..18195ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # pathspec-ruby CHANGELOG +## 3.0.0 (Major Release) + +### Breaking Changes + +- (Maint) Remove Ruby 3.1 support (EOL March 2025). The Gem now requires >= 3.2.0 +- Updated minimum required Ruby version in gemspec from >= 3.1.0 to >= 3.2.0 + +### Maintenance + +- Added Ruby 3.4 to testing matrix (Stable, Tested) +- Added Ruby 4.0.1 to testing matrix (Preview, Tested) +- Updated CI workflows to use Ruby 3.4 for gem publishing +- Updated README with comprehensive "Deprecated Rubies" section documenting historical deprecations +- Updated "Supported Rubies" section in README to reflect current testing matrix (3.2, 3.3, 3.4, 4.0.1) + ## 2.1.0 ## refactor/perf diff --git a/README.md b/README.md index 76686a8..ea576b5 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,20 @@ [Supported Rubies](https://www.ruby-lang.org/en/downloads/): -- 3.1 (Stable, Tested) - 3.2 (Stable, Tested) - 3.3 (Stable, Tested) +- 3.4 (Stable, Tested) +- 4.0.1 (Preview, Tested) + +## Deprecated Rubies + +The following Ruby versions are no longer supported. If you need to use an older Ruby version, please use an earlier version of this gem: + +- Ruby 3.1: Deprecated in version 3.0.0 (current project, not yet released) +- Ruby 3.0: Deprecated in version 2.0.0 (January 2024) +- Ruby 2.x (2.6-2.7): Deprecated in version 2.0.0 (January 2024) +- Ruby 2.5 and earlier: Deprecated in version 1.0.0 (January 2021) +- Ruby 1.8 and 1.9: Deprecated in version 0.2.0 (circa 2017) Match Path Specifications, such as .gitignore, in Ruby! diff --git a/pathspec.gemspec b/pathspec.gemspec index 0c0827d..be12ed5 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -18,7 +18,7 @@ Gem::Specification.new do |s| s.metadata['rubygems_mfa_required'] = 'true' s.homepage = 'https://github.com/highb/pathspec-ruby' s.license = 'Apache-2.0' - s.required_ruby_version = '>= 3.1.0' + s.required_ruby_version = '>= 3.2.0' s.add_development_dependency 'bundler', '~> 2.2' s.add_development_dependency 'fakefs', '~> 2.5' s.add_development_dependency 'kramdown', '~> 2.3' From 30abf091881af16feeec1198d9571e6e003b254d Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:52:55 -0800 Subject: [PATCH 58/70] build: Update bundler requirement to support Ruby 3.2-4.0 Update bundler dependency from ~> 2.2 to >= 2.5 to ensure compatibility with Ruby 3.2, 3.3, 3.4, and 4.0. Co-Authored-By: Claude Sonnet 4.5 --- pathspec.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathspec.gemspec b/pathspec.gemspec index be12ed5..e98aa88 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.homepage = 'https://github.com/highb/pathspec-ruby' s.license = 'Apache-2.0' s.required_ruby_version = '>= 3.2.0' - s.add_development_dependency 'bundler', '~> 2.2' + s.add_development_dependency 'bundler', '>= 2.5' s.add_development_dependency 'fakefs', '~> 2.5' s.add_development_dependency 'kramdown', '~> 2.3' s.add_development_dependency 'rake', '~> 13.0' From c56a4c421ad580cb163c653fad10a35ae07e2039 Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:54:29 -0800 Subject: [PATCH 59/70] build: Relax bundler requirement to min 2.4.19 to support ruby 3.2 --- pathspec.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathspec.gemspec b/pathspec.gemspec index e98aa88..9080858 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.homepage = 'https://github.com/highb/pathspec-ruby' s.license = 'Apache-2.0' s.required_ruby_version = '>= 3.2.0' - s.add_development_dependency 'bundler', '>= 2.5' + s.add_development_dependency 'bundler', '>= 2.4.19' s.add_development_dependency 'fakefs', '~> 2.5' s.add_development_dependency 'kramdown', '~> 2.3' s.add_development_dependency 'rake', '~> 13.0' From 26a97ef7d4f0c71f6f9a59f3c4c73e1da71e6685 Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:04:48 -0800 Subject: [PATCH 60/70] build: Add mise tooling and test matrix support - Update .tool-versions to Ruby 3.4.1 and bundler 2.6.3 - Add .mise.toml with tool definitions and task runners - Add test_matrix rake task to run tests across all Ruby versions in Docker - Document mise setup and development workflow in README This enables developers to easily test across Ruby 3.2, 3.3, 3.4, and 4.0.1 locally using Docker, matching the CI environment. Co-Authored-By: Claude Sonnet 4.5 --- .mise.toml | 23 +++++++++++++++++++++++ .tool-versions | 3 ++- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ Rakefile | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 .mise.toml diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 0000000..9691ada --- /dev/null +++ b/.mise.toml @@ -0,0 +1,23 @@ +[tools] +ruby = "3.4.1" +bundler = "2.6.3" + +[tasks.install] +run = "bundle install" +description = "Install gem dependencies" + +[tasks.test] +run = "bundle exec rake" +description = "Run rubocop, specs, and docs" + +[tasks."test:matrix"] +run = "bundle exec rake test_matrix" +description = "Run tests across all Ruby versions in Docker" + +[tasks.build] +run = "gem build pathspec.gemspec" +description = "Build the gem" + +[env] +# Ensure bundler uses the project's vendor/bundle directory +_.file = ".env" diff --git a/.tool-versions b/.tool-versions index 3294aed..1606afa 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1,2 @@ -ruby 3.3.0 +ruby 3.4.1 +bundler 2.6.3 diff --git a/README.md b/README.md index ea576b5..0800ad3 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,56 @@ git clone git@github.com:highb/pathspec-ruby.git cd pathspec-ruby && bash ./build_from_source.sh ``` +## Development Setup + +This project uses [mise](https://mise.jdx.dev/) for managing Ruby and bundler versions. + +### Install mise + +```shell +# macOS +brew install mise + +# Other platforms: https://mise.jdx.dev/getting-started.html +``` + +### Activate mise + +Add to your shell profile (`~/.zshrc`, `~/.bashrc`, etc.): + +```shell +eval "$(mise activate zsh)" # or bash, fish, etc. +``` + +### Install Dependencies + +```shell +# Install Ruby and bundler versions defined in .tool-versions +mise install + +# Install gem dependencies +mise run install +# or: bundle install +``` + +### Development Tasks + +```shell +# Run all tests (rubocop, rspec, docs) +mise run test +# or: bundle exec rake + +# Run tests across all Ruby versions (3.2, 3.3, 3.4, 4.0.1) using Docker +mise run test:matrix +# or: bundle exec rake test_matrix + +# Build the gem +mise run build +# or: gem build pathspec.gemspec +``` + +The `test:matrix` task runs the full test suite across all supported Ruby versions in Docker containers, matching the CI environment. + ## Contributing Pull requests, bug reports, and feature requests welcome! :smile: I've tried to write exhaustive tests but who knows what cases I've missed. diff --git a/Rakefile b/Rakefile index ab05425..a8e9873 100644 --- a/Rakefile +++ b/Rakefile @@ -26,3 +26,38 @@ task :docs do FileUtils.mkdir_p 'docs/man' File.write('docs/man/pathspec-rb.man.1', kramdown.to_man) end + +desc 'Run tests across all Ruby versions using Docker' +task :test_matrix do + ruby_versions = ['3.2', '3.3', '3.4', '4.0.1'] + failed_versions = [] + + ruby_versions.each do |version| + puts "\n#{'=' * 80}" + puts "Testing with Ruby #{version}" + puts '=' * 80 + + cmd = [ + 'docker', 'run', '--rm', + '-v', "#{Dir.pwd}:/app", + '-w', '/app', + "ruby:#{version}", + 'bash', '-c', + 'bundle install && bundle exec rake rubocop spec docs' + ].shelljoin + + success = system(cmd) + failed_versions << version unless success + end + + if failed_versions.any? + puts "\n#{'=' * 80}" + puts "FAILED on Ruby versions: #{failed_versions.join(', ')}" + puts '=' * 80 + exit 1 + else + puts "\n#{'=' * 80}" + puts 'All Ruby versions passed!' + puts '=' * 80 + end +end From 846aca4339f558203517fa7004b9fd6ba66ded05 Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:05:41 -0800 Subject: [PATCH 61/70] build: Add irb as development dependency for Ruby 4.0 IRB was removed from Ruby 4.0's default gems and must be explicitly declared as a dependency. This fixes the LoadError when fakefs tries to load irb. Co-Authored-By: Claude Sonnet 4.5 --- pathspec.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/pathspec.gemspec b/pathspec.gemspec index 9080858..07a39c6 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 3.2.0' s.add_development_dependency 'bundler', '>= 2.4.19' s.add_development_dependency 'fakefs', '~> 2.5' + s.add_development_dependency 'irb', '~> 1.14' s.add_development_dependency 'kramdown', '~> 2.3' s.add_development_dependency 'rake', '~> 13.0' s.add_development_dependency 'rspec', '~> 3.10' From 7738fe645873707ca34a5da5d8487c2f8c112635 Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:11:46 -0800 Subject: [PATCH 62/70] build: mise fixups --- .mise.toml | 1 - .tool-versions | 1 - 2 files changed, 2 deletions(-) diff --git a/.mise.toml b/.mise.toml index 9691ada..9fcd12a 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,6 +1,5 @@ [tools] ruby = "3.4.1" -bundler = "2.6.3" [tasks.install] run = "bundle install" diff --git a/.tool-versions b/.tool-versions index 1606afa..041df9a 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,2 +1 @@ ruby 3.4.1 -bundler 2.6.3 From 2208cab032d32a310666023bcbb716b43bb052ad Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:29:44 -0800 Subject: [PATCH 63/70] build: Fix RuboCop linting issues - Update TargetRubyVersion to 3.2 to match required_ruby_version - Move duplicate puts statement out of conditional branches in test_matrix task Co-Authored-By: Claude Sonnet 4.5 --- .rubocop.yml | 2 +- Rakefile | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 63c3ce1..47260ef 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,7 +1,7 @@ inherit_from: .rubocop_todo.yml AllCops: - TargetRubyVersion: 3.1 + TargetRubyVersion: 3.2 NewCops: enable Style/NumericPredicate: diff --git a/Rakefile b/Rakefile index a8e9873..367d3f3 100644 --- a/Rakefile +++ b/Rakefile @@ -50,13 +50,12 @@ task :test_matrix do failed_versions << version unless success end + puts "\n#{'=' * 80}" if failed_versions.any? - puts "\n#{'=' * 80}" puts "FAILED on Ruby versions: #{failed_versions.join(', ')}" puts '=' * 80 exit 1 else - puts "\n#{'=' * 80}" puts 'All Ruby versions passed!' puts '=' * 80 end From 9d2468aa8f5771d43134936c306828c0ee12fa2f Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:47:04 -0800 Subject: [PATCH 64/70] test: Add comprehensive CLI integration tests for 3.0.0 release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add complete integration test coverage for the pathspec-rb CLI executable with 23 tests covering all commands, flags, and error conditions. Changes: - Add spec/integration/cli_spec.rb with 23 integration tests - Test all subcommands: match, specs_match, tree - Test all flags: -f/--file, -t/--type, -v/--verbose - Test error handling: missing files, unknown commands - Test exit codes: 0 (success), 1 (no match), 2 (error) - Test negated patterns and default .gitignore behavior - Add match? predicate alias to PathSpec#match for Ruby conventions - Update Rakefile with separate test tasks: - spec: Run unit tests only - spec_integration: Run integration tests only - spec_all: Run all tests with unified coverage - Update default task to include integration tests - Update CI workflow to run integration tests across all Ruby versions - Update .mise.toml: - Fix bundler to use gem backend: "gem:bundler" - Add granular test tasks (test:unit, test:integration, test:all) - Update README with new test tasks and development workflows - Update CHANGELOG.md for 3.0.0 release: - Document all new features and improvements - Note bundler and irb dependency updates - Document test coverage improvement: 99.48% → 99.65% Test Results: - 248 total tests passing (225 unit + 23 integration) - Coverage: 99.65% (573/575 lines) - All tests pass on Ruby 3.4.1 Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/ruby.yml | 2 +- .mise.toml | 15 ++- CHANGELOG.md | 18 +++ README.md | 16 ++- Rakefile | 17 ++- lib/pathspec.rb | 1 + spec/integration/cli_spec.rb | 217 +++++++++++++++++++++++++++++++++++ 7 files changed, 279 insertions(+), 7 deletions(-) create mode 100644 spec/integration/cli_spec.rb diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index 6d9ca25..f0cba33 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -36,7 +36,7 @@ jobs: strategy: matrix: ruby-version: ['3.2', '3.3', '3.4', '4.0.1'] - raketasks: ['rubocop', 'spec', 'docs'] + raketasks: ['rubocop', 'spec', 'spec_integration', 'docs'] steps: - uses: actions/checkout@v6 - name: Set up Ruby diff --git a/.mise.toml b/.mise.toml index 9fcd12a..bf9161a 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,5 +1,6 @@ [tools] ruby = "3.4.1" +"gem:bundler" = "2.6.3" [tasks.install] run = "bundle install" @@ -7,7 +8,19 @@ description = "Install gem dependencies" [tasks.test] run = "bundle exec rake" -description = "Run rubocop, specs, and docs" +description = "Run rubocop, unit tests, integration tests, and docs" + +[tasks."test:unit"] +run = "bundle exec rake spec" +description = "Run unit tests only" + +[tasks."test:integration"] +run = "bundle exec rake spec_integration" +description = "Run integration tests only" + +[tasks."test:all"] +run = "bundle exec rake spec_all" +description = "Run all tests (unit + integration)" [tasks."test:matrix"] run = "bundle exec rake test_matrix" diff --git a/CHANGELOG.md b/CHANGELOG.md index 18195ba..3ddc285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,13 +7,31 @@ - (Maint) Remove Ruby 3.1 support (EOL March 2025). The Gem now requires >= 3.2.0 - Updated minimum required Ruby version in gemspec from >= 3.1.0 to >= 3.2.0 +### Features + +- Added `match?` predicate method as alias for `match` to follow Ruby conventions +- Added comprehensive CLI integration test suite (23 tests covering all commands, flags, and error handling) +- Added mise (formerly rtx) tooling support for managing Ruby and bundler versions +- Added `test_matrix` rake task to run tests across all Ruby versions (3.2, 3.3, 3.4, 4.0.1) using Docker +- Separated unit tests (`rake spec`) and integration tests (`rake spec_integration`) +- Added `spec_all` rake task to run complete test suite with unified coverage reporting + ### Maintenance - Added Ruby 3.4 to testing matrix (Stable, Tested) - Added Ruby 4.0.1 to testing matrix (Preview, Tested) - Updated CI workflows to use Ruby 3.4 for gem publishing +- Updated CI to run integration tests across all Ruby versions +- Updated bundler requirement from `~> 2.2` to `>= 2.5` for Ruby 3.2-4.0 compatibility +- Added `irb` as development dependency (required for Ruby 4.0+) +- Updated RuboCop TargetRubyVersion to 3.2 to match gemspec requirement +- Updated README with comprehensive development setup documentation + - mise installation and usage + - Development tasks and workflows + - Testing across Ruby version matrix - Updated README with comprehensive "Deprecated Rubies" section documenting historical deprecations - Updated "Supported Rubies" section in README to reflect current testing matrix (3.2, 3.3, 3.4, 4.0.1) +- Improved test coverage from 99.48% to 99.65% (573/575 lines) ## 2.1.0 diff --git a/README.md b/README.md index 0800ad3..5d4e094 100644 --- a/README.md +++ b/README.md @@ -160,10 +160,22 @@ mise run install ### Development Tasks ```shell -# Run all tests (rubocop, rspec, docs) +# Run all tests (rubocop, unit tests, integration tests, docs) mise run test # or: bundle exec rake +# Run only unit tests +mise run test:unit +# or: bundle exec rake spec + +# Run only integration tests +mise run test:integration +# or: bundle exec rake spec_integration + +# Run all specs (unit + integration) +mise run test:all +# or: bundle exec rake spec_all + # Run tests across all Ruby versions (3.2, 3.3, 3.4, 4.0.1) using Docker mise run test:matrix # or: bundle exec rake test_matrix @@ -173,7 +185,7 @@ mise run build # or: gem build pathspec.gemspec ``` -The `test:matrix` task runs the full test suite across all supported Ruby versions in Docker containers, matching the CI environment. +The `test:matrix` task runs the full test suite across all supported Ruby versions in Docker containers, matching the CI environment. Integration tests cover the CLI executable (`bin/pathspec-rb`). ## Contributing diff --git a/Rakefile b/Rakefile index 367d3f3..094ff01 100644 --- a/Rakefile +++ b/Rakefile @@ -2,7 +2,18 @@ begin require 'rspec/core/rake_task' - RSpec::Core::RakeTask.new(:spec) + + RSpec::Core::RakeTask.new(:spec) do |t| + t.pattern = 'spec/unit/**/*_spec.rb' + end + + RSpec::Core::RakeTask.new(:spec_integration) do |t| + t.pattern = 'spec/integration/**/*_spec.rb' + end + + RSpec::Core::RakeTask.new(:spec_all) do |t| + t.pattern = 'spec/**/*_spec.rb' + end rescue LoadError puts 'rspec rake task failed to load' end @@ -15,7 +26,7 @@ RuboCop::RakeTask.new(:rubocop) do |t| t.options = ['--display-cop-names'] end -task default: %i[rubocop spec docs] +task default: %i[rubocop spec spec_integration docs] desc 'Generate man page for executable script' task :docs do @@ -43,7 +54,7 @@ task :test_matrix do '-w', '/app', "ruby:#{version}", 'bash', '-c', - 'bundle install && bundle exec rake rubocop spec docs' + 'bundle install && bundle exec rake rubocop spec spec_integration docs' ].shelljoin success = system(cmd) diff --git a/lib/pathspec.rb b/lib/pathspec.rb index 4f468ab..b1bf47f 100644 --- a/lib/pathspec.rb +++ b/lib/pathspec.rb @@ -24,6 +24,7 @@ def match(path) matches = specs_matching(path.to_s) !matches.empty? && matches.all? {|m| m.inclusive?} end + alias match? match def specs_matching(path) @specs.select do |spec| diff --git a/spec/integration/cli_spec.rb b/spec/integration/cli_spec.rb new file mode 100644 index 0000000..8e6fc56 --- /dev/null +++ b/spec/integration/cli_spec.rb @@ -0,0 +1,217 @@ +# frozen_string_literal: true + +require 'spec_helper' +require 'open3' +require 'tmpdir' + +describe 'pathspec-rb CLI' do + let(:cli_path) { File.expand_path('../../bin/pathspec-rb', __dir__) } + let(:lib_path) { File.expand_path('../../lib', __dir__) } + let(:gitignore_simple) { File.expand_path('../files/gitignore_simple', __dir__) } + let(:gitignore_readme) { File.expand_path('../files/gitignore_readme', __dir__) } + let(:regex_simple) { File.expand_path('../files/regex_simple', __dir__) } + + def run_cli(*args) + env = { 'RUBYLIB' => lib_path } + stdout, stderr, status = Open3.capture3(env, 'ruby', cli_path, *args) + [stdout, stderr, status] + end + + describe 'help and errors' do + it 'shows help when no arguments provided' do + stdout, _stderr, status = run_cli + expect(stdout).to include('Usage: pathspec-rb') + expect(stdout).to include('Subcommands:') + expect(stdout).to include('specs_match') + expect(stdout).to include('tree') + expect(stdout).to include('match') + expect(status.exitstatus).to eq(2) + end + + it 'shows error for unreadable file' do + stdout, _stderr, status = run_cli('-f', '/nonexistent/file', 'match', 'test.txt') + expect(stdout).to include("Error: I couldn't read /nonexistent/file") + expect(status.exitstatus).to eq(2) + end + + it 'shows error for unknown subcommand' do + stdout, _stderr, status = run_cli('-f', gitignore_simple, 'unknown_command', 'test.txt') + expect(stdout).to include('Unknown sub-command unknown_command') + expect(stdout).to include('Usage: pathspec-rb') + expect(status.exitstatus).to eq(2) + end + end + + describe 'match subcommand' do + context 'with matching path' do + it 'exits with 0' do + _stdout, _stderr, status = run_cli('-f', gitignore_simple, 'match', 'test.md') + expect(status.exitstatus).to eq(0) + end + + it 'shows match message with verbose flag' do + stdout, _stderr, status = run_cli('-f', gitignore_simple, '-v', 'match', 'test.md') + expect(stdout).to include('test.md matches a spec') + expect(status.exitstatus).to eq(0) + end + end + + context 'with non-matching path' do + it 'exits with 1' do + _stdout, _stderr, status = run_cli('-f', gitignore_simple, 'match', 'other.txt') + expect(status.exitstatus).to eq(1) + end + + it 'shows no match message with verbose flag' do + stdout, _stderr, status = run_cli('-f', gitignore_simple, '-v', 'match', 'other.txt') + expect(stdout).to include('other.txt does not match') + expect(status.exitstatus).to eq(1) + end + end + + context 'with negated pattern' do + it 'does not match negated paths' do + _stdout, _stderr, status = run_cli('-f', gitignore_readme, 'match', 'abc/important.txt') + expect(status.exitstatus).to eq(1) + end + + it 'matches non-negated paths' do + _stdout, _stderr, status = run_cli('-f', gitignore_readme, 'match', 'abc/other.txt') + expect(status.exitstatus).to eq(0) + end + end + end + + describe 'specs_match subcommand' do + context 'with matching path' do + it 'exits with 0 and shows matching specs' do + stdout, _stderr, status = run_cli('-f', gitignore_readme, 'specs_match', 'abc/def.rb') + expect(stdout).to include('abc/**') + expect(status.exitstatus).to eq(0) + end + + it 'shows verbose message with -v flag' do + stdout, _stderr, status = run_cli('-f', gitignore_readme, '-v', 'specs_match', 'abc/def.rb') + expect(stdout).to include('abc/def.rb matches the following specs') + expect(stdout).to include('abc/**') + expect(status.exitstatus).to eq(0) + end + end + + context 'with non-matching path' do + it 'exits with 1' do + _stdout, _stderr, status = run_cli('-f', gitignore_readme, 'specs_match', 'xyz/file.txt') + expect(status.exitstatus).to eq(1) + end + + it 'shows no match message with verbose flag' do + stdout, _stderr, status = run_cli('-f', gitignore_readme, '-v', 'specs_match', 'xyz/file.txt') + expect(stdout).to include('xyz/file.txt does not match any specs') + expect(status.exitstatus).to eq(1) + end + end + end + + describe 'tree subcommand' do + around do |example| + Dir.mktmpdir do |temp_dir| + @temp_dir = temp_dir + example.run + end + end + + before do + # Create test directory structure + FileUtils.mkdir_p(File.join(@temp_dir, 'foo')) + FileUtils.mkdir_p(File.join(@temp_dir, 'other')) + FileUtils.touch(File.join(@temp_dir, 'foo', 'test.txt')) + FileUtils.touch(File.join(@temp_dir, 'foo', 'another.txt')) + FileUtils.touch(File.join(@temp_dir, 'other', 'file.txt')) + + # Create a gitignore that matches foo/** + @temp_gitignore = File.join(@temp_dir, '.gitignore') + File.write(@temp_gitignore, "foo/**\n") + end + + context 'with matching files' do + it 'exits with 0 and lists matching files' do + stdout, _stderr, status = run_cli('-f', @temp_gitignore, 'tree', @temp_dir) + expect(stdout).to include('foo') + expect(stdout.lines.any? { |line| line.include?('other') && !line.include?('another') }).to be false + expect(status.exitstatus).to eq(0) + end + + it 'shows verbose message with -v flag' do + stdout, _stderr, status = run_cli('-f', @temp_gitignore, '-v', 'tree', @temp_dir) + expect(stdout).to include("Files in #{@temp_dir} that match") + expect(status.exitstatus).to eq(0) + end + end + + context 'with no matching files' do + before do + # Create gitignore with pattern that won't match anything + File.write(@temp_gitignore, "nomatch/**\n") + end + + it 'exits with 1' do + _stdout, _stderr, status = run_cli('-f', @temp_gitignore, 'tree', @temp_dir) + expect(status.exitstatus).to eq(1) + end + + it 'shows no match message with verbose flag' do + stdout, _stderr, status = run_cli('-f', @temp_gitignore, '-v', 'tree', @temp_dir) + expect(stdout).to include('No file') + expect(stdout).to include('matched') + expect(status.exitstatus).to eq(1) + end + end + end + + describe 'type flag' do + context 'with git type (default)' do + it 'parses gitignore patterns' do + _stdout, _stderr, status = run_cli('-f', gitignore_simple, '-t', 'git', 'match', 'test.md') + expect(status.exitstatus).to eq(0) + end + end + + context 'with regex type' do + it 'parses regex patterns' do + _stdout, _stderr, status = run_cli('-f', regex_simple, '-t', 'regex', 'match', 'foo.md') + expect(status.exitstatus).to eq(0) + end + end + end + + describe 'file flag' do + it 'uses default .gitignore when not specified' do + Dir.mktmpdir do |dir| + gitignore_path = File.join(dir, '.gitignore') + File.write(gitignore_path, "test/**\n") + + Dir.chdir(dir) do + _stdout, _stderr, status = run_cli('match', 'test/file.txt') + expect(status.exitstatus).to eq(0) + end + end + end + + it 'uses specified file with -f flag' do + _stdout, _stderr, status = run_cli('-f', gitignore_simple, 'match', 'test.md') + expect(status.exitstatus).to eq(0) + end + + it 'uses specified file with --file flag' do + _stdout, _stderr, status = run_cli('--file', gitignore_simple, 'match', 'test.md') + expect(status.exitstatus).to eq(0) + end + end + + describe 'empty string match command' do + it 'treats empty string as match command' do + _stdout, _stderr, status = run_cli('-f', gitignore_simple, '', 'test.md') + expect(status.exitstatus).to eq(0) + end + end +end From e326b42b020ec6d3871c22126609ccc339f0b907 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:49:51 -0800 Subject: [PATCH 65/70] chore(deps): update dependency gem:bundler to v4 (#58) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .mise.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mise.toml b/.mise.toml index bf9161a..3b3333f 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,6 +1,6 @@ [tools] ruby = "3.4.1" -"gem:bundler" = "2.6.3" +"gem:bundler" = "4.0.3" [tasks.install] run = "bundle install" From 8fbcc0ae405a1ec5e34ea9e08aa8c69182c1097a Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:56:16 -0800 Subject: [PATCH 66/70] chore: Update CHANGELOG for 3.0.1 version bump release Add 3.0.1 entry noting this is a version bump only release to correct the gemspec version oversight in 3.0.0. Co-Authored-By: Claude Sonnet 4.5 --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ddc285..5b48d7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # pathspec-ruby CHANGELOG +## 3.0.1 (Patch Release) + +### Note + +This is a version bump only release to correct an oversight in the 3.0.0 release where the gemspec version was not updated before publishing. The gem published as 3.0.0 on RubyGems had version 2.1.0 in the gemspec. + +For the actual feature changes and improvements, see the [3.0.0 release](https://github.com/highb/pathspec-ruby/releases/tag/3.0.0). + ## 3.0.0 (Major Release) ### Breaking Changes From 6e25ba36188c8f6642cfe7f9ac77c041950be286 Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 13:34:10 -0800 Subject: [PATCH 67/70] feat: Add performance benchmarking with pattern scaling tests - Add benchmark script testing 1-150 pattern counts - Measure single path, batch path, and initialization performance - Include comprehensive README with M4 Pro benchmark results - Add rake benchmark task and mise benchmark task - Add benchmark-ips gem dependency - Document that benchmarks are not included in CI Results show linear to super-linear degradation: - 150 patterns: 78x slower for single match, 3.7x for batch - Batch matching most efficient at ~39k paths/sec with 150 patterns - Initialization most affected (196x slower at 150 patterns) Co-Authored-By: Claude Sonnet 4.5 --- .mise.toml | 4 + Rakefile | 26 ++++ benchmarks/README.md | 158 +++++++++++++++++++++ benchmarks/pattern_scaling.rb | 255 ++++++++++++++++++++++++++++++++++ lib/pathspec/version.rb | 5 + pathspec.gemspec | 1 + 6 files changed, 449 insertions(+) create mode 100644 benchmarks/README.md create mode 100755 benchmarks/pattern_scaling.rb create mode 100644 lib/pathspec/version.rb diff --git a/.mise.toml b/.mise.toml index 3b3333f..d549a80 100644 --- a/.mise.toml +++ b/.mise.toml @@ -30,6 +30,10 @@ description = "Run tests across all Ruby versions in Docker" run = "gem build pathspec.gemspec" description = "Build the gem" +[tasks.benchmark] +run = "bundle exec rake benchmark" +description = "Run performance benchmarks (not included in CI)" + [env] # Ensure bundler uses the project's vendor/bundle directory _.file = ".env" diff --git a/Rakefile b/Rakefile index 094ff01..6e77210 100644 --- a/Rakefile +++ b/Rakefile @@ -71,3 +71,29 @@ task :test_matrix do puts '=' * 80 end end + +desc 'Run performance benchmarks (requires benchmark-ips gem)' +task :benchmark do + puts 'Running performance benchmarks...' + puts 'This may take several minutes to complete.' + puts + + benchmark_script = File.join(__dir__, 'benchmarks', 'pattern_scaling.rb') + + unless File.exist?(benchmark_script) + puts 'Error: Benchmark script not found at benchmarks/pattern_scaling.rb' + exit 1 + end + + # Check if benchmark-ips is available + begin + require 'benchmark/ips' + rescue LoadError + puts 'Error: benchmark-ips gem is not installed' + puts 'Please run: bundle install' + exit 1 + end + + # Run the benchmark script + system('ruby', benchmark_script) || exit(1) +end diff --git a/benchmarks/README.md b/benchmarks/README.md new file mode 100644 index 0000000..c35afb3 --- /dev/null +++ b/benchmarks/README.md @@ -0,0 +1,158 @@ +# PathSpec Performance Benchmarks + +This document describes the performance benchmarking methodology and results for the pathspec-ruby library. + +## Methodology + +The benchmarks measure pattern matching performance as the number of patterns increases. This is based on the approach used by [python-pathspec](https://github.com/cpburnz/python-pathspec/blob/master/benchmarks_backends.md). + +### Test Configuration + +- **Pattern counts tested**: 1, 5, 15, 25, 50, 100, 150 patterns +- **Test dataset**: 1000 representative file paths with varying directory depths and file extensions +- **Pattern types**: Mix of glob patterns, directory matches, negations, and complex wildcards +- **Warmup time**: 2 seconds per test +- **Benchmark time**: 5 seconds per test +- **Measurement**: Iterations per second (i/s) using the `benchmark-ips` gem + +### Operations Benchmarked + +1. **Single path matching**: Testing `match()` method on 10 individual paths +2. **Batch path matching**: Testing `match_paths()` method on 100 paths at once +3. **Pattern initialization**: Testing `PathSpec.new()` construction time + +### Important Notes + +- File system I/O is not tested; all paths are pre-generated in memory +- Patterns are representative of real-world `.gitignore` files +- Tests focus on GitIgnore-style patterns (the most common use case) +- Results show how performance scales with pattern complexity + +## Running Benchmarks + +To run the benchmarks on your system: + +### Using mise (recommended) + +```bash +# Run benchmarks directly +mise run benchmark +``` + +### Using rake directly + +```bash +# Install dependencies (includes benchmark-ips gem) +bundle install + +# Run benchmarks (this takes several minutes) +bundle exec rake benchmark +``` + +The benchmark task is **not** included in CI pipelines and should be run manually when needed. + +## Results + +### Hardware: Apple M4 Pro + +**Specifications:** +- Processor: Apple M4 Pro +- Cores: 12 (8 performance + 4 efficiency) +- Memory: 24 GB RAM +- OS: macOS + +**Ruby Version:** 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [arm64-darwin25] + +#### Single Path Matching Performance + +Testing 10 individual path matches per iteration. + +| Patterns | Iterations/sec | Relative to baseline | Time per iteration | +|----------|----------------|----------------------|--------------------| +| 1 | 442,619 | 1.0x | 2.26 μs | +| 5 | 109,999 | 0.25x (4x slower) | 9.09 μs | +| 15 | 50,291 | 0.11x (8.8x slower) | 19.88 μs | +| 25 | 31,099 | 0.07x (14x slower) | 32.16 μs | +| 50 | 16,539 | 0.04x (27x slower) | 60.46 μs | +| 100 | 8,361 | 0.02x (53x slower) | 119.61 μs | +| 150 | 5,659 | 0.01x (78x slower) | 176.71 μs | + +#### Batch Path Matching Performance (100 paths) + +Testing `match_paths()` with 100 paths per iteration. + +| Patterns | Iterations/sec | Relative to baseline | Time per iteration | +|----------|----------------|----------------------|--------------------| +| 1 | 1,458 | 1.0x | 686 μs | +| 5 | 1,307 | 0.90x (1.1x slower) | 765 μs | +| 15 | 1,137 | 0.78x (1.3x slower) | 879 μs | +| 25 | 1,004 | 0.69x (1.5x slower) | 996 μs | +| 50 | 775 | 0.53x (1.9x slower) | 1.29 ms | +| 100 | 518 | 0.36x (2.8x slower) | 1.93 ms | +| 150 | 392 | 0.27x (3.7x slower) | 2.55 ms | + +#### Pattern Initialization Performance + +Testing `PathSpec.new()` construction time per iteration. + +| Patterns | Iterations/sec | Relative to baseline | Time per iteration | +|----------|----------------|----------------------|--------------------| +| 1 | 285,824 | 1.0x | 3.50 μs | +| 5 | 59,726 | 0.21x (4.8x slower) | 16.74 μs | +| 15 | 18,280 | 0.06x (16x slower) | 54.71 μs | +| 25 | 10,683 | 0.04x (27x slower) | 93.60 μs | +| 50 | 5,003 | 0.02x (57x slower) | 199.88 μs | +| 100 | 2,443 | 0.01x (117x slower) | 409.33 μs | +| 150 | 1,461 | 0.01x (196x slower) | 684.60 μs | + +### Analysis + +#### Performance Scaling Characteristics + +1. **Linear to slightly super-linear degradation**: All three operations show performance degradation that's roughly proportional to pattern count, with initialization showing the steepest decline. + +2. **Operation-specific impacts**: + - **Initialization** is most affected: ~196x slower at 150 patterns (0.68ms vs 3.5μs) + - **Single path matching**: ~78x slower at 150 patterns (177μs vs 2.3μs) + - **Batch matching**: ~3.7x slower at 150 patterns (2.55ms vs 686μs) - most resilient + +3. **Practical performance thresholds**: + - **1-25 patterns**: Excellent performance for all operations (< 100μs for initialization) + - **25-50 patterns**: Still very fast, suitable for most applications + - **50-100 patterns**: Noticeable but acceptable performance (~400μs initialization) + - **100+ patterns**: May be noticeable in tight loops or high-throughput scenarios + +4. **Batch matching efficiency**: The `match_paths()` method shows the best scaling because it amortizes the pattern matching cost across multiple paths. Even with 150 patterns, it can process ~39,200 paths per second (392 iterations × 100 paths). + +5. **Initialization vs matching trade-off**: + - Single pattern initialization is very fast (3.5μs), making it viable to create PathSpec objects on-demand + - With 100+ patterns, initialization cost becomes significant (~400μs), suggesting benefits from caching PathSpec objects + - However, matching operations remain efficient enough for most use cases + +6. **Real-world implications**: + - Typical `.gitignore` files have 20-50 meaningful patterns: performance is excellent + - Large enterprise `.gitignore` files with 100+ patterns: still sub-millisecond for most operations + - For high-frequency matching (e.g., watching file systems), cache PathSpec objects rather than recreating + +## Future Enhancements + +Potential areas for future benchmarking: + +1. **Pattern Complexity**: Compare simple glob patterns vs complex regex patterns +2. **Negation Overhead**: Test performance impact of `!` negation patterns +3. **Directory vs File Patterns**: Compare performance of patterns with trailing `/` +4. **Memory Profiling**: Track memory usage as pattern count increases +5. **Real-world Files**: Test against actual large `.gitignore` files from popular projects +6. **Tree Traversal**: Benchmark `match_tree()` on directory structures of varying sizes +7. **Pattern Types**: Compare GitIgnore vs Regex pattern performance +8. **Ruby Versions**: Compare performance across Ruby 3.2, 3.3, 3.4, and 4.0 + +## Contributing + +When contributing benchmark results: + +1. Always specify your hardware details (processor, cores, memory) +2. Include Ruby version used for testing +3. Run benchmarks multiple times to verify consistency +4. Note any significant background processes that might affect results +5. Update this README with your findings diff --git a/benchmarks/pattern_scaling.rb b/benchmarks/pattern_scaling.rb new file mode 100755 index 0000000..279c372 --- /dev/null +++ b/benchmarks/pattern_scaling.rb @@ -0,0 +1,255 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'bundler/setup' +require 'benchmark/ips' +require 'pathspec' + +# Benchmark configuration +PATTERN_COUNTS = [1, 5, 15, 25, 50, 100, 150].freeze +WARMUP_TIME = 2 +BENCHMARK_TIME = 5 + +# Generate a representative set of file paths for testing +def generate_test_paths(count = 1000) + paths = [] + + # Mix of different path types + extensions = %w[.rb .txt .log .tmp .swp .md .yml .json .xml .css .js .html] + directories = ['src', 'lib', 'test', 'spec', 'config', 'docs', 'bin', 'tmp', 'coverage', 'vendor'] + + count.times do |i| + depth = rand(1..4) + parts = depth.times.map { directories.sample } + filename = "file#{i}#{extensions.sample}" + paths << File.join(*parts, filename) + end + + paths +end + +# Generate gitignore patterns of varying complexity +def generate_patterns(count) + base_patterns = [ + '*.log', + '*.tmp', + '*.swp', + 'coverage/', + 'tmp/', + 'vendor/bundle/', + '.DS_Store', + '*.gem', + 'node_modules/', + 'dist/', + 'build/', + '*.pyc', + '__pycache__/', + '.env', + '.env.local', + 'secrets.yml', + '*.sqlite3', + 'log/*.log', + 'tmp/**/*', + 'public/assets/', + '.bundle/', + 'vendor/cache/', + 'doc/', + '.yardoc/', + 'coverage/**/*', + '*.rbc', + '*.sassc', + '.sass-cache/', + 'Gemfile.lock', + '.ruby-version', + '.ruby-gemset', + '.rvmrc', + '/config/database.yml', + '/config/secrets.yml', + '/config/credentials.yml.enc', + 'npm-debug.log', + 'yarn-error.log', + '.idea/', + '*.iml', + '.vscode/', + '*.code-workspace', + '.project', + '.classpath', + '.settings/', + 'target/', + '*.class', + '*.jar', + '*.war', + 'bin/', + 'obj/', + '*.exe', + '*.dll', + '*.so', + '*.dylib', + '**/*.backup', + '**/*.bak', + '**/*.old', + '**/._*', + '**/.~lock.*', + 'test/fixtures/files/', + 'spec/fixtures/files/', + '!important.txt', + '!config/database.yml.example', + 'cache/**/*.cache', + '*.min.js', + '*.min.css', + 'dist/**/*.map', + 'vendor/**/*.js', + 'public/uploads/', + 'storage/', + '**/*.zip', + '**/*.tar.gz', + '**/*.rar', + '.git/', + '.gitignore', + '.gitmodules', + '.gitattributes', + 'Thumbs.db', + 'Desktop.ini', + '*.lnk', + '*.stackdump', + '*.pid', + '*.seed', + '*.log.*', + 'pids/', + 'logs/', + 'results/', + '.npm/', + '.eslintcache', + '.stylelintcache', + 'reports/', + '*.tsbuildinfo', + '.tox/', + '.pytest_cache/', + '.coverage', + 'htmlcov/', + '*.prof', + '*.lprof', + '*.sage.py', + 'celerybeat-schedule', + '*.mo', + '*.pot', + 'local_settings.py', + 'db.sqlite3', + 'db.sqlite3-journal', + 'media/', + 'staticfiles/', + '.webassets-cache/', + 'instance/', + '.scrapy/', + '.ipynb_checkpoints/', + '__pypackages__/', + '*.manifest', + '*.spec', + 'pip-log.txt', + 'pip-delete-this-directory.txt', + '.env.*.local', + '.cache/', + '.parcel-cache/', + '.next/', + 'out/', + '.nuxt/', + '.vuepress/dist/', + '.serverless/', + '.fusebox/', + '.dynamodb/', + '.tern-port', + '.vscode-test', + '.yarn/cache/', + '.yarn/unplugged/', + '.yarn/build-state.yml', + '.yarn/install-state.gz', + '.pnp.*' + ] + + # Return the first 'count' patterns, cycling if needed + if count <= base_patterns.length + base_patterns.take(count) + else + patterns = base_patterns.dup + remaining = count - base_patterns.length + remaining.times do |i| + patterns << "generated_pattern_#{i}/**/*" + end + patterns + end +end + +puts "PathSpec Performance Benchmark" +puts "=" * 80 +puts "Testing pattern matching performance with varying pattern counts" +puts "Hardware: Apple M4 Pro (12 cores: 8 performance + 4 efficiency), 24 GB RAM" +puts "Ruby Version: #{RUBY_VERSION}" +puts "Test Configuration:" +puts " - Pattern counts: #{PATTERN_COUNTS.join(', ')}" +puts " - Test paths: 1000 representative file paths" +puts " - Warmup time: #{WARMUP_TIME}s" +puts " - Benchmark time: #{BENCHMARK_TIME}s per test" +puts "=" * 80 +puts + +# Pre-generate test data +test_paths = generate_test_paths(1000) +puts "Generated #{test_paths.length} test paths for benchmarking\n\n" + +results = {} + +PATTERN_COUNTS.each do |pattern_count| + patterns = generate_patterns(pattern_count) + pathspec = PathSpec.new(patterns, :git) + + puts "Benchmarking with #{pattern_count} patterns..." + puts "-" * 80 + + results[pattern_count] = {} + + # Benchmark 1: Single path matching + Benchmark.ips do |x| + x.config(time: BENCHMARK_TIME, warmup: WARMUP_TIME) + + x.report("match (single path)") do + test_paths.first(10).each do |path| + pathspec.match(path) + end + end + end + + # Store the result (we'll capture this manually from output) + puts + + # Benchmark 2: Batch path matching + # Note: match_paths expects paths relative to root, so we pass empty root + Benchmark.ips do |x| + x.config(time: BENCHMARK_TIME, warmup: WARMUP_TIME) + + x.report("match_paths (100 paths)") do + pathspec.match_paths(test_paths.first(100), '') + end + end + + puts + + # Benchmark 3: Pattern initialization + Benchmark.ips do |x| + x.config(time: BENCHMARK_TIME, warmup: WARMUP_TIME) + + x.report("initialization") do + PathSpec.new(patterns, :git) + end + end + + puts "\n" +end + +puts "=" * 80 +puts "Benchmark complete!" +puts "=" * 80 +puts "\nTo analyze results:" +puts "1. Review the iterations/second (i/s) for each pattern count" +puts "2. Compare how performance scales as pattern count increases" +puts "3. Identify which operations are most affected by pattern count" +puts "\nNote: Higher i/s (iterations per second) indicates better performance" diff --git a/lib/pathspec/version.rb b/lib/pathspec/version.rb new file mode 100644 index 0000000..626980b --- /dev/null +++ b/lib/pathspec/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class PathSpec + VERSION = '3.0.1' +end diff --git a/pathspec.gemspec b/pathspec.gemspec index 07a39c6..d7a758e 100644 --- a/pathspec.gemspec +++ b/pathspec.gemspec @@ -19,6 +19,7 @@ Gem::Specification.new do |s| s.homepage = 'https://github.com/highb/pathspec-ruby' s.license = 'Apache-2.0' s.required_ruby_version = '>= 3.2.0' + s.add_development_dependency 'benchmark-ips', '~> 2.0' s.add_development_dependency 'bundler', '>= 2.4.19' s.add_development_dependency 'fakefs', '~> 2.5' s.add_development_dependency 'irb', '~> 1.14' From a52ddf963b1906b689ecad874f6244dbb9e47324 Mon Sep 17 00:00:00 2001 From: Brandon High <759848+highb@users.noreply.github.com> Date: Wed, 14 Jan 2026 13:48:46 -0800 Subject: [PATCH 68/70] docs: Add comprehensive ROADMAP for future development Document potential features and enhancements including: - Additional pattern formats (Docker, Mercurial, npm, rsync) - Performance enhancements (alternative regex backends, caching) - Experimental Rust native backend exploration - Pattern validation and linting tools - Advanced filtering (case-insensitive, attribute-based) - API enhancements (streaming, introspection, composition) - Testing and tooling improvements All items are organized by category with clear implementation approaches, use cases, and considerations. No timelines specified. Rust backend section emphasizes learning goals and exploratory nature, with pure Ruby remaining the primary implementation. Co-Authored-By: Claude Sonnet 4.5 --- ROADMAP.md | 551 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 551 insertions(+) create mode 100644 ROADMAP.md diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..13bbab9 --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,551 @@ +# PathSpec Ruby Roadmap + +This document outlines potential features and enhancements for the pathspec-ruby library. Items are organized by category and represent ideas for future development, not commitments or timelines. + +## Additional Pattern Format Support + +### Docker Ignore Patterns + +Add support for `.dockerignore` files, which use a similar but slightly different syntax from `.gitignore`. + +**Key differences:** +- Different handling of `**` at the start of patterns +- Exception patterns work differently than gitignore +- Docker-specific pattern matching semantics + +**Implementation approach:** +- Add `PathSpec.from_dockerignore()` factory method +- Implement `DockerIgnoreSpec` class extending base `Spec` +- Document differences between Docker and Git pattern formats + +**Use case:** Enable Docker users to validate and test their `.dockerignore` files programmatically. + +--- + +### Mercurial Ignore Patterns + +Add support for `.hgignore` files used by Mercurial VCS. + +**Key features:** +- Support `syntax: regexp` directive for regex patterns +- Support `syntax: glob` directive for glob patterns +- Handle Mercurial-specific pattern semantics + +**Implementation approach:** +- Add `PathSpec.from_hgignore()` factory method +- Parse and respect syntax directives within files +- Implement `HgIgnoreSpec` class with dual-mode support + +**Use case:** Useful for polyglot VCS users and teams migrating between version control systems. + +--- + +### NPM/Yarn Ignore Patterns + +Add support for `.npmignore` and `.yarnignore` files with their subtle differences from gitignore. + +**Key differences:** +- Different default exclusions (node_modules, etc.) +- Different handling of empty directories +- Package-specific matching behaviors + +**Implementation approach:** +- Add `PathSpec.from_npmignore()` factory method +- Document default exclusions +- Handle package manager-specific semantics + +**Use case:** Enable JavaScript/Node.js developers to validate package exclusions. + +--- + +### Rsync Exclude Patterns + +Add support for rsync's exclude pattern format (`.rsyncignore`). + +**Key features:** +- Rsync has its own pattern syntax similar to gitignore but with differences +- Support for include/exclude pattern lists +- Support for merge-file directives + +**Implementation approach:** +- Add `PathSpec.from_rsyncignore()` factory method +- Implement `RsyncIgnoreSpec` class +- Document rsync-specific pattern behaviors + +**Use case:** Useful for deployment scripts and backup automation. + +--- + +## Performance Enhancements + +### Alternative Regex Backends + +Implement support for high-performance regex engines as alternatives to Ruby's built-in regex. + +**Potential backends:** +- **re2** - Google's RE2 engine via the `re2` gem (linear time matching, no backtracking) +- **Oniguruma** - Ruby's default regex engine, but could be used more explicitly +- **Hyperscan** - Intel's high-performance regex engine (if Ruby bindings become available) + +**Implementation approach:** +- Add backend selection API: `PathSpec.new(patterns, :git, backend: :re2)` +- Benchmark each backend with the existing benchmark suite +- Document trade-offs (feature support vs. performance) +- Follow the pattern used by Python's pathspec library + +**Benefits:** +- Significant performance improvements for pattern-heavy workloads +- Better performance scaling with 100+ patterns +- Reduced CPU usage in high-throughput scenarios + +**Considerations:** +- Some backends may not support all Ruby regex features +- Additional gem dependencies required +- Cross-platform compatibility testing needed + +--- + +### Pattern Compilation Caching + +Add intelligent caching for compiled pattern objects. + +**Features:** +- Cache compiled PathSpec objects by pattern set hash +- LRU eviction for memory management +- Thread-safe cache implementation + +**Use case:** Applications that repeatedly create PathSpec objects with the same patterns. + +--- + +## Experimental: Native Rust Backend + +Explore adding an optional Rust-powered native extension using the `ignore` crate as an alternative backend to the pure Ruby implementation. + +**Primary goal:** Learn Ruby/Rust FFI integration and gain hands-on experience with cross-language tooling. + +**Secondary goal:** Understand performance characteristics and share findings with the community. + +### Implementation Approach + +**Phase 1: Separate gem exploration** +- Create standalone `pathspec-native` gem with Rust implementation +- Use the Rust `ignore` crate (from ripgrep) as the pattern matching engine +- Implement Ruby bindings using `magnus` or `rb-sys` +- Maintain 100% API compatibility with pathspec-ruby +- Benchmark extensively against pure Ruby implementation + +**Phase 2: Optional integration (if Phase 1 succeeds)** +- Integrate as optional backend in main gem +- Maintain pure Ruby as default with automatic fallback +- Allow users to opt-in to native backend: `PathSpec.new(patterns, :git, backend: :native)` +- Ensure zero impact on users who don't want native dependencies + +### Technical Considerations + +**FFI tooling options:** +- **magnus** - Ruby bindings for Rust (modern, actively maintained) +- **rb-sys** - Low-level Ruby bindings (more control, more complexity) +- Compare both approaches and document trade-offs + +**The `ignore` crate benefits:** +- Battle-tested in ripgrep (widely used, well-optimized) +- Supports .gitignore patterns natively +- High-performance parallel file tree walking +- Maintained by experienced Rust developer (BurntSushi) + +**Cross-platform compilation:** +- Ensure builds work on Linux, macOS, Windows +- Set up CI/CD for automated native builds +- Consider pre-compiled gems for common platforms +- Document local build requirements + +### Goals + +1. **Learning outcomes:** + - Understand Ruby C extension API vs. Rust FFI approaches + - Learn `magnus`/`rb-sys` tooling and best practices + - Experience cross-platform native gem distribution + +2. **Performance insights:** + - Benchmark native vs. Ruby across different workload sizes + - Identify when native implementation provides benefits + - Measure memory usage differences + - Test with real-world .gitignore files (1, 10, 100, 1000+ patterns) + +3. **Community contribution:** + - Write detailed blog post about findings + - Share performance data and methodology + - Document FFI integration lessons learned + - Provide reusable example for other gem authors + +4. **Maintain pure Ruby as first-class:** + - Pure Ruby version remains the default + - No degradation of pure Ruby implementation + - Native backend is purely additive + +### Success Criteria + +- ✅ Native extension compiles successfully on Linux, macOS, and Windows +- ✅ 100% API compatibility - drop-in replacement for pure Ruby backend +- ✅ Comprehensive benchmark suite comparing both implementations +- ✅ Documented performance characteristics with clear guidance +- ✅ CI/CD pipeline builds and tests native extensions +- ✅ Clear installation instructions for native dependencies +- ✅ Published blog post with findings and recommendations + +### Non-Goals + +**This is explicitly NOT:** +- A rewrite of the gem - pure Ruby implementation stays and remains primary +- A required dependency - native extension is optional only +- A response to performance complaints - this is exploratory learning +- A commitment to long-term maintenance of native code +- An attempt to deprecate the Ruby implementation + +**What we're NOT optimizing for:** +- Absolute maximum performance - learning is the priority +- Production-critical performance - pure Ruby is already fast enough +- Replacing other tools - this is about understanding trade-offs + +### Open Questions + +Questions to answer through exploration: + +1. **Performance questions:** + - At what pattern count does native backend become beneficial? + - How does performance scale with directory tree size? + - What's the FFI call overhead for small workloads? + - Is parallel tree walking worth the complexity? + +2. **Developer experience questions:** + - How painful is cross-platform native gem distribution? + - What's the learning curve for magnus vs. rb-sys? + - How do we handle build failures gracefully? + - What's the maintenance burden of native code? + +3. **User experience questions:** + - Is opt-in vs. opt-out the right choice? + - How do we communicate when native backend is beneficial? + - What happens when native extension fails to load? + - Should we pre-compile for common platforms? + +### Potential Outcomes + +**Best case:** +- Learn valuable FFI skills +- Discover significant performance benefits for certain workloads +- Share useful findings with community +- Provide optional native backend for power users + +**Realistic case:** +- Learn valuable FFI skills +- Find that pure Ruby is "fast enough" for most use cases +- Discover native backend helps only for extreme workloads (1000+ patterns) +- Document when native extensions are/aren't worth it + +**Acceptable case:** +- Learn valuable FFI skills +- Conclude that FFI overhead negates performance benefits +- Decide not to integrate into main gem +- Share lessons learned in blog post + +All outcomes are valuable because the primary goal is learning. + +### Resources & References + +- **Rust `ignore` crate**: https://docs.rs/ignore/ +- **magnus (Ruby ↔ Rust)**: https://github.com/matsadler/magnus +- **rb-sys**: https://github.com/oxidize-rb/rb-sys +- **ripgrep** (uses `ignore` crate): https://github.com/BurntSushi/ripgrep +- **Rust native extensions guide**: https://github.com/oxidize-rb/oxidize-rb + +--- + +## Pattern Validation & Quality + +### Pattern Linting and Validation + +Add tools to check patterns for common mistakes and suggest improvements. + +**Features:** + +1. **Syntax error detection:** + - Invalid glob patterns (e.g., `*.txt/` - wildcard with trailing slash) + - Malformed bracket expressions + - Escaped characters in wrong contexts + +2. **Semantic warnings:** + - Patterns that can never match (e.g., `/foo` when matching relative paths) + - Redundant patterns (e.g., `*.log` followed by `error.log`) + - Overly broad patterns that might match unintended files + +3. **Performance suggestions:** + - Recommend more efficient pattern ordering + - Suggest combining similar patterns + - Identify expensive regex patterns + +4. **Style recommendations:** + - Inconsistent path separator usage + - Unnecessary escaping + - Patterns that could be simplified + +**Implementation approach:** +- Add `PathSpec#validate` method returning array of issues +- Implement `PathSpec::Linter` class with configurable rules +- Provide severity levels (error, warning, info) +- Include suggested fixes where applicable + +**API example:** +```ruby +pathspec = PathSpec.from_filename('.gitignore') +issues = pathspec.validate + +issues.each do |issue| + puts "#{issue.severity}: #{issue.message}" + puts " Pattern: #{issue.pattern}" + puts " Suggestion: #{issue.suggestion}" if issue.suggestion +end +``` + +**Use case:** Help developers write better ignore files and catch mistakes before they cause issues. + +--- + +### Pattern Testing Framework + +Add utilities to test pattern matching behavior. + +**Features:** +- Assert that specific paths match/don't match +- Generate test paths from patterns +- Coverage analysis (which patterns are actually being used) + +**Use case:** CI/CD pipelines that verify ignore patterns work as expected. + +--- + +## Advanced Filtering Features + +### Case-Insensitive Matching + +Add optional flag for case-insensitive pattern matching. + +**Implementation approach:** +- Add `case_sensitive` option to PathSpec constructor +- Default to true (current behavior) for backwards compatibility +- Convert patterns to case-insensitive regexes when disabled + +**API example:** +```ruby +# Match *.TXT, *.txt, *.Txt, etc. +pathspec = PathSpec.new(['*.txt'], :git, case_sensitive: false) +``` + +**Use case:** Cross-platform projects where case sensitivity varies (Windows vs. Linux/macOS). + +--- + +### Attribute-Based Filtering + +Extend pattern matching beyond filenames to include file attributes. + +**Features:** + +1. **File size patterns:** + - `size:>10MB` - Files larger than 10MB + - `size:<1KB` - Files smaller than 1KB + - `size:100KB..10MB` - Files in size range + +2. **Modification time patterns:** + - `modified:>7d` - Modified in last 7 days + - `modified:<2023-01-01` - Modified before date + - `modified:today` - Modified today + +3. **File permission patterns:** + - `mode:executable` - Executable files + - `mode:0644` - Specific permission mode + - `mode:user-writable` - Files writable by owner + +4. **File type patterns:** + - `type:symlink` - Symbolic links + - `type:directory` - Directories + - `type:file` - Regular files + +**Implementation approach:** +- Add `PathSpec#match_tree_with_attrs` method +- Create `AttributeSpec` class for attribute-based filtering +- Support combining path patterns with attribute filters + +**API example:** +```ruby +pathspec = PathSpec.new(['*.log', 'size:>100MB'], :git) +large_logs = pathspec.match_tree('logs/') +``` + +**Use case:** Clean up scripts, archival tools, security audits. + +--- + +### Glob Expansion + +Add ability to expand glob patterns into matching file lists without needing a root directory. + +**Features:** +- Generate all possible matches for a pattern +- Useful for testing and documentation +- Support limiting depth and count + +**Use case:** Pattern documentation, test generation, interactive explorers. + +--- + +## API Enhancements + +### Streaming API + +Add support for processing large file lists without loading everything into memory. + +**Implementation approach:** +- Add `PathSpec#match_stream` that yields matches +- Support lazy evaluation with Enumerator +- Optimize for large directory trees + +**API example:** +```ruby +pathspec = PathSpec.from_filename('.gitignore') +pathspec.match_stream('huge_directory/') do |matched_path| + process(matched_path) +end +``` + +**Use case:** Large repositories, file system indexing, backup tools. + +--- + +### Pattern Introspection + +Add methods to analyze and understand pattern behavior. + +**Features:** +- List all patterns that would match a given path +- Explain why a path matched (which pattern, why) +- Extract pattern metadata (complexity, type, etc.) + +**API example:** +```ruby +pathspec = PathSpec.from_filename('.gitignore') +explanation = pathspec.explain('coverage/index.html') +# => "Matched by pattern 'coverage/' at line 15 (directory match)" +``` + +**Use case:** Debugging ignore rules, understanding complex ignore files. + +--- + +### Pattern Composition + +Add utilities to combine multiple PathSpec objects with set operations. + +**Features:** +- Union: Match if any PathSpec matches +- Intersection: Match only if all PathSpecs match +- Difference: Match first PathSpec but not second + +**API example:** +```ruby +gitignore = PathSpec.from_filename('.gitignore') +dockerignore = PathSpec.from_filename('.dockerignore') + +# Files ignored by git OR docker +either = gitignore.union(dockerignore) + +# Files ignored by git but NOT by docker +git_only = gitignore.difference(dockerignore) +``` + +**Use case:** Complex filtering logic, comparing ignore files. + +--- + +## Testing & Quality + +### Compatibility Test Suite + +Add comprehensive tests against reference implementations. + +**Features:** +- Test against git's actual ignore behavior +- Test against docker's ignore behavior +- Cross-reference with Python pathspec library +- Generate compatibility reports + +**Use case:** Ensure accuracy and find edge cases. + +--- + +### Property-Based Testing + +Add property-based tests using the `rspec-propcheck` gem. + +**Features:** +- Generate random patterns and paths +- Verify invariants hold for all inputs +- Find edge cases automatically + +**Use case:** Improve robustness and find bugs. + +--- + +## Documentation & Tooling + +### Interactive Pattern Tester + +Create a CLI tool or web interface for testing patterns interactively. + +**Features:** +- Live pattern editing with instant feedback +- Visual highlighting of matches +- Pattern explanation and suggestions +- Save/load pattern sets + +**Use case:** Learning, debugging, pattern development. + +--- + +### Pattern Migration Tools + +Add utilities to convert between different pattern formats. + +**Features:** +- Convert gitignore to dockerignore +- Convert rsync excludes to gitignore +- Highlight patterns that don't translate cleanly + +**Use case:** Migrating between tools, maintaining consistency. + +--- + +## Contributing + +This roadmap is a living document. If you'd like to: +- Propose new features +- Discuss implementation approaches +- Contribute implementations + +Please open an issue or pull request on GitHub to start the conversation. + +--- + +## Prioritization Considerations + +When evaluating which features to implement, consider: + +1. **User impact** - How many users would benefit? +2. **Maintenance burden** - How much ongoing maintenance is required? +3. **Compatibility** - Does it maintain backwards compatibility? +4. **Dependencies** - Does it require new dependencies? +5. **Complexity** - How complex is the implementation? +6. **Standards compliance** - Does it follow established standards? + +Features that provide high user value with manageable complexity and maintenance burden should be prioritized. From b93548c7d8875612993bff264d5c15b2479ba817 Mon Sep 17 00:00:00 2001 From: Brandon High Date: Wed, 21 Jan 2026 12:41:04 -0800 Subject: [PATCH 69/70] Fix RuboCop offenses and add AGENTS.md (#60) * Fix RuboCop offenses in benchmarks/pattern_scaling.rb - Fix Style/WordArray for directories array - Fix Style/StringLiterals - use single quotes where appropriate - Fix Metrics/MethodLength by extracting patterns to separate method - Fix Layout/IndentationWidth and block alignment issues - Add rubocop:disable comment for remaining long method containing data All tests now pass with RuboCop 1.63.5 *Testing and fixes generated using Big Pickle/OpenCode Zen* * Add AGENT.md with comprehensive development guide - Include setup instructions using mise - Document all available commands and workflows - Provide testing strategies and common solutions - Outline project structure and dependencies - Include CI/CD information and release process *Documentation generated using Big Pickle/OpenCode Zen* * Migrate to AGENTS.md following https://agents.md/ standard - Adopt AGENTS.md format instead of custom AGENT.md - Maintain all essential setup, testing, and development information - Follow open standard for AI agent guidance used by 60k+ projects - Ensure compatibility with multiple AI coding agents *Migration performed using Big Pickle/OpenCode Zen* --------- Co-authored-by: Brandon High <759848+highb@users.noreply.github.com> --- AGENTS.md | 121 ++++++++++++++++++++++++++++++++++ benchmarks/pattern_scaling.rb | 68 ++++++++++--------- 2 files changed, 158 insertions(+), 31 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..baa53c0 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,121 @@ +# AGENTS.md + +PathSpec Ruby - .gitignore-style pattern matching in Ruby + +## Project overview + +Ruby gem implementing .gitignore-style pattern matching with both library API and CLI tool. Supports Ruby 3.2-4.0.1 with comprehensive test coverage and multi-Ruby CI. + +## Setup commands + +```bash +# Install mise (Ruby version manager) +brew install mise # macOS +# Other platforms: https://mise.jdx.dev/getting-started.html + +# Activate mise +eval "$(mise activate zsh)" # or bash, fish, etc. + +# Install Ruby and bundler versions +mise install + +# Install dependencies +mise run install +# or: bundle install +``` + +## Testing + +```bash +# Run all tests (lint, unit, integration, docs) +mise run test +# or: bundle exec rake + +# Unit tests only +mise run test:unit +# or: bundle exec rake spec + +# Integration tests (CLI) only +mise run test:integration +# or: bundle exec rake spec_integration + +# All specs (unit + integration) +mise run test:all +# or: bundle exec rake spec_all + +# Cross-Ruby matrix testing via Docker +mise run test:matrix +# or: bundle exec rake test_matrix +``` + +## Code style + +- Use RuboCop 1.63.5 for linting +- Method length limit: 69 lines +- Use single quotes for strings without interpolation +- Use `%w[]` for word arrays +- Auto-fix with: `bundle exec rubocop --autocorrect` +- For large data arrays: add `# rubocop:disable Metrics/MethodLength` + +## Build and release + +```bash +# Build gem +mise run build +# or: gem build pathspec.gemspec + +# Generate documentation +bundle exec rake docs + +# Development install +rake install +``` + +## Project structure + +``` +pathspec-ruby/ +├── lib/pathspec/ # Core library +│ ├── pathspec.rb # Main PathSpec class +│ └── patterns/ # Pattern implementations +├── bin/pathspec-rb # CLI executable +├── spec/ +│ ├── unit/ # Library tests +│ └── integration/ # CLI tests +├── benchmarks/ # Performance tests +├── docs/ # Documentation source +├── Rakefile # Build tasks +├── .tool-versions # Ruby/bundler versions +└── pathspec.gemspec # Gem spec +``` + +## Development workflow + +1. Make changes to `lib/` code +2. Add/update tests in `spec/unit/` for library changes +3. Add/update tests in `spec/integration/` for CLI changes +4. Run `mise run test` - must pass before committing +5. Fix any RuboCop offenses +6. Test cross-Ruby with `mise run test:matrix` +7. Commit with descriptive messages + +## CLI tool usage + +```bash +bundle exec pathspec-rb -f .gitignore match "file.swp" +bundle exec pathspec-rb -f .gitignore specs_match "file.swp" +bundle exec pathspec-rb -f .gitignore tree ./src +``` + +## Common issues + +**Bundler conflicts**: Always use `mise run install` to ensure correct versions from `.tool-versions` + +**RuboCop failures**: Auto-fix with `bundle exec rubocop --autocorrect`. Method length is common issue - extract large data arrays to separate methods with rubocop:disable comments + +**CI failures**: Check GitHub Actions. RuboCop and integration test failures are most common causes + +## Dependencies + +- **Runtime**: None (pure Ruby) +- **Development**: rspec (~> 3.10), rubocop (~> 1.63.0), fakefs (~> 2.5), kramdown (~> 2.3), benchmark-ips (~> 2.0) \ No newline at end of file diff --git a/benchmarks/pattern_scaling.rb b/benchmarks/pattern_scaling.rb index 279c372..2af3388 100755 --- a/benchmarks/pattern_scaling.rb +++ b/benchmarks/pattern_scaling.rb @@ -16,7 +16,7 @@ def generate_test_paths(count = 1000) # Mix of different path types extensions = %w[.rb .txt .log .tmp .swp .md .yml .json .xml .css .js .html] - directories = ['src', 'lib', 'test', 'spec', 'config', 'docs', 'bin', 'tmp', 'coverage', 'vendor'] + directories = %w[src lib test spec config docs bin tmp coverage vendor] count.times do |i| depth = rand(1..4) @@ -30,7 +30,24 @@ def generate_test_paths(count = 1000) # Generate gitignore patterns of varying complexity def generate_patterns(count) - base_patterns = [ + base_patterns = base_gitignore_patterns + + # Return the first 'count' patterns, cycling if needed + if count <= base_patterns.length + base_patterns.take(count) + else + patterns = base_patterns.dup + remaining = count - base_patterns.length + remaining.times do |i| + patterns << "generated_pattern_#{i}/**/*" + end + patterns + end +end + +# rubocop:disable Metrics/MethodLength +def base_gitignore_patterns + [ '*.log', '*.tmp', '*.swp', @@ -165,31 +182,20 @@ def generate_patterns(count) '.yarn/install-state.gz', '.pnp.*' ] - - # Return the first 'count' patterns, cycling if needed - if count <= base_patterns.length - base_patterns.take(count) - else - patterns = base_patterns.dup - remaining = count - base_patterns.length - remaining.times do |i| - patterns << "generated_pattern_#{i}/**/*" - end - patterns - end end +# rubocop:enable Metrics/MethodLength -puts "PathSpec Performance Benchmark" -puts "=" * 80 -puts "Testing pattern matching performance with varying pattern counts" -puts "Hardware: Apple M4 Pro (12 cores: 8 performance + 4 efficiency), 24 GB RAM" +puts 'PathSpec Performance Benchmark' +puts '=' * 80 +puts 'Testing pattern matching performance with varying pattern counts' +puts 'Hardware: Apple M4 Pro (12 cores: 8 performance + 4 efficiency), 24 GB RAM' puts "Ruby Version: #{RUBY_VERSION}" -puts "Test Configuration:" +puts 'Test Configuration:' puts " - Pattern counts: #{PATTERN_COUNTS.join(', ')}" -puts " - Test paths: 1000 representative file paths" +puts ' - Test paths: 1000 representative file paths' puts " - Warmup time: #{WARMUP_TIME}s" puts " - Benchmark time: #{BENCHMARK_TIME}s per test" -puts "=" * 80 +puts '=' * 80 puts # Pre-generate test data @@ -203,7 +209,7 @@ def generate_patterns(count) pathspec = PathSpec.new(patterns, :git) puts "Benchmarking with #{pattern_count} patterns..." - puts "-" * 80 + puts '-' * 80 results[pattern_count] = {} @@ -211,7 +217,7 @@ def generate_patterns(count) Benchmark.ips do |x| x.config(time: BENCHMARK_TIME, warmup: WARMUP_TIME) - x.report("match (single path)") do + x.report('match (single path)') do test_paths.first(10).each do |path| pathspec.match(path) end @@ -226,7 +232,7 @@ def generate_patterns(count) Benchmark.ips do |x| x.config(time: BENCHMARK_TIME, warmup: WARMUP_TIME) - x.report("match_paths (100 paths)") do + x.report('match_paths (100 paths)') do pathspec.match_paths(test_paths.first(100), '') end end @@ -237,7 +243,7 @@ def generate_patterns(count) Benchmark.ips do |x| x.config(time: BENCHMARK_TIME, warmup: WARMUP_TIME) - x.report("initialization") do + x.report('initialization') do PathSpec.new(patterns, :git) end end @@ -245,11 +251,11 @@ def generate_patterns(count) puts "\n" end -puts "=" * 80 -puts "Benchmark complete!" -puts "=" * 80 +puts '=' * 80 +puts 'Benchmark complete!' +puts '=' * 80 puts "\nTo analyze results:" -puts "1. Review the iterations/second (i/s) for each pattern count" -puts "2. Compare how performance scales as pattern count increases" -puts "3. Identify which operations are most affected by pattern count" +puts '1. Review the iterations/second (i/s) for each pattern count' +puts '2. Compare how performance scales as pattern count increases' +puts '3. Identify which operations are most affected by pattern count' puts "\nNote: Higher i/s (iterations per second) indicates better performance" From 813c99591c27a634ae5ee4b88a6ab727edece99a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 21 Jan 2026 13:21:24 -0800 Subject: [PATCH 70/70] chore(deps): update dependency gem:bundler to v4.0.4 (#59) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .mise.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mise.toml b/.mise.toml index d549a80..1b8df9a 100644 --- a/.mise.toml +++ b/.mise.toml @@ -1,6 +1,6 @@ [tools] ruby = "3.4.1" -"gem:bundler" = "4.0.3" +"gem:bundler" = "4.0.4" [tasks.install] run = "bundle install"