diff --git a/bin/magic_frozen_string_literal b/bin/magic_frozen_string_literal
index d3f8504..a15c53c 100755
--- a/bin/magic_frozen_string_literal
+++ b/bin/magic_frozen_string_literal
@@ -3,5 +3,19 @@
# A simple tool to prepend magic '# frozen_string_literal: true' comments to multiple ".rb" files
require_relative '../lib/add_magic_comment'
+require "optparse"
-AddMagicComment.process(ARGV)
+process_files = false
+OptionParser.new do |opts|
+ opts.banner = "Usage: magic_frozen_string_literal app/ lib/"
+
+ opts.on("-f", "--files", "Apply to specific files instead of files in directories") do |v|
+ process_files = true
+ end
+end.parse!
+
+if process_files
+ AddMagicComment.process_files_at(ARGV)
+else
+ AddMagicComment.process(ARGV)
+end
diff --git a/lib/add_magic_comment.rb b/lib/add_magic_comment.rb
index 713ad15..759b551 100644
--- a/lib/add_magic_comment.rb
+++ b/lib/add_magic_comment.rb
@@ -18,6 +18,7 @@ module AddMagicComment
"*.gemspec" => "# #{MAGIC_COMMENT}\n\n",
"*.rabl" => "# #{MAGIC_COMMENT}\n\n",
"*.jbuilder" => "# #{MAGIC_COMMENT}\n\n",
+ "*.pbbuilder" => "# #{MAGIC_COMMENT}\n\n",
"*.haml" => "-# #{MAGIC_COMMENT}\n",
"*.slim" => "-# #{MAGIC_COMMENT}\n"
}
@@ -25,41 +26,59 @@ module AddMagicComment
def self.process(argv)
directory = argv.first || Dir.pwd
- count = 0
+
+ touched_paths = []
EXTENSION_COMMENTS.each do |pattern, comment|
- filename_pattern = File.join(directory, "**", "#{pattern}")
- Dir.glob(filename_pattern).each do |filename|
- File.open(filename, "rb+") do |file|
- lines = file.readlines
- newline = detect_newline(lines.first)
- next unless lines.any?
- count += 1
-
- if lines.first =~ SHEBANG_PATTERN
- shebang = lines.shift
- end
-
- # remove current magic comment(s)
- while lines.first && (lines.first.match(MAGIC_COMMENT_PATTERN) || lines.first.match(EMPTY_LINE_PATTERN))
- lines.shift
- end
-
- # add magic comment as the first line
- lines.unshift(comment.gsub("\n", newline))
-
- # put shebang back
- if shebang
- lines.unshift(shebang)
- end
-
- file.pos = 0
- file.print(*lines)
- file.truncate(file.pos)
- end
+ file_path_pattern = File.join(directory, "**", "#{pattern}")
+ Dir.glob(file_path_pattern).each do |file_path|
+ process_file_at(file_path, comment, touched_paths)
+ end
+ end
+
+ puts "Magic comments added to #{touched_paths.size} source file(s)"
+ end
+
+ def self.process_file_at(path, comment, touched_paths)
+ File.open(path, "rb+") do |file|
+ lines = file.readlines
+ newline = detect_newline(lines.first)
+ return unless lines.any?
+
+ if lines.first =~ SHEBANG_PATTERN
+ shebang = lines.shift
+ end
+
+ # remove current magic comment(s)
+ while lines.first && (lines.first.match(MAGIC_COMMENT_PATTERN) || lines.first.match(EMPTY_LINE_PATTERN))
+ lines.shift
+ end
+
+ # add magic comment as the first line
+ lines.unshift(comment.gsub("\n", newline))
+
+ # put shebang back
+ if shebang
+ lines.unshift(shebang)
+ end
+
+ file.pos = 0
+ file.print(*lines)
+ file.truncate(file.pos)
+ end
+ touched_paths << path
+ end
+
+ def self.process_files_at(paths)
+ touched_paths = []
+ paths.each do |path|
+ matching_pattern_and_comment = EXTENSION_COMMENTS.find do |(glob_pattern, _comment)|
+ File.fnmatch(glob_pattern, path)
end
+ _, comment = matching_pattern_and_comment
+ process_file_at(path, comment, touched_paths) if comment
end
- puts "Magic comments added to #{count} source file(s)"
+ puts "Magic comments added to #{touched_paths.size} source file(s)"
end
def self.detect_newline(line)
diff --git a/spec/acceptance_spec.rb b/spec/acceptance_spec.rb
index 2bea2ab..df7f7ff 100644
--- a/spec/acceptance_spec.rb
+++ b/spec/acceptance_spec.rb
@@ -14,7 +14,7 @@
}
end
- it "inserts magic comments where expected", :aggregate_failures do
+ it "inserts magic comments across directories", :aggregate_failures do
AddMagicComment.process([directories[:test]])
Dir["#{directories[:test]}/*"].each do |path|
@@ -22,6 +22,18 @@
end
end
+ it "inserts magic comments just into specific files", :aggregate_failures do
+ paths = Dir.glob(directories[:test] + "/*.rb")
+ AddMagicComment.process_files_at(paths)
+
+ rb_paths = Dir["#{directories[:test]}/*.rb"]
+ rb_paths.each do |path|
+ assert_file_matches_expected(File.basename(path))
+ end
+
+ assert_file_not_touched("Rakefile")
+ end
+
def setup_test_files
FileUtils.mkdir_p(File.dirname(directories[:test]))
FileUtils.cp_r(directories[:input], directories[:test])
@@ -31,6 +43,12 @@ def teardown_test_files
FileUtils.rm_rf(directories[:test])
end
+ def assert_file_not_touched(filename)
+ processed_path = File.join(directories[:test], filename)
+ expected_path = File.join(directories[:expected], filename)
+ expect(FileUtils).not_to be_identical(processed_path, expected_path)
+ end
+
def assert_file_matches_expected(filename)
paths = {
test: File.join(directories[:test], filename),
diff --git a/spec/fixtures/expected/shebang_already_commented.rb b/spec/fixtures/expected/shebang_already_commented.rb
new file mode 100755
index 0000000..3795ca2
--- /dev/null
+++ b/spec/fixtures/expected/shebang_already_commented.rb
@@ -0,0 +1,4 @@
+#!/usr/bin/ruby
+# frozen_string_literal: true
+
+puts "hello"
diff --git a/spec/fixtures/input/Gemfile b/spec/fixtures/input/Gemfile
index 25115d0..c036588 100644
--- a/spec/fixtures/input/Gemfile
+++ b/spec/fixtures/input/Gemfile
@@ -1,5 +1,3 @@
-# frozen_string_literal: true
-
source 'https://rubygems.org'
gem 'magic_frozen_string_literal'
diff --git a/spec/fixtures/input/Rakefile b/spec/fixtures/input/Rakefile
index f039a8b..1737b57 100644
--- a/spec/fixtures/input/Rakefile
+++ b/spec/fixtures/input/Rakefile
@@ -1,5 +1,3 @@
-# frozen_string_literal: true
-
require "bundler/gem_tasks"
task :test do
diff --git a/spec/fixtures/input/blank_line.rb b/spec/fixtures/input/blank_line.rb
index ae917d5..bbad01b 100644
--- a/spec/fixtures/input/blank_line.rb
+++ b/spec/fixtures/input/blank_line.rb
@@ -1,3 +1 @@
-# frozen_string_literal: true
-
puts "hello"
diff --git a/spec/fixtures/input/config.ru b/spec/fixtures/input/config.ru
index 842bccc..f7ba0b5 100644
--- a/spec/fixtures/input/config.ru
+++ b/spec/fixtures/input/config.ru
@@ -1,5 +1,3 @@
-# frozen_string_literal: true
-
# This file is used by Rack-based servers to start the application.
require_relative 'config/environment'
diff --git a/spec/fixtures/input/shebang.rb b/spec/fixtures/input/shebang.rb
old mode 100644
new mode 100755
index 3795ca2..e69af1e
--- a/spec/fixtures/input/shebang.rb
+++ b/spec/fixtures/input/shebang.rb
@@ -1,4 +1,3 @@
#!/usr/bin/ruby
-# frozen_string_literal: true
puts "hello"
diff --git a/spec/fixtures/input/shebang_already_commented.rb b/spec/fixtures/input/shebang_already_commented.rb
new file mode 100755
index 0000000..3795ca2
--- /dev/null
+++ b/spec/fixtures/input/shebang_already_commented.rb
@@ -0,0 +1,4 @@
+#!/usr/bin/ruby
+# frozen_string_literal: true
+
+puts "hello"
diff --git a/spec/fixtures/input/shebang_blank_line.rb b/spec/fixtures/input/shebang_blank_line.rb
old mode 100644
new mode 100755
index 3795ca2..e69af1e
--- a/spec/fixtures/input/shebang_blank_line.rb
+++ b/spec/fixtures/input/shebang_blank_line.rb
@@ -1,4 +1,3 @@
#!/usr/bin/ruby
-# frozen_string_literal: true
puts "hello"
diff --git a/spec/fixtures/input/t1.haml b/spec/fixtures/input/t1.haml
index aeaeb94..d1ded0b 100644
--- a/spec/fixtures/input/t1.haml
+++ b/spec/fixtures/input/t1.haml
@@ -1,2 +1 @@
--# frozen_string_literal: true
Hello!
diff --git a/spec/fixtures/input/t1.rb b/spec/fixtures/input/t1.rb
index ae917d5..bbad01b 100644
--- a/spec/fixtures/input/t1.rb
+++ b/spec/fixtures/input/t1.rb
@@ -1,3 +1 @@
-# frozen_string_literal: true
-
puts "hello"
diff --git a/spec/fixtures/input/t1.slim b/spec/fixtures/input/t1.slim
index aeaeb94..d1ded0b 100644
--- a/spec/fixtures/input/t1.slim
+++ b/spec/fixtures/input/t1.slim
@@ -1,2 +1 @@
--# frozen_string_literal: true
Hello!
diff --git a/spec/fixtures/input/utf8.rb b/spec/fixtures/input/utf8.rb
index 904b2ba..0010968 100644
--- a/spec/fixtures/input/utf8.rb
+++ b/spec/fixtures/input/utf8.rb
@@ -1,3 +1 @@
-# frozen_string_literal: true
-
puts " "