# Copyright (c) 2020 Jerome Arbez-Gindre # frozen_string_literal: true require 'defmastership/modifier/update_def' require 'git' require 'tmpdir' module Defmastership module Modifier # modify one line after another class UpdateDefVersion < UpdateDef # @return [Hash{Symbol => Object}] the default configuration def self.default_config { def_type: '', ref_document: [], ref_tag: '', ref_repo: '.', first_version: '' } end # @param config [YAML] the modifier's provided configurations def initialize(config) @ref_document = Document.new Helper.normalilize_config!(config) if config.key?(:ref_document) super end # Apply the modifier on all provided asciidoc sources based on modifier's # +self.replacement_methods+ list # # @param adoc_sources [Hash{String => String}] asciidoc sources # * :key filename # * :value file content def do_modifications(adoc_sources) if ref_tag == '' ref_document.each { |ref_doc| @ref_document.parse_file_with_preprocessor(ref_doc) } else Dir.mktmpdir('defmastership') do |tmpdir| parse_ref_files_from_git(adoc_sources, tmpdir) end end super end private def parse_ref_files_from_git(adoc_sources, tmpdir) Git.clone(ref_repo, tmpdir, branch: ref_tag) ref_sources = ref_document.empty? ? adoc_sources.keys : ref_document ref_sources.each do |adoc_file| @ref_document.parse_file_with_preprocessor("#{tmpdir}/#{adoc_file}") end end def reference_replacement(reference, match) "#{reference}#{version_and_checksum_str(match)}" end def version_and_checksum_str(match) explicit_checksum = match[:explicit_checksum] version = version_string(match) return unless explicit_checksum || version "(#{version}#{explicit_checksum})" end def version_string(match) ref_definition = Helper.def_from_match(@ref_document, match) definition = Helper.def_from_match(document, match) return unless ref_definition Helper.ref_version(ref_definition, definition, first_version) end # Helper functions module Helper # @param doc [Document] the document with defintions # @param match [MatchData] Regexp match matching a reference # @return [Definition] the definition from a +Document+ with a matching reference def self.def_from_match(doc, match) doc.ref_to_def(match[:reference]) end # @param ref_definition [Definition] the definition from the reference document # @param definition [Definition] the definition from the current document # @param first_version [String] first version from configuration # @return [String] the current definition version def self.ref_version(ref_definition, definition, first_version) new_ref_version = ref_definition.explicit_version return new_ref_version if definition.sha256_short == ref_definition.sha256_short new_ref_version ? new_ref_version.next : first_version end # Make sure that ref_document configuration is an Array # # @param config [YAML] the definition from the reference document def self.normalilize_config!(config) ref_docs = config.fetch(:ref_document) config[:ref_document] = [ref_docs] if ref_docs.instance_of?(String) end end private_constant :Helper end end end