web_git 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/web_git/diff.rb CHANGED
@@ -1,233 +1,234 @@
1
- module WebGit
2
- class Diff
3
- def self.get_diff
4
- Dir.chdir(Rails.root) do
5
- `git diff`
6
- end
7
- end
8
1
 
9
- def self.get_each_left(diff)
10
- filenames = get_file_names("")
11
- files = file_diffs(diff)
12
- lefts = {}
13
- files.each_with_index do |file, i|
14
- file_content = ""
15
- lines = file.split("\n").drop(4)
16
- start_line = 0
17
- current_line_index = 0
18
- line_number = start_line + current_line_index
19
- lines.each do |line|
20
- if !line.match?(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/)
21
- if line.first != "+"
22
- file_content += "#{line_number}| " + line + "\n"
23
- line_number += 1
24
- end
25
- else
26
- current_line_index = 0
27
- # The line numbers in the output of a git diff match this regex
28
- numbers = line.scan(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/).map(&:join)
29
- # If left, starting line number is the first one in a split Array
30
- start_line = numbers.first.split(" ").first.
31
- split(",").first.to_i.abs
32
- line_number = start_line + current_line_index
33
- file_content += "\n"
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
34
27
  end
35
- end
36
- lefts[filenames[i]] = file_content.chomp "\n"
37
- end
38
- lefts
39
- end
40
-
41
- def self.get_each_right(diff)
42
- filenames = get_file_names("")
43
- files = file_diffs(diff)
44
- rights = {}
45
- files.each_with_index do |file, i|
46
- file_content = ""
47
- lines = file.split("\n").drop(4)
48
- start_line = 0
49
- current_line_index = 0
50
- line_number = start_line + current_line_index
51
- lines.each do |line|
28
+ else
29
+ current_line_index = 0
52
30
  # The line numbers in the output of a git diff match this regex
53
- # @@ -61,18 +61,15 @@
54
- if !line.match?(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/)
55
- if line.first != "-"
56
- file_content += "#{line_number}| " + line + "\n"
57
- line_number += 1
58
- end
59
- else
60
- current_line_index = 0
61
- numbers = line.scan(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/).map(&:join)
62
- # If right, start line is the second in a split Array
63
- start_line = numbers.first.split(" ").second.
64
- split(",").first.to_i.abs
65
- line_number = start_line + current_line_index
66
- file_content += "\n"
67
- end
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"
68
37
  end
69
- rights[filenames[i]] = file_content.chomp "\n"
70
38
  end
71
- rights
39
+ lefts[filenames[i]] = file_content.chomp "\n"
72
40
  end
73
-
74
- def self.get_last_commit_hash
75
- Dir.chdir(Rails.root) do
76
- log = `git log -1 --oneline`
77
- log.split.first
78
- end
79
- end
80
-
81
- def self.file_diffs(diff)
82
- diff.scan(/diff --git.*?(?=diff --git|\z)/m)
83
- end
84
-
85
- def self.match_other_files(line, file, filenames)
86
- filenames.each do |other_file|
87
- if file != other_file
88
- # It looks like:
89
- # --- a/<path-to-file>
90
- # +++ b/<path-to-file>
91
- if line.include?('diff --git a/' + other_file + ' b/' + other_file)
92
- return true
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
93
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"
94
70
  end
95
71
  end
96
- false
72
+ rights[filenames[i]] = file_content.chomp "\n"
97
73
  end
98
-
99
- def self.get_file_names(commit)
100
- Dir.chdir(Rails.root) do
101
- if commit.blank?
102
- filenames = `git diff --name-only`
103
- else
104
- filenames = `git diff-tree --no-commit-id --name-only -r #{commit}`
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
105
95
  end
106
- filenames.split("\n")
107
96
  end
108
97
  end
109
-
110
- def self.get_last_diff
111
- Dir.chdir(Rails.root) do
112
- `git diff -M HEAD~1`
113
- 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)
114
107
  end
115
-
116
- def self.get_last_left(diff)
117
- filenames = get_file_names(get_last_commit_hash)
118
- files = file_diffs(diff)
119
- ones = {}
120
- files.each_with_index do |file, i|
121
- file_content = ""
122
- lines = file.split("\n").drop(4)
123
- lines.each do |line|
124
- # The line numbers in the output of a git diff match this regex
125
- # @@ -61,18 +61,15 @@
126
- if !line.match?(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/)
127
- if line.first != "+"
128
- line.slice!(0)
129
- file_content += line + "\n"
130
- end
131
- else
132
- file_content += "\n"
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"
133
131
  end
132
+ else
133
+ file_content += "\n"
134
134
  end
135
- ones[filenames[i]] = file_content.chomp "\n"
136
135
  end
137
- ones
136
+ ones[filenames[i]] = file_content.chomp "\n"
138
137
  end
139
-
140
- def self.get_last_right(diff)
141
- filenames = get_file_names(get_last_commit_hash)
142
- files = file_diffs(diff)
143
- ones = {}
144
- files.each_with_index do |file, i|
145
- file_content = ""
146
- lines = file.split("\n").drop(4)
147
- lines.each do |line|
148
- if !line.match?(/@@ ([-]\d+,\d+\s[+]\d+,\d+) @@/)
149
- if line.first != "+"
150
- elsif line.first == "+"
151
- line.slice!(0)
152
- file_content += line + "\n"
153
- end
154
- else
155
- file_content += "\n"
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"
156
154
  end
155
+ else
156
+ file_content += "\n"
157
157
  end
158
- ones[filenames[i]] = file_content.chomp "\n"
159
158
  end
160
- ones
159
+ ones[filenames[i]] = file_content.chomp "\n"
161
160
  end
162
-
163
- def self.last_to_html(diff)
164
- left_hash = get_last_left(diff)
165
- right_hash = get_last_right(diff)
166
-
167
- html_output = '<link rel="stylesheet"' +
168
- 'href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/' +
169
- 'bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/' +
170
- '1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">'
171
- html_output += '<style>'
172
- html_output += Diffy::CSS
173
- html_output += '</style>'
174
- html_output += '<div class="card">'
175
- left_hash.keys.each do |file|
176
- html_output += '<div class="file mb-4 p-3">'
177
- html_output += '<h4>' + file + '</h4>'
178
- html_output += Diffy::Diff.new(
179
- left_hash[file],
180
- right_hash[file],
181
- :include_plus_and_minus_in_html => true
182
- ).to_s(:html)
183
- html_output += '</div>'
184
- 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
185
  html_output += '</div>'
186
- html_output
187
186
  end
188
-
189
- def self.diff_to_html(diff)
190
- left_hash = get_each_left(diff)
191
- right_hash = get_each_right(diff)
192
- html_output = '<div style="overflow-y: scroll;height:400px">'
193
- html_output += '<style>'
194
- html_output += Diffy::CSS
195
- html_output += '</style>'
196
- html_output += '<div class="row mb-3">'
197
- html_output += '<div class="col-md-12 offset" style="overflow-y: scroll;">'
198
-
199
- left_hash.keys.each do |file|
200
- html_output += '<div class="row text-center">
201
- <div class="col-12">
202
- <h4>'
203
- html_output+= file.to_s
204
- html_output += '</h4>
205
- </div>
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>
206
207
  </div>
207
- <div class="row mb-4">
208
- <div class="col-6">'
209
- html_output += Diffy::SplitDiff.new(
210
- left_hash[file],
211
- right_hash[file],
212
- :format => :html
213
- ).left
214
-
215
- html_output +=
216
- '</div>
217
- <div class="col-6">'
218
- html_output += Diffy::SplitDiff.new(
219
- left_hash[file],
220
- right_hash[file],
221
- :format => :html
222
- ).right
223
-
224
- html_output += '</div></div>'
225
- end
226
- html_output += "</div>"
227
- html_output += "</div>"
228
- html_output += "</div>"
229
- html_output
230
-
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>'
231
227
  end
228
+ html_output += "</div>"
229
+ html_output += "</div>"
230
+ html_output += "</div>"
231
+ html_output
232
+
233
+ end
232
234
  end
233
- end
@@ -0,0 +1,3 @@
1
+ module WebGit
2
+ class AuthenticationError < StandardError; end
3
+ end
@@ -0,0 +1,114 @@
1
+ module WebGit
2
+ require "git"
3
+ require "ansispan"
4
+
5
+ class Graph
6
+ require "action_view"
7
+ require "action_view/helpers"
8
+ include ActionView::Helpers::DateHelper
9
+ attr_accessor :heads
10
+
11
+ def initialize(git)
12
+ @git = git
13
+ @full_list = []
14
+ @heads = {}
15
+ end
16
+
17
+ def to_hash
18
+
19
+ has_changes = has_untracked_changes?
20
+ if has_changes
21
+ temporarily_stash_changes
22
+ end
23
+
24
+ draw_graph
25
+
26
+ if has_changes
27
+ stash_pop
28
+ end
29
+ @full_list
30
+ end
31
+
32
+ def self.project_root
33
+ if defined?(Rails) && Rails.respond_to?("root")
34
+ return Rails.root
35
+ end
36
+
37
+ if defined?(Bundler)
38
+ return Bundler.root
39
+ end
40
+
41
+ Dir.pwd
42
+ end
43
+
44
+ def cli_graph
45
+ Dir.chdir(Graph.project_root) do
46
+ @cli_graph = `git log --oneline --decorate --graph --all --color`
47
+ all_commits = `git log --all --format=format:%H`.split("\n").map{|a| a.slice(0,7)}
48
+
49
+ @cli_graph = Ansispan.convert(@cli_graph)
50
+ all_commits.each do |sha|
51
+ sha_button = "<span class=\"commit\"><button class=\"btn btn-link sha\">#{sha}</button></span>"
52
+ @cli_graph.gsub!(sha, sha_button)
53
+ end
54
+ end
55
+ @cli_graph
56
+ end
57
+
58
+ def has_untracked_changes?
59
+ @git.diff.size > 0
60
+ end
61
+
62
+ def temporarily_stash_changes
63
+ @git.add(all: true)
64
+ stash_count = Git::Stashes.new(@git).count
65
+ Git::Stash.new(@git, "Temporary Stash #{stash_count}")
66
+ end
67
+
68
+ def stash_pop
69
+ stashes = Git::Stashes.new(@git)
70
+ stashes.apply(0)
71
+ end
72
+
73
+ def draw_graph
74
+ starting_branch = @git.current_branch
75
+ branches = @git.branches.local.map(&:name)
76
+ branches.each do |branch_name|
77
+ branch = { branch: branch_name }
78
+ @git.checkout(branch_name)
79
+ log_commits = build_array_of_commit_hashes
80
+ branch[:log] = log_commits
81
+ branch[:head] = log_commits.last[:sha]
82
+ @full_list.push branch
83
+ end
84
+ @git.checkout(starting_branch)
85
+
86
+ @full_list.each do |branch_hash|
87
+ head_sha = branch_hash[:head]
88
+ branch_name = branch_hash[:branch]
89
+
90
+ if @heads[head_sha].nil?
91
+ @heads[head_sha] = [branch_name]
92
+ else
93
+ @heads[head_sha].push branch_name
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+ def build_array_of_commit_hashes
100
+ log_commits = []
101
+ @git.log.sort_by(&:date).each do |git_commit_object|
102
+ commit = {}
103
+ commit[:sha] = git_commit_object.sha.slice(0..7)
104
+ commit[:date] = git_commit_object.date
105
+ commit[:formatted_date] = time_ago_in_words(git_commit_object.date)
106
+ commit[:message] = git_commit_object.message
107
+ commit[:author] = git_commit_object.author.name
108
+ commit[:heads] = []
109
+ log_commits.push commit
110
+ end
111
+ log_commits
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,34 @@
1
+ require 'timeout'
2
+ require 'web_git/exceptions'
3
+
4
+ module WebGit
5
+ class Heroku
6
+ def self.authenticate(email, password)
7
+ raise ArgumentError.new("Email and password cannot be blank.") if email.blank? || password.blank?
8
+ script = File.join( File.dirname(__FILE__), '/../scripts/heroku_login.exp')
9
+
10
+ command = "#{script} #{email} #{password}"
11
+ rout, wout = IO.pipe
12
+ pid = Process.spawn(command, :out => wout)
13
+
14
+ begin
15
+ status = Timeout.timeout(30) do
16
+ _, status = Process.wait2(pid)
17
+ wout.close
18
+ end
19
+ stdout = rout.readlines.join("\n")
20
+ rout.close
21
+ message = stdout.match(/Error.*\./).to_s
22
+ raise WebGit::AuthenticationError.new(message) if stdout.include?("Error")
23
+
24
+ rescue Timeout::Error
25
+ Process.kill('TERM', script_pid)
26
+ raise Timeout::Error.new("Sign in took longer than 30 seconds.")
27
+ end
28
+ end
29
+
30
+ def self.whoami
31
+ `heroku whoami`.chomp
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,8 @@
1
+ # required for git
2
+ class String
3
+ def strip_heredoc
4
+ indent = scan(/^[ \t]*(?=\S)/).min.size || 0
5
+ gsub(/^[ \t]{#{indent}}/, '')
6
+ end
7
+ end
8
+