bundler-merge 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. checksums.yaml +7 -0
  2. data/bin/bundler-merge +149 -0
  3. metadata +48 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '0796111c27239fe0ddcefe28599af439ccc1d4215ee755c602eaa06371c4d33f'
4
+ data.tar.gz: 2cf800c59580e18b1a545dbefa0d85c01658f90b353fad4f39c0962e47726c84
5
+ SHA512:
6
+ metadata.gz: 3b3b6e2dd9550be1a4c1bf0b8c5801b0cd19c3282eff6b10557bda247cd0a862d18239e55ac6bb1b29442e381624e0eb6268f75ffba5666a7af95e136fd34247
7
+ data.tar.gz: 18dac0c8aee1b97f4698993403fb8a31f848b98e3274de11b2223a9ebb4027cfe4ada65c791388541fe66b923906c422d3e58badca5c2182ef40c6fe9ab444c2
data/bin/bundler-merge ADDED
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # [merge "bundler"]
4
+ # name = Gemfile.lock merge driver
5
+ # driver = bundler-merge %O %A %B
6
+
7
+ # Known sections:
8
+ # * GIT
9
+ # * PATH
10
+ # * GEM
11
+ # * PLATFORMS
12
+ # * DEPENDENCIES
13
+ # * BUNDLED WITH
14
+ # * RUBY VERSION
15
+
16
+ Section = Struct.new(:name, :text) do
17
+ def key
18
+ case name
19
+ when "GIT", "PATH", "GEM"
20
+ remote = text[/^ remote: (.+)$/, 1] || fail("remote missing")
21
+ "#{name}:#{remote}"
22
+ else
23
+ name
24
+ end
25
+ end
26
+
27
+ def self.build(name, internal)
28
+ new(name, "#{name}\n#{internal}")
29
+ end
30
+ end
31
+
32
+ class Lockfile
33
+ attr_reader :sections, :path
34
+ def initialize(path)
35
+ @path = path
36
+ @sections = []
37
+ section = nil
38
+ File.foreach(path) do |line|
39
+ if line == "\n"
40
+ section = nil
41
+ elsif line =~ /\A[A-Z]/
42
+ name = line.chomp
43
+ section = Section.new(name, line.dup)
44
+ @sections << section
45
+ else
46
+ section.text << line
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ class Diff3
53
+ Chunk = Struct.new(:o, :a, :b) do
54
+ alias_method :original, :o
55
+ end
56
+
57
+ def initialize(o, a, b)
58
+ @chunks = Hash.new { |h, k| h[k] = Chunk.new }
59
+ o.each { |s| @chunks[key(s)].o = s }
60
+ a.each { |s| @chunks[key(s)].a = s }
61
+ b.each { |s| @chunks[key(s)].b = s }
62
+ end
63
+
64
+ def key(x)
65
+ x
66
+ end
67
+
68
+ def merge(x)
69
+ fail("conflict")
70
+ end
71
+
72
+ def result
73
+ @chunks.values.map do |chunk|
74
+ if chunk.original == chunk.a
75
+ # only changed by B (or no change at all)
76
+ chunk.b
77
+ elsif chunk.original == chunk.b
78
+ # only changed by A
79
+ chunk.a
80
+ elsif chunk.a == chunk.b
81
+ # both changed in same way
82
+ chunk.a
83
+ else
84
+ # Ah dang it's a real merge
85
+ merge(chunk)
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ class DependencyDiff3 < Diff3
92
+ def key(dep)
93
+ dep[/ ([^ !]+)/, 1]
94
+ end
95
+ end
96
+
97
+ class GemDiff3 < Diff3
98
+ def key(dep)
99
+ dep[/ ([^ !]+)/, 1]
100
+ end
101
+ end
102
+
103
+ class LockfileDiff3 < Diff3
104
+ def key(section)
105
+ section.key
106
+ end
107
+
108
+ def merge(chunk)
109
+ fail("conflict") unless chunk.o
110
+
111
+ name = chunk.o.name
112
+
113
+ if false
114
+ elsif name == "DEPENDENCIES"
115
+ diff3 = DependencyDiff3.new(*chunk.to_a.map do |s|
116
+ s.text.lines[1..]
117
+ end)
118
+ Section.build(name, diff3.result.join)
119
+ elsif name == "GEM"
120
+ gems = chunk.to_a.map do |s|
121
+ specs = s.text[/^ specs:\n((:? .+\n)*)/, 1]
122
+ specs = specs.split(/^(?= [^ ])/)
123
+ end
124
+ diff3 = GemDiff3.new(*gems)
125
+ prefix = chunk.o.text[/\A.+\n specs:\n/m]
126
+ text = "#{prefix}#{diff3.result.join}"
127
+ Section.new(name, text)
128
+ elsif name == "BUNDLED WITH"
129
+ # Just take ours
130
+ chunk.a
131
+ else
132
+ fail("unimplemented")
133
+ end
134
+ end
135
+ end
136
+
137
+ argv = ARGV.dup
138
+ stdout = !!argv.delete("-p")
139
+
140
+ if argv.size != 3
141
+ puts "Usage: #$0 %A %O %B"
142
+ exit 1
143
+ end
144
+
145
+ local, base, remote = files = argv
146
+ diff3 = LockfileDiff3.new(*[base, local, remote].map { |f| Lockfile.new(f).sections })
147
+ result = diff3.result.map(&:text).join("\n")
148
+ output = stdout ? STDOUT : File.open(local, "w")
149
+ output.puts result
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bundler-merge
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - John Hawthorn
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-10-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A tool to resolve merge conflicts in Gemfile.lock
14
+ email:
15
16
+ executables:
17
+ - bundler-merge
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - bin/bundler-merge
22
+ homepage: https://github.com/jhawthorn/bundler-merge
23
+ licenses:
24
+ - MIT
25
+ metadata:
26
+ homepage_uri: https://github.com/jhawthorn/bundler-merge
27
+ source_code_uri: https://github.com/jhawthorn/bundler-merge
28
+ changelog_uri: https://github.com/jhawthorn/bundler-merge
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - ">="
36
+ - !ruby/object:Gem::Version
37
+ version: 2.7.0
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubygems_version: 3.5.16
45
+ signing_key:
46
+ specification_version: 4
47
+ summary: A merge driver for Gemfile.lock
48
+ test_files: []
OSZAR »