Class: Avm::Git::Issue::Complete

Inherits:
Object
  • Object
show all
Includes:
EacRubyUtils::SimpleCache
Defined in:
lib/avm/git/issue/complete.rb,
lib/avm/git/issue/complete/_push.rb,
lib/avm/git/issue/complete/_test.rb,
lib/avm/git/issue/complete/_remote.rb,
lib/avm/git/issue/complete/_commits.rb,
lib/avm/git/issue/complete/_tracker.rb,
lib/avm/git/issue/complete/_local_tag.rb,
lib/avm/git/issue/complete/validation.rb,
lib/avm/git/issue/complete/_validations.rb,
lib/avm/git/issue/complete/_git_subrepos.rb,
lib/avm/git/issue/complete/_local_branch.rb,
lib/avm/git/issue/complete/_working_tree.rb

Defined Under Namespace

Classes: Validation

Constant Summary collapse

VALIDATIONS =
{
  clean_workspace: 'Clean workspace?',
  branch_name: 'Branch name',
  branch_hash: 'Branch hash',
  follow_master: 'Follow master?',
  commits: 'Commits?',
  bifurcations: 'Bifurcations?',
  dry_push: 'Dry push?',
  git_subrepos: 'Git subrepos ok?',
  test: 'Test ok?'
}.with_indifferent_access.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Complete

Returns a new instance of Complete.



19
20
21
22
23
24
25
# File 'lib/avm/git/issue/complete.rb', line 19

def initialize(options)
  consumer = ::EacRubyUtils::OptionsConsumer.new(options)
  dir, @skip_validations = consumer.consume_all(:dir, :skip_validations)
  validate_skip_validations
  consumer.validate
  @git = ::Avm::Launcher::Git::Base.new(dir)
end

Instance Attribute Details

#skip_validationsObject (readonly)

Returns the value of attribute skip_validations.



17
18
19
# File 'lib/avm/git/issue/complete.rb', line 17

def skip_validations
  @skip_validations
end

Instance Method Details

#assert_tagObject



9
10
11
12
13
14
15
16
# File 'lib/avm/git/issue/complete/_local_tag.rb', line 9

def assert_tag
  if tag_hash
    return if tag_hash == branch_hash

    delete_tag
  end
  create_tag
end

#bifurcations_resultObject



20
21
22
23
24
25
26
27
# File 'lib/avm/git/issue/complete/_commits.rb', line 20

def bifurcations_result
  commits.each do |commit|
    if multiple_parents?(commit)
      return ::Avm::Result.error("#{commit} has multiple parents")
    end
  end
  ::Avm::Result.success('no')
end

#branch_hash_resultObject



25
26
27
28
29
30
# File 'lib/avm/git/issue/complete/_local_branch.rb', line 25

def branch_hash_result
  ::Avm::Result.success_or_error(
    branch_hash.present?,
    branch_hash
  )
end

#branch_hash_uncachedObject



13
14
15
# File 'lib/avm/git/issue/complete/_local_branch.rb', line 13

def branch_hash_uncached
  @git.rev_parse("refs/heads/#{branch}")
end

#branch_nameObject



17
18
19
# File 'lib/avm/git/issue/complete/_local_branch.rb', line 17

def branch_name
  branch.split('/')[-1]
end

#branch_name_resultObject



21
22
23
# File 'lib/avm/git/issue/complete/_local_branch.rb', line 21

def branch_name_result
  ::Avm::Result.success_or_error(issue_id.present?, branch_name)
end

#branch_uncachedObject



9
10
11
# File 'lib/avm/git/issue/complete/_local_branch.rb', line 9

def branch_uncached
  @git.current_branch
end

#clean_workspace?Boolean

Returns:

  • (Boolean)


11
12
13
# File 'lib/avm/git/issue/complete/_working_tree.rb', line 11

def clean_workspace?
  @git.dirty_files.none?
end

#clean_workspace_resultObject



7
8
9
# File 'lib/avm/git/issue/complete/_working_tree.rb', line 7

def clean_workspace_result
  ::Avm::Result.success_or_error(clean_workspace?, 'yes', 'no')
end

#clipboard_copy_tracker_messageObject



9
10
11
12
# File 'lib/avm/git/issue/complete/_tracker.rb', line 9

def clipboard_copy_tracker_message
  ::Clipboard.copy(textile_tracker_message)
  infov 'Copied to clipboard', textile_tracker_message
end

#commit_parents(commit) ⇒ Object



33
34
35
36
# File 'lib/avm/git/issue/complete/_commits.rb', line 33

def commit_parents(commit)
  @git.execute!('log', '--pretty=%P', '-n', '1', commit).split(' ').map(&:strip)
      .select(&:present?)
end

#commits_resultObject



9
10
11
# File 'lib/avm/git/issue/complete/_commits.rb', line 9

def commits_result
  ::Avm::Result.success_or_error(commits.any?, 'yes', 'none')
end

#commits_uncachedObject



13
14
15
16
17
18
# File 'lib/avm/git/issue/complete/_commits.rb', line 13

def commits_uncached
  return [] unless branch_hash && follow_master?

  interval = remote_master_hash ? "#{remote_master_hash}..#{branch_hash}" : branch_hash
  @git.execute!('rev-list', interval).each_line.map(&:strip)
end

#create_tagObject



31
32
33
# File 'lib/avm/git/issue/complete/_local_tag.rb', line 31

def create_tag
  git(['tag', branch_name, branch_hash])
end

#delete_tagObject



18
19
20
21
# File 'lib/avm/git/issue/complete/_local_tag.rb', line 18

def delete_tag
  info 'Removendo tag...'
  git(['tag', '-d', branch_name])
end

#dry_push_argsObject



7
8
9
# File 'lib/avm/git/issue/complete/_push.rb', line 7

def dry_push_args
  %w[push --dry-run] + [remote_name] + pushs
end

#dry_push_resultObject



11
12
13
14
15
16
17
18
19
20
21
# File 'lib/avm/git/issue/complete/_push.rb', line 11

def dry_push_result
  return ::Avm::Result.error('Nothing to push') if pushs.empty?

  r = @git.execute(dry_push_args)
  message = if r.fetch(:exit_code).zero?
              'ok'
            else
              r.fetch(:stderr) + "\n#{::Shellwords.join(dry_push_args)}"
            end
  ::Avm::Result.success_or_error(r.fetch(:exit_code).zero?, message)
end

#follow_master?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/avm/git/issue/complete/_local_branch.rb', line 39

def follow_master?
  remote_master_hash ? @git.descendant?(branch_hash, remote_master_hash) : true
end

#follow_master_resultObject



32
33
34
35
36
37
# File 'lib/avm/git/issue/complete/_local_branch.rb', line 32

def follow_master_result
  return ::Avm::Result.neutral('No branch hash') unless branch_hash

  r = follow_master?
  ::Avm::Result.success_or_error(r, 'yes', 'no')
end

#git_subrepos_resultObject



10
11
12
13
14
15
16
17
# File 'lib/avm/git/issue/complete/_git_subrepos.rb', line 10

def git_subrepos_result
  return ::Avm::Result.error('Unclean workspace') unless clean_workspace?

  infom 'Checking Git subrepos...'
  r = ::Avm::Git::SubrepoChecks.new(::EacGit::Local.new(@git)).add_all_subrepos
  r.check_remote = true
  r.result
end

#issue_idObject



41
42
43
44
# File 'lib/avm/git/issue/complete.rb', line 41

def issue_id
  m = branch_name.match(/\A#{Regexp.quote('issue_')}(\d+)\z/)
  m ? m[1].to_i : nil
end

#master_pushObject



36
37
38
# File 'lib/avm/git/issue/complete/_push.rb', line 36

def master_push
  remote_master_hash != branch_hash ? "#{branch_hash}:refs/heads/master" : nil
end

#multiple_parents?(commit) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/avm/git/issue/complete/_commits.rb', line 29

def multiple_parents?(commit)
  commit_parents(commit).count > 1
end

#pushObject



23
24
25
26
27
28
29
30
# File 'lib/avm/git/issue/complete/_push.rb', line 23

def push
  if pushs.empty?
    info 'PUSH: Nada a enviar'
  else
    info "PUSH: enviando \"#{pushs}\"..."
    git(%w[push origin] + pushs)
  end
end

#pushs_uncachedObject



32
33
34
# File 'lib/avm/git/issue/complete/_push.rb', line 32

def pushs_uncached
  [master_push, remove_branch_push, tag_push].reject(&:nil?)
end

#remote_branch_hashObject



11
12
13
# File 'lib/avm/git/issue/complete/_remote.rb', line 11

def remote_branch_hash
  remote_hashs["refs/heads/#{branch}"]
end

#remote_master_hashObject



7
8
9
# File 'lib/avm/git/issue/complete/_remote.rb', line 7

def remote_master_hash
  remote_hashs['refs/heads/master']
end

#remote_tag_hashObject



15
16
17
# File 'lib/avm/git/issue/complete/_remote.rb', line 15

def remote_tag_hash
  remote_hashs[tag]
end

#remove_branch_pushObject



40
41
42
# File 'lib/avm/git/issue/complete/_push.rb', line 40

def remove_branch_push
  remote_branch_hash ? ":refs/heads/#{branch}" : nil
end

#remove_local_branchObject



43
44
45
46
47
48
# File 'lib/avm/git/issue/complete/_local_branch.rb', line 43

def remove_local_branch
  info 'Removendo branch local...'
  bn = branch_name
  git(['checkout', branch_hash])
  git(['branch', '-D', bn])
end

#runObject



31
32
33
34
35
36
37
38
39
# File 'lib/avm/git/issue/complete.rb', line 31

def run
  return false unless valid?

  assert_tag
  push
  remove_local_branch
  clipboard_copy_tracker_message
  true
end

#start_bannerObject



27
28
29
# File 'lib/avm/git/issue/complete.rb', line 27

def start_banner
  validations_banner
end

#tagObject



23
24
25
# File 'lib/avm/git/issue/complete/_local_tag.rb', line 23

def tag
  "refs/tags/#{branch_name}"
end

#tag_hashObject



27
28
29
# File 'lib/avm/git/issue/complete/_local_tag.rb', line 27

def tag_hash
  @git.rev_parse(tag)
end

#tag_pushObject



44
45
46
47
48
# File 'lib/avm/git/issue/complete/_push.rb', line 44

def tag_push
  return nil unless !remote_tag_hash || remote_tag_hash != branch_hash

  "#{branch_hash}:#{tag}"
end

#test_resultObject



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/avm/git/issue/complete/_test.rb', line 11

def test_result
  test_command = configuration.if_present(&:any_test_command)
  return ::Avm::Result.success('unconfigured') if test_command.blank?

  infom "Running test command \"#{test_command}\"..."
  result = test_command.execute
  test_result_log(result)
  if result.fetch(:exit_code).zero?
    ::Avm::Result.success('yes')
  else
    ::Avm::Result.error('no')
  end
end

#valid?Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/avm/git/issue/complete/_validations.rb', line 23

def valid?
  validations.map(&:result).none?(&:error?)
end

#validate_skip_validationsObject



33
34
35
36
37
38
39
# File 'lib/avm/git/issue/complete/_validations.rb', line 33

def validate_skip_validations
  skip_validations.each do |validation|
    next if VALIDATIONS.keys.include?(validation)

    raise "\"#{validation}\" is not a registered validation"
  end
end

#validations_bannerObject



27
28
29
30
31
# File 'lib/avm/git/issue/complete/_validations.rb', line 27

def validations_banner
  validations.each do |v|
    infov "[#{v.key}] #{v.label}", v.result.label
  end
end