Module: Autowow::Features::Vcs
Class Method Summary
collapse
Instance Method Summary
collapse
Methods included from Executor
#pretty, #pretty_with_output, #quiet, #tty_params
#add, #add_remote, #branch, #branch_force_delete, #branch_list, #changes_not_on_remote, #checkout, #cmd, #commit, #create, #current_branch, #current_ref, #fetch, #git_status, #hard_reset, #merge, #pull, #push, #rebase, #remotes, #set_upstream, #show_ref, #stash, #stash_pop, #terminal_options, #upstream_tracking
Class Method Details
.add_upstream ⇒ Object
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
# File 'lib/autowow/features/vcs.rb', line 69
def self.add_upstream
logger.error("Not a git repository.") and return unless is_git?
logger.warn("Already has upstream.") and return if has_upstream?
remote_list = pretty_with_output.run(remotes).out
url = URI.parse(origin_push_url(remote_list))
host = "api.#{url.host}"
path = "/repos#{url.path}"
request = Net::HTTP.new(host, url.port)
request.verify_mode = OpenSSL::SSL::VERIFY_NONE
request.use_ssl = url.scheme == "https"
logger.info("Fetching repo info from #{host}#{path}\n\n")
response = request.get(path)
if response.kind_of?(Net::HTTPRedirection)
logger.error("Repository moved / renamed. Update remote or implement redirect handling. :)")
elsif response.kind_of?(Net::HTTPNotFound)
logger.error("Repository not found. Maybe it is private.")
elsif response.kind_of?(Net::HTTPSuccess)
parsed_response = JSON.parse(response.body)
logger.warn("Not a fork.") and return unless parsed_response["fork"]
parent_url = parsed_response.dig("parent", "html_url")
pretty.run(add_remote("upstream", parent_url)) unless parent_url.to_s.empty?
pretty_with_output.run(remotes)
else
logger.error("Github API (#{url.scheme}://#{host}#{path}) could not be reached: #{response.body}")
end
end
|
.clear_branches ⇒ Object
124
125
126
127
128
129
130
131
132
133
134
135
136
|
# File 'lib/autowow/features/vcs.rb', line 124
def self.clear_branches
pretty_with_output.run(branch)
branch_removed = false
(branches - ["master", working_branch]).each do |branch|
if branch_pushed(branch)
pretty.run(branch_force_delete(branch))
branch_removed = true
end
end
pretty_with_output.run(branch) if branch_removed
end
|
.force_pull ⇒ Object
53
54
55
56
57
58
59
60
61
|
# File 'lib/autowow/features/vcs.rb', line 53
def self.force_pull
pretty_with_output.run(git_status)
branch = working_branch
pretty_with_output.run(fetch("--all"))
pretty_with_output.run(hard_reset("origin/#{branch}"))
pretty_with_output.run(git_status)
end
|
.hi ⇒ Object
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# File 'lib/autowow/features/vcs.rb', line 35
def self.hi
logger.error("In a git repository. Try 1 level higher.") && return if is_git?
latest_project_info = get_latest_repo_info
logger.info("\nHang on, updating your local projects and remote forks...\n\n")
git_projects.each do |project|
Dir.chdir(project) do
logger.info("\nGetting #{project} in shape...")
yield if block_given?
update_project
end
end
greet(latest_project_info)
end
|
.hi! ⇒ Object
23
24
25
26
27
28
29
30
31
32
33
|
# File 'lib/autowow/features/vcs.rb', line 23
def self.hi!
logger.error("In a git repository. Try 1 level higher.") && return if is_git?
hi do
logger.info("Removing unused branches...")
clear_branches
logger.info("Adding upstream...")
add_upstream
logger.info("Removing unused gems...")
Gem.gem_clean
end
end
|
.open ⇒ Object
63
64
65
66
67
|
# File 'lib/autowow/features/vcs.rb', line 63
def self.open
url = origin_push_url(quiet.run(remotes).out)
logger.info("Opening #{url}")
Launchy.open(url)
end
|
.origin_push_url(remotes) ⇒ Object
98
99
100
101
102
103
104
|
# File 'lib/autowow/features/vcs.rb', line 98
def self.origin_push_url(remotes)
origin_push_url_ssl_dot_git(remotes) or
origin_push_url_ssl(remotes) or
origin_push_url_https_dot_git(remotes) or
origin_push_url_https(remotes)
end
|
.origin_push_url_https(remotes) ⇒ Object
106
107
108
|
# File 'lib/autowow/features/vcs.rb', line 106
def self.origin_push_url_https(remotes)
remotes[%r{(?<=origin(\s))http(s?)://[a-zA-Z\-_./]*(?=(\s)\(push\))}]
end
|
.origin_push_url_https_dot_git(remotes) ⇒ Object
110
111
112
|
# File 'lib/autowow/features/vcs.rb', line 110
def self.origin_push_url_https_dot_git(remotes)
remotes[%r{(?<=origin(\s))http(s?)://[a-zA-Z\-_./]*(?=(\.)git(\s)\(push\))}]
end
|
.origin_push_url_ssl(remotes) ⇒ Object
119
120
121
122
|
# File 'lib/autowow/features/vcs.rb', line 119
def self.origin_push_url_ssl(remotes)
url = remotes[%r{(?<=origin(\s)git@)[a-zA-Z\-_./:]*(?=(\s)\(push\))}]
"https://#{url.gsub(':', '/')}" if url
end
|
.origin_push_url_ssl_dot_git(remotes) ⇒ Object
114
115
116
117
|
# File 'lib/autowow/features/vcs.rb', line 114
def self.origin_push_url_ssl_dot_git(remotes)
url = remotes[%r{(?<=origin(\s)git@)[a-zA-Z\-_./:]*(?=(\.)git(\s)\(push\))}]
"https://#{url.gsub(':', '/')}" if url
end
|
Instance Method Details
#any_branch_not_pushed? ⇒ Boolean
247
248
249
|
# File 'lib/autowow/features/vcs.rb', line 247
def any_branch_not_pushed?
branches.reject { |branch| branch_pushed(branch) }.any?
end
|
#branch_merged ⇒ Object
187
188
189
190
191
192
193
194
195
196
197
198
199
|
# File 'lib/autowow/features/vcs.rb', line 187
def branch_merged
pretty_with_output.run(git_status)
branch = working_branch
logger.error("Nothing to do.") and return if branch.eql?("master")
keep_changes do
pretty_with_output.run(checkout("master"))
pretty_with_output.run(pull)
end
pretty_with_output.run(branch_force_delete(branch))
pretty_with_output.run(git_status)
end
|
#branch_pushed(branch) ⇒ Object
205
206
207
|
# File 'lib/autowow/features/vcs.rb', line 205
def branch_pushed(branch)
is_tracked?(branch) && commits_pushed?(branch)
end
|
#branches ⇒ Object
262
263
264
|
# File 'lib/autowow/features/vcs.rb', line 262
def branches
quiet.run(branch_list.join(" ")).out.clean_lines
end
|
#check_projects_older_than(quantity, unit) ⇒ Object
234
235
236
237
238
239
240
241
242
243
244
245
|
# File 'lib/autowow/features/vcs.rb', line 234
def check_projects_older_than(quantity, unit)
old_projects = Fs.older_than(git_projects, quantity, unit)
deprecated_projects = old_projects.reject do |project|
Dir.chdir(project) { any_branch_not_pushed? || uncommitted_changes?(quiet.run(git_status).out) }
end
logger.info("The following projects have not been touched for more than #{quantity} #{unit} and all changes have been pushed, maybe consider removing them?") unless deprecated_projects.empty?
deprecated_projects.each do |project|
time_diff = TimeDifference.between(File.mtime(project), Time.now).humanize_higher_than(:weeks).downcase
logger.info(" #{File.basename(project)} (#{time_diff})")
end
end
|
#commits_pushed?(branch) ⇒ Boolean
209
210
211
|
# File 'lib/autowow/features/vcs.rb', line 209
def commits_pushed?(branch)
quiet.run(changes_not_on_remote(branch)).out.strip.empty?
end
|
#get_latest_repo_info ⇒ Object
251
252
253
254
255
256
|
# File 'lib/autowow/features/vcs.rb', line 251
def get_latest_repo_info
latest = latest_repo
time_diff = TimeDifference.between(File.mtime(latest), Time.now).humanize_higher_than(:days).downcase
time_diff_text = time_diff.empty? ? "recently" : "#{time_diff} ago"
"It looks like you were working on #{File.basename(latest)} #{time_diff_text}.\n\n"
end
|
#git_projects ⇒ Object
286
287
288
289
290
291
292
|
# File 'lib/autowow/features/vcs.rb', line 286
def git_projects
Fs.ls_dirs.select do |dir|
Dir.chdir(dir) do
is_git?
end
end
end
|
#greet(latest_project_info = nil) ⇒ Object
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
|
# File 'lib/autowow/features/vcs.rb', line 213
def greet(latest_project_info = nil)
logger.info("\nGood morning!\n\n")
if is_git?
logger.error("Inside repo, cannot show report about all repos.")
else
latest_project_info ||= get_latest_repo_info
logger.info(latest_project_info)
check_projects_older_than(1, :months)
end
return unless Rbenv.exists?
obsolete_rubies = Rbenv.obsolete_versions
if obsolete_rubies.any?
logger.info("\nThe following Ruby versions are not used by any projects, maybe consider removing them?")
obsolete_rubies.each do |ruby_verion|
logger.info(" #{ruby_verion}")
end
end
end
|
#has_upstream? ⇒ Boolean
166
167
168
|
# File 'lib/autowow/features/vcs.rb', line 166
def has_upstream?
quiet.run(remotes).out.include?("upstream")
end
|
#is_git? ⇒ Boolean
281
282
283
284
|
# File 'lib/autowow/features/vcs.rb', line 281
def is_git?
status = quiet.run!(git_status)
Fs.git_folder_present && status.success? && !status.out.include?("Initial commit")
end
|
#is_tracked?(branch) ⇒ Boolean
49
50
51
|
# File 'lib/autowow/features/vcs.rb', line 49
def is_tracked?(branch)
!quiet.run!(Vcs.upstream_tracking(branch).join(" ")).out.strip.empty?
end
|
#keep_changes ⇒ Object
270
271
272
273
274
275
276
277
278
279
|
# File 'lib/autowow/features/vcs.rb', line 270
def keep_changes
status = quiet.run(git_status).out
pop_stash = uncommitted_changes?(status)
quiet.run(stash) if pop_stash
begin
yield if block_given?
ensure
quiet.run(stash_pop) if pop_stash
end
end
|
#latest_repo ⇒ Object
258
259
260
|
# File 'lib/autowow/features/vcs.rb', line 258
def latest_repo
Fs.latest(git_projects)
end
|
#on_branch(branch) ⇒ Object
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
# File 'lib/autowow/features/vcs.rb', line 170
def on_branch(branch)
keep_changes do
start_branch = working_branch
switch_needed = !start_branch.eql?(branch)
if switch_needed
result = pretty.run!(checkout(branch))
pretty.run(create(branch)) unless result.success?
end
begin
yield if block_given?
ensure
pretty.run(checkout(start_branch)) if switch_needed
end
end
end
|
#pull_upstream ⇒ Object
157
158
159
160
161
162
163
164
|
# File 'lib/autowow/features/vcs.rb', line 157
def pull_upstream
upstream_remote = "upstream"
remote = "origin"
branch = "master"
pretty_with_output.run(fetch(upstream_remote)).out
pretty_with_output.run(merge("#{upstream_remote}/#{branch}")).out
pretty_with_output.run(push(remote, branch))
end
|
#uncommitted_changes?(status) ⇒ Boolean
266
267
268
|
# File 'lib/autowow/features/vcs.rb', line 266
def uncommitted_changes?(status)
!(status.include?("nothing to commit, working tree clean") or status.include?("nothing added to commit but untracked files present") or status.include?("nothing to commit, working directory clean"))
end
|
#update_project ⇒ Object
144
145
146
147
148
149
150
151
152
153
154
155
|
# File 'lib/autowow/features/vcs.rb', line 144
def update_project
logger.info("Updating #{File.expand_path('.')} ...")
logger.error("Not a git repository.") and return unless is_git?
status = quiet.run(git_status).out
if uncommitted_changes?(status) && working_branch.eql?("master")
logger.warn("Skipped: uncommitted changes on master.") and return
end
on_branch("master") do
has_upstream? ? pull_upstream : pretty_with_output.run(pull)
end
end
|
#update_projects ⇒ Object
138
139
140
141
142
|
# File 'lib/autowow/features/vcs.rb', line 138
def update_projects
Fs.in_place_or_subdirs(is_git?) do
update_project
end
end
|
#working_branch ⇒ Object
201
202
203
|
# File 'lib/autowow/features/vcs.rb', line 201
def working_branch
quiet.run(current_branch).out.strip
end
|