Module: ReleaseManager::Git::Utilities
- Included in:
- Changelog, ControlRepo, PuppetModule, Puppetfile, R10kDeployer, Sandbox
- Defined in:
- lib/release_manager/git/utilites.rb
Instance Method Summary collapse
- #add_all(pathspec = []) ⇒ Object
- #add_file(file) ⇒ Object
-
#add_remote(url, remote_name = 'upstream', reset_url = false) ⇒ Rugged::Remote
A rugged remote object.
-
#apply_diff(diff) ⇒ Object
- Rugged::Diff
-
a rugged diff object Not fully tested.
- #apply_patch(file) ⇒ Object
-
#author ⇒ Hash
The author information used in a commit message.
-
#author_email ⇒ String
-
the author email found in the config.
-
-
#author_name ⇒ String
-
the author name found in the config.
-
-
#branch_exist?(name) ⇒ Boolean
-
true if the branch exist.
-
-
#changed_files(src_ref, dst_ref) ⇒ Array[String]
The changed files in the commit or all the commits in the diff between src and dst.
-
#checkout_branch(name, options = {}) ⇒ Rugged::Branch
Returns the rugged branch object.
- #cherry_pick(commit) ⇒ Object
-
#cli_create_commit(message) ⇒ Object
TODO: change this to rugged implementation.
-
#clone(url, path) ⇒ Rugged::Repository
Clones the url if the clone path already exists, nothing is done.
-
#create_branch(name, target = 'upstream/master') ⇒ Rugged::Branch
we should be creating the branch from upstream.
- #create_commit(message) ⇒ Object
-
#create_diff(src_ref, dst_ref) ⇒ Rugged::Diff
A rugged diff object between src and dst.
-
#create_diff_obj(src, dst) ⇒ Object
with status, old_path, new_path, and content status can be one of: :added, :deleted, :modified, :renamed, :copied, :ignored, :untracked, :typechange.
- #create_local_tag(name, ref, message = nil) ⇒ Object
- #credentials ⇒ Object
-
#current_branch ⇒ String
The name of the current branch.
-
#current_branch?(name) ⇒ Boolean
Returns true if the current branch is the name.
-
#delete_branch(name) ⇒ Object
deletes the branch with the given name.
- #fetch(remote_name = 'upstream', tags = false) ⇒ Object
- #fetch_cli(remote) ⇒ Object
-
#find_or_create_remote(remote_name) ⇒ Rugged::Remote
find the remote or create a new remote with the name as source.
-
#find_ref(sha_or_ref) ⇒ String
The oid of the sha or ref.
- #find_tag(id) ⇒ Rugged::Tag
-
#get_content(oid) ⇒ String
The contents of the file from the object.
-
#git_command ⇒ String
The git command with.
-
#git_url?(name) ⇒ MatchData
Is the name actually a url?.
- #push_branch(remote_name, branch, force = false) ⇒ Object
-
#push_tags(remote_name, id = nil) ⇒ Object
push all the tags to the remote.
-
#rebase_branch(branch_name, target, remote = nil) ⇒ Object
TODO: change this to rugged implementation.
-
#ref_exists?(sha1_or_ref) ⇒ Boolean
True if the ref exists.
-
#remote_exists?(name) ⇒ Boolean
-
return true if the remote name and url are defined in the git repo.
-
-
#remote_from_name(name) ⇒ Rugged::Remote
Given the url find the remote with that url.
-
#remote_from_url(url) ⇒ Rugged::Remote
Given the url find the remote with that url.
-
#remote_url_matches?(name, url) ⇒ Boolean
-
true if the url matches a remote url already defined.
-
- #remove_file(file) ⇒ Object
- #repo ⇒ Object
-
#tag_exists?(name) ⇒ Boolean
-
return true if the tag exists.
-
-
#tags ⇒ Array
-
returns an array of tag names.
-
- #transports ⇒ Object
- #up2date?(src_ref, dst_ref) ⇒ Boolean
Instance Method Details
#add_all(pathspec = []) ⇒ Object
262 263 264 265 266 |
# File 'lib/release_manager/git/utilites.rb', line 262 def add_all(pathspec = []) index = repo.index index.add_all index.write end |
#add_file(file) ⇒ Object
269 270 271 272 273 274 275 |
# File 'lib/release_manager/git/utilites.rb', line 269 def add_file(file) logger.debug("Adding file #{file}") return add_all if file == '.' index = repo.index file.slice!(repo.workdir) index.add(:path => file, :oid => Rugged::Blob.from_workdir(repo, file), :mode => 0100644, valid: false) end |
#add_remote(url, remote_name = 'upstream', reset_url = false) ⇒ Rugged::Remote
Returns a rugged remote object.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/release_manager/git/utilites.rb', line 61 def add_remote(url, remote_name = 'upstream', reset_url = false ) return false unless git_url?(url) url = url.gsub('"', '') # remove quotes if url contains quotes if remote_exists?(remote_name) # ensure the correct url is set # this sets a non persistant fetch url unless remote_url_matches?(remote_name, url) if reset_url logger.info("Resetting #{remote_name} remote to #{url} for #{path}") repo.remotes.set_url(remote_name,url) repo.remotes[remote_name] end end else logger.info("Adding #{remote_name} remote to #{url} for #{path}") repo.remotes.create(remote_name, url) end end |
#apply_diff(diff) ⇒ Object
- Rugged::Diff
-
a rugged diff object
Not fully tested
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 |
# File 'lib/release_manager/git/utilites.rb', line 298 def apply_diff(diff) diff.deltas.each do |d| case d.status when :deleted remove_file(d.new_file[:path]) File.delete(File.join(path, path)) when :added, :modified add_file(d.new_file[:path]) when :renamed remove_file(d.old_file[:path]) File.delete(File.join(path, path)) add_file(d.new_file[:path]) else logger.warn("File has a status of #{d.status}") end end end |
#apply_patch(file) ⇒ Object
278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/release_manager/git/utilites.rb', line 278 def apply_patch(file) # TODO: change this to rugged implementation empty = File.read(file).length < 1 logger.info("Applying patch #{file}") output = '' logger.debug("The patch file is empty for some reason") if empty Dir.chdir(path) do output = `#{git_command} apply #{file} 2>&1` end raise PatchError.new(output) unless $?.success? end |
#author ⇒ Hash
Returns the author information used in a commit message.
257 258 259 |
# File 'lib/release_manager/git/utilites.rb', line 257 def {:email=>, :time=>Time.now, :name=>} end |
#author_email ⇒ String
Returns - the author email found in the config.
252 253 254 |
# File 'lib/release_manager/git/utilites.rb', line 252 def repo.config.get('user.email') || Rugged::Config.global.get('user.email') || ENV['GIT_USER_EMAIL'] end |
#author_name ⇒ String
Returns - the author name found in the config.
247 248 249 |
# File 'lib/release_manager/git/utilites.rb', line 247 def repo.config.get('user.name') || Rugged::Config.global.get('user.name') || ENV['GIT_USER_NAME'] end |
#branch_exist?(name) ⇒ Boolean
Returns - true if the branch exist.
95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/release_manager/git/utilites.rb', line 95 def branch_exist?(name) # ensure we have the latest branches remote_name, ref = name.split('/', 2) if name.include?('/') remote_name, ref = name.split('/', 2) else ref = name end # check to see if we just needed to fetch the upstreams fetch(remote_name) unless (repo.branches.exist?(name) || ref_exists?(name) || tag_exists?(ref)) repo.branches.exist?(name) || ref_exists?(name) || tag_exists?(ref) end |
#changed_files(src_ref, dst_ref) ⇒ Array[String]
Returns the changed files in the commit or all the commits in the diff between src and dst.
401 402 403 404 405 406 |
# File 'lib/release_manager/git/utilites.rb', line 401 def changed_files(src_ref, dst_ref) src = repo.lookup(find_ref(src_ref)) src = src.kind_of?(Rugged::Tag::Annotation) ? src.target : src dst = repo.lookup(find_ref(dst_ref)) dst.diff(src).deltas.map { |d| [d.old_file[:path], d.new_file[:path]] }.flatten.uniq end |
#checkout_branch(name, options = {}) ⇒ Rugged::Branch
Returns the rugged branch object
204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/release_manager/git/utilites.rb', line 204 def checkout_branch(name, = {}) if current_branch?(name) logger.debug("Checking out branch: #{name} for #{path}") repo.checkout(name, ) logger.debug("Checked out branch: #{current_branch} for #{path}") else # already checked out logger.debug("Currently on branch #{name} for #{path}") repo.branches[name] end end |
#cherry_pick(commit) ⇒ Object
392 393 394 395 396 |
# File 'lib/release_manager/git/utilites.rb', line 392 def cherry_pick(commit) return unless commit repo.cherrypick(commit) logger.info("Cherry picking commit with id: #{commit}") end |
#cli_create_commit(message) ⇒ Object
TODO: change this to rugged implementation
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
# File 'lib/release_manager/git/utilites.rb', line 361 def cli_create_commit() output = nil Dir.chdir(path) do output = `#{git_command} commit --message '#{}' 2>&1` end if $?.success? logger.info("Created commit #{}") else if output =~ /nothing\sto\scommit/ logger.info("Nothing to commit") else logger.error output end return false end end |
#clone(url, path) ⇒ Rugged::Repository
Clones the url if the clone path already exists, nothing is done
42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/release_manager/git/utilites.rb', line 42 def clone(url, path) if File.exists?(File.join(path, '.git')) add_remote(url, 'upstream') fetch('upstream') repo else logger.info("Cloning repo with url: #{url} to #{path}") r = Rugged::Repository.clone_at(url, path, { #progress: lambda { |output| logger.debug output }, credentials: credentials.call(url) }) r end end |
#create_branch(name, target = 'upstream/master') ⇒ Rugged::Branch
we should be creating the branch from upstream
110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/release_manager/git/utilites.rb', line 110 def create_branch(name, target = 'upstream/master') # fetch the remote if defined in the target unless branch_exist?(name) remote_name, ref = target.split('/', 2) fetch(remote_name) logger.info("Creating branch: #{name} for #{path} from #{target}") found_ref = find_ref(target) repo.create_branch(name, found_ref) else repo.branches[name] end end |
#create_commit(message) ⇒ Object
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 |
# File 'lib/release_manager/git/utilites.rb', line 334 def create_commit() unless and raise GitError.new("Git username and email must be set, current: #{.inspect}") end # get the index for this repository repo.status { |file, status_data| logger.debug "#{file} has status: #{status_data.inspect}" } index = repo.index = {} [:author] = [:message] = [:committer] = [:parents] = repo.empty? ? [] : [repo.head.target].compact [:update_ref] = 'HEAD' [:tree] = index.write_tree index.write oid = Rugged::Commit.create(repo, ) if oid logger.info("Created commit #{}") repo.status { |file, status_data| logger.debug "#{file} has status: #{status_data.inspect}" } else logger.warn("Something went wrong with the commit") end oid end |
#create_diff(src_ref, dst_ref) ⇒ Rugged::Diff
Returns a rugged diff object between src and dst.
433 434 435 436 437 438 439 440 |
# File 'lib/release_manager/git/utilites.rb', line 433 def create_diff(src_ref, dst_ref) logger.debug("Creating a diff between #{dst_ref} and #{src_ref}") src = repo.lookup(find_ref(src_ref)) src = src.kind_of?(Rugged::Tag::Annotation) ? src.target : src dst = repo.lookup(find_ref(dst_ref)) dst = dst.kind_of?(Rugged::Tag::Annotation) ? dst.target : dst dst.diff(src) end |
#create_diff_obj(src, dst) ⇒ Object
with status, old_path, new_path, and content status can be one of: :added, :deleted, :modified, :renamed, :copied, :ignored, :untracked, :typechange
421 422 423 424 425 426 427 428 |
# File 'lib/release_manager/git/utilites.rb', line 421 def create_diff_obj(src, dst) diff = create_diff(src, dst) diff.deltas.map do |d| { old_path: d.old_file[:path], status: d.status, new_path: d.new_file[:path], content: get_content(d.new_file[:oid]) } end end |
#create_local_tag(name, ref, message = nil) ⇒ Object
196 197 198 199 200 |
# File 'lib/release_manager/git/utilites.rb', line 196 def create_local_tag(name, ref, = nil) ||= name logger.info("Creating tag #{name} which points to #{ref}") repo..create(name, ref, {:message => } ) end |
#credentials ⇒ Object
33 34 35 |
# File 'lib/release_manager/git/utilites.rb', line 33 def credentials @credentials ||= ReleaseManager::Git::Credentials.new(nil) end |
#current_branch ⇒ String
Returns the name of the current branch.
183 184 185 |
# File 'lib/release_manager/git/utilites.rb', line 183 def current_branch repo.head.name.sub(/^refs\/heads\//, '') end |
#current_branch?(name) ⇒ Boolean
Returns true if the current branch is the name
189 190 191 |
# File 'lib/release_manager/git/utilites.rb', line 189 def current_branch?(name) current_branch != name end |
#delete_branch(name) ⇒ Object
deletes the branch with the given name
125 126 127 128 |
# File 'lib/release_manager/git/utilites.rb', line 125 def delete_branch(name) repo.branches.delete(name) !branch_exist?(name) end |
#fetch(remote_name = 'upstream', tags = false) ⇒ Object
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/release_manager/git/utilites.rb', line 14 def fetch(remote_name = 'upstream', = false) remote_name ||= 'upstream' return unless remote_exists?(remote_name) remote = repo.remotes[remote_name] = {credentials: credentials.call(remote.url)} logger.info("Fetching remote #{remote_name} from #{remote.url}") [:certificate_check] = lambda { |valid, host| true } if ENV['GIT_SSL_NO_VERIFY'] fetch_cli(remote_name) # helps get tags remote.fetch() end |
#fetch_cli(remote) ⇒ Object
this is a hack to get around libgit2 inability to get remote tags
292 293 294 |
# File 'lib/release_manager/git/utilites.rb', line 292 def fetch_cli(remote) `#{git_command} fetch #{remote} 2>&1 > /dev/null` end |
#find_or_create_remote(remote_name) ⇒ Rugged::Remote
find the remote or create a new remote with the name as source
219 220 221 222 223 |
# File 'lib/release_manager/git/utilites.rb', line 219 def find_or_create_remote(remote_name) remote_from_name(remote_name) || remote_from_url(remote_name) || add_remote(remote_name, 'source', true) end |
#find_ref(sha_or_ref) ⇒ String
Returns the oid of the sha or ref.
454 455 456 457 458 459 460 461 462 463 464 465 466 |
# File 'lib/release_manager/git/utilites.rb', line 454 def find_ref(sha_or_ref) case sha_or_ref when Rugged::Object sha_or_ref.oid else begin repo.rev_parse_oid(sha_or_ref) rescue Rugged::ReferenceError => e tag = repo..find{|t| t.name == sha_or_ref.split('/').last} repo.rev_parse_oid(tag.target.oid) if tag end end end |
#find_tag(id) ⇒ Rugged::Tag
149 150 151 152 153 154 155 |
# File 'lib/release_manager/git/utilites.rb', line 149 def find_tag(id) if id.length >= 40 repo..find {|t| t.target.oid == id } else repo..find {|t| t.name == id } end end |
#get_content(oid) ⇒ String
Returns the contents of the file from the object.
410 411 412 413 414 |
# File 'lib/release_manager/git/utilites.rb', line 410 def get_content(oid) return nil if oid =~ /0000000000000000000000000000000000000000/ obj = repo.read(oid) obj.data end |
#git_command ⇒ String
Returns the git command with.
321 322 323 |
# File 'lib/release_manager/git/utilites.rb', line 321 def git_command @git_command ||= "git --work-tree=#{path} --git-dir=#{repo.path}" end |
#git_url?(name) ⇒ MatchData
Is the name actually a url?
242 243 244 |
# File 'lib/release_manager/git/utilites.rb', line 242 def git_url?(name) /(?:git|ssh|https?|git@[-\w.]+):(\/\/)?(.*?)(\.git)(\/?|\#[-\d\w._]+?)$/.match(name) end |
#push_branch(remote_name, branch, force = false) ⇒ Object
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/release_manager/git/utilites.rb', line 131 def push_branch(remote_name, branch, force = false) remote = find_or_create_remote(remote_name) raise RemoteNotFound, "Remote named: #{remote_name} was not found" unless remote b = repo.branches[branch] raise InvalidBranchName.new("Branch #{branch} does not exist locally, cannot push") unless b refs = [b.canonical_name] refs = refs.map { |r| r.prepend('+') } if force logger.info("Pushing branch #{branch} to remote #{remote.url}") remote.push(refs, credentials: credentials) end |
#push_tags(remote_name, id = nil) ⇒ Object
push all the tags to the remote
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
# File 'lib/release_manager/git/utilites.rb', line 166 def (remote_name, id = nil) remote = find_or_create_remote(remote_name) raise RemoteNotFound, "Remote named: #{remote_name} was not found" unless remote all_refs = repo..map(&:canonical_name) refs = if id tag = find_tag(id) tag.canonical_name if tag else all_refs end raise NoTagsExists, "No tags were pushed" if refs.empty? logger.debug("Pushing refs #{refs}") logger.info("Pushing tags to remote #{remote.url}") remote.push(refs, credentials: credentials) end |
#rebase_branch(branch_name, target, remote = nil) ⇒ Object
TODO: change this to rugged implementation
382 383 384 385 386 387 388 389 390 |
# File 'lib/release_manager/git/utilites.rb', line 382 def rebase_branch(branch_name, target, remote = nil) src = [remote, target].compact.join('/') # produces upstream/master Dir.chdir(path) do checkout_branch(branch_name) logger.info("Rebasing #{branch_name} with #{src}") output = `#{git_command} rebase #{src} 2>&1` raise GitError.new(output) unless $?.success? end end |
#ref_exists?(sha1_or_ref) ⇒ Boolean
Returns true if the ref exists.
444 445 446 447 448 449 450 |
# File 'lib/release_manager/git/utilites.rb', line 444 def ref_exists?(sha1_or_ref) begin find_ref(sha1_or_ref) rescue Rugged::ReferenceError => e false end end |
#remote_exists?(name) ⇒ Boolean
Returns - return true if the remote name and url are defined in the git repo.
82 83 84 |
# File 'lib/release_manager/git/utilites.rb', line 82 def remote_exists?(name) repo.remotes[name] end |
#remote_from_name(name) ⇒ Rugged::Remote
Given the url find the remote with that url
228 229 230 |
# File 'lib/release_manager/git/utilites.rb', line 228 def remote_from_name(name) repo.remotes.find { |r| r.name.eql?(name) } unless git_url?(name) end |
#remote_from_url(url) ⇒ Rugged::Remote
Given the url find the remote with that url
235 236 237 |
# File 'lib/release_manager/git/utilites.rb', line 235 def remote_from_url(url) repo.remotes.find { |r| r.url.eql?(url) } if git_url?(url) end |
#remote_url_matches?(name, url) ⇒ Boolean
Returns - true if the url matches a remote url already defined.
89 90 91 |
# File 'lib/release_manager/git/utilites.rb', line 89 def remote_url_matches?(name, url) repo.remotes[name].url.eql?(url) end |
#remove_file(file) ⇒ Object
326 327 328 329 330 331 |
# File 'lib/release_manager/git/utilites.rb', line 326 def remove_file(file) logger.debug("Removing file #{file}") index = repo.index File.unlink(file) index.remove(file) end |
#repo ⇒ Object
9 10 11 |
# File 'lib/release_manager/git/utilites.rb', line 9 def repo @repo ||= Rugged::Repository.new(path) end |
#tag_exists?(name) ⇒ Boolean
Returns - return true if the tag exists.
159 160 161 |
# File 'lib/release_manager/git/utilites.rb', line 159 def tag_exists?(name) .include?(name) end |
#tags ⇒ Array
Returns - returns an array of tag names.
143 144 145 |
# File 'lib/release_manager/git/utilites.rb', line 143 def repo..map(&:name) end |
#transports ⇒ Object
25 26 27 28 29 30 31 |
# File 'lib/release_manager/git/utilites.rb', line 25 def transports [:ssh, :https].each do |transport| unless ::Rugged.features.include?(transport) logger.warn("Rugged has been compiled without support for %{transport}; Git repositories will not be reachable via %{transport}. Try installing libssh-devel") % {transport: transport} end end end |
#up2date?(src_ref, dst_ref) ⇒ Boolean
316 317 318 |
# File 'lib/release_manager/git/utilites.rb', line 316 def up2date?(src_ref, dst_ref) create_diff(src_ref, dst_ref).deltas.count < 1 end |