iv-mexx/git-releaselog

View on GitHub
lib/git-releaselog.rb

Summary

Maintainability
C
1 day
Test Coverage
require "rugged"
require "logger"
require "git-releaselog/changelog_helpers"
require "git-releaselog/changelog"
require "git-releaselog/version"

module Releaselog
  class Releaselog
    def self.generate_releaselog(options = {})
    repo_path = options.fetch(:repo_path, '.')
    from_ref_name = options.fetch(:from_ref, nil).strip if options.fetch(:from_ref, nil)
    to_ref_name = options.fetch(:to_ref, nil).strip if options.fetch(:to_ref, nil)
    scope = options.fetch(:scope, nil)
    format = options.fetch(:format, 'slack')
    generate_complete = options.fetch(:generate_complete, false)
    verbose = options.fetch(:verbose, false)

    # Initialize Logger
    logger = Logger.new(STDOUT)
    logger.level = verbose ?  Logger::DEBUG : Logger::ERROR

    # Initialize Repo
    begin
      repo = Rugged::Repository.discover(repo_path)
    rescue Rugged::OSError => e
      puts ("Current directory is not a git repo")
      logger.error(e.message)
      exit
    end

    # Find if we're operating on tags
    from_ref = tagWithName(repo, from_ref_name)
    to_ref = tagWithName(repo, to_ref_name)
    latest_tag = latestTagID(repo, logger)

    if from_ref
      logger.info("Found Tag #{from_ref.name} to start from")
    end

    if to_ref
      logger.info("Found Tag #{to_ref.name} to end at")
    end

    if latest_tag
      logger.info("Latest Tag found: #{latest_tag.name}")
    end

    if generate_complete && repo.tags.count > 0
      sorted_tags = repo.tags.sort { |t1, t2| t1.target.time <=> t2.target.time }
      changeLogs = []
      sorted_tags.each_with_index do |tag, index|
        logger.info("Tag #{tag.name} with date #{tag.target.time}")

        if index == 0
            # First Interval: Generate from start of Repo to the first Tag
            changes = searchGitLog(repo, nil, tag.target, scope, logger)
            changeLogs += [Changelog.new(changes, nil, tag, nil, nil)]

            logger.info("Parsing from start of the repo to #{tag.target.oid}")
            logger.info("First Tag: #{tag.name}: #{changes.count} changes")
          else
            # Normal interval: Generate from one Tag to the next Tag
            previousTag = sorted_tags[index-1]
            changes = searchGitLog(repo, previousTag.target, tag.target, scope, logger)
            changeLogs += [Changelog.new(changes, previousTag, tag, nil, nil)]

            logger.info("Parsing from #{tag.target.oid} to #{previousTag.target.oid}")
            logger.info("Tag #{previousTag.name} to #{tag.name}: #{changes.count} changes")
          end
        end

        if sorted_tags.count > 0
          lastTag = sorted_tags.last
          # Last Interval: Generate from last Tag to HEAD
          changes = searchGitLog(repo, lastTag.target, repo.head.target, scope, logger)
          changeLogs += [Changelog.new(changes, lastTag, nil, nil, nil)]

          logger.info("Parsing from #{lastTag.target.oid} to HEAD")
          logger.info("Tag #{lastTag.name} to HEAD: #{changes.count} changes")
        end

        # Print the changelog
        if format == "md"
          changeLogs.reverse.map { |log| "#{log.to_md}\n" }
        elsif format == "slack"
          changeLogs.reduce("") { |log, version| log + "#{version.to_slack}\n" }
        else
          logger.error("Unknown Format: `#{format}`")
        end
      else
        # From which commit should the log be followed? Will default to the latest tag
        commit_from = (from_ref && from_ref.target) || commit(repo, from_ref_name, logger) || latest_tag && (latest_tag.target)
        logger.info("Commit-From: #{commit_from.oid}")

        # To which commit should the log be followed? Will default to HEAD
        commit_to = (to_ref && to_ref.target) || commit(repo, to_ref_name, logger) || repo.head.target
        logger.info("Commit-To: #{commit_to.oid}")


        changes = searchGitLog(repo, commit_from, commit_to, scope, logger)
        # Create the changelog
        log = Changelog.new(changes, from_ref, to_ref, commit_from, commit_to)

        # Print the changelog
        case format
        when "md"
          log.to_md
        when "slack"
          log.to_slack
        when "raw"
          log
        else
          logger.error("Unknown Format: `#{format}`")
        end
      end
    end
  end
end