From: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Date: Mon, 15 Sep 2025 16:15:46 +0000 (+0000) Subject: Change tilde to hyphen in version strings to fix markdown formatting X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=211715c801a1de191fe7f812cbbfd0e92a5e80b4;p=thirdparty%2Ftvheadend.git Change tilde to hyphen in version strings to fix markdown formatting Co-authored-by: Flole998 <9951871+Flole998@users.noreply.github.com> --- diff --git a/support/bintray.py b/support/bintray.py new file mode 100755 index 000000000..7c65a3a6d --- /dev/null +++ b/support/bintray.py @@ -0,0 +1,373 @@ +#! /usr/bin/env python + +# +# TVH bintray tool, compatible with both python2 and python3 +# + +import os +import sys +import json +import base64 +import traceback +try: + # Python 3 + import urllib.request as urllib + from urllib.parse import urlencode +except ImportError: + # Python 2 + import urllib2 as urllib + from urllib import urlencode + +def env(key): + if key in os.environ: return os.environ[key] + return None + +DEBUG=False + +BINTRAY_API='https://bintray.com/api/v1' +BINTRAY_USER=env('BINTRAY_USER') +BINTRAY_PASS=env('BINTRAY_PASS') +BINTRAY_REPO=env('BINTRAY_REPO') +BINTRAY_COMPONENT=env('BINTRAY_COMPONENT') +BINTRAY_ORG=env('BINTRAY_ORG') or 'tvheadend' +BINTRAY_PACKAGE='tvheadend' + +PACKAGE_DESC='Tvheadend is a TV streaming server and recorder for Linux, FreeBSD and Android' + +class Response(object): + def __init__(self, response): + self.url = response.geturl() + self.code = response.getcode() + self.reason = response.msg + self.headers = response.info() + if 'Content-type' in self.headers and self.headers['Content-type'] == 'application/json': + self.body = json.loads(response.read()) + else: + self.body = response.read() + +class Bintray(object): + + def __init__(self, path, headers=None): + self._headers = headers or {} + self._path = path or [] + a = '%s:%s' % (BINTRAY_USER, BINTRAY_PASS) + self._auth = b'Basic ' + base64.b64encode(a.encode('utf-8')) + + def opener(self): + if DEBUG: + return urllib.build_opener(urllib.HTTPSHandler(debuglevel=1)) + else: + return urllib.build_opener() + + def _push(self, data, binary=None, method='PUT'): + content_type = 'application/json' + if binary: + content_type = 'application/binary' + else: + data = json.dumps(data) + opener = self.opener() + path = self._path + if path[0] != '/': path = '/' + path + request = urllib.Request(BINTRAY_API + path, data=data) + request.add_header('Content-Type', content_type) + request.add_header('Authorization', self._auth) + request.get_method = lambda: method + try: + r = Response(opener.open(request)) + except urllib.HTTPError as e: + r = Response(e) + return r + + def get(self, binary=None): + return self._push(None, method='GET') + + def delete(self, binary=None): + return self._push(None, method='DELETE') + + def put(self, data, binary=None): + return self._push(data, binary) + + def post(self, data): + return self._push(data, method='POST') + +def error(lvl, msg, *args): + sys.stderr.write(msg % args + '\n') + sys.exit(lvl) + +def info(msg, *args): + print('BINTRAY: ' + msg % args) + +def do_upload(*args): + if len(args) < 2: error(1, 'upload [url] [file]') + bpath, file = args[0], args[1] + data = open(file, 'rb').read() + resp = Bintray(bpath).put(data, binary=1) + if resp.code != 200 and resp.code != 201: + if resp.code == 409: + error(0, 'HTTP WARNING "%s" %s %s', resp.url, resp.code, resp.reason) + error(10, 'HTTP ERROR "%s" %s %s', resp.url, resp.code, resp.reason) + +def get_ver(version): + if version.find('-') > 0: + version, git = version.split('-', 1) + else: + git = None + try: + major, minor, rest = version.split('.', 2) + except: + major, minor = version.split('.', 1) + rest = '' + return (major, minor, rest, git) + +def get_path(version, repo): + major, minor, rest, git = get_ver(version) + if int(major) >= 4 and int(minor) & 1 == 0: + if repo in ['fedora', 'centos', 'rhel'] and git.find('~') <= 0: + return '%s.%s-release' % (major, minor) + return '%s.%s' % (major, minor) + return 't' + +def get_component(version): + major, minor, rest, git = get_ver(version) + if int(major) >= 4 and int(minor) & 1 == 0: + if git and git.find('~') > 0: + return 'stable-%s.%s' % (major, minor) + return 'release-%s.%s' % (major, minor) + return 'unstable' + +def get_repo(filename, hint=None): + if hint: return hint + if BINTRAY_REPO: return BINTRAY_REPO + name, ext = os.path.splitext(filename) + if ext == '.deb': + return 'deb' + if ext == '.rpm': + if name.find('.centos') > 0: + return 'centos' + elif name.find('.fc') > 0: + return 'fedora' + elif name.find('.el') > 0: + return 'rhel' + +def rpmversion(name): + ver = type('',(object,),{})() + rpmbase, ver.arch = name.rsplit('.', 1) + rpmname, rpmversion = rpmbase.rsplit('-', 1) + rpmname, rpmversion2 = rpmname.rsplit('-', 1) + rpmversion = rpmversion2 + '-' + rpmversion + rpmver1, rpmver2 = rpmversion.split('-', 1) + rpmversion, ver.dist = rpmver2.split('.', 1) + ver.version = rpmver1 + '-' + rpmversion + return ver + +def get_bintray_params(filename, hint=None): + filename = filename.strip() + basename = os.path.basename(filename) + name, ext = os.path.splitext(basename) + args = type('',(object,),{})() + args.org = BINTRAY_ORG + args.repo = get_repo(basename, hint) + args.package = BINTRAY_PACKAGE + extra = [] + if args.repo == 'deb': + debbase, debarch = name.rsplit('_', 1) + try: + debname, debversion = debbase.split('_', 1) + except: + debname, debversion = debbase.split('-', 1) + debversion, debdistro = debversion.rsplit('~', 1) + args.version = debversion + args.path = 'pool/' + get_path(debversion, args.repo) + '/' + args.package + extra.append('deb_component=' + (BINTRAY_COMPONENT or get_component(debversion))) + extra.append('deb_distribution=' + debdistro) + extra.append('deb_architecture=' + debarch) + else: + rpmver = rpmversion(name) + args.version = rpmver.version + args.path = 'linux/' + get_path(rpmver.version, args.repo) + \ + '/' + rpmver.dist + '/' + rpmver.arch + extra = ';'.join(extra) + if extra: extra = ';' + extra + return (basename, args, extra) + +def do_publish(*args): + return + if len(args) < 1: error(1, 'upload [file with the file list]') + if not DEBUG: + branches = os.popen('git branch --contains HEAD').readlines() + ok = 0 + for b in branches: + if b[0] == '*': + b = b[1:] + b = b.strip() + if b == 'master' or b.startswith('release/'): + ok = 1 + break + if not ok: + info('BINTRAY upload - invalid branches\n%s', branches) + sys.exit(0) + files = open(args[0]).readlines() + args = None + for file in files: + try: + basename, args, extra = get_bintray_params(file) + hint = args.repo + break + except: + pass + if not args: + for file in files: + try: + basename, args, extra = get_bintray_params(file) + except: + traceback.print_exc() + bpath = '/packages/tvheadend/%s/tvheadend/versions' % args.repo + data = { 'name': args.version, 'desc': PACKAGE_DESC } + resp = Bintray(bpath).post(data) + if resp.code != 200 and resp.code != 201 and resp.code != 409: + error(10, 'Version %s/%s: HTTP ERROR %s %s', + args.repo, args.version, resp.code, resp.reason) + info('Version %s/%s created', args.repo, args.version) + for file in files: + file = file.strip() + basename, args, extra = get_bintray_params(file, hint) + pub = 1 + if "-dirty" in basename.lower(): + pub = 0 + bpath = '/content/%s/%s/%s/%s/%s/%s%s;publish=%s' % \ + (args.org, args.repo, args.package, args.version, + args.path, basename, extra, pub) + data = open(file, 'rb').read() + resp = Bintray(bpath).put(data, binary=1) + if resp.code != 200 and resp.code != 201: + error(10, 'File %s (%s): HTTP ERROR "%s" %s', + file, bpath, resp.code, resp.reason) + else: + info('File %s: uploaded', file) + +def get_versions(repo, package): + bpath = '/packages/%s/%s/%s' % (BINTRAY_ORG, repo, package) + resp = Bintray(bpath).get() + if resp.code != 200 and resp.code != 201: + error(10, ' %s/%s: HTTP ERROR %s %s', + repo, package, resp.code, resp.reason) + return resp.body + +def get_files(repo, package, unpublished=0): + bpath = '/packages/%s/%s/%s/files?include_unpublished=%d' % (BINTRAY_ORG, repo, package, unpublished) + resp = Bintray(bpath).get() + if resp.code != 200 and resp.code != 201: + error(10, ' %s/%s: HTTP ERROR %s %s', + repo, package, resp.code, resp.reason) + return resp.body + +def delete_file(repo, file): + bpath = '/content/%s/%s/%s' % (BINTRAY_ORG, repo, urllib.quote(file)) + resp = Bintray(bpath).delete() + if resp.code != 200 and resp.code != 201: + error(10, ' %s/%s: HTTP ERROR %s %s', + repo, file, resp.code, resp.reason) + +def delete_up_to_count(repo, files, max_count, auxfcn=None): + files.sort(key=lambda x: x['sortkey'], reverse=True) + key = '' + count = 0 + for f in files: + a, b = f['sortkey'].split('*') + if a == key: + if count > max_count: + info('delete %s', f['path']) + if auxfcn: + auxfcn(repo, f['path']) + else: + delete_file(repo, f['path']) + else: + info('keep %s', f['path']) + count += 1 + else: + key = a + count = 0 + +def do_tidy(*args): + + def fedora_delete(repo, path): + rest = '-' + '-'.join(path.split('tvheadend-')[1:]) + for f in files: + if f['path'].find(rest) >= 0: + delete_file(repo, f['path']) + + def fedora_files(repo): + files = get_files(repo, 'tvheadend') + sfiles = [] + for f in files: + if f['name'].startswith('tvheadend-debuginfo-'): + continue + if f['name'].find('~') < 0: + continue + name, ext = os.path.splitext(f['name']) + rpmver = rpmversion(name) + f['ver1'], f['ver2'] = rpmver.version.split('~')[0].split('-') + f['sortkey'] = "%s/%s/%s*%08d" % (rpmver.dist, rpmver.arch, f['ver1'], long(f['ver2'])) + sfiles.append(f) + return files, sfiles + + files, sfiles = fedora_files('centos') + delete_up_to_count('centos', sfiles, 10, fedora_delete) + + files, sfiles = fedora_files('fedora') + delete_up_to_count('fedora', sfiles, 10, fedora_delete) + + #files = get_files('misc', 'staticlib', 1) + #for f in files: + # a, b = f['path'].split('-') + # f['sortkey'] = a + '*' + f['created'] + #delete_up_to_count('misc', files, 4) + +def do_unknown(*args): + r = 'Please, specify a valid command:\n' + for n in globals(): + if n.startswith('do_') and n != 'do_unknown': + r += ' ' + n[3:] + '\n' + error(1, r[:-1]) + +def test_filename(): + FILES=[ + "tvheadend_4.3-86~g7d2c4e8~xenial_amd64.deb", + "tvheadend_4.3-86~g7d2c4e8~xenial_arm64.deb", + "tvheadend_4.3-666~a6b0mfyj-dirty~jessie_armhf.deb", + "tvheadend-4.3-86~g7d2c4e8.el7.centos.x86_64.rpm", + "tvheadend-4.3-86~g7d2c4e8.fc24.x86_64.rpm", + "tvheadend-4.2.2~xenial_amd64.deb", + "tvheadend_4.2.2~xenial_arm64.deb", + "tvheadend-4.2.2-1.el7.centos.x86_64.rpm", + "tvheadend-4.2.2-1.fc24.x86_64.rpm", + "tvheadend-4.2.2-1~g82c8872~xenial_amd64.deb", + "tvheadend_4.2.2-1~g82c8872~xenial_arm64.deb", + "tvheadend-4.2.2-1~g82c8872.el7.centos.x86_64.rpm", + "tvheadend-4.2.2-1~g82c8872.fc24.x86_64.rpm", + ] + from pprint import pprint + for f in FILES: + basename, args, extra = get_bintray_params(f) + print('\n') + print('BASENAME:', basename) + print('EXTRA:', extra) + pprint(vars(args), indent=2) + +def main(argv): + global DEBUG + if len(argv) > 1 and argv[1] == '--test-filename': + return test_filename() + if not BINTRAY_USER or not BINTRAY_PASS: + error(2, 'No credentals') + if len(argv) > 1 and argv[1] == '--debug': + DEBUG=1 + argv.pop(0) + cmd = 'do_' + (len(argv) > 1 and argv[1] or 'unknown') + if cmd in globals(): + globals()[cmd](*argv[2:]) + else: + do_unknown() + +if __name__ == "__main__": + main(sys.argv)