web_git 0.0.2.1 → 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.
- checksums.yaml +4 -4
- data/Gemfile +7 -20
- data/Gemfile.lock +103 -175
- data/README.markdown +30 -8
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/lib/generators/web_git/install_generator.rb +47 -0
- data/lib/scripts/heroku_login.exp +58 -0
- data/lib/views/status.erb +381 -0
- data/lib/web_git/diff.rb +234 -0
- data/lib/web_git/exceptions.rb +3 -0
- data/lib/web_git/graph.rb +114 -0
- data/lib/web_git/heroku.rb +34 -0
- data/lib/web_git/string.rb +8 -0
- data/lib/web_git.rb +204 -7
- data/web_git.gemspec +33 -74
- metadata +36 -142
- data/ansi2html.sh +0 -514
- data/app/assets/javascripts/web_git/application.js +0 -22
- data/app/assets/javascripts/web_git/bootstrap.min.js +0 -6
- data/app/assets/javascripts/web_git/popper.min.js +0 -4
- data/app/assets/stylesheets/web_git/application.scss +0 -12
- data/app/assets/stylesheets/web_git/bootstrap.min.css +0 -6
- data/app/assets/stylesheets/web_git/font-awesome.min.css +0 -4
- data/app/assets/stylesheets/web_git/octicons.css +0 -5
- data/app/controllers/web_git/application_controller.rb +0 -5
- data/app/controllers/web_git/branches_controller.rb +0 -38
- data/app/controllers/web_git/commands_controller.rb +0 -50
- data/app/controllers/web_git/commits_controller.rb +0 -46
- data/app/views/layouts/web_git/application.html.erb +0 -39
- data/app/views/web_git/commands/hello.html.erb +0 -1
- data/app/views/web_git/commands/status.html.erb +0 -245
- data/config/routes.rb +0 -10
- data/lib/web_git/engine.rb +0 -9
- data/web_git-0.0.2.gem +0 -0
@@ -0,0 +1,381 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
|
7
|
+
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css">
|
8
|
+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
|
9
|
+
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
|
10
|
+
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
|
11
|
+
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
|
12
|
+
<style>
|
13
|
+
.unchanged {
|
14
|
+
display: none !important;
|
15
|
+
}
|
16
|
+
.commit:hover {
|
17
|
+
color: red;
|
18
|
+
}
|
19
|
+
.heroku {
|
20
|
+
background-color: #7952b3;
|
21
|
+
}
|
22
|
+
|
23
|
+
.btn-heroku {
|
24
|
+
color: #fff;
|
25
|
+
background-color: #7952b3;
|
26
|
+
border-color: #7952b3;
|
27
|
+
}
|
28
|
+
|
29
|
+
.btn-heroku:hover {
|
30
|
+
color: #fff;
|
31
|
+
background-color: #614092;
|
32
|
+
border-color: #6d48a4;
|
33
|
+
}
|
34
|
+
.btn-outline-heroku {
|
35
|
+
color: #7952b3;
|
36
|
+
border-color: #7952b3;
|
37
|
+
background-color: #fff;
|
38
|
+
}
|
39
|
+
.border-heroku {
|
40
|
+
border-color: #7952b3 !important;
|
41
|
+
}
|
42
|
+
</style>
|
43
|
+
<title>Git Client</title>
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
<div class="container mt-3">
|
47
|
+
<div class="row">
|
48
|
+
<div class="col-md-12">
|
49
|
+
<% if @notice.present? %>
|
50
|
+
<div class="alert alert-success alert-dismissable" role="alert">
|
51
|
+
<%= @notice %>
|
52
|
+
|
53
|
+
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
54
|
+
<span aria-hidden="true">×</span>
|
55
|
+
</button>
|
56
|
+
</div>
|
57
|
+
<% elsif @alert.present? %>
|
58
|
+
|
59
|
+
<div class="alert alert-warning alert-dismissable" role="alert">
|
60
|
+
<%= @alert %>
|
61
|
+
|
62
|
+
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
63
|
+
<span aria-hidden="true">×</span>
|
64
|
+
</button>
|
65
|
+
</div>
|
66
|
+
<% end %>
|
67
|
+
</div>
|
68
|
+
</div>
|
69
|
+
<ul class="nav nav-tabs nav-fill">
|
70
|
+
<li class="nav-item">
|
71
|
+
<a class="nav-link active" id="git-tab" href="#git">Git</a>
|
72
|
+
</li>
|
73
|
+
<li class="nav-item">
|
74
|
+
<a class="nav-link" id="heroku-tab" href="#heroku">Heroku</a>
|
75
|
+
</li>
|
76
|
+
</ul>
|
77
|
+
|
78
|
+
<div class="tab-content pt-2">
|
79
|
+
<div class="tab-pane active" id="git" role="tabpanel" aria-labelledby="profile-tab">
|
80
|
+
<div class="row mb-4">
|
81
|
+
<div class="col">
|
82
|
+
<div class="card">
|
83
|
+
<h1 class="card-header">
|
84
|
+
<% if !@diff.nil? %>
|
85
|
+
On branch <code><%= @current_branch %></code>
|
86
|
+
<% else %>
|
87
|
+
<code>git status</code>
|
88
|
+
<% end %>
|
89
|
+
</h1>
|
90
|
+
|
91
|
+
<div class="card-body">
|
92
|
+
<%# if false %>
|
93
|
+
<% unless @status.include?("nothing to commit, working tree clean") %>
|
94
|
+
<p class="h4 mb-3 text-center">
|
95
|
+
You have changes
|
96
|
+
</p>
|
97
|
+
<% @statuses.each do |status| %>
|
98
|
+
<% filelist = status[:file_list].join("\n") %>
|
99
|
+
<% if filelist.length > 0 %>
|
100
|
+
<%= status[:name] %>
|
101
|
+
<pre><%= filelist.strip %></pre>
|
102
|
+
<% end %>
|
103
|
+
<% end %>
|
104
|
+
|
105
|
+
<% if !@diff.nil? %>
|
106
|
+
<%= @diff %>
|
107
|
+
<% end %>
|
108
|
+
|
109
|
+
<p class="h4 my-3 text-center">
|
110
|
+
What do you want to do?
|
111
|
+
</p>
|
112
|
+
|
113
|
+
<div class="row">
|
114
|
+
<div class="col">
|
115
|
+
<div class="card">
|
116
|
+
<div class="card-header h6">
|
117
|
+
Commit your changes to the current branch
|
118
|
+
</div>
|
119
|
+
|
120
|
+
<div class="card-body">
|
121
|
+
<form action="/git/commit" method="post">
|
122
|
+
<div class="form-group">
|
123
|
+
<label for="title">Title</label>
|
124
|
+
<input class="form-control" type="text" name="title" placeholder="Enter a title for your commit (required)..." required>
|
125
|
+
</div>
|
126
|
+
|
127
|
+
<div class="form-group">
|
128
|
+
<label for="description">Description</label>
|
129
|
+
<textarea class="form-control" name="description" placeholder="Enter a longer description of your changes (optional)..."></textarea>
|
130
|
+
</div>
|
131
|
+
|
132
|
+
<button class="btn btn-primary btn-block">
|
133
|
+
Commit to <%= @current_branch %>
|
134
|
+
</button>
|
135
|
+
</form>
|
136
|
+
</div>
|
137
|
+
</div>
|
138
|
+
</div>
|
139
|
+
|
140
|
+
<div class="col">
|
141
|
+
<div class="row mb-2">
|
142
|
+
<div class="col">
|
143
|
+
<div class="card">
|
144
|
+
<div class="card-header h6">
|
145
|
+
Switch to a new branch
|
146
|
+
</div>
|
147
|
+
|
148
|
+
<div class="card-body">
|
149
|
+
<form action="/git/branch/checkout" class="full-width mb-2" method="post">
|
150
|
+
<div class="form-group">
|
151
|
+
<label for="branch_name" class="sr-only">Branch name</label>
|
152
|
+
<input type="text" name="branch_name" id="branch_name" class="form-control" placeholder="Enter a name for the branch to create..." required>
|
153
|
+
</div>
|
154
|
+
<button class="btn btn-success btn-block">
|
155
|
+
<i class="fas fa-code-branch mr-1"></i>
|
156
|
+
Create a new branch
|
157
|
+
</button>
|
158
|
+
</form>
|
159
|
+
</div>
|
160
|
+
</div>
|
161
|
+
</div>
|
162
|
+
</div>
|
163
|
+
|
164
|
+
<div class="row">
|
165
|
+
<div class="col">
|
166
|
+
<div class="card">
|
167
|
+
<div class="card-header h6">
|
168
|
+
Discard your changes
|
169
|
+
</div>
|
170
|
+
|
171
|
+
<div class="card-body">
|
172
|
+
<a class="btn btn-block btn-danger" href="/git/stash">
|
173
|
+
<i class="far fa-trash-alt"></i>
|
174
|
+
Discard your changes
|
175
|
+
</a>
|
176
|
+
</div>
|
177
|
+
</div>
|
178
|
+
</div>
|
179
|
+
</div>
|
180
|
+
</div>
|
181
|
+
</div>
|
182
|
+
|
183
|
+
<% else %>
|
184
|
+
|
185
|
+
<div class="row">
|
186
|
+
<div class="col">
|
187
|
+
<h6 class="card-subtitle mb-2 text-muted">
|
188
|
+
<div>
|
189
|
+
Remote:
|
190
|
+
</div>
|
191
|
+
<%= @remotes.first %>
|
192
|
+
</h6>
|
193
|
+
<pre><%= @status %></pre>
|
194
|
+
<%# TODO why is this here? %>
|
195
|
+
<% if @current_branch != "master" %>
|
196
|
+
<form action="/git/push" method="post">
|
197
|
+
<button type="submit" class="btn btn-primary btn-block mb-4" data-html="true" data-toggle="tooltip" data-placement="top" title="<code>git push</code>">
|
198
|
+
<i class="fas fa-upload mr-1"></i>
|
199
|
+
Push to GitHub
|
200
|
+
</button>
|
201
|
+
</form>
|
202
|
+
<% else %>
|
203
|
+
<form action="/git/push" method="post">
|
204
|
+
<button type="submit" class="btn btn-primary btn-block mb-4" data-html="true" data-toggle="tooltip" data-placement="top" title="<code>git push -u origin <%= @current_branch %></code>">
|
205
|
+
<i class="fas fa-upload mr-1"></i>
|
206
|
+
Push to GitHub
|
207
|
+
</button>
|
208
|
+
</form>
|
209
|
+
<% end %>
|
210
|
+
<form action="/git/pull" method="post">
|
211
|
+
<button type="submit" class="btn btn-primary btn-block mb-4" data-html="true" data-toggle="tooltip" data-placement="top" title="<code>git pull</code>">
|
212
|
+
<i class="fas fa-download mr-1"></i>
|
213
|
+
Pull from GitHub
|
214
|
+
</button>
|
215
|
+
</form>
|
216
|
+
<p>
|
217
|
+
The last thing you did was:
|
218
|
+
</p>
|
219
|
+
|
220
|
+
<blockquote class="blockquote">
|
221
|
+
<%= @last_commit_message %>
|
222
|
+
</blockquote>
|
223
|
+
<a href="#latest_diff_html" class="btn btn-secondary btn-block mb-4" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="latest_diff_html">
|
224
|
+
<i class="far fa-eye mr-1"></i>
|
225
|
+
Show last commit
|
226
|
+
</a>
|
227
|
+
|
228
|
+
<div id="latest_diff_html" class="collapse">
|
229
|
+
<iframe srcdoc="<%= @last_diff_html %>" width="100%" height="400" class="mb-3">
|
230
|
+
</iframe>
|
231
|
+
</div>
|
232
|
+
</div>
|
233
|
+
|
234
|
+
<div class="col">
|
235
|
+
<ul class="list-group">
|
236
|
+
<li class="list-group-item list-group-item-success">
|
237
|
+
New Branch
|
238
|
+
</li>
|
239
|
+
|
240
|
+
<li class="list-group-item">
|
241
|
+
<form action="/git/branch/checkout" method="post">
|
242
|
+
<div class="form-group">
|
243
|
+
<label for="branch_name">
|
244
|
+
Go ahead, experiment!
|
245
|
+
</label>
|
246
|
+
<input
|
247
|
+
id="branch_name" class="form-control" type="text"
|
248
|
+
name="branch_name" required
|
249
|
+
placeholder="Enter a name for the new branch..."
|
250
|
+
>
|
251
|
+
</div>
|
252
|
+
<button class="btn btn-success btn-block"
|
253
|
+
data-html="true" data-toggle="tooltip"
|
254
|
+
data-placement="top" title="<code>git checkout -b [BRANCH NAME]</code>"
|
255
|
+
>
|
256
|
+
<i class="fas fa-code-branch mr-1"></i>
|
257
|
+
Create branch
|
258
|
+
</button>
|
259
|
+
</form>
|
260
|
+
</li>
|
261
|
+
<li class="list-group-item list-group-item-info">
|
262
|
+
Existing branches
|
263
|
+
</li>
|
264
|
+
<% @branches.each do |branch| %>
|
265
|
+
<li class="list-group-item justify-content-between">
|
266
|
+
<%= branch %>
|
267
|
+
<div class="btn-group">
|
268
|
+
<!-- TODO method post, pass branch name-->
|
269
|
+
<form action="/git/branch/checkout" method="post">
|
270
|
+
<button value="<%= branch %>" name="branch_name" type="submit" class="btn btn-primary btn-sm" data-html="true" data-toggle="tooltip" data-placement="top" title="<code>git checkout <%= branch %></code>">
|
271
|
+
<i class="fas fa-exchange-alt"></i>
|
272
|
+
</button>
|
273
|
+
</form>
|
274
|
+
<form action="/git/branch/delete" method="post">
|
275
|
+
<button type="submit" value="<%= branch %>" name="branch_name" class="btn btn-warning btn-sm" data-html="true" data-toggle="tooltip" data-placement="top" title="<code>git branch -d <%= branch %></code>">
|
276
|
+
<i class="far fa-trash-alt"></i>
|
277
|
+
</button>
|
278
|
+
</form>
|
279
|
+
</div>
|
280
|
+
</li>
|
281
|
+
<% end %>
|
282
|
+
</ul>
|
283
|
+
</div>
|
284
|
+
</div>
|
285
|
+
<% end %>
|
286
|
+
</div>
|
287
|
+
</div>
|
288
|
+
</div>
|
289
|
+
</div>
|
290
|
+
|
291
|
+
<div class="row mb-4">
|
292
|
+
<div class="col">
|
293
|
+
<div class="card">
|
294
|
+
<h2 class="card-header">
|
295
|
+
History
|
296
|
+
</h2>
|
297
|
+
|
298
|
+
<div class="card-body">
|
299
|
+
<p class="lead">Do you want to jump back in time and go down a different path?</p>
|
300
|
+
<form action="/git/branch/checkout/new" method="post">
|
301
|
+
<div class="form-group">
|
302
|
+
<label for="commit_hash">Branch off of</label>
|
303
|
+
<input type="text" class="form-control" name="commit_hash"
|
304
|
+
id="commit_hash" required
|
305
|
+
placeholder="Enter the sequence of digits preceding the commit (it's "hash") that you want to branch off of...">
|
306
|
+
</div>
|
307
|
+
|
308
|
+
<div class="form-group">
|
309
|
+
<label for="branch_name">Branch name</label>
|
310
|
+
<input type="text" class="form-control" name="branch_name"
|
311
|
+
id="branch_name" placeholder="Enter a name for the new branch..."
|
312
|
+
required >
|
313
|
+
</div>
|
314
|
+
|
315
|
+
<% if @changed_files.count > 0 %>
|
316
|
+
<button disabled="disabled" class="btn btn-primary btn-block">
|
317
|
+
Can't go back in time while you have pending changes. Commit or discard them first.
|
318
|
+
</button>
|
319
|
+
<% else %>
|
320
|
+
<!-- TODO use JS to replace -->
|
321
|
+
<button class="btn btn-success btn-block" data-toggle="tooltip" data-html="true" data-placement="top" title="<code>git checkout [OLD HASH]; git checkout -b [NEW BRANCH NAME]</code>">
|
322
|
+
Create a new branch off of previous commit
|
323
|
+
</button>
|
324
|
+
<% end%>
|
325
|
+
</form>
|
326
|
+
</div>
|
327
|
+
<pre class="bg-dark text-white p-3"><%= @cli_graph_interactive %></pre>
|
328
|
+
</div>
|
329
|
+
</div>
|
330
|
+
</div>
|
331
|
+
</div>
|
332
|
+
<div class="tab-pane" id="heroku" role="tabpanel" aria-labelledby="home-tab">
|
333
|
+
<ul class="list-group">
|
334
|
+
<li class="list-group-item heroku text-white d-flex justify-content-between">
|
335
|
+
<% if @heroku_auth.empty? %>
|
336
|
+
<span>Log in</span>
|
337
|
+
<% else %>
|
338
|
+
<span>Logged in as:</span>
|
339
|
+
<span><%= @heroku_auth %></span>
|
340
|
+
<% end %>
|
341
|
+
</li>
|
342
|
+
<% if @heroku_auth.empty? %>
|
343
|
+
<div class="border border-heroku p-4">
|
344
|
+
<form action="/git/heroku/login" method="post">
|
345
|
+
<div class="form-group">
|
346
|
+
<label for="heroku_email">Email address</label>
|
347
|
+
<input type="email" class="form-control" name="heroku_email" id="heroku_email" aria-describedby="emailHelp">
|
348
|
+
</div>
|
349
|
+
<div class="form-group">
|
350
|
+
<label for="heroku_password">Password</label>
|
351
|
+
<input type="password" class="form-control" name="heroku_password" id="heroku_password">
|
352
|
+
</div>
|
353
|
+
<button type="submit" data-html="true" data-toggle="tooltip"
|
354
|
+
data-placement="top" title="<code>heroku login -i</code>" class="btn btn-heroku btn-block">Log in</button>
|
355
|
+
</form>
|
356
|
+
</div>
|
357
|
+
|
358
|
+
<% end %>
|
359
|
+
</ul>
|
360
|
+
</div>
|
361
|
+
</div>
|
362
|
+
</div>
|
363
|
+
<script>
|
364
|
+
|
365
|
+
$(document).ready(function() {
|
366
|
+
$(".sha").click(function() {
|
367
|
+
var text = this.textContent
|
368
|
+
$("#commit_hash").val(text);
|
369
|
+
});
|
370
|
+
$(function () {
|
371
|
+
$('[data-toggle="tooltip"]').tooltip()
|
372
|
+
})
|
373
|
+
$('.nav-tabs a').on('click', function (event) {
|
374
|
+
event.preventDefault()
|
375
|
+
$(this).tab('show')
|
376
|
+
})
|
377
|
+
});
|
378
|
+
|
379
|
+
</script>
|
380
|
+
</body>
|
381
|
+
</html>
|
data/lib/web_git/diff.rb
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
|
2
|
+
require "diffy"
|
3
|
+
require "git"
|
4
|
+
class Diff
|
5
|
+
|
6
|
+
def self.get_diff
|
7
|
+
# Dir.chdir(Rails.root) do
|
8
|
+
`git diff`
|
9
|
+
# end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.get_each_left(diff)
|
13
|
+
filenames = get_file_names("")
|
14
|
+
files = file_diffs(diff)
|
15
|
+
lefts = {}
|
16
|
+
files.each_with_index do |file, i|
|
17
|
+
file_content = ""
|
18
|
+
lines = file.split("\n").drop(4)
|
19
|
+
start_line = 0
|
20
|
+
current_line_index = 0
|
21
|
+
line_number = start_line + current_line_index
|
22
|
+
lines.each do |line|
|
23
|
+
if !line.match?(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/)
|
24
|
+
if line[0] != "+"
|
25
|
+
file_content += "#{line_number}| " + line + "\n"
|
26
|
+
line_number += 1
|
27
|
+
end
|
28
|
+
else
|
29
|
+
current_line_index = 0
|
30
|
+
# The line numbers in the output of a git diff match this regex
|
31
|
+
numbers = line.scan(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/).map(&:join)
|
32
|
+
# If left, starting line number is the first one in a split Array
|
33
|
+
start_line = numbers[0].split(" ")[0].
|
34
|
+
split(",")[0].to_i.abs
|
35
|
+
line_number = start_line + current_line_index
|
36
|
+
file_content += "\n"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
lefts[filenames[i]] = file_content.chomp "\n"
|
40
|
+
end
|
41
|
+
lefts
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.get_each_right(diff)
|
45
|
+
filenames = get_file_names("")
|
46
|
+
files = file_diffs(diff)
|
47
|
+
rights = {}
|
48
|
+
files.each_with_index do |file, i|
|
49
|
+
file_content = ""
|
50
|
+
lines = file.split("\n").drop(4)
|
51
|
+
start_line = 0
|
52
|
+
current_line_index = 0
|
53
|
+
line_number = start_line + current_line_index
|
54
|
+
lines.each do |line|
|
55
|
+
# The line numbers in the output of a git diff match this regex
|
56
|
+
# @@ -61,18 +61,15 @@
|
57
|
+
if !line.match?(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/)
|
58
|
+
if line[0] != "-"
|
59
|
+
file_content += "#{line_number}| " + line + "\n"
|
60
|
+
line_number += 1
|
61
|
+
end
|
62
|
+
else
|
63
|
+
current_line_index = 0
|
64
|
+
numbers = line.scan(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/).map(&:join)
|
65
|
+
# If right, start line is the second in a split Array
|
66
|
+
start_line = numbers[0].split(" ")[1].
|
67
|
+
split(",")[0].to_i.abs
|
68
|
+
line_number = start_line + current_line_index
|
69
|
+
file_content += "\n"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
rights[filenames[i]] = file_content.chomp "\n"
|
73
|
+
end
|
74
|
+
rights
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.get_last_commit_hash
|
78
|
+
working_dir = Dir.pwd
|
79
|
+
git = Git.open(working_dir)
|
80
|
+
git.log.first.sha.slice(0, 7)
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.file_diffs(diff)
|
84
|
+
diff.scan(/diff --git.*?(?=diff --git|\z)/m)
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.match_other_files(line, file, filenames)
|
88
|
+
filenames.each do |other_file|
|
89
|
+
if file != other_file
|
90
|
+
# It looks like:
|
91
|
+
# --- a/<path-to-file>
|
92
|
+
# +++ b/<path-to-file>
|
93
|
+
if line.include?('diff --git a/' + other_file + ' b/' + other_file)
|
94
|
+
return true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
false
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.get_file_names(commit)
|
102
|
+
git = Git.open(Dir.pwd)
|
103
|
+
if commit.empty?
|
104
|
+
filenames = git.status.changed.keys
|
105
|
+
else
|
106
|
+
filenames = git.diff(commit, "HEAD").map(&:path)
|
107
|
+
end
|
108
|
+
filenames
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.get_last_diff
|
112
|
+
# Dir.chdir(Rails.root) do
|
113
|
+
`git diff -M HEAD~1`
|
114
|
+
# end
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.get_last_left(diff)
|
118
|
+
filenames = get_file_names("HEAD~1")
|
119
|
+
files = file_diffs(diff)
|
120
|
+
ones = {}
|
121
|
+
files.each_with_index do |file, i|
|
122
|
+
file_content = ""
|
123
|
+
lines = file.split("\n").drop(4)
|
124
|
+
lines.each do |line|
|
125
|
+
# The line numbers in the output of a git diff match this regex
|
126
|
+
# @@ -61,18 +61,15 @@
|
127
|
+
if !line.match?(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/)
|
128
|
+
if line[0] != "+"
|
129
|
+
line.slice!(0)
|
130
|
+
file_content += line + "\n"
|
131
|
+
end
|
132
|
+
else
|
133
|
+
file_content += "\n"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
ones[filenames[i]] = file_content.chomp "\n"
|
137
|
+
end
|
138
|
+
ones
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.get_last_right(diff)
|
142
|
+
filenames = get_file_names("HEAD~1")
|
143
|
+
files = file_diffs(diff)
|
144
|
+
ones = {}
|
145
|
+
files.each_with_index do |file, i|
|
146
|
+
file_content = ""
|
147
|
+
lines = file.split("\n").drop(4)
|
148
|
+
lines.each do |line|
|
149
|
+
if !line.match?(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/)
|
150
|
+
if line[0] != "+"
|
151
|
+
elsif line[0] == "+"
|
152
|
+
line.slice!(0)
|
153
|
+
file_content += line + "\n"
|
154
|
+
end
|
155
|
+
else
|
156
|
+
file_content += "\n"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
ones[filenames[i]] = file_content.chomp "\n"
|
160
|
+
end
|
161
|
+
ones
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.last_to_html(diff)
|
165
|
+
left_hash = get_last_left(diff)
|
166
|
+
right_hash = get_last_right(diff)
|
167
|
+
|
168
|
+
html_output = '<link rel="stylesheet"' +
|
169
|
+
'href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/' +
|
170
|
+
'bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/' +
|
171
|
+
'1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">'
|
172
|
+
html_output += '<style>'
|
173
|
+
html_output += Diffy::CSS
|
174
|
+
html_output += '</style>'
|
175
|
+
html_output += '<div class="card" style="overflow-y: scroll;max-height:400px">'
|
176
|
+
left_hash.keys.each do |file|
|
177
|
+
html_output += '<div class="file mb-4 p-1">'
|
178
|
+
html_output += '<h4>' + file + '</h4>'
|
179
|
+
html_output += Diffy::Diff.new(
|
180
|
+
left_hash[file],
|
181
|
+
right_hash[file],
|
182
|
+
:include_plus_and_minus_in_html => true,
|
183
|
+
:allow_empty_diff => false
|
184
|
+
).to_s(:html)
|
185
|
+
html_output += '</div>'
|
186
|
+
end
|
187
|
+
html_output += '</div>'
|
188
|
+
html_output
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.diff_to_html(diff)
|
192
|
+
left_hash = get_each_left(diff)
|
193
|
+
right_hash = get_each_right(diff)
|
194
|
+
html_output = '<div style="overflow-y: scroll;height:400px">'
|
195
|
+
html_output += '<style>'
|
196
|
+
html_output += Diffy::CSS
|
197
|
+
html_output += '</style>'
|
198
|
+
html_output += '<div class="row mb-3">'
|
199
|
+
html_output += '<div class="col-md-12 offset" style="overflow-y: scroll;">'
|
200
|
+
|
201
|
+
left_hash.keys.each do |file|
|
202
|
+
html_output += '<div class="row text-center">
|
203
|
+
<div class="col-12">
|
204
|
+
<h4>'
|
205
|
+
html_output+= file.to_s
|
206
|
+
html_output += '</h4>
|
207
|
+
</div>
|
208
|
+
</div>
|
209
|
+
<div class="row mb-4">
|
210
|
+
<div class="col-6">'
|
211
|
+
html_output += Diffy::SplitDiff.new(
|
212
|
+
left_hash[file],
|
213
|
+
right_hash[file],
|
214
|
+
:format => :html
|
215
|
+
).left
|
216
|
+
|
217
|
+
html_output +=
|
218
|
+
'</div>
|
219
|
+
<div class="col-6">'
|
220
|
+
html_output += Diffy::SplitDiff.new(
|
221
|
+
left_hash[file],
|
222
|
+
right_hash[file],
|
223
|
+
:format => :html
|
224
|
+
).right
|
225
|
+
|
226
|
+
html_output += '</div></div>'
|
227
|
+
end
|
228
|
+
html_output += "</div>"
|
229
|
+
html_output += "</div>"
|
230
|
+
html_output += "</div>"
|
231
|
+
html_output
|
232
|
+
|
233
|
+
end
|
234
|
+
end
|