def fetch_tag_shas_async(tags)
      i = 0
      threads = []
      print_in_same_line("Fetching SHAs for tags: #{i}/#{tags.count}\r") if @options[:verbose]

      tags.each_slice(MAX_THREAD_NUMBER) do |tags_slice|
        tags_slice.each do |tag|
          threads << Thread.new do
            # Use oldest commit because comparing two arbitrary tags may be diverged
            commits_in_tag = fetch_compare(oldest_commit["sha"], tag["name"])
            tag["shas_in_tag"] = commits_in_tag["commits"].collect { |commit| commit["sha"] }
            print_in_same_line("Fetching SHAs for tags: #{i + 1}/#{tags.count}") if @options[:verbose]
            i += 1
          end
        end
        threads.each(&:join)
        threads = []
      end

      # to clear line from prev print
      print_empty_line

      Helper.log.info "Fetching SHAs for tags: #{i}"
      nil
    end
def fetch_tag_shas_async(tags)
      i = 0
      threads = []
      print_in_same_line("Fetching SHAs for tags: #{i}/#{tags.count}\r") if @options[:verbose]

      tags.each_slice(MAX_THREAD_NUMBER) do |tags_slice|
        tags_slice.each do |tag|
          threads << Thread.new do
            # Use oldest commit because comparing two arbitrary tags may be diverged
            commits_in_tag = fetch_compare(oldest_commit["sha"], tag["name"])
            tag["shas_in_tag"] = commits_in_tag["commits"].collect { |commit| commit["sha"] }
            print_in_same_line("Fetching SHAs for tags: #{i + 1}/#{tags.count}") if @options[:verbose]
            i += 1
          end
        end
        threads.each(&:join)
        threads = []
      end

      # to clear line from prev print
      print_empty_line

      Helper.log.info "Fetching SHAs for tags: #{i}"
      nil
    end
Fetch all SHAs occurring in or before a given tag and add them to
 "shas_in_tag"

 @param [Array] tags The array of tags.
 @return [Nil] No return; tags are updated in-place.