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.
@@ -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">&times;</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">&times;</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 &quot;hash&quot;) 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>
@@ -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
@@ -0,0 +1,3 @@
1
+ module WebGit
2
+ class AuthenticationError < StandardError; end
3
+ end