diffstitch 1.0.3
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 +7 -0
- data/CHANGELOG.md +80 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/bin/diffstitch +6 -0
- data/diffstitch.gemspec +35 -0
- data/lib/diffstitch/assets/app.js +104 -0
- data/lib/diffstitch/assets/bootstrap.min.css +6 -0
- data/lib/diffstitch/assets/index.html.erb +43 -0
- data/lib/diffstitch/assets/styles.css +218 -0
- data/lib/diffstitch/cli.rb +98 -0
- data/lib/diffstitch/generator.rb +42 -0
- data/lib/diffstitch/git.rb +26 -0
- data/lib/diffstitch/version.rb +5 -0
- data/lib/diffstitch.rb +9 -0
- metadata +132 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/* ── Variables ──────────────────────────────────────────────────── */
|
|
2
|
+
:root {
|
|
3
|
+
--gh-canvas: #ffffff;
|
|
4
|
+
--gh-surface: #f6f8fa;
|
|
5
|
+
--gh-border: #d0d7de;
|
|
6
|
+
--gh-text: #1f2328;
|
|
7
|
+
--gh-muted: #57606a;
|
|
8
|
+
--gh-link: #0969da;
|
|
9
|
+
--gh-nav-bg: #24292f;
|
|
10
|
+
--gh-nav-border: #30363d;
|
|
11
|
+
--gh-nav-text: #f0f6fc;
|
|
12
|
+
|
|
13
|
+
--gh-add-bg: #e6ffec;
|
|
14
|
+
--gh-add-num-bg: #abf2bc;
|
|
15
|
+
--gh-add-num-text: #033a16;
|
|
16
|
+
--gh-add-num-border:#56d364;
|
|
17
|
+
|
|
18
|
+
--gh-del-bg: #ffebe9;
|
|
19
|
+
--gh-del-num-bg: rgba(255,129,130,.4);
|
|
20
|
+
--gh-del-num-text: #82071e;
|
|
21
|
+
--gh-del-num-border:rgba(255,129,130,.6);
|
|
22
|
+
|
|
23
|
+
--gh-hunk-bg: #ddf4ff;
|
|
24
|
+
--gh-hunk-text: #0550ae;
|
|
25
|
+
--gh-hunk-border: rgba(84,174,255,.3);
|
|
26
|
+
|
|
27
|
+
--mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* ── Page shell ─────────────────────────────────────────────────── */
|
|
31
|
+
|
|
32
|
+
body { background: var(--gh-canvas); color: var(--gh-text); }
|
|
33
|
+
|
|
34
|
+
/* ── Top nav (GitHub dark bar) ──────────────────────────────────── */
|
|
35
|
+
|
|
36
|
+
.topnav {
|
|
37
|
+
background: var(--gh-nav-bg);
|
|
38
|
+
border-bottom: 1px solid var(--gh-nav-border);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.topnav h1 { color: var(--gh-nav-text); }
|
|
42
|
+
|
|
43
|
+
.branch-select {
|
|
44
|
+
background-color: #21262d !important;
|
|
45
|
+
color: var(--gh-nav-text) !important;
|
|
46
|
+
border-color: #30363d !important;
|
|
47
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%238b949e' d='M1 1l5 5 5-5'/%3E%3C/svg%3E") !important;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.branch-select:focus {
|
|
51
|
+
border-color: #58a6ff !important;
|
|
52
|
+
box-shadow: 0 0 0 3px rgba(88,166,255,.25) !important;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* ── Panel chrome ───────────────────────────────────────────────── */
|
|
56
|
+
|
|
57
|
+
.panel-left { border-right: 1px solid var(--gh-border); }
|
|
58
|
+
|
|
59
|
+
.panel-header {
|
|
60
|
+
padding: .375rem .875rem;
|
|
61
|
+
background: var(--gh-surface);
|
|
62
|
+
border-bottom: 1px solid var(--gh-border);
|
|
63
|
+
font-family: var(--mono);
|
|
64
|
+
font-size: 12px;
|
|
65
|
+
flex-shrink: 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.panel-header .fw-semibold { color: var(--gh-link); }
|
|
69
|
+
|
|
70
|
+
.ds-badge {
|
|
71
|
+
display: inline-block;
|
|
72
|
+
padding: 1px 7px;
|
|
73
|
+
font-size: 11px;
|
|
74
|
+
font-family: var(--mono);
|
|
75
|
+
background: var(--gh-surface);
|
|
76
|
+
color: var(--gh-muted);
|
|
77
|
+
border: 1px solid var(--gh-border);
|
|
78
|
+
border-radius: 2em;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* ── Empty state ────────────────────────────────────────────────── */
|
|
82
|
+
|
|
83
|
+
.empty-state {
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
justify-content: center;
|
|
87
|
+
height: 200px;
|
|
88
|
+
font-family: var(--mono);
|
|
89
|
+
font-size: 13px;
|
|
90
|
+
font-style: italic;
|
|
91
|
+
color: var(--gh-muted);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* ── Scrollbar ──────────────────────────────────────────────────── */
|
|
95
|
+
|
|
96
|
+
.panel-content::-webkit-scrollbar { width: 8px; height: 8px; }
|
|
97
|
+
.panel-content::-webkit-scrollbar-track { background: var(--gh-canvas); }
|
|
98
|
+
.panel-content::-webkit-scrollbar-thumb { background: var(--gh-border); border-radius: 4px; }
|
|
99
|
+
.panel-content::-webkit-scrollbar-thumb:hover { background: var(--gh-muted); }
|
|
100
|
+
|
|
101
|
+
/* ── diff2html overrides ── GitHub colour palette ───────────────── */
|
|
102
|
+
|
|
103
|
+
/* Strip diff2html's own borders/margins so our panel chrome takes over */
|
|
104
|
+
.panel-content .d2h-wrapper { background: var(--gh-canvas); }
|
|
105
|
+
|
|
106
|
+
.panel-content .d2h-file-wrapper {
|
|
107
|
+
border: none;
|
|
108
|
+
border-bottom: 1px solid var(--gh-border);
|
|
109
|
+
border-radius: 0;
|
|
110
|
+
margin: 0;
|
|
111
|
+
background: var(--gh-canvas);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Force single-column layout (we already split the two d2h sides ourselves) */
|
|
115
|
+
.panel-content .d2h-files-diff { display: block !important; }
|
|
116
|
+
.panel-content .d2h-file-side-diff {
|
|
117
|
+
width: 100% !important;
|
|
118
|
+
display: block !important;
|
|
119
|
+
border: none !important;
|
|
120
|
+
float: none !important;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* File header */
|
|
124
|
+
.panel-content .d2h-file-header {
|
|
125
|
+
background: var(--gh-surface) !important;
|
|
126
|
+
border-bottom: 1px solid var(--gh-border) !important;
|
|
127
|
+
border-radius: 0 !important;
|
|
128
|
+
padding: 6px 14px !important;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.panel-content .d2h-file-name {
|
|
132
|
+
color: var(--gh-link) !important;
|
|
133
|
+
font-size: 12px;
|
|
134
|
+
font-family: var(--mono);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Added / removed tags (e.g. "+3 -1") */
|
|
138
|
+
.panel-content .d2h-tag {
|
|
139
|
+
font-size: 11px !important;
|
|
140
|
+
border-radius: 2em !important;
|
|
141
|
+
}
|
|
142
|
+
.panel-content .d2h-added-tag {
|
|
143
|
+
background: var(--gh-add-bg) !important;
|
|
144
|
+
color: var(--gh-add-num-text) !important;
|
|
145
|
+
border: 1px solid var(--gh-add-num-border) !important;
|
|
146
|
+
}
|
|
147
|
+
.panel-content .d2h-deleted-tag {
|
|
148
|
+
background: var(--gh-del-bg) !important;
|
|
149
|
+
color: var(--gh-del-num-text) !important;
|
|
150
|
+
border: 1px solid rgba(255,129,130,.6) !important;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Code table */
|
|
154
|
+
.panel-content .d2h-code-wrapper { border: none; }
|
|
155
|
+
|
|
156
|
+
.panel-content table.d2h-diff-table {
|
|
157
|
+
width: 100%;
|
|
158
|
+
font-size: 12px;
|
|
159
|
+
font-family: var(--mono);
|
|
160
|
+
border-collapse: collapse;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* Unchanged lines */
|
|
164
|
+
.panel-content td.d2h-code-line,
|
|
165
|
+
.panel-content td.d2h-code-side-line { background: var(--gh-canvas); }
|
|
166
|
+
|
|
167
|
+
/* Deletions */
|
|
168
|
+
.panel-content td.d2h-del { background: var(--gh-del-bg) !important; }
|
|
169
|
+
.panel-content td.d2h-del .d2h-del { background: rgba(255,129,130,.4); border-radius: 2px; }
|
|
170
|
+
|
|
171
|
+
/* Additions */
|
|
172
|
+
.panel-content td.d2h-ins { background: var(--gh-add-bg) !important; }
|
|
173
|
+
.panel-content td.d2h-ins .d2h-ins { background: rgba(171,242,188,.8); border-radius: 2px; }
|
|
174
|
+
|
|
175
|
+
/* Line number gutter */
|
|
176
|
+
.panel-content .d2h-code-linenumber,
|
|
177
|
+
.panel-content td.d2h-code-side-linenumber {
|
|
178
|
+
position: sticky;
|
|
179
|
+
left: 0;
|
|
180
|
+
z-index: 2;
|
|
181
|
+
background: var(--gh-surface) !important;
|
|
182
|
+
border-right: 1px solid var(--gh-border) !important;
|
|
183
|
+
color: var(--gh-muted) !important;
|
|
184
|
+
min-width: 44px;
|
|
185
|
+
width: 44px;
|
|
186
|
+
padding: 0 10px !important;
|
|
187
|
+
text-align: right;
|
|
188
|
+
user-select: none;
|
|
189
|
+
font-family: var(--mono);
|
|
190
|
+
font-size: 12px;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.panel-content .d2h-code-linenumber.d2h-del,
|
|
194
|
+
.panel-content td.d2h-code-side-linenumber.d2h-del {
|
|
195
|
+
background: var(--gh-del-num-bg) !important;
|
|
196
|
+
border-right-color: var(--gh-del-num-border) !important;
|
|
197
|
+
color: var(--gh-del-num-text) !important;
|
|
198
|
+
z-index: 2;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.panel-content .d2h-code-linenumber.d2h-ins,
|
|
202
|
+
.panel-content td.d2h-code-side-linenumber.d2h-ins {
|
|
203
|
+
background: var(--gh-add-num-bg) !important;
|
|
204
|
+
border-right-color: var(--gh-add-num-border) !important;
|
|
205
|
+
color: var(--gh-add-num-text) !important;
|
|
206
|
+
z-index: 2;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* Hunk / context header */
|
|
210
|
+
.panel-content td.d2h-info,
|
|
211
|
+
.panel-content .d2h-info {
|
|
212
|
+
background: var(--gh-hunk-bg) !important;
|
|
213
|
+
color: var(--gh-hunk-text) !important;
|
|
214
|
+
border-top: 1px solid var(--gh-hunk-border) !important;
|
|
215
|
+
border-bottom: 1px solid var(--gh-hunk-border) !important;
|
|
216
|
+
font-family: var(--mono);
|
|
217
|
+
font-size: 12px;
|
|
218
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'optparse'
|
|
4
|
+
require 'launchy'
|
|
5
|
+
|
|
6
|
+
module Diffstitch
|
|
7
|
+
class CLI
|
|
8
|
+
OUTPUT_BASE = File.join('.diffstitch', 'output')
|
|
9
|
+
|
|
10
|
+
def self.start(argv = ARGV)
|
|
11
|
+
new.run(argv)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def run(argv)
|
|
15
|
+
options = parse_options!(argv)
|
|
16
|
+
validate_repo!
|
|
17
|
+
validate_args!(argv)
|
|
18
|
+
|
|
19
|
+
base = argv[0]
|
|
20
|
+
branches = argv[1..]
|
|
21
|
+
|
|
22
|
+
verify_refs!(base, branches)
|
|
23
|
+
|
|
24
|
+
title = options[:title] || "diffstitch: #{branches.join(' | ')} vs #{base}"
|
|
25
|
+
output_dir = options[:output] || derived_output(base, branches)
|
|
26
|
+
diffs = collect_diffs(base, branches)
|
|
27
|
+
|
|
28
|
+
Generator.new(base: base, branches: branches, diffs: diffs, title: title).write(output_dir)
|
|
29
|
+
|
|
30
|
+
index = File.expand_path(File.join(output_dir, 'index.html'))
|
|
31
|
+
puts "Generated: #{index}"
|
|
32
|
+
open_in_browser(index) if options[:open]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def parse_options!(argv)
|
|
38
|
+
options = { output: nil, open: false }
|
|
39
|
+
|
|
40
|
+
OptionParser.new do |opts|
|
|
41
|
+
opts.banner = <<~BANNER
|
|
42
|
+
diffstitch — compare multiple git branches against a base in a split HTML view
|
|
43
|
+
|
|
44
|
+
Usage: diffstitch <base> <branch1> [branch2 ...] [options]
|
|
45
|
+
BANNER
|
|
46
|
+
|
|
47
|
+
opts.on('-o', '--output DIR', "Output directory (default: #{OUTPUT_BASE}/<base>_vs_<branches>)") do |v|
|
|
48
|
+
options[:output] = v
|
|
49
|
+
end
|
|
50
|
+
opts.on('--open', 'Open result in browser after generating') { options[:open] = true }
|
|
51
|
+
opts.on('--title TITLE', 'Custom page title') { |v| options[:title] = v }
|
|
52
|
+
opts.on_tail('-v', '--version', 'Show version') do
|
|
53
|
+
puts VERSION
|
|
54
|
+
exit
|
|
55
|
+
end
|
|
56
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
57
|
+
puts opts
|
|
58
|
+
exit
|
|
59
|
+
end
|
|
60
|
+
end.parse!(argv)
|
|
61
|
+
|
|
62
|
+
options
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def validate_repo!
|
|
66
|
+
abort 'Error: not inside a git repository.' unless Git.in_repo?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def validate_args!(argv)
|
|
70
|
+
return if argv.length >= 2
|
|
71
|
+
|
|
72
|
+
abort "Error: provide a base branch and at least one comparison branch.\n" \
|
|
73
|
+
'Usage: diffstitch <base> <branch1> [branch2 ...]'
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def verify_refs!(base, branches)
|
|
77
|
+
[base, *branches].each { |ref| Git.verify_ref!(ref) }
|
|
78
|
+
rescue Git::Error => e
|
|
79
|
+
abort "Error: #{e.message}"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def collect_diffs(base, branches)
|
|
83
|
+
branches.to_h { |branch| [branch, Git.diff(base, branch)] }
|
|
84
|
+
rescue Git::Error => e
|
|
85
|
+
abort "Error: #{e.message}"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def derived_output(base, branches)
|
|
89
|
+
sanitize = ->(b) { b.gsub(%r{[/\\]}, '-') }
|
|
90
|
+
name = "#{sanitize.call(base)}_vs_#{branches.map(&sanitize).join('_')}"
|
|
91
|
+
File.join(OUTPUT_BASE, name)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def open_in_browser(path)
|
|
95
|
+
Launchy.open(path)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'erb'
|
|
6
|
+
|
|
7
|
+
module Diffstitch
|
|
8
|
+
class Generator
|
|
9
|
+
ASSETS_DIR = File.expand_path('assets', __dir__)
|
|
10
|
+
|
|
11
|
+
def initialize(base:, branches:, diffs:, title:)
|
|
12
|
+
@base = base
|
|
13
|
+
@branches = branches
|
|
14
|
+
@diffs = diffs
|
|
15
|
+
@title = title
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def write(output_dir)
|
|
19
|
+
FileUtils.mkdir_p(output_dir)
|
|
20
|
+
write_data_js(output_dir)
|
|
21
|
+
%w[bootstrap.min.css styles.css app.js].each { |f| FileUtils.cp(asset(f), output_dir) }
|
|
22
|
+
write_html(output_dir)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def asset(name)
|
|
28
|
+
File.join(ASSETS_DIR, name)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def write_data_js(dir)
|
|
32
|
+
payload = JSON.generate({ base: @base, title: @title, branches: @diffs })
|
|
33
|
+
File.write(File.join(dir, 'data.js'), "const DIFF_DATA = #{payload};\n")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def write_html(dir)
|
|
37
|
+
title = @title
|
|
38
|
+
template = ERB.new(File.read(asset('index.html.erb')), trim_mode: '-')
|
|
39
|
+
File.write(File.join(dir, 'index.html'), template.result(binding))
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
|
|
5
|
+
module Diffstitch
|
|
6
|
+
module Git
|
|
7
|
+
class Error < StandardError; end
|
|
8
|
+
|
|
9
|
+
def self.in_repo?
|
|
10
|
+
_, _, status = Open3.capture3('git', 'rev-parse', '--git-dir')
|
|
11
|
+
status.success?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.verify_ref!(ref)
|
|
15
|
+
_, err, status = Open3.capture3('git', 'rev-parse', '--verify', "#{ref}^{commit}")
|
|
16
|
+
raise Error, "'#{ref}' is not a valid branch or commit.\n#{err.strip}" unless status.success?
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.diff(base, branch)
|
|
20
|
+
out, err, status = Open3.capture3('git', 'diff', "#{base}..#{branch}", '--no-color')
|
|
21
|
+
raise Error, "git diff #{base}..#{branch} failed:\n#{err.strip}" unless status.success?
|
|
22
|
+
|
|
23
|
+
out
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
data/lib/diffstitch.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: diffstitch
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.3
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Steven Roomberg
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-05-22 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: launchy
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '3.1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: rake
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '13.0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '13.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.13'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.13'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rubocop
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '1.0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '1.0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rubocop-rspec
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '3.0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - "~>"
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '3.0'
|
|
83
|
+
description: A CLI tool that generates a side-by-side HTML report comparing multiple
|
|
84
|
+
git branches against a common base branch.
|
|
85
|
+
email:
|
|
86
|
+
- stevenroomberg@gmail.com
|
|
87
|
+
executables:
|
|
88
|
+
- diffstitch
|
|
89
|
+
extensions: []
|
|
90
|
+
extra_rdoc_files: []
|
|
91
|
+
files:
|
|
92
|
+
- CHANGELOG.md
|
|
93
|
+
- Gemfile
|
|
94
|
+
- LICENSE
|
|
95
|
+
- bin/diffstitch
|
|
96
|
+
- diffstitch.gemspec
|
|
97
|
+
- lib/diffstitch.rb
|
|
98
|
+
- lib/diffstitch/assets/app.js
|
|
99
|
+
- lib/diffstitch/assets/bootstrap.min.css
|
|
100
|
+
- lib/diffstitch/assets/index.html.erb
|
|
101
|
+
- lib/diffstitch/assets/styles.css
|
|
102
|
+
- lib/diffstitch/cli.rb
|
|
103
|
+
- lib/diffstitch/generator.rb
|
|
104
|
+
- lib/diffstitch/git.rb
|
|
105
|
+
- lib/diffstitch/version.rb
|
|
106
|
+
homepage: https://github.com/sroomberg/diffstitch
|
|
107
|
+
licenses:
|
|
108
|
+
- MIT
|
|
109
|
+
metadata:
|
|
110
|
+
homepage_uri: https://github.com/sroomberg/diffstitch
|
|
111
|
+
source_code_uri: https://github.com/sroomberg/diffstitch
|
|
112
|
+
changelog_uri: https://github.com/sroomberg/diffstitch/blob/main/CHANGELOG.md
|
|
113
|
+
post_install_message:
|
|
114
|
+
rdoc_options: []
|
|
115
|
+
require_paths:
|
|
116
|
+
- lib
|
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
118
|
+
requirements:
|
|
119
|
+
- - ">="
|
|
120
|
+
- !ruby/object:Gem::Version
|
|
121
|
+
version: 2.7.0
|
|
122
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
|
+
requirements:
|
|
124
|
+
- - ">="
|
|
125
|
+
- !ruby/object:Gem::Version
|
|
126
|
+
version: '0'
|
|
127
|
+
requirements: []
|
|
128
|
+
rubygems_version: 3.5.22
|
|
129
|
+
signing_key:
|
|
130
|
+
specification_version: 4
|
|
131
|
+
summary: Compare multiple git branches against a base in a split HTML view
|
|
132
|
+
test_files: []
|