Newer
Older
# coding: utf-8
# archversion - Archlinux Version Controller
# Copyright © 2012 Sébastien Luttringer
#
# 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, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
'''Archlinux Version Controller'''
from archversion import VERSION, DEFAULT_CONFIG_FILENAME, DEFAULT_CACHE_FILENAME
from archversion.config import BaseConfigFile
from archversion.database import JsonDatabase
from archversion.error import BaseError, MissingConfigFile, NoSuchFile
from archversion.error import ERR_FATAL, ERR_ABORT, ERR_UNKNOWN
from archversion.pacman import parse_pkgbuild, pkgbuild_set_version, pkgbuild_update_checksums
from archversion.version import VersionController
from email.mime.text import MIMEText
from io import StringIO
from smtplib import SMTP
def parse_argv():
'''Parse command line arguments'''
p_main = argparse.ArgumentParser()
p_main.add_argument("--version", action="version",
p_main.add_argument("--debug", action="store_true",
help="debug mode")
p_main.add_argument("-c", "--config", default=None,
help="config file path")
p_main.add_argument("-C", "--cache", default=None,
help="cache file path")
sp_main = p_main.add_subparsers()
help="list configured packages")
p_conf.add_argument("-s", "--sort", action="store_true",
help="sort listing")
p_conf.add_argument("packages", nargs='*', help="only check these packages")
# sync parser
p_sync = sp_main.add_parser("sync",
help="retrieve upstream and dowstream versions")
p_sync.add_argument("-s", "--sort", action="store_true",
help="sort syncing")
p_sync.add_argument("packages", nargs='*', help="only sync these packages")
p_sync.set_defaults(func=command_sync)
help="list check against modes")
p_modes.set_defaults(func=command_modes)
p_report.add_argument("-f", "--fresh", action="store_true",
help="Only report fresh versions")
p_report.add_argument("-n", "--new", action="store_true",
help="Only report new versions")
p_report.add_argument("-s", "--sort", action="store_true",
help="sync packages versions before report")
p_report.add_argument("packages", nargs='*',
help="only report these packages")
p_report.set_defaults(func=command_report)
# sendmail parser
p_sendmail = sp_main.add_parser("sendmail",
help="sendmail packages versions by mail")
p_sendmail.add_argument("-f", "--fresh", action="store_true",
help="Only sendmail fresh versions")
p_sendmail.add_argument("-n", "--new", action="store_true",
help="Only sendmail new versions")
p_sendmail.add_argument("-s", "--sort", action="store_true",
help="sort packages by name")
p_sendmail.add_argument("-S", "--sync", action="store_true",
help="sync packages versions before sendmail")
p_sendmail.add_argument("--to", help="mail destination address")
p_sendmail.add_argument("--smtp", help="smtp server")
p_sendmail.add_argument("packages", nargs='*',
help="only sendmail these packages")
p_sendmail.set_defaults(func=command_sendmail)
help="update a PKGBUILD with the latest version")
p_update.add_argument("-p", "--path", default="PKGBUILD",
help="name of the file to update. Default PKGBUILD")
p_update.add_argument("-c", "--checksum", action="store_true",
help="run updpkgsums after update")
p_update.add_argument("-S", "--no-sync", action="store_false",
help="don't sync packages versions prior update")
namespace = p_main.parse_args()
# Ensure subparser was choosen
if "func" not in namespace:
p_main.error("missing argument")
return namespace
def command_config(args, vctrl):
'''list configured packages'''
if len(args.packages) > 0:
vctrl.reduce_packages(args.packages)
if args.sort:
vctrl.sort_packages()
vctrl.print_names()
def command_modes(args, vctrl):
'''list checking against modes'''
vctrl.print_modes()
def command_sync(args, vctrl):
'''Handle sync command call'''
# reduce the package list
if len(args.packages) > 0:
vctrl.reduce_packages(args.packages)
# sort packages if asked
if args.sort:
vctrl.sort_packages()
# start syncing
vctrl.sync_packages()
def command_report(args, vctrl):
'''Handle report command call'''
vctrl.reduce_packages(args.packages)
# sync if asked
if args.sync:
vctrl.sync_packages()
# start report
vctrl.print_versions(args.new, args.fresh)
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
def command_sendmail(args, vctrl):
'''Handle sendmail command call'''
# check args
try:
to = vctrl.packages["ARCHVERSION"]["mailto"]
subject = vctrl.packages["ARCHVERSION"]["mailsubject"]
smtp = vctrl.packages["ARCHVERSION"]["smtp"]
except KeyError:
logging.error("Invalid sendmail config in section [ARCHVERSION]")
exit(1)
# capture a report
stdout = StringIO()
stdout_bak = sys.stdout
sys.stdout = stdout
command_report(args, vctrl)
sys.stdout = stdout_bak
# no data, no mail!
if len(stdout.getvalue()) == 0:
return
# format the mail
msg = MIMEText(stdout.getvalue())
msg['Subject'] = subject
msg['From'] = "Archversion <version@archlinux.org>"
msg['To'] = to
# send the mail
try:
s = SMTP(smtp)
s.send_message(msg)
s.quit()
except Exception as exp:
logging.error("Sendmail fail: %s" % exp)
exit(1)
def command_update(args, vctrl):
'''Handle update command call'''
if not os.path.exists(args.path):
raise NoSuchFile(args.path)
if os.getresuid()[1] == 0:
logging.warn("Warning: You should not run this as root")
pkgdict = parse_pkgbuild(args.path)
pkgname = pkgdict.get("pkgname0", pkgdict.get("pkgbase", None))
pkgver = pkgdict.get("pkgver", None)
# some sanity checks
raise BaseError("Unable to detect pkgname in %s" % args.path)
if pkgname not in vctrl.packages:
raise BaseError("No registered package %s" % pkgname)
# redure packge list to the extracted one
vctrl.reduce_packages((pkgname,))
# sync if not refused
if not args.no_sync:
vctrl.sync_packages()
upver = vctrl.cache["upstream"].get(pkgname, {}).get("version", None)
if upver is None:
raise BaseError("Unable to detect upstream version of %s" % pkgname)
# print what we detect
print("Package name: %s" % pkgname)
print("PKGBUILD version: %s" % pkgver)
print("Version are the same. Do nothing!")
return
# update version with upstream
pkgbuild_set_version(args.path, upver)
# update checksum
if args.checksum:
pkgbuild_update_checksums(args.path)
def main():
'''Program entry point'''
try:
# parse command line
args = parse_argv()
# set global debug mode
if args.debug:
logging.getLogger().setLevel(logging.DEBUG)
# load configuration
packages = BaseConfigFile(args.config, DEFAULT_CONFIG_FILENAME)
# load cache database
cachedb = JsonDatabase()
cachedb.load(args.cache, DEFAULT_CACHE_FILENAME)
# load checking controller
vctrl = VersionController(packages, cachedb)
# call command function
return args.func(args, vctrl)
except KeyboardInterrupt:
exit(ERR_ABORT)
except BaseError as exp:
logging.error(exp)
exit(ERR_FATAL)
except Exception as exp:
logging.error("Unknown error. Please report it with --debug.")
logging.error(exp)
if logging.getLogger().getEffectiveLevel() == logging.DEBUG:
raise