aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Müller <ulm@gentoo.org>2009-08-15 12:58:33 +0000
committerUlrich Müller <ulm@gentoo.org>2009-08-15 12:58:33 +0000
commitfb7a3575dbaea290f4babeb17575af23ce91ad5f (patch)
treed08324276a6a5b95c45f1e2e8b9fcdd682c37c79 /modules/news.eselect
parentAdd quotes. (diff)
downloadeselect-fb7a3575dbaea290f4babeb17575af23ce91ad5f.tar.gz
eselect-fb7a3575dbaea290f4babeb17575af23ce91ad5f.tar.bz2
eselect-fb7a3575dbaea290f4babeb17575af23ce91ad5f.zip
Rename news-tng module to news.
svn path=/trunk/; revision=612
Diffstat (limited to 'modules/news.eselect')
-rw-r--r--modules/news.eselect404
1 files changed, 404 insertions, 0 deletions
diff --git a/modules/news.eselect b/modules/news.eselect
new file mode 100644
index 0000000..5b8f269
--- /dev/null
+++ b/modules/news.eselect
@@ -0,0 +1,404 @@
+# Copyright 2005-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+inherit package-manager
+
+DESCRIPTION="Read Gentoo (\"GLEP 42\") news items"
+MAINTAINER="ulm@gentoo.org"
+SVN_DATE='$Date$'
+VERSION=$(svn_date_to_version "${SVN_DATE}")
+
+NEWS_DIR="${EPREFIX}/var/lib/gentoo/news"
+
+# read list of news items
+# list of parameters may contain "unread" or "read"
+# returns one item per line: status/repository/name
+# sort order: 1. "unread" before "read", 2. by repository
+find_items() {
+ local stat repos=$(get_repositories) repo item
+ for stat in "$@"; do
+ for repo in ${repos}; do
+ file="${ROOT}${NEWS_DIR}/news-${repo}.${stat}"
+ [[ -f ${file} ]] || continue
+ for item in $(<"${file}"); do
+ echo "${stat}/${repo}/${item}"
+ done
+ done
+ done
+}
+
+# write list of items to file
+# first parameter is "unread" or "read"
+# second parameter is the repository
+# list of items is expected in global array "items"
+write_item_list() {
+ local stat=$1 repo=$2 item update
+ for item in "${items[@]}"; do
+ [[ ${item%%/*} = ${stat} ]] || continue
+ item=${item#*/}
+ [[ ${item%%/*} = ${repo} ]] && update="${update} ${item#*/}"
+ done
+ file="${ROOT}${NEWS_DIR}/news-${repo}.${stat}"
+ for item in ${update}; do
+ echo "${item}"
+ done >"${file}"
+ if [[ $? -ne 0 ]]; then
+ write_error_msg \
+ "Cannot update list of news items for repository \"${repo}\""
+ return 1
+ fi
+ # GLEP 42 says the file should be in the portage group and group writable
+ chgrp portage "${file}" 2>/dev/null && chmod 664 "${file}" 2>/dev/null
+ return 0
+}
+
+# read a given item
+# first parameter is the directory
+# second parameter is the item's name
+# optional third parameter may be "header", "body", or "existsp"
+read_item() {
+ local dir=$1 item=$2 what=$3 file lang command=""
+ for lang in $(accepted_languages); do
+ file="${ROOT}${dir}/${item}/${item}.${lang}.txt"
+ [[ -f "${file}" ]] || continue
+ case "${what}" in
+ header) command="/^$/Q" ;;
+ body) command="0,/^$/d" ;;
+ existsp) return 0 ;;
+ esac
+ sed -e "${command}" "${file}" || die "Error reading ${file}"
+ return
+ done
+ return 1
+}
+
+# find directory for a given repository (and cache it)
+# affects variable "dir" and arrays "repos" and "dirs" by side effect
+find_repo_dir() {
+ local repo=$1 i
+ for (( i = 0; i < ${#repos[@]}; i++ )); do
+ [[ ${repos[i]} = ${repo} ]] && break
+ done
+ if [[ ${i} -eq ${#repos[@]} ]]; then
+ repos[i]=${repo}
+ dirs[i]=$(get_repo_news_dir "${repo}")
+ fi
+ dir=${dirs[i]}
+}
+
+# return list of accepted languages
+accepted_languages() {
+ local lc=${LC_ALL:-${LANG}}
+ lc=${lc%%[^[:alpha:]]*}
+ [[ -n ${lc} && ${lc} != en ]] && echo ${lc}
+ echo en
+}
+
+# calculate day of week for given year ($1), month ($2), and day ($3)
+# using Chr. Zeller's formula for the new calendar
+day_of_week() {
+ local a=${1##*(0)} m=${2##*(0)} q=${3##*(0)}
+ local -a wd=( Sat Sun Mon Tue Wed Thu Fri )
+ [[ ${m} -le 2 ]] && (( a--, m += 12 ))
+ echo ${wd[(q + (m+1)*13/5 + a + a/4 - a/100 + a/400) % 7]}
+}
+
+# encode header as quoted-printable
+rfc2047_encode() {
+ local s=$1 i c LC_ALL=C
+ echo -n "=?UTF-8?Q?"
+ for (( i=0; i<${#s}; i++ )); do
+ c=${s:i:1}
+ if [[ ${c} =~ [-A-Za-z0-9!*+/] ]]; then
+ echo -n "${c}"
+ elif [[ ${c} = ' ' ]]; then
+ echo -n '_'
+ else
+ printf '=%02X' "'${c}"
+ fi
+ done
+ echo "?="
+}
+
+# output message header in e-mail/mbox format
+mail_header() {
+ local item=$1 author=$2 title=$3 posted=$4
+ local -a mname=( 0 Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec )
+ local year=0001 month=01 day=01 time="00:00:00" wd addr name
+
+ # "date -d" is not portable, therefore we do manual processing
+ if [[ ${posted} == +([0-9])-+([0-9])-+([0-9]) ]]; then
+ year=${posted%%-*}
+ month=${posted#*-*(0)}; month=${month%%-*}
+ day=${posted##*-}
+ fi
+ wd=$(day_of_week "${year}" "${month}" "${day}")
+
+ if [[ ${author} == *([^\<\>])\<+([^\<\>])\> ]]; then
+ # GLEP 42 says this must look like "Real Name <email@address>"
+ name=${author%%*( )<*}
+ addr=${author##*<}; addr=${addr%%>*}
+ elif [[ ${author} == +([^\<\>]) ]]; then
+ addr=${author}
+ fi
+
+ [[ ${name} != *([[:ascii:]]) || ${name} =~ [\]\[()\<\>\",.:\;@\\] ]] \
+ && name=$(rfc2047_encode "${name}")
+ [[ ${title} != *([[:ascii:]]) ]] && title=$(rfc2047_encode "${title}")
+
+ echo "From ${addr} ${wd} ${mname[month]} ${day} ${time} ${year}"
+ echo "From: ${name} <${addr}>"
+ #echo "Reply-To: DO NOT REPLY <devnull@localhost.invalid>"
+ echo "Subject: ${title}"
+ echo "Date: ${wd}, ${day} ${mname[month]} ${year} ${time} +0000"
+ echo "Message-Id: <glep42-${item}@gentoo.org>"
+ echo "MIME-Version: 1.0"
+ echo "Content-Type: text/plain; charset=UTF-8"
+ echo "Content-Transfer-Encoding: 8bit"
+}
+
+### list action
+
+describe_list() {
+ echo "List news items"
+}
+
+do_list() {
+ local item stat repo dir header line title posted i=1
+ local ifs_save=${IFS-$' \t\n'}
+ local -a repos dirs
+
+ set -- $(find_items unread read)
+ write_list_start "News items:"
+ for item in "$@"; do
+ stat=${item%%/*}; item=${item#*/}
+ repo=${item%%/*}; item=${item#*/}
+ find_repo_dir "${repo}"
+ header=$(read_item "${dir}" "${item}" header)
+ IFS=$'\n'
+ title="(${item} - no title)"
+ posted="(no date) "
+ for line in ${header}; do
+ case "${line%%:*}" in
+ Title) title=${line##*([^:]):*([[:space:]])} ;;
+ Posted) posted=${line##*([^:]):*([[:space:]])} ;;
+ esac
+ done
+ IFS=${ifs_save}
+ if [[ ${stat} = unread ]]; then
+ write_numbered_list_entry $((i++)) "$(highlight \
+ "${posted}$(space $((12 - ${#posted})))(unread) ${title}")"
+ else
+ write_numbered_list_entry $((i++)) \
+ "${posted}$(space $((12 - ${#posted})))(read) ${title}"
+ fi
+ done
+ [[ $# -eq 0 ]] && write_kv_list_entry "(none found)" ""
+}
+
+### count action
+
+describe_count() {
+ echo "Display number of news items"
+}
+
+describe_count_options() {
+ echo "new : Count unread news items (default)"
+ echo "all : Count all news items"
+}
+
+do_count() {
+ local status
+ [[ $1 = all ]] && status="unread read" || status="unread"
+ set -- $(find_items ${status})
+ echo $#
+}
+
+### read action
+
+describe_read() {
+ echo "Read news items"
+}
+
+describe_read_options() {
+ echo "new : Read unread news items (default)"
+ echo "all : Read all news items"
+ echo "item : Number of item (from 'list' action)"
+ echo "--mbox : Output in mbox format"
+ echo "--raw : Output in raw format"
+}
+
+describe_read_parameters() {
+ echo "<item>..."
+}
+
+do_read() {
+ local -a items=( $(find_items unread read) ) repos dirs
+ local n=${#items[@]} format=cooked ifs_save=${IFS-$' \t\n'}
+ local item repo stat dir header line i seq repos_upd author title posted
+
+ while [[ $# -gt 0 ]]; do
+ case ${1##--} in
+ mbox) format=mbox ;;
+ raw) format=raw ;;
+ *) break ;;
+ esac
+ shift
+ done
+
+ # expand special values "new" and "all"
+ if [[ $# -eq 0 || $1 = new || $1 = all ]]; then
+ for (( i = 1; i <= n; i++ )); do
+ [[ $1 = all || ${items[i-1]%%/*} = unread ]] || break
+ seq="${seq} ${i}"
+ done
+ set -- ${seq}
+ [[ $# -eq 0 && ${format} = cooked ]] && echo "No news is good news."
+ fi
+
+ for i in "$@"; do
+ if ! is_number "${i}" || [[ ${i} -lt 1 || ${i} -gt ${#items[@]} ]]
+ then
+ write_warning_msg "Bad item number: ${i}"
+ continue
+ fi
+ item=${items[--i]}
+ stat=${item%%/*}; item=${item#*/}
+ repo=${item%%/*}; item=${item#*/}
+ find_repo_dir "${repo}"
+ case ${format} in
+ raw)
+ read_item "${dir}" "${item}"
+ ;;
+ cooked)
+ write_list_start "${item}"
+ header=$(read_item "${dir}" "${item}" header)
+ IFS=$'\n'
+ for line in ${header}; do
+ case "${line%%:*}" in
+ Title)
+ write_kv_list_entry "${line%%:*}" \
+ "$(highlight "${line##*([^:]):*([[:space:]])}")"
+ ;;
+ Author|Translator|Posted|Revision)
+ write_kv_list_entry "${line%%:*}" \
+ "${line##*([^:]):*([[:space:]])}"
+ ;;
+ esac
+ done
+ IFS=${ifs_save}
+ echo
+ read_item "${dir}" "${item}" body
+ ;;
+ mbox)
+ header=$(read_item "${dir}" "${item}" header)
+ author=""; title=""; posted=""
+ IFS=$'\n'
+ for line in ${header}; do
+ case "${line%%:*}" in
+ Author) : ${author:=${line##*([^:]):*([[:space:]])}} ;;
+ Title) : ${title:=${line##*([^:]):*([[:space:]])}} ;;
+ Posted) : ${posted:=${line##*([^:]):*([[:space:]])}} ;;
+ esac
+ done
+ mail_header "${item}" "${author}" "${title}" "${posted}"
+ echo
+ for line in ${header}; do
+ case "${line%%:*}" in
+ Title|Author|Translator|Posted|Revision)
+ echo "${line}" ;;
+ esac
+ done
+ IFS=${ifs_save}
+ echo
+ read_item "${dir}" "${item}" body | sed 's/^>*From />&/;$q'
+ ;;
+ esac
+ [[ $? -ne 0 ]] && write_error_msg "Error reading item \"${item}\""
+ echo
+
+ [[ ${stat} = unread ]] || continue
+ # move from "unread" to "read"
+ unset items[i]
+ items[n++]=read/${repo}/${item}
+ has ${repo} ${repos_upd} || repos_upd="${repos_upd} ${repo}"
+ done
+
+ # update lists of read/unread items
+ for repo in ${repos_upd}; do
+ write_item_list read ${repo} && write_item_list unread ${repo}
+ done
+}
+
+### unread action
+
+describe_unread() {
+ echo "Mark read news items as unread again"
+}
+
+describe_unread_options() {
+ echo "all : Mark all news items as unread"
+ echo "item : Number of item (from 'list' action)"
+}
+
+describe_unread_parameters() {
+ echo "<item>..."
+}
+
+do_unread() {
+ local -a items=( $(find_items unread read) )
+ local n=${#items[@]} item repo stat i seq repos_upd
+
+ # expand special value "all"
+ if [[ $1 = all ]]; then
+ for (( i = 1; i <= n; i++ )); do
+ seq="${seq} ${i}"
+ done
+ set -- ${seq}
+ fi
+
+ for i in "$@"; do
+ if ! is_number "${i}" || [[ ${i} -lt 1 || ${i} -gt ${#items[@]} ]]
+ then
+ write_warning_msg "Bad item number: ${i}"
+ continue
+ fi
+ item=${items[--i]}
+ stat=${item%%/*}; item=${item#*/}
+ repo=${item%%/*}; item=${item#*/}
+ [[ ${stat} = read ]] || continue
+ # move from "read" to "unread"
+ unset items[i]
+ items[n++]=unread/${repo}/${item}
+ has ${repo} ${repos_upd} || repos_upd="${repos_upd} ${repo}"
+ done
+
+ # update lists of unread/read items
+ for repo in ${repos_upd}; do
+ write_item_list unread ${repo} && write_item_list read ${repo}
+ done
+}
+
+### purge action
+
+describe_purge() {
+ echo "Purge read news"
+}
+
+do_purge() {
+ local -a items=( $(find_items read) )
+ local item i repos
+
+ # find repos with nonempty lists
+ for (( i = 0; i < ${#items[@]}; i++ )); do
+ item=${items[i]#*/}
+ has "${item%%/*}" ${repos} || repos="${repos} ${item%%/*}"
+ done
+
+ # purge list of read items
+ items=()
+ for repo in ${repos}; do
+ write_item_list read ${repo}
+ done
+}