class CaretakerCore

Docs to go here

Description should go here

This is the core file @author Wolf

Description should go here

Description should go here

Description should go here

Description should go here

Constants

CATEGORIES
DEFAULT_CATEGORY
DEFAULT_CONFIG
INITIAL_TAG

Class Constants

VERSION

Public Class Methods

run(options = {}) click to toggle source

Docs to go here

# File lib/caretaker-core.rb, line 20
def run(options = {})
    # Will throw an exception if not a git repo
    check_for_git_repo

    # Set the initial config and handle user supplied options
    config = init_config(options)

    # Get URL and slug for the repo, will throw and exception if no remote origin is set
    repository, slug = git_repo_details

    # Add to config for easy access
    config[:repo_url] = repository

    # Really do the processing
    tags, chronological, categorised = real_process(config)

    # Return the data to the calling function
    { :tags => tags, :commits => { :chronological => chronological, :categorised => categorised }, :repo => { :url => repository, :slug => slug } }.to_json
end

Private Class Methods

check_for_git_repo() click to toggle source

Are we running this from within a git repo??

# File lib/caretaker-core/git.rb, line 14
def check_for_git_repo
    raise StandardError.new('Directory does not contain a git repository - aborting') unless execute_command('git rev-parse --show-toplevel')
end
execute_command(cmd) click to toggle source

Execute a given command and return the output from stdout or false if it fails

# File lib/caretaker-core/git.rb, line 65
def execute_command(cmd)
    Open3.popen3(cmd) do |_stdin, stdout, _stderr, wait_thr|
        return stdout.read.chomp if wait_thr.value.success?
    end
    false
end
extract_tag(refs, old_tag) click to toggle source
# File lib/caretaker-core/utils.rb, line 23
def extract_tag(refs, old_tag)
    tag = old_tag
    if refs.include? 'tag: '
        refs = refs.gsub(/.*tag:/i, '')
        refs = refs.gsub(/,.*/i, '')
        tag = refs.gsub(/\).*/i, '')
    end
    tag.to_s.strip
end
generate_tag_list(parsed) click to toggle source

Make everything else private so it cannot be accessed directly

# File lib/caretaker-core/tags.rb, line 15
def generate_tag_list(parsed)
    parsed.keys
end
get_category(commit_message) click to toggle source

This method reeks of :reek:DuplicateMethodCall, :reek:NestedIterators rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity

# File lib/caretaker-core/core.rb, line 91
def get_category(commit_message)
    commit_message_downcase = commit_message.downcase

    # Does it match a primary category ?
    category = CATEGORIES.select { |key, _values| commit_message_downcase.start_with?(key.downcase) }.map(&:first).join

    # If not a primary category, does it match one of the aliases?
    category = CATEGORIES.select { |_key, values| values.any? { |value| commit_message_downcase.start_with?(value.downcase) } }.map(&:first).join if category.empty?

    # If in doubt set to the default
    category = DEFAULT_CATEGORY if category.empty?

    category
end
get_child_messages(parent) click to toggle source

comment to go here

# File lib/caretaker-core/git.rb, line 43
def get_child_messages(parent)
    body = execute_command("git log --pretty=format:'%b' -n 1 #{parent}")

    body.split("\n").each { |line| line.sub!('*', '') }.map(&:strip).reject(&:empty?).map { |line| line } unless body.empty?
end
get_parts(line, tag) click to toggle source
# File lib/caretaker-core/core.rb, line 69
def get_parts(line, tag)
    date, hash, hash_full, commit_message, tag = split_log_entries(line, tag)
    commit_message, child_commit_messages, commit_type = process_commit_message(commit_message, hash)
    category = get_category(commit_message)

    [hash, hash_full, commit_message, child_commit_messages, commit_type, category, date, tag]
end
get_pr_number(all_matches) click to toggle source

rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity

# File lib/caretaker-core/core.rb, line 107
def get_pr_number(all_matches)
    all_matches.to_a.compact.pop
end
git_remote_origin() click to toggle source

Has a remote origin been setup?

# File lib/caretaker-core/git.rb, line 21
def git_remote_origin
    origin = execute_command('git config --get remote.origin.url')
    raise StandardError.new('remote.origin.url is not set - aborting') unless origin

    origin = origin.delete_suffix('.git') if origin.end_with?('.git')
    origin.gsub(':', '/').gsub('git@', 'https://') if origin.start_with?('git@')
end
git_repo_details() click to toggle source

stuff

# File lib/caretaker-core/git.rb, line 52
def git_repo_details
    origin = git_remote_origin
    uri = URI.parse(origin)

    slug = uri.path.delete_prefix('/')
    repository = "https://#{uri.host}/#{slug}"

    [repository, slug]
end
init_config(options) click to toggle source

Setup the require global configuration

# File lib/caretaker-core/core.rb, line 27
def init_config(options)
    # Assign the default config
    config = DEFAULT_CONFIG

    # Merge in any user supplied options/config and return
    config.merge(options)
end
init_results(parsed) click to toggle source

This method reeks of :reek:NestedIterators

# File lib/caretaker-core/process.rb, line 16
def init_results(parsed)
    chronological = {}
    categorised = {}

    parsed.each do |tag|
        tag_str = tag.to_s

        chronological[tag_str] = []

        categorised[tag_str] = {}
        CATEGORIES.each { |category, _array| categorised[tag_str][category.to_s] = [] }
    end

    [chronological, categorised]
end
parse_git_log_entries(config, log_entries) click to toggle source

Limitations with regards to Pull Requests

  1. Squished commits work as exepected and the contents of the child commmits is available

  2. Rebased commits show as local commits as there is no way to see where they came from

  3. Unsquished commits only show the PR commit_message as the child commits are ignored

This method reeks of :reek:TooManyStatements { max_statements: 6 }

# File lib/caretaker-core/core.rb, line 57
def parse_git_log_entries(config, log_entries)
    logs = {}
    tag = INITIAL_TAG

    log_entries.each do |line|
        tag, data = process_single_line(config, line, tag)

        (logs[tag] ||= []) << data if data
    end
    logs
end
process_commit_message(commit_message, hash) click to toggle source
# File lib/caretaker-core/core.rb, line 133
def process_commit_message(commit_message, hash)
    patterns_array = [/Merge pull request #(\d+).*/, /\.*\(#(\d+)\)*\)/]
    patterns = Regexp.union(patterns_array)

    child_commit_messages = false
    commit_type = :pr

    if commit_message.scan(/Merge pull request #(\d+).*/m).size.positive? || commit_message.scan(/\.*\(#(\d+)\)*\)/m).size.positive?
        message, child_commit_messages = process_merge_request(commit_message, hash, patterns)
    else
        message, commit_type = process_normal_commit(commit_message)
    end
    [message, child_commit_messages, commit_type]
end
process_merge_request(merge_message, hash, patterns) click to toggle source
# File lib/caretaker-core/core.rb, line 118
def process_merge_request(merge_message, hash, patterns)
    matches = merge_message.match(patterns).captures

    new_message = generate_pr_link(matches)

    child_commit_messages = get_child_messages(hash)

    [new_message, child_commit_messages]
end
process_normal_commit(commit_message) click to toggle source
# File lib/caretaker-core/core.rb, line 128
def process_normal_commit(commit_message)
    commit_type = :commit
    [commit_message, commit_type]
end
process_results(parsed) click to toggle source

This method reeks of :reek:NestedIterators

# File lib/caretaker-core/process.rb, line 33
def process_results(parsed)
    chronological, categorised = init_results(parsed.keys)

    parsed.each do |tag, array|
        tag_str = tag.to_s

        array.each do |arr|
            (chronological[tag_str] ||= []) << arr
            (categorised[tag_str][arr[:category]] ||= []) << arr
        end
    end
    [chronological, categorised]
end
process_single_line(config, line, tag) click to toggle source
# File lib/caretaker-core/core.rb, line 77
def process_single_line(config, line, tag)
    hash, hash_full, commit_message, child_commit_messages, commit_type, category, date, tag = get_parts(line, tag)

    return false if category.downcase == 'skip:'

    commit_message = commit_message.sub(/.*?:/, '').strip if config[:remove_categories]

    data = { :hash => hash, :hash_full => hash_full, :commit_message => commit_message, :child_commit_messages => child_commit_messages, :commit_type => commit_type, :category => category, :date => date }

    [tag, data]
end
real_process(config) click to toggle source
# File lib/caretaker-core/core.rb, line 35
def real_process(config)
    log_entries = retrieve_git_log_entries

    return [ [], [], [] ] unless log_entries

    parsed = parse_git_log_entries(config, log_entries)

    tags = generate_tag_list(parsed)

    chronological, categorised = process_results(parsed)

    [tags, chronological, categorised]
end
retrieve_git_log_entries() click to toggle source

comment to go here

# File lib/caretaker-core/git.rb, line 32
def retrieve_git_log_entries
    log_entries = execute_command("git log --first-parent --oneline --pretty=format:'%h|%H|%d|%s|%cs'")

    return false unless log_entries

    log_entries.split("\n")
end
split_log_entries(line, tag) click to toggle source

Make everything else private so it cannot be accessed directly

# File lib/caretaker-core/utils.rb, line 15
def split_log_entries(line, tag)
    hash, hash_full, refs, commit_message, date = line.split('|')

    tag = extract_tag(refs, tag)

    [date, hash, hash_full, commit_message, tag]
end