# Functions for parsing changelogs
#
# Copyright (C) 2012, 2018 Patrick McDermott
#
# This file is part of opkbuild.
#
# opkbuild 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 3 of the License, or
# (at your option) any later version.
#
# opkbuild 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 opkbuild. If not, see .
OB_CHANGELOG_SOURCE=
OB_CHANGELOG_VERSION=
OB_CHANGELOG_DISTRIBUTION=
OB_CHANGELOG_CHANGES=
OB_CHANGELOG_MAINTAINER=
OB_CHANGELOG_DATE=
_ob_parse_changelog_error()
{
local file=
local line_nr=
local msg_id=
local file_info=
local orig_text_domain=
file="${1}"
line_nr="${2}"
msg_id="${3}"
shift 3
file_info="$(printf '%20s(l%d):' "${file}" "${line_nr}")"
orig_text_domain="$(ob_get_text_domain)"
ob_set_text_domain "${_OB_INTERNAL_TEXT_DOMAIN}"
ob_warn "${file_info} $(ob_get_msg "${msg_id}")" "${@}"
ob_set_text_domain "${orig_text_domain}"
return 0
}
_ob_get_changelog_expect_str()
{
local orig_text_domain=
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 "${orig_text_domain}"
return 0
}
## @brief Parse a changelog file
## @details \fBob_parse_changelog\fP parses a \fIchangelog\fP file, formatted as
## specified at
## . For
## each version entry, \fBob_parse_changelog\fP calls \fIentry_cb\fP
## after setting \fIOB_CHANGELOG_SOURCE\fP to the source package name,
## \fIOB_CHANGELOG_VERSION\fP to the source package version,
## \fIOB_CHANGELOG_DISTRIBUTION\fP to the list of distributions into
## which the package should be installed, \fIOB_CHANGELOG_CHANGES\fP to
## the formatted heading (source package name, source package version,
## and distributions list) and change details,
## \fIOB_CHANGELOG_MAINTAINER\fP to the name and e-mail address of the
## package maintainer, and \fPOB_CHANGELOG_DATE\fP to the date of
## packaging. \fBob_parse_changelog\fP stops parsing either at the end
## of the \fIchangelog\fP file or when \fIentry_cb\fP returns non-zero.
## @operand file req The file to parse, or "-" for standard input.
## @operand entry_cb req Callback to run for each entry.
## @return Returns 0 after parsing, or 125 on missing arguments.
## @stderr Prints error messages on parse errors.
## @pure maybe This function sets global variables, but they're only intended
## for use by \fIentry_cb\fP, which is called during the lifetime of
## this function. Whether this function is subshell-safe in
## practice depends on whether \fIentry_cb\fP is subshell-safe.
ob_parse_changelog()
{
local file=
local entry_cb=
local line_nr=
local line=
local line_=
local expect=
local blank_lines=
local source=
local distribution=
local version=
local maintainer=
local date=
if [ ${#} -eq 2 ]; then
file="${1}"
entry_cb="${2}"
else
return 125
fi
# Parsing logic based on that of dpkg.
line_nr=0
expect='first_heading'
while IFS= read line; do
line_nr=$(($line_nr + 1))
if [ -z "${line}" ]; then
if [ "${expect}" = 'start_changes' ]; then
OB_CHANGELOG_CHANGES="${OB_CHANGELOG_CHANGES}${_OB_LF}${line}"
elif [ "${expect}" = 'next_or_eof' ]; then
:
elif [ "${expect}" != 'changes_or_trailer' ]; then
_ob_parse_changelog_error "${file}" "${line_nr}" \
'changelog_found_blank_line' \
"$(_ob_get_changelog_expect_str "${expect}")"
else
blank_lines="${blank_lines}${_OB_LF}${line}"
fi
elif [ "${line# }" = "${line}" ]; then
if [ "${expect}" != 'first_heading' -a \
"${expect}" != 'next_or_eof' ]; then
_ob_parse_changelog_error "${file}" "${line_nr}" \
'changelog_found_heading' \
"$(_ob_get_changelog_expect_str "${expect}")"
fi
source="${line%% (*}"
line_="${line#* (}"
distribution="${line_##*) }"
line_="${line_%) *}"
version="${line_}"
if [ -z "${source}" -o -z "${distribution}" -o \
-z "${version}" -o \
"${version% *}" != "${version}" ]; then
_ob_parse_changelog_error "${file}" "${line_nr}" \
'changelog_bad_heading'
OB_CHANGELOG_SOURCE=
OB_CHANGELOG_VERSION=
OB_CHANGELOG_DISTRIBUTION=
OB_CHANGELOG_CHANGES=
else
if ! ob_validate_source_name "${source}"; then
_ob_parse_changelog_error \
"${file}" "${line_nr}" \
'changelog_bad_source' "${source}"
fi
if ! ob_parse_version "${version}"; then
_ob_parse_changelog_error \
"${file}" "${line_nr}" \
'changelog_bad_source_version' "${version}"
fi
OB_CHANGELOG_SOURCE="${source}"
OB_CHANGELOG_VERSION="${version}"
OB_CHANGELOG_DISTRIBUTION="${distribution}"
OB_CHANGELOG_CHANGES="${line}"
fi
expect='start_changes'
blank_lines=
elif [ "${line# -- }" != "${line}" ]; then
if [ "${expect}" != 'changes_or_trailer' ]; then
_ob_parse_changelog_error "${file}" "${line_nr}" \
'changelog_found_trailer' \
"$(_ob_get_changelog_expect_str "${expect}")"
fi
line="${line# -- }"
maintainer="${line%% *}"
date="${line#* }"
if [ -z "${maintainer}" -o -z "${date}" -o \
"${maintainer}" = "${date}" ]; then
_ob_parse_changelog_error "${file}" "${line_nr}" \
'changelog_bad_trailer'
OB_CHANGELOG_MAINTAINER=
OB_CHANGELOG_DATE=
elif [ -n "${OB_CHANGELOG_SOURCE}" ]; then
OB_CHANGELOG_MAINTAINER="${maintainer}"
OB_CHANGELOG_DATE="${date}"
"${entry_cb}"
if [ ${?} -ne 0 ]; then
return 0
fi
fi
expect='next_or_eof'
blank_lines=
elif [ "${line# --}" != "${line}" ]; then
_ob_parse_changelog_error "${file}" "${line_nr}" \
'changelog_bad_trailer'
elif [ "${line## }" != "${line}" ]; then
if [ "${expect}" != 'start_changes' -a \
"${expect}" != 'changes_or_trailer' ]; then
_ob_parse_changelog_error "${file}" "${line_nr}" \
'changelog_found_change' \
"$(_ob_get_changelog_expect_str "${expect}")"
fi
OB_CHANGELOG_CHANGES="${OB_CHANGELOG_CHANGES}${_OB_LF}${blank_lines}${line}"
expect='changes_or_trailer'
blank_lines=
else
_ob_parse_changelog_error "${file}" "${line_nr}" \
'changelog_bad_line'
blank_lines=
fi
done <<-EOF
$(cat "${file}")
EOF
if [ "${expect}" != 'next_or_eof' ]; then
_ob_parse_changelog_error "${file}" "${line_nr}" \
'changelog_found_eof' \
"$(_ob_get_changelog_expect_str "${expect}")"
fi
return 0
}