rails-diff 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 282714f27151e8626a70a7a5d583dd16d5f623b5bd6dc5a18b0bd3799972c9b0
4
- data.tar.gz: 97096cefae2cadbd8708d19cb1d6bfa448a3f324d85b1fa406196de6cc776494
3
+ metadata.gz: 3b0a335992f7491133b576710e538fd0adc5d3bde79919e2fa60d145ae3e6055
4
+ data.tar.gz: f429b3d0d895f23bbda625a29172e3528bc86db2cb1e74fc6803aa7d2105c65e
5
5
  SHA512:
6
- metadata.gz: 3aac33eb6514f976ef2d69b98b9a9afcbaf488b4dd10966f7895296cbec5035800851c6ce274a1bbd4dfdd09bda75c95474bb4aa1c441611ff52513e4acc4ccd
7
- data.tar.gz: 12c2327650881b2de7fcecd7b154106b1445794d8088b12f23f6c0fa2a528d9026c434a4ed6e3b056ccf1bc5d037a7e4c7a958ffa77f74b1ed039fd319e13e3e
6
+ metadata.gz: abe0d4f2ae2cf533aefa251726547b2eda321758edbf14882fc5948314d0e72eab78c054b238661f127df065fa6da0956b3469b07e2d219e35a199442443908e
7
+ data.tar.gz: 3bba7f7a5c9711601f7dcb11163947913103185f60a31dc3bd7f9e79c0b055fee8fad650a8abbb65c36b69deccec780f36b821c646216363f8a6286fcacb5318
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.7.0] - 2026-03-17
4
+
5
+ - Replace `diffy` with `difftastic` for better diff output with syntax highlighting.
6
+ - Add `--ref` option to compare against a specific tag, branch, or commit SHA (`--commit` is kept as an alias).
7
+ - [BUGFIX] `--commit` (now `--ref`) failed with shallow clones when the ref wasn't locally available.
8
+
3
9
  ## [0.6.0] - 2025-07-25
4
10
 
5
11
  - Add `--only` option to only include specific files or directories in the diff.
@@ -70,6 +76,7 @@ M## [0.1.1] - 2025-02-21
70
76
 
71
77
  - Initial release
72
78
 
79
+ [0.7.0]: https://github.com/matheusrich/rails-diff/releases/tag/v0.7.0
73
80
  [0.6.0]: https://github.com/matheusrich/rails-diff/releases/tag/v0.6.0
74
81
  [0.5.0]: https://github.com/matheusrich/rails-diff/releases/tag/v0.5.0
75
82
  [0.4.1]: https://github.com/matheusrich/rails-diff/releases/tag/v0.4.1
data/README.md CHANGED
@@ -41,8 +41,8 @@ rails-diff file Dockerfile --clear-cache
41
41
  # Fail if there are differences (useful for CI)
42
42
  rails-diff file Dockerfile --fail-on-diff
43
43
 
44
- # Compare a specific commit
45
- rails-diff file Dockerfile --commit 7df1b8
44
+ # Compare a specific ref (tag, branch, or commit SHA)
45
+ rails-diff file Dockerfile --ref v8.0.0
46
46
  ```
47
47
 
48
48
  ### Compare generator files
@@ -63,8 +63,8 @@ rails-diff generated scaffold Post --skip app/views app/helpers
63
63
  # Fail if there are differences (useful for CI)
64
64
  rails-diff generated scaffold Post --fail-on-diff
65
65
 
66
- # Compare a specific commit
67
- rails-diff generated authentication --commit 7df1b8
66
+ # Compare a specific ref (tag, branch, or commit SHA)
67
+ rails-diff generated authentication --ref v8.0.0
68
68
  ```
69
69
 
70
70
  ### Compare dotfiles (configuration files)
@@ -74,16 +74,39 @@ rails-diff generated authentication --commit 7df1b8
74
74
  rails-diff dotfiles
75
75
  ```
76
76
 
77
+ ### Compare infrastructure files
78
+
79
+ Compare all Rails-generated infrastructure files at once. This includes everything except `app/` and `lib/` (your application code): `bin/`, `config/`, `db/`, `public/`, `Dockerfile`, `Gemfile`, `Rakefile`, dotfiles, and more.
80
+
81
+ ```bash
82
+ # Compare all infrastructure files
83
+ rails-diff infra
84
+
85
+ # Compare only specific directories
86
+ rails-diff infra --only bin config
87
+
88
+ # Skip additional directories
89
+ rails-diff infra --skip db
90
+
91
+ # Fail if there are differences (useful for CI)
92
+ rails-diff infra --fail-on-diff
93
+ ```
94
+
77
95
  ### Global Options
78
96
 
97
+ These options can be used with any of the commands above.
98
+
79
99
  #### --fail-on-diff
80
100
 
81
101
  If this option is specified, the command will exit with a non-zero status code if there are any differences between your files and the generated ones. This can be particularly useful when using the gem in Continuous Integration (CI) environments.
82
102
 
83
- #### --commit <commit_hash>
103
+ #### --ref <ref>
104
+
105
+ Specify a tag, branch, or commit SHA to compare against. If not provided, the
106
+ latest commit on main will be used by default. `--commit` is kept as an alias.
84
107
 
85
- Specify the commit hash you want to compare against. If not provided, the latest
86
- commit on main will be used by default.
108
+ > [!NOTE]
109
+ > When using a commit SHA, the full 40-character SHA is required (short SHAs are not supported).
87
110
 
88
111
  #### --new-app-options <options>
89
112
 
@@ -148,7 +171,7 @@ The gem caches the generated Rails application to avoid regenerating it on every
148
171
  - The cache directory doesn't exist (or is cleared with the `--clear-cache` option)
149
172
  - You use `--new-app-options` with different options
150
173
  - You change your `~/.railsrc` file
151
- - You use `--commit` with a different commit
174
+ - You use `--ref` with a different ref
152
175
 
153
176
  You can also force clear the cache by using the `--no-cache` option (or its alias `--clear-cache`) with any command.
154
177
 
@@ -5,7 +5,7 @@ module Rails
5
5
  class CLI < Thor
6
6
  class_option :no_cache, type: :boolean, desc: "Clear cache before running", aliases: ["--clear-cache"]
7
7
  class_option :fail_on_diff, type: :boolean, desc: "Fail if there are differences"
8
- class_option :commit, type: :string, desc: "Compare against a specific commit"
8
+ class_option :ref, type: :string, desc: "Compare against a specific ref (tag, branch, or commit SHA)", aliases: ["--commit"]
9
9
  class_option :new_app_options, type: :string, desc: "Options to pass to the rails new command"
10
10
  class_option :debug, type: :boolean, desc: "Print debug information", aliases: ["-d"]
11
11
 
@@ -19,7 +19,7 @@ module Rails
19
19
  diff = Rails::Diff.file(
20
20
  *files,
21
21
  no_cache: options[:no_cache],
22
- commit: options[:commit],
22
+ ref: options[:ref],
23
23
  new_app_options: options[:new_app_options]
24
24
  )
25
25
  return if diff.empty?
@@ -45,7 +45,24 @@ module Rails
45
45
  no_cache: options[:no_cache],
46
46
  skip: options[:skip],
47
47
  only: options[:only],
48
- commit: options[:commit],
48
+ ref: options[:ref],
49
+ new_app_options: options[:new_app_options]
50
+ )
51
+ return if diff.empty?
52
+
53
+ options[:fail_on_diff] ? abort(diff) : puts(diff)
54
+ end
55
+
56
+ desc "infra", "Compare non-application files in your repository (everything except app/ and lib/) with the ones generated by Rails"
57
+ option :skip, type: :array, desc: "Additional files or directories to skip", aliases: ["-s"], default: []
58
+ option :only, type: :array, desc: "Only include specific files or directories", aliases: ["-o"], default: []
59
+ def infra
60
+ ENV["DEBUG"] = "true" if options[:debug]
61
+ diff = Rails::Diff.infra(
62
+ no_cache: options[:no_cache],
63
+ skip: options[:skip],
64
+ only: options[:only],
65
+ ref: options[:ref],
49
66
  new_app_options: options[:new_app_options]
50
67
  )
51
68
  return if diff.empty?
@@ -2,29 +2,20 @@
2
2
 
3
3
  module Rails
4
4
  module Diff
5
- class FileTracker
6
- def initialize(base_dir, skip = [], only = [])
7
- @base_dir = base_dir
8
- @skip = skip
9
- @only = only
10
- end
5
+ module FileTracker
6
+ DEFAULT_EXCLUSIONS = %w[.git tmp log test].freeze
11
7
 
12
- def new_files
13
- files_before = list_files(@base_dir)
8
+ def self.new_files(base_dir, only:, skip: [])
9
+ files_before = list_files(base_dir)
14
10
  yield
15
- files_after = list_files(@base_dir, @skip, @only)
11
+ files_after = list_files(base_dir, skip:, only:)
16
12
  files_after - files_before
17
13
  end
18
14
 
19
- private
20
-
21
- def list_files(dir, skip = [], only = [])
15
+ def self.list_files(dir, skip: [], only: [], exclusions: DEFAULT_EXCLUSIONS)
22
16
  files = Dir.glob("#{dir}/**/*", File::FNM_DOTMATCH).reject do |it|
23
17
  File.directory?(it) ||
24
- it.start_with?("#{dir}/.git") ||
25
- it.start_with?("#{dir}/tmp") ||
26
- it.start_with?("#{dir}/log") ||
27
- it.start_with?("#{dir}/test") ||
18
+ exclusions.any? { |e| it.start_with?("#{dir}/#{e}") } ||
28
19
  skip.any? { |s| it.start_with?("#{dir}/#{s}") }
29
20
  end
30
21
 
@@ -5,10 +5,10 @@ module Rails
5
5
  class RailsAppGenerator
6
6
  RAILSRC_PATH = "#{ENV["HOME"]}/.railsrc"
7
7
 
8
- def initialize(commit: nil, new_app_options: nil, no_cache: false, logger: Logger, cache_dir: Rails::Diff::CACHE_DIR)
8
+ def initialize(ref: nil, new_app_options: nil, no_cache: false, logger: Logger, cache_dir: Rails::Diff::CACHE_DIR)
9
9
  @new_app_options = new_app_options.to_s.split
10
10
  @rails_repo = RailsRepo.new(logger:, cache_dir:)
11
- @commit = commit
11
+ @ref = ref
12
12
  @logger = logger
13
13
  @cache_dir = cache_dir
14
14
  clear_cache if no_cache
@@ -44,8 +44,8 @@ module Rails
44
44
  Shell.run!("bin/rails", "destroy", generator_name, *args, logger:)
45
45
  logger.info "Running generator: rails generate #{generator_name} #{args.join(" ")}"
46
46
 
47
- FileTracker.new(template_app_path, skip, only)
48
- .new_files { Shell.run!("bin/rails", "generate", generator_name, *args, logger:) }
47
+ FileTracker
48
+ .new_files(template_app_path, skip:, only:) { Shell.run!("bin/rails", "generate", generator_name, *args, logger:) }
49
49
  .map { |it| it.delete_prefix("#{template_app_path}/") }
50
50
  end
51
51
  end
@@ -54,9 +54,9 @@ module Rails
54
54
 
55
55
  attr_reader :new_app_options, :rails_repo, :logger, :cache_dir
56
56
 
57
- def commit = @commit ||= rails_repo.latest_commit
57
+ def ref = @ref ||= rails_repo.latest_commit
58
58
 
59
- def rails_cache_dir_key = "rails-#{commit.first(10)}"
59
+ def rails_cache_dir_key = "rails-#{ref.first(10)}"
60
60
 
61
61
  def railsrc_options
62
62
  @railsrc_options ||= File.exist?(RAILSRC_PATH) ? File.readlines(RAILSRC_PATH) : []
@@ -69,7 +69,7 @@ module Rails
69
69
  end
70
70
 
71
71
  def create_new_rails_app
72
- checkout_rails_commit
72
+ checkout_rails_ref
73
73
  generate_app
74
74
  end
75
75
 
@@ -81,7 +81,7 @@ module Rails
81
81
  rails_repo.new_app(template_app_path, rails_new_options)
82
82
  end
83
83
 
84
- def checkout_rails_commit = rails_repo.checkout(commit)
84
+ def checkout_rails_ref = rails_repo.checkout(ref)
85
85
 
86
86
  def rails_new_options
87
87
  @rails_new_options ||= (new_app_options + railsrc_options).compact
@@ -9,10 +9,13 @@ module Rails
9
9
  @rails_repo = rails_repo
10
10
  end
11
11
 
12
- def checkout(commit)
12
+ def checkout(ref)
13
13
  on_rails_dir do
14
- logger.info "Checking out Rails (at commit #{commit[0..6]})"
15
- Shell.run!("git", "checkout", commit, logger:)
14
+ logger.info "Checking out Rails (at #{ref})"
15
+ unless Shell.run!("git", "checkout", ref, abort: false, logger:)
16
+ Shell.run!("git", "fetch", "--depth", "1", "origin", ref, logger:)
17
+ Shell.run!("git", "checkout", "FETCH_HEAD", logger:)
18
+ end
16
19
  end
17
20
  end
18
21
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rails
4
4
  module Diff
5
- VERSION = "0.6.1"
5
+ VERSION = "0.7.0"
6
6
  end
7
7
  end
data/lib/rails/diff.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "rails"
4
- require "diffy"
4
+ require "difftastic"
5
5
  require "fileutils"
6
6
  require_relative "diff/cli"
7
7
  require_relative "diff/file_tracker"
@@ -16,8 +16,8 @@ module Rails
16
16
  CACHE_DIR = File.expand_path("#{ENV["HOME"]}/.rails-diff/cache")
17
17
 
18
18
  class << self
19
- def file(*files, no_cache: false, commit: nil, new_app_options: nil)
20
- app_generator = RailsAppGenerator.new(commit:, new_app_options:, no_cache:)
19
+ def file(*files, no_cache: false, ref: nil, new_app_options: nil)
20
+ app_generator = RailsAppGenerator.new(ref:, new_app_options:, no_cache:)
21
21
  app_generator.create_template_app
22
22
 
23
23
  files
@@ -25,13 +25,26 @@ module Rails
25
25
  .join("\n")
26
26
  end
27
27
 
28
- def generated(generator_name, *args, no_cache: false, skip: [], only: [], commit: nil, new_app_options: nil)
29
- app_generator = RailsAppGenerator.new(commit:, new_app_options:, no_cache:)
28
+ def generated(generator_name, *args, no_cache: false, skip: [], only: [], ref: nil, new_app_options: nil)
29
+ app_generator = RailsAppGenerator.new(ref:, new_app_options:, no_cache:)
30
30
  app_generator.create_template_app
31
31
  app_generator.install_app_dependencies
32
32
 
33
33
  app_generator.run_generator(generator_name, *args, skip, only)
34
- .map { |it| diff_with_header(it, app_generator.template_app_path) }
34
+ .filter_map { |it| diff_with_header(it, app_generator.template_app_path) }
35
+ .join("\n\n")
36
+ end
37
+
38
+ def infra(no_cache: false, skip: [], only: [], ref: nil, new_app_options: nil)
39
+ app_generator = RailsAppGenerator.new(ref:, new_app_options:, no_cache:)
40
+ app_generator.create_template_app
41
+
42
+ default_skip = %w[app lib]
43
+ effective_skip = (default_skip + skip).uniq
44
+
45
+ FileTracker.list_files(app_generator.template_app_path, skip: effective_skip, only:)
46
+ .map { |f| f.delete_prefix("#{app_generator.template_app_path}/") }
47
+ .filter_map { |it| diff_with_header(it, app_generator.template_app_path) }
35
48
  .join("\n\n")
36
49
  end
37
50
 
@@ -52,12 +65,13 @@ module Rails
52
65
  return "File not found in the Rails template" unless File.exist?(rails_file)
53
66
  return "File not found in your repository" unless File.exist?(repo_file)
54
67
 
55
- Diffy::Diff.new(
56
- rails_file,
57
- repo_file,
58
- context: 2,
59
- source: "files"
60
- ).to_s(:color).chomp
68
+ differ = Difftastic::Differ.new(
69
+ color: :always,
70
+ left_label: "Rails File (#{file})",
71
+ right_label: "Repo File (#{file})"
72
+ )
73
+
74
+ differ.diff_files(rails_file, repo_file).chomp
61
75
  end
62
76
  end
63
77
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-diff
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matheus Richard
@@ -24,19 +24,19 @@ dependencies:
24
24
  - !ruby/object:Gem::Version
25
25
  version: '7.0'
26
26
  - !ruby/object:Gem::Dependency
27
- name: diffy
27
+ name: difftastic
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: '3.4'
32
+ version: '0.8'
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '3.4'
39
+ version: '0.8'
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: thor
42
42
  requirement: !ruby/object:Gem::Requirement