Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/support_engine/file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module SupportEngine
module File
class << self
# Regex to select encoding details from file -bi command results
CHARSET_DETECT_REGEXP = /charset=(.*)\n/.freeze
CHARSET_DETECT_REGEXP = /charset=(.*)\n/
# Default fallback encoding
DEFAULT_ENCODING = 'utf-8'

Expand Down
4 changes: 4 additions & 0 deletions lib/support_engine/git.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ class << self
# @param local_path [String] local path to which we clone
# @return [Boolean] true if repository got cloned
# @raise [Errors::FailedShellCommand] raised when anything went wrong
# rubocop:disable Naming/PredicateMethod
def clone_mirror(remote_path, local_path)
# rubocop:enable Naming/PredicateMethod
Shell.call("git clone --mirror #{remote_path} #{local_path}/.git/")
Shell.call_in_path(local_path, 'git remote update --prune')
Shell.call_in_path(local_path, 'git config --bool core.bare false')
Expand All @@ -22,7 +24,9 @@ def clone_mirror(remote_path, local_path)
# @param path [String] path of a current repository build
# @param ref [String] branch or commit that we want to checkout to
# @return [Boolean] true if we were able to checkout
# rubocop:disable Naming/PredicateMethod
def checkout(path, ref)
# rubocop:enable Naming/PredicateMethod
result = SupportEngine::Shell.call_in_path(
path,
"git checkout #{ref}",
Expand Down
18 changes: 10 additions & 8 deletions lib/support_engine/git/branch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class Branch < Base
DETACH_STRING = 'HEAD detached'

# Regexp to remove the '* ' prefix of current branch
CURRENT_BRANCH_SANITIZER = /\A\*\s{1}/.freeze
CURRENT_BRANCH_SANITIZER = /\A\*\s{1}/

class << self
# Detects a given commit branch
Expand All @@ -45,13 +45,13 @@ def commit(path, commit_hash)

# If the head points to HEAD it means that the repo is in the detach state
# and we need to pick the latest ref to get a head branch
head = head == 'HEAD' ? sanitize_branch(Ref.latest(path)) : head
head = sanitize_branch(Ref.latest(path)) if head == 'HEAD'

candidates = call_in_path!(path, cmd)[:stdout]
.split("\n")
.map { |cand| cand.gsub(CURRENT_BRANCH_SANITIZER, '') }
.map(&:strip)
.tap { |arr| arr.delete_if { |cand| cand.include?(DETACH_STRING) } }
.split("\n")
.map { |cand| cand.gsub(CURRENT_BRANCH_SANITIZER, '') }
.map(&:strip)
.tap { |arr| arr.delete_if { |cand| cand.include?(DETACH_STRING) } }

resolve_branch(
candidates,
Expand Down Expand Up @@ -151,7 +151,9 @@ def resolve_branch(each_ref, commit_hash, head)
# @param commit_hash [String] commit hash we're checking
# @param head [String] name of the head branch
# @return [String] origin branch of a commit hash
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
def resolve_from_origins(origin_refs, commit_hash, head)
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
# We prioritize head branches as main branches of a commit if they are in the head
return head if origin_refs.any? do |candidate|
candidate.include?('origin/HEAD') || candidate.include?("refs/heads/#{head}")
Expand All @@ -172,7 +174,7 @@ def resolve_from_origins(origin_refs, commit_hash, head)
end

# And we pick the first one with and sanitize it to get only the branch name
(branch || candidates.first)
branch || candidates.first
end

# When we cannot find branch of a commit hash, we try to find pull request as it probably
Expand Down Expand Up @@ -201,7 +203,7 @@ def sanitize_branch(branch)
raise SupportEngine::Errors::UnknownBranch unless branch

UNWANTED_PREFIXES.each { |prefix| branch.gsub!(/\A#{prefix}/, '') }
branch.gsub!(%r{\/head\z}, '') if branch.start_with?('pull/')
branch.delete_suffix!('/head') if branch.start_with?('pull/')

branch
end
Expand Down
2 changes: 1 addition & 1 deletion lib/support_engine/git/commits.rb
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def clean_for_each_ref_results(data, source)
{
commit_hash: part2[0],
committed_at: Time.zone.parse(part1[0]),
source: source
source:
}
end
data.uniq! { |h| h[:commit_hash] }
Expand Down
2 changes: 2 additions & 0 deletions lib/support_engine/git/gc.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ class << self
# @raise [SupportEngine::Errors::FailedShellCommand] raised when anything went wrong
# @example Reset state (watch out - this will reset for real!)
# SupportEngine::Git::Gc.reset('./') #=> true
# rubocop:disable Naming/PredicateMethod
def reset(path)
# rubocop:enable Naming/PredicateMethod
Shell::Git.call_in_path(path, :reset, '--hard HEAD')
Shell::Git.call_in_path(path, :clean, '-f -d')
true
Expand Down
2 changes: 1 addition & 1 deletion lib/support_engine/git/log.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def shortstat(path, limit: nil, since: 20.years.ago)
# @param path [String] path of a current repository build
# @return [DateTime] datetime of a head commit
def head_committed_at(path)
Time.parse(Shell::Git.call_in_path(path, :log, '-1 --format=%cd').first)
Time.zone.parse(Shell::Git.call_in_path(path, :log, '-1 --format=%cd').first)
end
end
end
Expand Down
10 changes: 6 additions & 4 deletions lib/support_engine/git/ref.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ def latest(local_path)
# @example
# Git::Ref.head(<local_path>) #=>
# {:stdout=>"develop\n", :stderr=>"", :exit_code=>0}
def head(local_path, raise_on_invalid_exit = true)
def head(local_path, raise_on_invalid_exit: true)
Shell.call_in_path(
local_path,
'git rev-parse --abbrev-ref HEAD',
raise_on_invalid_exit: raise_on_invalid_exit
raise_on_invalid_exit:
)
end

Expand All @@ -41,7 +41,7 @@ def head(local_path, raise_on_invalid_exit = true)
# @example
# Git::Ref.head!(<local_path>) #=> develop
def head!(local_path)
result = head(local_path, false)
result = head(local_path, raise_on_invalid_exit: false)
return result[:stdout].strip if head?(result)

Shell.call_in_path(local_path, "git symbolic-ref HEAD #{latest(local_path)}")
Expand All @@ -52,13 +52,15 @@ def head!(local_path)
# @param result [Hash] hash with 3 keys describing output
# (stdout, stderr, exit_code)
# @return [Boolean]
# rubocop:disable Rails/NegateInclude
def head?(result)
result[:stderr].empty? || \
result[:stderr].empty? ||
!result[:stderr].include?(
"fatal: ambiguous argument 'HEAD': " \
'unknown revision or path not in the working tree'
)
end
# rubocop:enable Rails/NegateInclude
end
end
end
Expand Down
27 changes: 10 additions & 17 deletions lib/support_engine/git/repo_builder/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,29 @@ module RepoBuilder
class Base
class << self
# @return [String] Where should we put our test dummy repo
def location
::File.join(SupportEngine.gem_root, 'tmp', "test_repo_#{name}")
end
def location = ::File.join(SupportEngine.gem_root, 'tmp', "test_repo_#{name}")

# @return [String] Path to .git folder of our location
def location_git
::File.join(location, '.git')
end
def location_git = ::File.join(location, '.git')

# @return [String] Origin poiting to external location
def origin
"https://something.origin/#{name}"
end
def origin = "https://something.origin/#{name}"

# @return [String] Default committer that is git compatible
# @example
# self.committer #=> 'Committer <committer@coditsu.io>'
def committer
Committer.call
end
def committer = Committer.call

# @return [String] underscored name of current class without modules
# @example
# self.name #=> 'master_mirror'
def name
to_s.split('::').last.underscore
end
def name = to_s.split('::').last.underscore

# @param message [String] commit message that we want to have
# @param author [String] author details in git compatible format
# @param committed_at [Time, DateTime] time of a commit (now is the default)
# @return [String] git commit command with proper message, date and author
def commit(message, author: committer, committed_at: Time.now)
def commit(message, author: committer, committed_at: Time.current)
cmd = []
cmd << "GIT_COMMITTER_DATE='#{committed_at}'"
cmd << "git commit --no-gpg-sign -m '#{message}'"
Expand All @@ -56,9 +46,12 @@ def commit(message, author: committer, committed_at: Time.now)
# Creates a dummy repository in LOCATION with some commits and branches
def bootstrap
destroy
SupportEngine::Shell.call(const_get(:BOOTSTRAP_CMD))
SupportEngine::Shell.call(bootstrap_cmd)
end

# @return [String] Bootstrap command - override in subclasses
def bootstrap_cmd = raise NotImplementedError

# Destroys dummy repository directory
def destroy
FileUtils.rm_r(location, secure: true) if Dir.exist?(location)
Expand Down
44 changes: 23 additions & 21 deletions lib/support_engine/git/repo_builder/broken_head_ref.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,29 @@ module RepoBuilder
# Creates repository with no master branch and broken head ref
class BrokenHeadRef < Base
# Steps we need to take in order to setup dummy repository
BOOTSTRAP_CMD = [
"git init #{location}",
"cd #{location}",
'echo "hash = { \'test\' => 1 }" > master.rb',
'git add --all ./',
commit('master commit'),
'git branch develop',
'git checkout develop',
'echo "hash = { \'test\' => 2 }" > develop.rb',
'git add --all ./',
commit('develop commit'),
'git branch different-branch',
'git checkout different-branch',
'touch different-branch.txt',
'git add --all ./',
commit('different-branch commit'),
'git checkout develop',
"git remote add origin #{origin}",
'git branch -D master',
'echo "ref: refs/heads/master" > .git/HEAD'
].join(' && ').freeze
def self.bootstrap_cmd
[
"git init #{location}",
"cd #{location}",
'echo "hash = { \'test\' => 1 }" > master.rb',
'git add --all ./',
commit('master commit'),
'git branch develop',
'git checkout develop',
'echo "hash = { \'test\' => 2 }" > develop.rb',
'git add --all ./',
commit('develop commit'),
'git branch different-branch',
'git checkout different-branch',
'touch different-branch.txt',
'git add --all ./',
commit('different-branch commit'),
'git checkout develop',
"git remote add origin #{origin}",
'git branch -D master',
'echo "ref: refs/heads/master" > .git/HEAD'
].join(' && ')
end
end
end
end
Expand Down
30 changes: 16 additions & 14 deletions lib/support_engine/git/repo_builder/master.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@ module RepoBuilder
# Creates repository with master branch
class Master < Base
# Steps we need to take in order to setup dummy repository
BOOTSTRAP_CMD = [
"git init #{location}",
"cd #{location}",
'echo "hash = { \'test\' => 1 }" > master.rb',
'git add --all ./',
commit('master commit', committed_at: 2.days.ago),
'git branch different-branch',
'git checkout different-branch',
'touch different-branch.txt',
'git add --all ./',
commit('different-branch commit'),
'git checkout master',
"git remote add origin #{origin}"
].join(' && ').freeze
def self.bootstrap_cmd
[
"git init #{location}",
"cd #{location}",
'echo "hash = { \'test\' => 1 }" > master.rb',
'git add --all ./',
commit('master commit', committed_at: 2.days.ago),
'git branch different-branch',
'git checkout different-branch',
'touch different-branch.txt',
'git add --all ./',
commit('different-branch commit'),
'git checkout master',
"git remote add origin #{origin}"
].join(' && ')
end
end
end
end
Expand Down
4 changes: 3 additions & 1 deletion lib/support_engine/git/repo_builder/master_bare_mirror.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ module RepoBuilder
# Creates new mirror repository from master repository
class MasterBareMirror < Base
# Steps we need to take in order to setup dummy repository with --mirror
BOOTSTRAP_CMD = "git clone --mirror #{Master.location} #{location}/.git/"
def self.bootstrap_cmd
"git clone --mirror #{Master.location} #{location}/.git/"
end
end
end
end
Expand Down
42 changes: 22 additions & 20 deletions lib/support_engine/git/repo_builder/master_multiple_committers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,28 @@ module RepoBuilder
# Creates repository with master branch and multiple committers
class MasterMultipleCommitters < Base
# Steps we need to take in order to setup dummy repository
BOOTSTRAP_CMD = [
"git init #{location}",
"cd #{location}",
'echo "hash = { \'test\' => 1 }" > master.rb',
'git add --all ./',
commit('master commit'),
'echo "hash = { \'test\' => 2 }" > master.rb',
'git add --all ./',
commit('master commit committer2', author: 'Committer2 <committer2@coditsu.io>'),
'echo "hash = { \'test\' => 3 }" > master.rb',
'git add --all ./',
commit('master commit committer3', author: 'Committer3 <committer3@coditsu.io>'),
'git branch different-branch',
'git checkout different-branch',
'touch different-branch.txt',
'git add --all ./',
commit('different-branch commit'),
'git checkout master',
"git remote add origin #{origin}"
].join(' && ').freeze
def self.bootstrap_cmd
[
"git init #{location}",
"cd #{location}",
'echo "hash = { \'test\' => 1 }" > master.rb',
'git add --all ./',
commit('master commit'),
'echo "hash = { \'test\' => 2 }" > master.rb',
'git add --all ./',
commit('master commit committer2', author: 'Committer2 <committer2@coditsu.io>'),
'echo "hash = { \'test\' => 3 }" > master.rb',
'git add --all ./',
commit('master commit committer3', author: 'Committer3 <committer3@coditsu.io>'),
'git branch different-branch',
'git checkout different-branch',
'touch different-branch.txt',
'git add --all ./',
commit('different-branch commit'),
'git checkout master',
"git remote add origin #{origin}"
].join(' && ')
end
end
end
end
Expand Down
30 changes: 16 additions & 14 deletions lib/support_engine/git/repo_builder/master_only.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@ module RepoBuilder
# Creates repository with master branch only
class MasterOnly < Base
# Steps we need to take in order to setup dummy repository
BOOTSTRAP_CMD = [
"git init #{location}",
"cd #{location}",
'echo "hash = { \'test\' => 1 }" > master.rb',
'git add --all ./',
commit('master commit', committed_at: 2.days.ago),
'echo "hash = { \'test\' => 2 }" > master.rb',
'git add --all ./',
commit('master commit 2', committed_at: 1.days.ago),
'echo "hash = { \'test\' => 3 }" > master.rb',
'git add --all ./',
commit('master commit 3', committed_at: 0.days.ago),
"git remote add origin #{origin}"
].join(' && ').freeze
def self.bootstrap_cmd
[
"git init #{location}",
"cd #{location}",
'echo "hash = { \'test\' => 1 }" > master.rb',
'git add --all ./',
commit('master commit', committed_at: 2.days.ago),
'echo "hash = { \'test\' => 2 }" > master.rb',
'git add --all ./',
commit('master commit 2', committed_at: 1.day.ago),
'echo "hash = { \'test\' => 3 }" > master.rb',
'git add --all ./',
commit('master commit 3', committed_at: 0.days.ago),
"git remote add origin #{origin}"
].join(' && ')
end
end
end
end
Expand Down
Loading