forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgit_repository.rb
171 lines (143 loc) · 4.38 KB
/
git_repository.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
require "rugged"
class GitRepository < ApplicationRecord
include AuthenticationMixin
GIT_REPO_DIRECTORY = Rails.root.join('data/git_repos')
validates :url, :format => URI::regexp(%w(http https file)), :allow_nil => false
default_value_for :verify_ssl, OpenSSL::SSL::VERIFY_PEER
validates :verify_ssl, :inclusion => {:in => [OpenSSL::SSL::VERIFY_NONE, OpenSSL::SSL::VERIFY_PEER]}
has_many :git_branches, :dependent => :destroy
has_many :git_tags, :dependent => :destroy
after_destroy :delete_repo_dir # TODO: Need to distribute this to all systems
INFO_KEYS = %w(commit_sha commit_message commit_time name).freeze
def refresh
update_repo
transaction do
refresh_branches
refresh_tags
self.last_refresh_on = Time.now.utc
save!
end
end
def branch_info(name)
ensure_refreshed
branch = git_branches.detect { |item| item.name == name }
raise "Branch #{name} not found" unless branch
branch.attributes.slice(*INFO_KEYS)
end
def tag_info(name)
ensure_refreshed
tag = git_tags.detect { |item| item.name == name }
raise "Tag #{name} not found" unless tag
tag.attributes.slice(*INFO_KEYS)
end
def entries(ref, path)
ensure_refreshed
with_worktree do |worktree|
worktree.ref = ref
worktree.entries(path)
end
end
def checkout(ref, path)
ensure_refreshed
with_worktree do |worktree|
message = "Checking out #{url}@#{ref} to #{path}..."
_log.info(message)
worktree.ref = ref
worktree.checkout(path)
_log.info("#{message}...Complete")
end
path
end
def directory_name
raise ActiveRecord::RecordNotSaved if new_record?
File.join(GIT_REPO_DIRECTORY, id.to_s)
end
def self_signed_cert_cb(_valid, _host)
true
end
def with_worktree
handling_worktree_errors do
yield worktree
end
end
def update_repo
with_worktree do |worktree|
message = "Updating #{url} in #{directory_name}..."
_log.info(message)
worktree.send(:fetch_and_merge)
_log.info("#{message}...Complete")
end
@updated_repo = true
end
private
def ensure_refreshed
refresh unless @updated_repo
end
def refresh_branches
with_worktree do |worktree|
current_branches = git_branches.index_by(&:name)
worktree.branches(:remote).each do |branch|
info = worktree.branch_info(branch)
attrs = {:name => branch,
:commit_sha => info[:commit_sha],
:commit_time => info[:time],
:commit_message => info[:message]}
stored_branch = current_branches.delete(branch)
stored_branch ? stored_branch.update_attributes!(attrs) : git_branches.create!(attrs)
end
git_branches.delete(current_branches.values)
end
end
def refresh_tags
with_worktree do
current_tags = git_tags.index_by(&:name)
worktree.tags.each do |tag|
info = worktree.tag_info(tag)
attrs = {:name => tag,
:commit_sha => info[:commit_sha],
:commit_time => info[:time],
:commit_message => info[:message]}
stored_tag = current_tags.delete(tag)
stored_tag ? stored_tag.update_attributes(attrs) : git_tags.create!(attrs)
end
git_tags.delete(current_tags.values)
end
end
def worktree
@worktree ||= begin
clone_repo unless Dir.exist?(directory_name)
fetch_worktree
end
end
def fetch_worktree
GitWorktree.new(worktree_params)
end
def clone_repo
handling_worktree_errors do
message = "Cloning #{url} to #{directory_name}..."
_log.info(message)
GitWorktree.new(worktree_params.merge(:clone => true, :url => url))
@updated_repo = true
_log.info("#{message}...Complete")
end
end
def handling_worktree_errors
yield
rescue ::Rugged::NetworkError => err
raise MiqException::MiqUnreachableError, err.message
rescue => err
raise MiqException::Error, err.message
end
def worktree_params
params = {:path => directory_name}
params[:certificate_check] = method(:self_signed_cert_cb) if verify_ssl == OpenSSL::SSL::VERIFY_NONE
if authentications.any?
params[:username] = default_authentication.userid
params[:password] = default_authentication.password
end
params
end
def delete_repo_dir
FileUtils.rm_rf(directory_name)
end
end