mirror of
https://github.com/bvanroll/_dotfiles.git
synced 2025-08-30 04:22:47 +00:00
141 lines
4.3 KiB
Python
Executable File
141 lines
4.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
# List available updates from the Arch User Repository (AUR)
|
|
|
|
# Copyright 2018 Johannes Lange
|
|
#
|
|
# 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 3 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/>.
|
|
|
|
import json
|
|
import os
|
|
import requests
|
|
import socket
|
|
import subprocess as sp
|
|
|
|
block_button = os.environ['BLOCK_BUTTON'] if 'BLOCK_BUTTON' in os.environ else None
|
|
block_button = int(block_button) if block_button else None
|
|
|
|
|
|
class Args(object):
|
|
def add_argument(self, name, default='', arg_type=str):
|
|
val = default
|
|
if name in os.environ:
|
|
val = os.environ[name]
|
|
if arg_type == list:
|
|
val = val.split()
|
|
val = arg_type(val)
|
|
setattr(self, name.lower(), val)
|
|
return val
|
|
|
|
|
|
args = Args()
|
|
args.add_argument('UPDATE_COLOR', 'yellow')
|
|
args.add_argument('QUIET', 0, int)
|
|
args.add_argument('IGNORE', [], list)
|
|
args.add_argument('CACHE_UPDATES', 0, int)
|
|
args.add_argument('FORCE_IPV4', 1, int)
|
|
|
|
|
|
def version_in_aur(pkg):
|
|
p = {'v': '5', 'type': 'search', 'by': 'name', 'arg': pkg}
|
|
response = requests.get('https://aur.archlinux.org/rpc/', params=p)
|
|
response = response.json()
|
|
for r in response['results']:
|
|
if r['Name'] == pkg:
|
|
return r['Version']
|
|
|
|
return "NotFound"
|
|
|
|
|
|
def vcs_version(pkg, ver):
|
|
""" Try to find a sensible version for VSC packages
|
|
|
|
If pkg looks like a VCS package according to
|
|
https://wiki.archlinux.org/index.php/VCS_package_guidelines
|
|
try to extract a sensible (= comparable) version number.
|
|
"""
|
|
|
|
suffices = ['-cvs', '-svn', '-hg', '-darcs', '-bzr', '-git']
|
|
if not any(pkg.endswith(suffix) for suffix in suffices):
|
|
# does not look like a VCS package
|
|
return ver
|
|
|
|
if '.r' in ver:
|
|
# of the form RELEASE.rREVISION: only use the release
|
|
return ver.split('.r')[0]
|
|
# no base release to compare, just return None
|
|
return None
|
|
|
|
if args.force_ipv4:
|
|
# This is useful, because the AUR API often gets timeouts with
|
|
# IPV6 and the call does not return.
|
|
|
|
# monkey-patch this function to always return the IPV4-version,
|
|
# even if capable of IPV6
|
|
requests.packages.urllib3.util.connection.allowed_gai_family = (
|
|
lambda: socket.AF_INET
|
|
)
|
|
|
|
# show the list of updates already cached
|
|
if args.cache_updates and block_button in [2, 3]:
|
|
if '_update_cache' in os.environ:
|
|
updates = os.environ['_update_cache']
|
|
else:
|
|
updates = 'no updates cached'
|
|
sp.call(['notify-send', 'AUR updates', updates or 'up to date'])
|
|
|
|
# get list of foreign packages -- assumed to be from the AUR
|
|
packages = sp.check_output(['pacman', '-Qm']).decode('utf8')
|
|
|
|
installed_version = {}
|
|
for pkg in packages.split('\n'):
|
|
if not pkg:
|
|
continue
|
|
pkg, ver = pkg.split()
|
|
installed_version[pkg] = ver
|
|
|
|
updates = []
|
|
for pkg in installed_version.keys():
|
|
if pkg in args.ignore:
|
|
continue
|
|
v_aur = version_in_aur(pkg)
|
|
v_inst = installed_version[pkg]
|
|
if vcs_version(pkg, v_aur) != vcs_version(pkg, v_inst):
|
|
updates.append(pkg + ' (%s -> %s)' % (v_inst, v_aur))
|
|
|
|
# create the message for the block
|
|
n_updates = len(updates)
|
|
msg = ''
|
|
if n_updates > 0:
|
|
msg = "<span color='{0}'>{1} AUR updates</span>".format(args.update_color, n_updates)
|
|
elif not args.quiet:
|
|
msg = 'AUR up to date'
|
|
|
|
# turn it into a json message
|
|
msg = {'full_text': msg}
|
|
|
|
# cache the new updates list
|
|
if args.cache_updates:
|
|
msg['_update_cache'] = '\n'.join(updates)
|
|
|
|
print(json.dumps(msg))
|
|
|
|
# if you don't use caching, show the new list of updates
|
|
if not args.cache_updates and block_button in [2, 3]:
|
|
sp.call(['notify-send', 'AUR updates', '\n'.join(updates) or 'up to date'])
|
|
|
|
if not 'BLOCK_NAME' in os.environ and n_updates > 0:
|
|
# not called by i3blocks: show the complete list
|
|
print('\n'.join(updates))
|