# opkbuild
# lib/changelog
# Functions for parsing changelogs.
#
# Copyright (C) 2012 Patrick "P. J." McDermott
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

[ -n "${_OB_CHANGELOG_SM}" ] && return 0
_OB_CHANGELOG_SM='true'

ob_use messages
ob_use locale
ob_use metadata

OB_CHANGELOG_SOURCE=
OB_CHANGELOG_VERSION=
OB_CHANGELOG_DISTRIBUTION=
OB_CHANGELOG_CHANGES=
OB_CHANGELOG_MAINTAINER=
OB_CHANGELOG_DATE=

ob_parse_changelog()
{
	_ob_local _obpch_file _obpch_entry_cb \
		_obpch_line_nr _obpch_line _obpch_line_ \
		_obpch_expect _obpch_blank_lines \
		_obpch_source _obpch_distribution _obpch_version \
		_obpch_maintainer _obpch_date

	if [ ${#} -eq 2 ]; then
		_obpch_file="${1}"
		_obpch_entry_cb="${2}"
	else
		_ob_return 125
		return ${?}
	fi

	# Parsing logic based on that of dpkg.

	_obpch_line_nr=0
	_obpch_expect='first_heading'

	while IFS= read _obpch_line; do
		_obpch_line_nr=$(($_obpch_line_nr + 1))
		if [ -z "${_obpch_line}" ]; then
			if [ "${_obpch_expect}" = 'start_changes' ]; then
				OB_CHANGELOG_CHANGES="${OB_CHANGELOG_CHANGES}
${_obpch_line}"
			elif [ "${_obpch_expect}" = 'next_or_eof' ]; then
				:
			elif [ "${_obpch_expect}" != 'changes_or_trailer' ]; then
				_ob_parse_changelog_error "${_obpch_line_nr}" \
					'changelog_found_blank_line' \
					"$(_ob_get_changelog_expect_str "${_obpch_expect}")"
			else
				_obpch_blank_lines="${_obpch_blank_lines}
${_obpch_line}"
			fi
		elif [ "${_obpch_line# }" = "${_obpch_line}" ]; then
			if [ "${_obpch_expect}" != 'first_heading' -a \
					"${_obpch_expect}" != 'next_or_eof' ]; then
				_ob_parse_changelog_error "${_obpch_line_nr}" \
					'changelog_found_heading' \
					"$(_ob_get_changelog_expect_str "${_obpch_expect}")"
			fi
			_obpch_source="${_obpch_line%% (*}"
			_obpch_line_="${_obpch_line#* (}"
			_obpch_distribution="${_obpch_line_##*) }"
			_obpch_line_="${_obpch_line_%) *}"
			_obpch_version="${_obpch_line_}"
			if [ -z "${_obpch_source}" -o -z "${_obpch_distribution}" -o \
					-z "${_obpch_version}" -o \
					"${_obpch_version% *}" != "${_obpch_version}" ]; then
				_ob_parse_changelog_error "${_obpch_line_nr}" \
					'changelog_bad_heading'
				OB_CHANGELOG_SOURCE=
				OB_CHANGELOG_VERSION=
				OB_CHANGELOG_DISTRIBUTION=
				OB_CHANGELOG_CHANGES=
			else
				if ! ob_validate_source_name "${_obpch_source}"; then
					_ob_parse_changelog_error "${_obpch_line_nr}" \
						'changelog_bad_source' "${source}"
				fi
				if ! ob_parse_version "${_obpch_version}"; then
					_ob_parse_changelog_error "${_obpch_line_nr}" \
						'changelog_bad_source_version' "${_obpch_version}"
				fi
				OB_CHANGELOG_SOURCE="${_obpch_source}"
				OB_CHANGELOG_VERSION="${_obpch_version}"
				OB_CHANGELOG_DISTRIBUTION="${_obpch_distribution}"
				OB_CHANGELOG_CHANGES="${_obpch_line}"
			fi
			_obpch_expect='start_changes'
			_obpch_blank_lines=
		elif [ "${_obpch_line# -- }" != "${_obpch_line}" ]; then
			if [ "${_obpch_expect}" != 'changes_or_trailer' ]; then
				_ob_parse_changelog_error "${_obpch_line_nr}" \
					'changelog_found_trailer' \
					"$(_ob_get_changelog_expect_str "${_obpch_expect}")"
			fi
			_obpch_line="${_obpch_line# -- }"
			_obpch_maintainer="${_obpch_line%%  *}"
			_obpch_date="${_obpch_line#*  }"
			if [ -z "${_obpch_maintainer}" -o -z "${_obpch_date}" -o \
					"${_obpch_maintainer}" = "${_obpch_date}" ]; then
				_ob_parse_changelog_error "${_obpch_line_nr}" \
					'changelog_bad_trailer'
				OB_CHANGELOG_MAINTAINER=
				OB_CHANGELOG_DATE=
			elif [ -n "${OB_CHANGELOG_SOURCE}" ]; then
				OB_CHANGELOG_MAINTAINER="${_obpch_maintainer}"
				OB_CHANGELOG_DATE="${_obpch_date}"
				"${_obpch_entry_cb}"
				if [ ${?} -ne 0 ]; then
					_ob_return 0
					return ${?}
				fi
			fi
			_obpch_expect='next_or_eof'
			_obpch_blank_lines=
		elif [ "${_obpch_line# --}" != "${_obpch_line}" ]; then
			_ob_parse_changelog_error "${_obpch_line_nr}" \
				'changelog_bad_trailer'
		elif [ "${_obpch_line##  }" != "${_obpch_line}" ]; then
			if [ "${_obpch_expect}" != 'start_changes' -a \
					"${_obpch_expect}" != 'changes_or_trailer' ]; then
				_ob_parse_changelog_error "${_obpch_line_nr}" \
					'changelog_found_change' \
					"$(_ob_get_changelog_expect_str "${_obpch_expect}")"
			fi
			OB_CHANGELOG_CHANGES="${OB_CHANGELOG_CHANGES}
${_obpch_blank_lines}${_obpch_line}"
			_obpch_expect='changes_or_trailer'
			_obpch_blank_lines=
		else
			_ob_parse_changelog_error "${_obpch_line_nr}" \
				'changelog_bad_line'
			_obpch_blank_lines=
		fi
	done <"${_obpch_file}"

	if [ "${_obpch_expect}" != 'next_or_eof' ]; then
		_ob_parse_changelog_error "${_obpch_line_nr}" \
			'changelog_found_eof' \
			"$(_ob_get_changelog_expect_str "${_obpch_expect}")"
	fi

	_ob_return 0
	return ${?}
}

_ob_parse_changelog_error()
{
	_ob_local _obpche_file _obpche_line_nr _obpche_msg_id \
		_obpche_file_info _obpche_orig_text_domain

	_obpche_file="${1}"
	_obpche_line_nr="${2}"
	_obpche_msg_id="${3}"
	shift 3

	_obpche_file_info="$(printf '%20s(l%d):' "${_obpche_file}" \
		"${_obpche_line_nr}")"

	_obpche_orig_text_domain="$(ob_get_text_domain)"
	ob_set_text_domain "${_OB_INTERNAL_TEXT_DOMAIN}"

	ob_warn "${_obpche_file_info} $(ob_get_msg "${_obpche_msg_id}")" "${@}"

	ob_set_text_domain "${_obpche_orig_text_domain}"

	_ob_return 0
	return ${?}
}

_ob_get_changelog_expect_str()
{
	_ob_local _obgces_orig_text_domain

	_obgces_orig_text_domain="$(ob_get_text_domain)"
	ob_set_text_domain "${_OB_INTERNAL_TEXT_DOMAIN}"

	echo "$(ob_get_msg "changelog_expect_${1}")"

	ob_set_text_domain "${_obgces_orig_text_domain}"

	_ob_return 0
	return ${?}
}