leave_it 0.1.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 132986cf5b0e44f0189e98b45bf98c35d4d95e4902d33a1506c670d05c8857e3
4
+ data.tar.gz: a306605029ddfa8d6d22f89d0ba20fd142022ab751e2587e1a5484aca232a585
5
+ SHA512:
6
+ metadata.gz: 92a74d4b08f4cfdd2c65c0f561d4d1e8b1ed44e47270111d1498af174c04fff51a111aeb373e3129e6712f0bed88176a3ba8ff0843279fea23167b1987acf22a
7
+ data.tar.gz: 357daaa2b78d54edece4473569e60a2a11232a4928603eadc08738d38cbda4a8e2e4fc7a33b7806c23436d869fb3bd71ae78cde1fd993ea405cffc3fe0cccc5a
data/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ This project adheres to [Semantic Versioning](https://semver.org/) and [Keep a Changelog](https://keepachangelog.com/).
6
+
7
+ ---
8
+
9
+ ## [0.1.1] - 2025-06-24
10
+
11
+ ### Fixed
12
+ - Corrected homepage link in gemspec.
13
+
14
+ ---
15
+
16
+ ## [0.1.0] - 2025-06-24
17
+
18
+ ### Added
19
+ - Initial release.
20
+ - CLI tool to parse `Gemfile.lock` and inject pessimistic `~>` version constraints into `Gemfile`.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 mykbren
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # leave_it
2
+
3
+ **Inject pessimistic (`~>`) version constraints into your Gemfile from your Gemfile.lock automatically, preventing major updates during bundling and allowing only safe patch and minor version upgrades.**
4
+
5
+ If I had to describe the motivation behind this tool in one sentence, it would be:
6
+ **No more pain after `bundle update` — keep your Gemfile locked to working versions, and update dependencies one by one only when needed.** (⇀‸↼‶)
7
+
8
+ PS. Patches can still break functionality sometimes, but by nature they shouldn’t — this tool helps minimize those risks. (`_´)ゞ
9
+
10
+ ---
11
+
12
+ ## Motivation
13
+
14
+ Managing Ruby gem dependencies can be tricky, especially when your Gemfile includes gems without explicit version constraints. Running bundle update often results in major version bumps that introduce breaking changes or cause unexpected instability in your project.
15
+
16
+ I was tired of manually specifying version constraints and constantly dealing with surprise major upgrades during bundling that break things — wasting hours debugging incompatibilities.
17
+
18
+ Another common pain is resurrecting an old project from its Gemfile.lock. The lockfile helps you restore the exact gem versions that last worked, but sometimes you need to update a few libraries to get the project running on newer Ruby or system environments. Then, running bundle update without precise version constraints causes a flood of major upgrades, breaking your app's functionality completely — and leaving you staring at a wall of errors (╯°□°)╯︵ ┻━┻
19
+
20
+ This tool solves those headaches by scanning your Gemfile.lock and automatically injecting the correct pessimistic (~>) version constraints into your Gemfile for any gems missing them. This keeps your dependencies safely locked, prevents unintentional major upgrades, and helps maintain project stability — whether you’re actively developing or resurrecting legacy code.
21
+
22
+ ---
23
+
24
+ ## Features
25
+
26
+ * Parses your `Gemfile.lock` for exact gem versions.
27
+ * Adds pessimistic version constraints (`~> x.y.z`) to unversioned gems in your `Gemfile`.
28
+ * Keeps existing version constraints untouched.
29
+ * Simple CLI interface — just run in your project directory.
30
+ * Helps reduce unintended major version updates and improves bundle stability.
31
+
32
+ ---
33
+
34
+ ## Installation
35
+
36
+ Add this line to your Gemfile:
37
+
38
+ ```ruby
39
+ gem 'leave_it'
40
+ ```
41
+
42
+ Then execute:
43
+
44
+ ```bash
45
+ bundle install
46
+ ```
47
+
48
+ Or install it yourself with:
49
+
50
+ ```bash
51
+ gem install leave_it
52
+ ```
53
+
54
+ ---
55
+
56
+ ## Usage
57
+
58
+ Run the CLI from your project root directory (where `Gemfile` and `Gemfile.lock` reside):
59
+
60
+ ```bash
61
+ leave-it .
62
+ ```
63
+
64
+ This will update your `Gemfile` in-place, adding `~>` version constraints for all gems missing them, based on the versions locked in your `Gemfile.lock`.
65
+
66
+ ---
67
+
68
+ ## Example
69
+
70
+ Before:
71
+
72
+ ```ruby
73
+ gem 'rake'
74
+ gem 'rspec', '~> 3.10'
75
+ ```
76
+
77
+ After running `leave-it .`:
78
+
79
+ ```ruby
80
+ gem 'rake', '~> 13.0.6'
81
+ gem 'rspec', '~> 3.10'
82
+ ```
83
+
84
+ ---
85
+
86
+ ## Development
87
+
88
+ Clone the repo and run tests:
89
+
90
+ ```bash
91
+ git clone https://github.com/mykbren/leave_it.git
92
+ cd leave_it
93
+ bundle install
94
+ bundle exec rspec
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Contributing
100
+
101
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/mykbren/leave_it](https://github.com/mykbren/leave_it).
102
+
103
+ ---
104
+
105
+ ## License
106
+
107
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/bin/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'leave_it'
6
+
7
+ require 'irb'
8
+ IRB.start(__FILE__)
data/bin/leave-it ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'leave_it'
5
+
6
+ LeaveIt.run(ARGV.first || '.')
data/bin/setup ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
data/leave_it.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/leave_it/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'leave_it'
7
+ spec.version = LeaveIt::VERSION
8
+ spec.authors = ['mykbren']
9
+ spec.email = ['myk.bren@gmail.com']
10
+
11
+ spec.summary = 'Injects pessimistic (~>) version constraints into your Gemfile from Gemfile.lock'
12
+ spec.description = <<~DESC.strip
13
+ CLI tool that scans Gemfile.lock and updates your Gemfile by adding pessimistic (~>) version
14
+ constraints to unversioned gems.
15
+ DESC
16
+ spec.homepage = 'https://github.com/mykbren/leave_it'
17
+ spec.license = 'MIT'
18
+ spec.required_ruby_version = '>= 2.7.0'
19
+ spec.metadata['homepage_uri'] = spec.homepage
20
+ spec.metadata['source_code_uri'] = spec.homepage
21
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/blob/main/CHANGELOG.md"
22
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
23
+
24
+ # Includes all files tracked by git
25
+ spec.files = Dir.glob('lib/**/*') + Dir.glob('bin/*') + ['README.md', 'CHANGELOG.md', 'LICENSE.txt',
26
+ 'leave_it.gemspec']
27
+
28
+ spec.bindir = 'bin'
29
+ spec.executables = ['leave-it']
30
+ spec.require_paths = ['lib']
31
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LeaveIt
4
+ class CLI
5
+ def self.run(path)
6
+ gemfile = File.join(path, 'Gemfile')
7
+ lockfile = File.join(path, 'Gemfile.lock')
8
+
9
+ unless File.exist?(gemfile) && File.exist?(lockfile)
10
+ puts "❌ Gemfile or Gemfile.lock not found in #{path}"
11
+ exit(1)
12
+ end
13
+
14
+ versions = parse_lockfile_versions(lockfile)
15
+ updated = update_gemfile_versions(gemfile, versions)
16
+ File.write(gemfile, updated)
17
+
18
+ puts "✅ Gemfile in #{path} updated successfully."
19
+ end
20
+
21
+ def self.parse_lockfile_versions(lockfile)
22
+ versions = {}
23
+ File.foreach(lockfile) { |line| process_lockfile_line(line, versions) }
24
+ versions
25
+ end
26
+
27
+ def self.update_gemfile_versions(gemfile, lock_versions)
28
+ new_lines = []
29
+ File.foreach(gemfile) { |line| new_lines << process_gemfile_line(line, lock_versions) }
30
+ new_lines.join
31
+ end
32
+
33
+ def self.process_lockfile_line(line, versions)
34
+ @in_gem_section ||= false
35
+ @in_gem_section = true if gem_section_start?(line)
36
+ return unless @in_gem_section
37
+
38
+ if gem_line?(line)
39
+ gem_name, version = parse_gem_line(line)
40
+ versions[gem_name] = version
41
+ elsif line.strip.empty?
42
+ @in_gem_section = false
43
+ end
44
+ end
45
+
46
+ def self.process_gemfile_line(line, lock_versions)
47
+ if gem_declaration_line?(line)
48
+ indent, gem_name, _, version, rest = parse_gem_declaration_line(line)
49
+
50
+ if version.nil? && lock_versions[gem_name]
51
+ version_str = pessimistic_version(lock_versions[gem_name])
52
+ return "#{indent}gem '#{gem_name}', '#{version_str}'#{rest}\n"
53
+ end
54
+ end
55
+
56
+ line
57
+ end
58
+
59
+ def self.gem_section_start?(line)
60
+ line.strip == 'GEM'
61
+ end
62
+
63
+ def self.gem_line?(line)
64
+ line =~ /^\s{4}(\S+)\s\(([^)]+)\)/
65
+ end
66
+
67
+ def self.parse_gem_line(line)
68
+ match = line.match(/^\s{4}(\S+)\s\(([^)]+)\)/)
69
+ [match[1], match[2]]
70
+ end
71
+
72
+ def self.gem_declaration_line?(line)
73
+ line =~ /^(\s*)gem ['"]([^'"]+)['"](,\s*['"]([^'"]+)['"])?(.*)$/
74
+ end
75
+
76
+ def self.parse_gem_declaration_line(line)
77
+ match = line.match(/^(\s*)gem ['"]([^'"]+)['"](,\s*['"]([^'"]+)['"])?(.*)$/)
78
+ [match[1], match[2], match[3], match[4], match[5]]
79
+ end
80
+
81
+ def self.pessimistic_version(version)
82
+ parts = version.split('.')
83
+ if parts.length >= 3
84
+ "~> #{parts[0]}.#{parts[1]}.#{parts[2]}"
85
+ else
86
+ "~> #{version}"
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LeaveIt
4
+ VERSION = '0.1.1'
5
+ end
data/lib/leave_it.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'leave_it/version'
4
+ require_relative 'leave_it/cli'
5
+
6
+ module LeaveIt
7
+ def self.run(path = '.')
8
+ CLI.run(path)
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leave_it
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - mykbren
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-06-24 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |-
14
+ CLI tool that scans Gemfile.lock and updates your Gemfile by adding pessimistic (~>) version
15
+ constraints to unversioned gems.
16
+ email:
17
+ - myk.bren@gmail.com
18
+ executables:
19
+ - leave-it
20
+ extensions: []
21
+ extra_rdoc_files: []
22
+ files:
23
+ - CHANGELOG.md
24
+ - LICENSE.txt
25
+ - README.md
26
+ - bin/console
27
+ - bin/leave-it
28
+ - bin/setup
29
+ - leave_it.gemspec
30
+ - lib/leave_it.rb
31
+ - lib/leave_it/cli.rb
32
+ - lib/leave_it/version.rb
33
+ homepage: https://github.com/mykbren/leave_it
34
+ licenses:
35
+ - MIT
36
+ metadata:
37
+ homepage_uri: https://github.com/mykbren/leave_it
38
+ source_code_uri: https://github.com/mykbren/leave_it
39
+ changelog_uri: https://github.com/mykbren/leave_it/blob/main/CHANGELOG.md
40
+ allowed_push_host: https://rubygems.org
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 2.7.0
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubygems_version: 3.4.10
57
+ signing_key:
58
+ specification_version: 4
59
+ summary: Injects pessimistic (~>) version constraints into your Gemfile from Gemfile.lock
60
+ test_files: []