From 507a3cd734a8b78f5bd4c6ebb8e41057ea9bac08 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Thu, 29 Dec 2016 17:03:03 +0100 Subject: [PATCH] news_to_releases_xml.rb: add script for converting NEWS.md file to releases.xml --- src/tools/modules/news.rb | 52 +++++++++++++++++++++++ src/tools/news_to_releases_xml.rb | 70 +++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 src/tools/modules/news.rb create mode 100755 src/tools/news_to_releases_xml.rb diff --git a/src/tools/modules/news.rb b/src/tools/modules/news.rb new file mode 100644 index 000000000..e308895d6 --- /dev/null +++ b/src/tools/modules/news.rb @@ -0,0 +1,52 @@ +def parse_news file_name + news = [] + current_line = [] + version = 'HEAD' + date = 'unknown' + type = 'Other changes' + + flush = lambda do + if !current_line.empty? + news << { + :content => current_line.join(' '), + :version => version, + :date => date, + :type => type + } + current_line = [] + end + end + + IO.readlines(file_name).each do |line| + is_continuation = %r{^\s}.match(line) + line = line.chomp.gsub(%r{^\s+}, '').gsub(%r{\s+}, ' ') + + next if line.empty? + + flush.call if %r{^[#*]}.match(line) + + # # Version 9.7.1 "Pandemonium" 2016-12-27 + # # Version 0.6.4 2003-08-27 + + if match = %r{ ^\# \s+ Version \s+ (? [0-9.-]+) (?: \s+ " (?.+) " )? \s+ (?\d+)-(?\d+)-(?\d+) }x.match(line) + version = match[:version] + date = sprintf("%04d-%02d-%02d", match[:year].to_i, match[:month].to_i, match[:day].to_i) + type = 'Other changes' + + elsif %r{ ^\#\# \s+ (.+) }x.match(line) + type = $1 + + elsif %r{ ^\# }x.match(line) && !is_continuation + fail "Don't know what to do with this line: #{line}" + + else + flush.call if /^\*/.match(line) + current_line << line.gsub(/^\*\s*/, '') unless line.empty? + + end + end + + flush.call + + news.chunk { |e| e[:version] } +end diff --git a/src/tools/news_to_releases_xml.rb b/src/tools/news_to_releases_xml.rb new file mode 100755 index 000000000..cf7c2f2ce --- /dev/null +++ b/src/tools/news_to_releases_xml.rb @@ -0,0 +1,70 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'pp' +require 'builder' +require 'rexml/document' +require 'trollop' + +require_relative 'modules/news' + +def create_all_releases_xml news + releases_xml = REXML::Document.new File.new($opts[:releases]) + builder = Builder::XmlMarkup.new( :indent => $opts[:noindent] ? 0 : 2 ) + + node_to_hash = lambda { |xpath| + begin + Hash[ *REXML::XPath.first(releases_xml, xpath).elements.collect { |e| [ e.name, e.text ] }.flatten ] + rescue + Hash.new + end + } + + builder.instruct! :xml, :version => "1.0", :encoding => "UTF-8" + + xml = builder.tag!('mkvtoolnix-releases') do + builder.tag!('latest-source', node_to_hash.call("/mkvtoolnix-releases/latest-source")) + builder.tag!('latest-windows-pre', node_to_hash.call("/mkvtoolnix-releases/latest-windows-pre")) + + builder.tag! 'latest-windows-binary' do + builder.tag! 'installer-url', node_to_hash.call("/mkvtoolnix-releases/latest-windows-binary/installer-url") + builder.tag! 'portable-url', node_to_hash.call("/mkvtoolnix-releases/latest-windows-binary/portable-url") + end + + news.each do |release| + attributes = { + "version" => release[0], + }.merge node_to_hash.call("/mkvtoolnix-releases/release[version='#{release[0]}']") + + builder.release attributes do + builder.changes do + release[1].each do |entry| + builder.change(entry[:content], entry.reject { |key| [:version, :content, :date].include? key }) + end + end + end + end + end + + puts xml +end + +def parse_opts + opts = Trollop::options do + opt :news, "News source file", :type => String, :default => 'NEWS.md' + opt :releases, "releases.xml source file", :type => String, :default => 'releases.xml' + opt :noindent, "do not indent the XML" + end + + Trollop::die :news, "must be given and exist" if !opts[:news] || !File.exist?(opts[:news]) + Trollop::die :releases, "must be given and exist" if !opts[:releases] || !File.exist?(opts[:releases]) + + opts +end + +def main + $opts = parse_opts + create_all_releases_xml parse_news($opts[:news]) +end + +main